Java 使用频率从android获取超声波

Java 使用频率从android获取超声波,java,android,signal-processing,fft,audiorecord,Java,Android,Signal Processing,Fft,Audiorecord,我想从任何Android设备上获取超声波,比如频率在18KHz和19KHz之间的超声波 我使用下面的代码来计算频率,但它似乎没有给我正确的频率。我得到的频率保持在11 KHz和13 KHz之间 private void calculateFrequency() { // 1 - Initialize audio int channel_config = AudioFormat.CHANNEL_CONFIGURATION_MONO; int format =

我想从任何Android设备上获取超声波,比如频率在18KHz和19KHz之间的超声波

我使用下面的代码来计算频率,但它似乎没有给我正确的频率。我得到的频率保持在11 KHz和13 KHz之间

private void        calculateFrequency()
{
    // 1 - Initialize audio
    int channel_config = AudioFormat.CHANNEL_CONFIGURATION_MONO;
    int format = AudioFormat.ENCODING_PCM_16BIT;
    int sampleRate = 8000;
    int bufferSize = 2048;

    if (bufferSize < AudioRecord.getMinBufferSize(sampleRate, channel_config, format))
        bufferSize = AudioRecord.getMinBufferSize(sampleRate, channel_config, format);
    AudioRecord audioInput = new AudioRecord(AudioSource.MIC, sampleRate, channel_config, format, bufferSize);

    // 2 - Get sound
    byte[] audioBuffer = new byte[bufferSize];
    audioInput.startRecording();
    int nbRead = audioInput.read(audioBuffer, 0, bufferSize);
    audioInput.stop();
    audioInput.release();

    // 3 - Transform to double array
    double[] micBufferData = new double[bufferSize];
    final int bytesPerSample = 2; // As it is 16bit PCM
    final double amplification = 100.0; // choose a number as you like
    for (int index = 0, floatIndex = 0; index < nbRead - bytesPerSample + 1; index += bytesPerSample, floatIndex++) {
        double sample = 0;
        for (int b = 0; b < bytesPerSample; b++) {
            int v = audioBuffer[index + b];
            if (b < bytesPerSample - 1 || bytesPerSample == 1) {
                v &= 0xFF;
            }
            sample += v << (b * 8);
        }
        double sample32 = amplification * (sample / 32768.0);
        micBufferData[floatIndex] = sample32;
    }

    // 4 - Create complex array
    Complex[] fftTempArray = new Complex[bufferSize];
    for (int i=0; i<bufferSize; i++)
    {
        fftTempArray[i] = new Complex(micBufferData[i], 0);
    }

    // 5 - Calculate FFT
    Complex[] fftArray = FFT.fft(fftTempArray);

    // 6 - Calculate magnitude
    double[] magnitude = new double[bufferSize / 2];
    for (int i = 0; i < (bufferSize / 2); i++)
    {
        magnitude[i] = Math.sqrt(fftArray[i*2].re() * fftArray[i*2].re() + fftArray[i*2].im() * fftArray[i*2].im());
    }

    // 7 - Get maximum magnitude
    double max_magnitude = -1;
    for (int i = 0; i < bufferSize / 2; i++)
    {
        if (magnitude[i] > max_magnitude)
        {
            max_magnitude = magnitude[i];
        }
    }

    // 8 - Calculate frequency
    int freq = (int)(max_magnitude * sampleRate / bufferSize);

    ((TextView) findViewById(R.id.textView1)).setText("FREQUENCY = " + freq + "Hz");
}
private void calculateFrequency()
{
//1-初始化音频
int channel\u config=AudioFormat.channel\u CONFIGURATION\u MONO;
int format=AudioFormat.ENCODING_PCM_16位;
int-sampleRate=8000;
int bufferSize=2048;
if(bufferSizesample+=v为了获得正确的无混叠频率估计值,必须使用比音频输入中最高频率两倍以上的采样率(可能要大10%到20%以避免滤波器衰减),从而比您想要找到的最高频率高出两倍以上

这是由于采样定理要求的奈奎斯特速率


因此,如果您想找到19 kHz信号,则需要接近48000的采样率。

步骤7和8不太正确-您需要使用具有最大幅度的FFT单元索引来确定频率:

    // 7 - Get maximum magnitude
    double max_magnitude = -1;
    int max_magnitude_index = -1;
    for (int i = 0; i < bufferSize / 2; i++)
    {
        if (magnitude[i] > max_magnitude)
        {
            max_magnitude = magnitude[i];
            max_magnitude_index = i;
        }
    }

    // 8 - Calculate frequency
    int freq = (int)(max_magnitude_imdex * sampleRate / bufferSize);
//7-获取最大幅值
双倍最大值=1;
int max_magnity_index=-1;
对于(int i=0;i最大震级)
{
最大震级=震级[i];
最大震级指数=i;
}
}
//8-计算频率
int freq=(int)(最大振幅指数*采样器/缓冲区大小);

正如@hotpaw2所指出的,您的采样率在8 kHz时太低了-至少需要44.1 kHz,最好是48 kHz。

好主意。请您为我解释一下:
int freq=(int)(最大振幅*采样器/缓冲区大小)
。我使用了这个答案:见代码的最后一行错误在第7步和第8步-你需要最大震级的索引来确定频率,而不是震级本身。请更仔细地查看链接答案中的伪代码。根据奈奎斯特的说法,你的采样率必须超过感兴趣频率的两倍ix震级指数中的值错误?有时像i=max_length_of_震级,而freq=46000+谢谢你的回答。我将采样率设置为48kHz,并如你所说更改了第7步和第8步。当我尝试不产生声音时,频率听起来正常40-200 Hz。但当我从第二部手机以19kHz的频率产生超声波时我没有很好的数值,有时我会得到23kHz。你知道手机是否真的能产生超声波吗?你认为用我电脑的扬声器产生超声波会更好吗?大多数消费者级传感器(麦克风和扬声器)在手机、电脑等设备中,由于它们不是真正为“高保真”而设计的,所以在~15 kHz以上的频率下会很难工作使用。在这个频率范围内,你可能会发现很难做任何可靠的事情。@PaulR hey buddy,你知道为什么有时最大震级指数返回非常大的值吗?频率不正确,就像我有500赫兹,应用程序有时计算它为45000/49000和其他大的数字一样?@Peter:听起来像个错误-可能会发布一个新的问题你的代码和尽可能多的背景信息?