質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

0回答

3211閲覧

スマートフォン内蔵マイクを二つ同時使用した際のエラーについて

nextmura

総合スコア12

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

1グッド

2クリップ

投稿2016/09/27 12:10

今現在僕はスマートフォン内蔵のマイク、詳しくは受話口にあるマイクとスマートフォンの背にあるカムコーダと呼ばれるマイク二つを使って新しいスマートフォン操作手法を考えてます。カムコーダとは普段は通話中のノイズキャンセリングのために用いられるマイクです。
現在はスマートフォンのマイクとカムコーダから音データを収集し、音データにFFT(高速フーリエ変換)を行うことで一番大きな音の抽出まではできています。最終的には手を鳴らすといった音が二つのマイクのどちらに音が先に到達したかによって音の方向を特定できるようなシステムを目指しています。

しかし現在、一つのスレッド内で受話口マイクとカムコーダ二つのマイクから同時に音を集音しFFTを行うとなると処理が重くなってしまったのか、
W/AudioRecord: obtainBuffer timed out (is the CPU pegged?) user=00000000, server=00000000
上記のようなエラーメッセージが発生しています。

これに対して、バッファーのサイズ変更、サンプリングレートの変更等の対策を試みましたがどれもうまくいきませんでした。使用している機材は、XPERIA Zエスオーゼで、Android studioの使用APIは24、javaのバージョンは1.8です。
FFTは別のクラスとして今回はFFT4gというオープンクラスを使用しています。FFT4g → https://github.com/YSRKEN/Ooura-FFT-Library-by-Other-Language/blob/master/Java/fft4g.java

ソースコードをいかに載せます。
package com.example.muraishi.myapplication;
import android.app.Activity;
import android.content.Context;
import android.media.AudioRecord;
import android.os.Bundle;
import android.media.AudioFormat;
import android.media.MediaRecorder;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import android.os.Environment;
import android.util.Log;
import android.view.Menu;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {

//private String sdPath = ""; //SDカードにデータを記録するための変数 //private int startflag = 0; //データの取得が開始しているか判別するための変数 //private int step = 0;// データの記録回数 //FileOutputStream fos = null; //出力先を格納するための変数(単位はバイト) //OutputStreamWriter osw = null; //上記の変数fosを出力形式にするために必要な変数) //BufferedWriter bfw = null; //最終的な出力先が格納される変数 // サンプリングレート int SAMPLING_RATE = 44100; // FFTのポイント数 int FFT_SIZE = 4096; // デシベルベースラインの設定 double dB_baseline = Math.pow(2, 15) * FFT_SIZE * Math.sqrt(2); // 分解能の計算 double resol = ((SAMPLING_RATE / (double) FFT_SIZE)); double resol0re0; double resol0re1; double resol1re0; double resol1re1; double counter=0; double rere0=0; double rere1=0; AudioRecord audioRec1 = null; AudioRecord audioRec2 = null; boolean bIsRecording = false; int bufSize; Thread fft;//スレッド作成 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bufSize = AudioRecord.getMinBufferSize(SAMPLING_RATE, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); } @Override protected void onResume() { super.onResume(); // AudioRecordの作成 audioRec1 = new AudioRecord(MediaRecorder.AudioSource.CAMCORDER, SAMPLING_RATE, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufSize * 2); audioRec2 = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLING_RATE, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufSize * 2); audioRec1.startRecording(); audioRec2.startRecording(); bIsRecording = true; //フーリエ解析スレッド fft = new Thread(new Runnable() { @Override public void run() { byte buf0[] = new byte[bufSize * 2]; byte buf1[] = new byte[bufSize * 2]; while (bIsRecording) { audioRec1.read(buf0, 0, buf0.length); int size1 = audioRec1.read(buf0, 0, buf0.length); audioRec2.read(buf1, 0, buf1.length); int size2 = audioRec2.read(buf1, 0, buf1.length); //エンディアン変換 ByteBuffer bf0 = ByteBuffer.wrap(buf0); ByteBuffer bf1 = ByteBuffer.wrap(buf1); bf0.order(ByteOrder.LITTLE_ENDIAN); bf1.order(ByteOrder.LITTLE_ENDIAN); short[] s0 = new short[(int) bufSize]; short[] s1 = new short[(int) bufSize]; for (int i = bf0.position(); i < bf0.capacity() / 2; i++) { s0[i] = bf0.getShort(); } for (int i = bf1.position(); i < bf1.capacity() / 2; i++) { s1[i] = bf1.getShort(); } //FFTクラスの作成と値の引き渡し FFT4g fft = new FFT4g(FFT_SIZE); double[] FFTdata0 = new double[FFT_SIZE]; double[] FFTdata1 = new double[FFT_SIZE]; for (int i = 0; i < FFT_SIZE; i++) { FFTdata0[i] = (double) s0[i]; FFTdata1[i] = (double) s1[i]; } fft.rdft(1, FFTdata0); fft.rdft(1, FFTdata1); // デシベルの計算 double[] dbfs0 = new double[FFT_SIZE / 2]; double[] dbfs1 = new double[FFT_SIZE / 2]; double max_db0 = -120d; double max_db1 = -120d; int max_i0 = 0; int max_i1 = 0; for (int i = 0; i < FFT_SIZE; i += 2) { dbfs0[i / 2] = (int) (20 * Math.log10(Math.sqrt(Math .pow(FFTdata0[i], 2) + Math.pow(FFTdata0[i + 1], 2)) / dB_baseline)); dbfs1[i / 2] = (int) (20 * Math.log10(Math.sqrt(Math .pow(FFTdata1[i], 2) + Math.pow(FFTdata1[i + 1], 2)) / dB_baseline)); if (max_db0 < dbfs0[i / 2]) { max_db0 = dbfs0[i / 2]; max_i0 = i / 2; } if (max_db1 < dbfs1[i / 2]) { max_db1 = dbfs1[i / 2]; max_i1 = i / 2; } } //音量が最大の周波数と,その音量を表示 Log.d("fft", "周波数:" + resol * max_i1 + " [Hz] 音量:" + max_db0 + " [dB]"); counter += 1; if(counter % 2 == 1) { resol0re0 = max_db0; resol1re0 = max_db1; } else{ resol0re1 = max_db0; resol1re1 = max_db1; } if(counter % 2 == 0) { rere0 = resol0re1 - resol0re0;//マックスdBの差分 rere1 = resol1re1 - resol1re0;// } else{ rere0 = resol0re0 - resol0re1; rere1 = resol1re0 - resol1re1; } Log.d("fft","カムコ"+rere0+"マイク"+rere1); } // 録音停止 audioRec1.stop(); audioRec1.release(); audioRec2.stop(); audioRec2.release(); } }); //スレッドのスタート fft.start(); } private static boolean checkBeforeWritefile(File file){ if (file.exists()){ if (file.isFile() && file.canWrite()){ return true; } } return false; } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; }

}

KiyoshiMotoki👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問