java - programacion - Mostrando un doble(frecuencia) que se actualiza constantemente durante la grabaciĆ³n con Android
manual android studio avanzado (3)
SetContentView en onProgressUpdate es un error. Realmente no desea cambiar el diseño xml
Estoy construyendo una aplicación de Android que muestra la frecuencia de una nota sostenida con el algoritmo de FFT. Estoy usando métodos de Jtransform. Mi problema actualmente es que no puedo mostrar la frecuencia en la pantalla. El siguiente código es el cálculo de fft freqency y el AsynchTask que debe mostrar la frecuencia en un cuadro de texto
import edu.emory.mathcs.jtransforms.fft.DoubleFFT_1D;
public class Tuning 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
int blockSize = 1024; // deal with this many samples at a time
int sampleRate = 44100; // 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
// On Start Up
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.tuning);
tv = (TextView) findViewById(R.id.lbl1);
}
// The Record and analysis class
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];
audioRecord.startRecording(); // Start working
fft = new DoubleFFT_1D(blockSize);
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;
}
//audiodataDoubles now holds data to work with
fft.complexForward(audioDataDoubles);
// Calculate the Real and imaginary and Magnitude.
for(int i = 0; i < blockSize; i++){
// real is stored in first part of array
re[i] = audioDataDoubles[i*2];
// imaginary is stored in the sequential part
im[i] = audioDataDoubles[(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);
}
} catch(Throwable t){
Log.e("AudioRecord", "Recording Failed");
}
return null;
}
// This should display the Frequency
protected void onProgressUpdate(Double value){
//print the frequency
setContentView(R.layout.tuning);
String info = Double.toString(value);
//TextView doubleView = (TextView) findViewById(R.id.DoubleView);
tv.setText(info);
}
// For the click of the button
public void onClick(View v){
if(started){
started = false;
startStopButton.setText("Start");
recordTask.cancel(true);
} else {
started = true;
startStopButton.setText("Stop");
recordTask = new RecordAudio();
recordTask.execute();
}
}
He verificado otras preguntas similares y no puedo encontrar el error en mi código.
EDITAR : agregó onClick()
al código. Sé que se está calculando la frecuencia y, de acuerdo con Eclipse, en ningún momento se onProgressUpdate()
al onProgressUpdate()
.
Intenta reemplazar
protected void onProgressUpdate(Double value){
//print the frequency
setContentView(R.layout.tuning);
String info = Double.toString(value);
con
protected void onProgressUpdate(Double... value){
//print the frequency
String info = Double.toString(value[0]);
Para otros que no tengan jtransforms.jar, consulte http://sourceforge.net/projects/jtransforms/
Además de lo que dijo Alexei , en su respuesta , creo que también ha codificado incorrectamente la firma de método de onProgressUpdate()
:
protected void onProgressUpdate(Double value){
Esto significa que su versión de onProgressUpdate()
no está anulando nada de AsyncTask , y nunca se llamará.
Entonces, incluyendo el punto sobre no llamar a setContentView()
repetidamente, su método final debería verse así:
protected void onProgressUpdate(Double... frequencies){
//print the frequency
String info = Double.toString(frequencies[0]);
tv.setText(info);
}