前提
AndroidでJTransFormsを使って周波数スペクトルアナライザを作成しようとしています。
ですが、静かな部屋で実施していても不要なスペクトルが検出されてしまいます。
キザギザの不定形なグラフになってしまいます。
ピアノのA4の440hzの音を検出することは一応できます。
実現したいこと
不要なスペクトルを除去すること(ほとんどが40db以下ですが40db以下でも必要なスペクトルはあります)
またピークを検出するために邪魔になっているのでこれを直したいです。
該当のソースコード
java
1 Handler handler= new Handler(); 2 WebView webView; 3 4 final static int SAMPLING_RATE = 44100; 5 final static int FFT_SIZE = 4096 * 2; 6 AudioRecord audioRec = null; 7 boolean bIsRecording = false; 8 int bufSize = FFT_SIZE / 2; 9 private double[] window = null; 10 String msg = ""; 11 double dB_baseline = Math.pow(2, 15)*FFT_SIZE*Math.sqrt(2); 12 final static double MAX_DB = 120; 13 14 Thread recodingFFTthread; 15 16 @Override 17 protected void onCreate(Bundle savedInstanceState) { 18 super.onCreate(savedInstanceState); 19 setContentView(R.layout.activity_main); 20 21 webView = (WebView) findViewById(R.id.webViewMain); 22 webView.getSettings().setJavaScriptEnabled(true); 23 webView.setWebChromeClient(new WebChromeClient()); 24 webView.addJavascriptInterface(new JavaScriptInterface(), "android"); 25 webView.loadUrl("file:///android_asset/test.html"); 26 27 java.util.Arrays.fill(noise_dbfs, (double) 0); 28 } 29 30 @Override 31 protected void onResume() { 32 super.onResume(); 33 34 //マイク使用の権限をユーザーから取得する 35 permission(android.Manifest.permission.RECORD_AUDIO); 36 37 noise_sampling_count = 0; 38 39 //AudioRecordの作成 40 audioRec = new AudioRecord( 41 MediaRecorder.AudioSource.CAMCORDER, 42 SAMPLING_RATE, 43 AudioFormat.CHANNEL_IN_MONO, 44 AudioFormat.ENCODING_PCM_16BIT, 45 bufSize * 2); 46 47 audioRec.startRecording(); 48 bIsRecording = true; 49 recodingFFTthread = new Thread(new Runnable() { 50 @Override 51 public void run() { 52 NoiseSuppressor noiseSuppressor = null; 53 if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) 54 { 55// noiseSuppressor = NoiseSuppressor.create(audioRec.getAudioSessionId()); 56 Log.d("DEBUG", "NoiseSuppressor.isAvailable() " + NoiseSuppressor.isAvailable()); 57 } 58 59 short buf[] = new short[bufSize]; 60 while (bIsRecording) { 61 audioRec.read(buf, 0, buf.length); 62 // Log.d("audiorecord", String.valueOf(buf.length)); 63 DoubleFFT_1D fft = new DoubleFFT_1D(FFT_SIZE) ; 64 double[] FFTdata = new double[(buf.length + 24 * buf.length) * 2]; 65 System.arraycopy(applyWindow(buf), 0, FFTdata, 0, buf.length); 66 67// double[] FFTdata = new double[FFT_SIZE]; 68// for(int i=0;i<FFT_SIZE;i++){ 69// FFTdata[i] = (double) buf[i]; 70// } 71 fft.realForward(FFTdata); 72 //dBFS計算 73 double[] dbfs = new double[FFT_SIZE/2]; 74 int max_i = 0; 75 double max_db = 0; 76 for(int i=0;i<FFT_SIZE;i+=2){ 77 dbfs[i/2]= MAX_DB + (int) 78 (20*Math.log10( Math.sqrt(Math.pow(FFTdata[i], 2) 79 +Math.pow(FFTdata[i+1], 2))/dB_baseline)); 80 if(max_db < dbfs[i/2]){ 81 max_db = dbfs[i/2]; 82 max_i = i/2; 83 } 84 } 85 86 int hz = (int)((SAMPLING_RATE/ (double) FFT_SIZE) * max_i); 87 Log.i("音声", hz + "[Hz]" + max_db + "[max_db]"); 88 89 int[] peeks = getPeeks(dbfs); 90 91 StringJoiner sj_dbfs = new StringJoiner(","); 92 for (double item : dbfs) { 93 sj_dbfs.add(String.valueOf(item)); 94 } 95 96 // ここでWebViewと通信してスペクトルを可視化している 97 handler.post(new Runnable() { 98 @Override 99 public void run() { 100 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 101 webView.evaluateJavascript("refreshHzBarGraph([" + sj_dbfs.toString() + "]);", null); 102 } else { 103 webView.loadUrl("javascript:refreshHzBarGraph([" + sj_dbfs.toString() + "]);"); 104 } 105 } 106 }); 107 108 109 } 110 // 録音停止 111 audioRec.stop(); 112 audioRec.release(); 113 if(noiseSuppressor != null) 114 { 115 noiseSuppressor.release(); 116 } 117 } 118 }); 119 recodingFFTthread.start(); 120 }
試したこと
何個かの物理端末でテストした
NoiseSuppressorは期待した動作をしませんでした
スピーカーをミュートにしてみた
補足情報(FW/ツールのバージョンなど)
<uses-sdk android:minSdkVersion="21" />よろしくお願いいたします。
追加情報
ご指摘いただきありがとうございます。
サンプルとして連続した5個のスペクトル数値配列情報を記載します。
Logcatで出力したので400文字程度で区切られていますが、低周波数帯域でノイズが多いことがわかりました。
1列目はhzです。
https://wikiwiki.jp/umeteratail/
あなたの回答
tips
プレビュー