当前位置: 首页 > 面试题库 >

显示使用Android录制时不断更新的双精度(频率)

蒋茂
2023-03-14
问题内容

我正在构建一个使用FFT算法显示持续音符频率的android应用程序。我正在使用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<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();
       }
   }

我检查了其他类似的问题,但在我的代码中找不到错误。

编辑 :添加onClick()到代码。我知道频率是在计算的,根据Eclipse,在任何时候都onProgressUpdate()不会被调用。


问题答案:

除了什么阿列克谢说在他的回答,我想你也编码错误的方法签名onProgressUpdate():onProgressUpdate中的SetContentView是错误。您真的不想更改布局xml

protected void onProgressUpdate(Double value){

这意味着您的的版本onProgressUpdate()实际上并未覆盖AsyncTask的任何内容,并且将永远不会被调用。

因此,包括 setContentView()重复调用的要点,您的最终方法应如下所示:

protected void onProgressUpdate(Double... frequencies){
    //print the frequency 
    String info = Double.toString(frequencies[0]);
    tv.html" target="_blank">setText(info);
}


 类似资料:
  • 问题内容: 我用双精度(小数)出现了这个问题。 当double = 1.234567时,我使用 所以结果是1.234 但是当我的倍数是10时 ,结果将是10,000, 我希望这是10 他们是否可以说他只在“ usefull”时才显示小数? 我看到了一些有关此的文章,但是那是php或c#,找不到关于android / java的东西(也许我看起来不太好)。 希望你们能帮我这个忙。 编辑,现在我使用类

  • 问题内容: java中双值的乘法运算符的保证精度是多少? 例如,2.2 * 100是220.00000000000003,但是220是双精度数。220.00000000000003是220之后的下一个两倍。 问题答案: 乘法工作正常,但不能精确表示为双精度。最接近的双打是: 2.199999999999999733(0x4001999999999999) 2.200000000000000177(

  • 问题内容: 如果我有以下小数点数字: 然后我得到以下输出: 我想要的是: 问题答案: 可能令人困惑的部分是 的表示整个数(包括小数)的长度,而不仅仅是小数之前的部分。该代表的小数位数。 因此,要使格式正确无误,最多可以有小数点前4个数字和小数点后3个位,实际上是所需的格式。

  • IEEE 754双精度浮点格式的二进制精度为53位,转换为log10(2^53)~ 16位有效十进制数字。 如果使用双精度格式将浮点数存储在内存中的64位长字中,52位为有效位,1位为隐藏位,但使用更高的精度将数字输出到屏幕,那么实际上从内存中读取哪些数据并将其写入输出? 当单词的总长度为64位时,机器上的从内存中读取操作是否只是简单地读取更多位并将它们解释为数字意义的加法? 例如,以数字0.1为

  • 本文向大家介绍C#浮点,双精度,十进制,包括了C#浮点,双精度,十进制的使用技巧和注意事项,需要的朋友参考一下 示例 浮动 float是.NET数据类型的别名System.Single。它允许存储IEEE 754单精度浮点数。存在此数据类型mscorlib.dll,每个C#项目在创建它们时都会隐式引用该数据类型。 大致范围:-3.4×10 38至3.4×10 38 十进制精度:6-9个有效数字 记

  • 我想要得到一个特定位置附近的所有商店,但似乎我有一个查询字符串的问题。我已经检查了postgis的版本是PostGIS2.5.2_2。我也检查过,看看经度和纬度是否有双精度。 我尝试将查询重写到不同的查询字符串中,但仍然得到相同的错误。 我的实体: 我的存储库接口: 在postgres数据库中工作,但在java应用程序中,它返回一个错误: psqlException:error:“:”处或附近的语