Android获得audio实时?

我一直在尝试使用fft实时获取声audio率(数字),我有运行时错误。 任何人都可以帮忙吗?

package com.example.recordsound; import edu.emory.mathcs.jtransforms.fft.DoubleFFT_1D; import ca.uol.aig.fftpack.RealDoubleFFT; public class MainActivity extends Activity implements OnClickListener{ int audioSource = MediaRecorder.AudioSource.MIC; // Audio source is the device MIC int channelConfig = AudioFormat.CHANNEL_IN_MONO; // Recording in mono int audioEncoding = AudioFormat.ENCODING_PCM_16BIT; // Records in 16bit private DoubleFFT_1D fft; // The fft double array private RealDoubleFFT transformer; int blockSize = 256; // deal with this many samples at a time int sampleRate = 8000; // Sample rate in Hz public double frequency = 0.0; // the frequency given RecordAudio recordTask; // Creates a Record Audio command TextView tv; // Creates a text view for the frequency boolean started = false; Button startStopButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView)findViewById(R.id.textView1); startStopButton= (Button)findViewById(R.id.button1); } @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; } private class RecordAudio extends AsyncTask<Void, Double, Void>{ @Override protected Void doInBackground(Void... params){ /*Calculates the fft and frequency of the input*/ //try{ int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioEncoding); // Gets the minimum buffer needed AudioRecord audioRecord = new AudioRecord(audioSource, sampleRate, channelConfig, audioEncoding, bufferSize); // The RAW PCM sample recording short[] buffer = new short[blockSize]; // Save the raw PCM samples as short bytes // double[] audioDataDoubles = new double[(blockSize*2)]; // Same values as above, as doubles // ----------------------------------------------- double[] re = new double[blockSize]; double[] im = new double[blockSize]; double[] magnitude = new double[blockSize]; // ---------------------------------------------------- double[] toTransform = new double[blockSize]; tv.setText("Hello"); // fft = new DoubleFFT_1D(blockSize); try{ audioRecord.startRecording(); //Start }catch(Throwable t){ Log.e("AudioRecord", "Recording Failed"); } while(started){ /* Reads the data from the microphone. it takes in data * to the size of the window "blockSize". The data is then * given in to audioRecord. The int returned is the number * of bytes that were read*/ int bufferReadResult = audioRecord.read(buffer, 0, blockSize); // Read in the data from the mic to the array for(int i = 0; i < blockSize && i < bufferReadResult; i++) { /* dividing the short by 32768.0 gives us the * result in a range -1.0 to 1.0. * Data for the compextForward is given back * as two numbers in sequence. Therefore audioDataDoubles * needs to be twice as large*/ // audioDataDoubles[2*i] = (double) buffer[i]/32768.0; // signed 16 bit //audioDataDoubles[(2*i)+1] = 0.0; toTransform[i] = (double) buffer[i] / 32768.0; // signed 16 bit } //audiodataDoubles now holds data to work with // fft.complexForward(audioDataDoubles); transformer.ft(toTransform); //------------------------------------------------------------------------------------------ // Calculate the Real and imaginary and Magnitude. for(int i = 0; i < blockSize; i++){ // real is stored in first part of array re[i] = toTransform[i*2]; // imaginary is stored in the sequential part im[i] = toTransform[(i*2)+1]; // magnitude is calculated by the square root of (imaginary^2 + real^2) magnitude[i] = Math.sqrt((re[i] * re[i]) + (im[i]*im[i])); } double peak = -1.0; // Get the largest magnitude peak for(int i = 0; i < blockSize; i++){ if(peak < magnitude[i]) peak = magnitude[i]; } // calculated the frequency frequency = (sampleRate * peak)/blockSize; //---------------------------------------------------------------------------------------------- /* calls onProgressUpdate * publishes the frequency */ publishProgress(frequency); try{ audioRecord.stop(); } catch(IllegalStateException e){ Log.e("Stop failed", e.toString()); } } // } return null; } protected void onProgressUpdate(Double... frequencies){ //print the frequency String info = Double.toString(frequencies[0]); tv.setText(info); } } @Override public void onClick(View v) { // TODO Auto-generated method stub if(started){ started = false; startStopButton.setText("Start"); recordTask.cancel(true); } else { started = true; startStopButton.setText("Stop"); recordTask = new RecordAudio(); recordTask.execute(); } } } 

AS ASON当我使用OnClick运行程序时,它崩溃了我尝试了两个用于fft的库,但一次只运行一个库,以查看库是否工作一旦到达将FFT块对象分配给FFT对象的那一行它可以崩溃任何一个帮助

Solutions Collecting From Web of "Android获得audio实时?"

试试这个FFT:

 public class FFT { int n, m; // Lookup tables. Only need to recompute when size of FFT changes. double[] cos; double[] sin; public FFT(int n) { this.n = n; this.m = (int) (Math.log(n) / Math.log(2)); // Make sure n is a power of 2 if (n != (1 << m)) throw new RuntimeException("FFT length must be power of 2"); // precompute tables cos = new double[n / 2]; sin = new double[n / 2]; for (int i = 0; i < n / 2; i++) { cos[i] = Math.cos(-2 * Math.PI * i / n); sin[i] = Math.sin(-2 * Math.PI * i / n); } } public void fft(double[] x, double[] y) { int i, j, k, n1, n2, a; double c, s, t1, t2; // Bit-reverse j = 0; n2 = n / 2; for (i = 1; i < n - 1; i++) { n1 = n2; while (j >= n1) { j = j - n1; n1 = n1 / 2; } j = j + n1; if (i < j) { t1 = x[i]; x[i] = x[j]; x[j] = t1; t1 = y[i]; y[i] = y[j]; y[j] = t1; } } // FFT n1 = 0; n2 = 1; for (i = 0; i < m; i++) { n1 = n2; n2 = n2 + n2; a = 0; for (j = 0; j < n1; j++) { c = cos[a]; s = sin[a]; a += 1 << (m - i - 1); for (k = j; k < n; k = k + n2) { t1 = c * x[k + n1] - s * y[k + n1]; t2 = s * x[k + n1] + c * y[k + n1]; x[k + n1] = x[k] - t1; y[k + n1] = y[k] - t2; x[k] = x[k] + t1; y[k] = y[k] + t2; } } } } } 

它应该解决你的想法。 如果您决定重新使用它,请给作者适当的评价。

出处/作者: EricLarch

如果您真的想要进行实时audio分析,基于Java的方法将不会执行。 我在2013年第四季度为我的公司做了类似的任务,我们决定使用Kiss FFT (也许是最简单的具有BSD许可证的FFT库),使用NDK为Android编译。

原生的C / C ++方法比Java相比快了许多 。 与前者相比,我们已经能够在几乎所有中高端设备上进行实时audio解码audiofunction分析 ,而后者显然是不可能的。

强烈build议您考虑将本机方法作为完成此任务的最佳select。 吻FFT是一个非常简单的库(字面意思是Keep It Simple FFT ),在Android上编译和使用它不会遇到太多麻烦。 你不会失望的performance结果。

你解决了这个问题吗? 由于ArrayIndexOutOfBoundsException而发生挤压。

所以,修改你的代码来:

  double[] re = new double[blockSize]; double[] im = new double[blockSize]; double[] magnitude = new double[blockSize]; // Calculate the Real and imaginary and Magnitude. for(int i = 0; i < blockSize+1; i++){ try { // real is stored in first part of array re[i] = toTransform[i * 2]; // imaginary is stored in the sequential part im[i] = toTransform[(i * 2) + 1]; // magnitude is calculated by the square root of (imaginary^2 + real^2) magnitude[i] = Math.sqrt((re[i] * re[i]) + (im[i] * im[i])); }catch (ArrayIndexOutOfBoundsException e){ Log.e("test", "NULL"); } } double peak = -1.0; // Get the largest magnitude peak for(int i = 0; i < blockSize; i++){ if(peak < magnitude[i]) peak = magnitude[i]; } // calculated the frequency frequency = Double.toString((sampleRate * peak)/blockSize);