java android audio real-time frequency

java - Android consigue frecuencias de sonido en tiempo real?



audio real-time (3)

¿Resolviste el problema? El aplastamiento se produce debido a la excepción ArrayIndexOutOfBoundsException.

Por lo tanto, modifique su código para:

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);

He estado tratando de obtener la frecuencia de sonido (número) en tiempo real usando fft y tengo errores de tiempo de ejecución. ¿Alguien puede ayudar?

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(); } } }

Tan pronto como ejecute el programa con el OnClick se bloquea, probé dos bibliotecas para el ftp pero ejecuté una a la vez para ver si la biblioteca funciona o no tan pronto como llega a la línea donde asigno el tamaño del bloque al objeto FFT se bloquea puede ayudar alguien


Prueba este 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; } } } } }

Debe abordar lo que tienes en mente. Si decidió reutilizarlo, otorgue el crédito correspondiente al autor.

Fuente / Autor: EricLarch


Si realmente desea realizar un análisis de audio en tiempo real , un enfoque basado en Java no funcionará. Tuve una tarea similar en el cuarto trimestre de 2013 para mi empresa, y decidimos usar Kiss FFT (quizás la biblioteca de FFT más simple con una licencia BSD), compilada para Android usando el NDK.

Un enfoque nativo de C / C ++ es muchísimo más rápido que su contraparte de Java. Con el primero, hemos podido realizar decodificación de audio en tiempo real y análisis de características de audio en casi todos los dispositivos de gama media a alta, algo que obviamente era imposible con el segundo.

Le sugiero encarecidamente que considere el enfoque nativo como su mejor opción para realizar esta tarea. Kiss FFT es una biblioteca realmente simple (literalmente significa Keep It Simple FFT ), y no encontrarás muchos problemas al compilarlo y usarlo en Android. No te decepcionarán los resultados de rendimiento.