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

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

ただいまの
回答率

90.53%

  • Java

    15539questions

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

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

受付中

回答 0

投稿

  • 評価
  • クリップ 2
  • VIEW 1,152

nextmura

score 4

今現在僕はスマートフォン内蔵のマイク、詳しくは受話口にあるマイクとスマートフォンの背にあるカムコーダと呼ばれるマイク二つを使って新しいスマートフォン操作手法を考えてます。カムコーダとは普段は通話中のノイズキャンセリングのために用いられるマイクです。
現在はスマートフォンのマイクとカムコーダから音データを収集し、音データに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;
}

}

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

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

同じタグがついた質問を見る

  • Java

    15539questions

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