AndroidでFFTが安定しない
- 評価
- クリップ 1
- VIEW 2,127
AudioRecordとjtransformsを使用してボタンをクリックするごとにFFTを行うプログラムを作っています。
しかし、値が安定せずに困っています。使い方が間違っているのでしょうか?
ご教授お願いいたします。
ある程度、ボタンを使い方は改造途中なので間違っています・・・
package com.example.testfft004;
import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import org.jtransforms.fft.DoubleFFT_1D;
public class MainActivity extends Activity implements View.OnClickListener {
/** Called when the activity is first created. */
final static int SAMPLING_RATE = 44100;
AudioRecord audioRec = null;
Button btn = null;
boolean bIsRecording = false;
int bufSize;
final static int FFT_SIZE = 512;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button)findViewById(R.id.button_id);
btn.setOnClickListener(this);
// バッファサイズの計算
bufSize = AudioRecord.getMinBufferSize(
SAMPLING_RATE,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT);
if (FFT_SIZE > bufSize) {
bufSize = FFT_SIZE;
}
// AudioRecordの作成
audioRec = new AudioRecord(
MediaRecorder.AudioSource.MIC,
SAMPLING_RATE,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
bufSize);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (v == btn) {
if (bIsRecording) {
bIsRecording = false;
}
else {
// 録音開始
Log.v("AudioRecord", "startRecording");
audioRec.startRecording();
bIsRecording = true;
// 録音スレッド
new Thread(new Runnable() {
@Override
public void run() {
byte buf[] = new byte[bufSize];
// TODO Auto-generated method stub
// 録音データ読み込み
audioRec.read(buf, 0, buf.length);
// 録音停止
//audioRec.stop();
//高速フーリエ変換
DoubleFFT_1D fft = new DoubleFFT_1D(FFT_SIZE);
double[] FFTdata = new double[FFT_SIZE];
for (int i = 0; i < FFT_SIZE; i++) {
FFTdata[i] = (double) buf[i];
}
fft.realForward(FFTdata);
double[] dbfs = new double[FFT_SIZE / 2];
double max_db = 0;
int max_i = 0;
for (int i = 0; i < FFT_SIZE / 2; i += 2) {
dbfs[i / 2] = (int) (Math.sqrt(Math.pow(FFTdata[i], 2) + Math.pow(FFTdata[i + 1], 2)));
if (max_db < dbfs[i / 2]) {
max_db = dbfs[i / 2];
max_i = i / 2;
}
}
//Log.d("db", "Hz" + (SAMPLING_RATE/ (double) FFT_SIZE)*max_i*2 + "maxdb" + max_db);
}
}).start();
}
}
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
audioRec.release();
}
}
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
0
なんとなくですが、AudioFormat.ENCODING_PCM_16BIT なので、
FFTdata[i] = (double) buf[i]; としているところで
2バイト取ると良かったりしますかね?
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.37%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2016/05/20 13:07
FFTdata[i] = (double) (buf[i*2] << 8 + buf[i*2+1]);
もしくは、
byte buf の型を short buf に変えるとか・・?
2016/05/25 22:59
解決方法ですが、
fft.realForward(FFTdata);
がライブラリにおいてFFTを行う関数なのですがwhile文の中に入れたところ安定した結果が得られるようになりました。audioRec.stop();はwhile文の外に出しました。
原因が正直分からないところです。
アドバイス誠にありがとうございました。