显示使用Android录制时不断更新的双倍(频率)
我正在构建一个Android应用程序,它使用FFT算法显示持续音符的频率。 我正在使用Jtransform方法。 我目前的问题是我无法在屏幕上显示频率。 以下代码是fft频率计算和AsynchTask,它应该在文本框中显示频率
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{ @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(); } }
我检查了其他类似的问题,我在代码中找不到错误。
编辑 :添加onClick()
代码。 我知道频率正在计算中,根据Eclipse的说法, onProgressUpdate()
不会被调用。
除了阿列克谢所说的 , 在他的回答中 ,我认为你还错误地编码了onProgressUpdate()
的方法签名:
protected void onProgressUpdate(Double value){
这意味着您的onProgressUpdate()
版本实际上没有覆盖AsyncTask中的任何内容,并且永远不会被调用。
因此,包括不重复调用setContentView()
的观点,您的最终方法应如下所示:
protected void onProgressUpdate(Double... frequencies){ //print the frequency String info = Double.toString(frequencies[0]); tv.setText(info); }
onProgressUpdate中的SetContentView是一个错误。 你真的不想改变布局xml
尝试更换
protected void onProgressUpdate(Double value){ //print the frequency setContentView(R.layout.tuning); String info = Double.toString(value);
同
protected void onProgressUpdate(Double... value){ //print the frequency String info = Double.toString(value[0]);
对于没有jtransforms.jar的其他人,请参阅http://sourceforge.net/projects/jtransforms/
- Android,在网络共享和连接到接入点时检测WiFi的本地IP和子网掩码
- 是否有可能从Android / Java或iPhone / objective-C中的代码中获取变量名称以进行调试
- RecyclerView单项ID
- 通过surfaceview使用zxing条形码阅读器
- Androidexception(不可信服务器证书):https带有服务器身份validation的XML请求
- 多个警报在引导后重新启动
- Android从mySql获取数据
- SimpleDateFormat解析日期在某些Android设备上有所不同
- 将RecyclerView.OnItemTouchListener中的MotionEvent传递给GestureDetectorCompat