android中fsk信号的fft分析

android中fsk信号的fft分析,android,audio,signal-processing,fft,Android,Audio,Signal Processing,Fft,我正在记录采样率为8000的fsk信号,它包含两个频率,“1”为800Hz,“0”为400Hz,编码消息为char“8”00111000 eahc位,使用16384个样本表示。我使用以下代码捕获音频字节,唯一的区别是我将它们写入ByteArrayOutputStream 在我完成录制后,每次我都会向FFT函数发送16384个样本,以分析播放的频率。出于某种原因,有时它能工作我设法提取正确的位,有时它不能0.0,在我的一次调试中,我看到它分析的第一个频率大约是1190Hz,当它应该大约为400Hz

我正在记录采样率为8000的fsk信号,它包含两个频率,“1”为800Hz,“0”为400Hz,编码消息为char“8”00111000 eahc位,使用16384个样本表示。我使用以下代码捕获音频字节,唯一的区别是我将它们写入ByteArrayOutputStream

在我完成录制后,每次我都会向FFT函数发送16384个样本,以分析播放的频率。出于某种原因,有时它能工作我设法提取正确的位,有时它不能0.0,在我的一次调试中,我看到它分析的第一个频率大约是1190Hz,当它应该大约为400Hz时,另一件事发生了,第六个位一直给我800hz,当它应该为400Hz时。我检查了FFT结果向量幅值,发现400Hz频率也存在,其幅值高于800Hz,因此我假设这是位“0”。 我做错了什么

提取位的音频处理代码:

private void ExtractDataBits() 
{
    byte[] byteArrayData = ByteArrayAudioData.toByteArray();
    sExtractedBits="";
    double binSize =((double)sampleRate/numberOfFFTPoints);//fftpoints= 16384
    int HighFreqPos =(int) (freqOfHighTone/binSize);
    int LowFreqPos =(int) (freqOfLowTone/binSize);

    double[] daOriginalSine = convertBytes2SineWave(byteArrayData);
    double[] smallArray;
    int NumOfRuns = daOriginalSine.length/numberOfFFTPoints;
    int startIndex = 0;

    while(NumOfRuns > 0)
    {
        smallArray = new double[numberOfFFTPoints];
        System.arraycopy(daOriginalSine, startIndex, smallArray, 0, numberOfFFTPoints);
        double[] fftRes = calculateFFT(smallArray);
        if(mPeakPos == HighFreqPos)
            sExtractedBits += "1";
        else if(mPeakPos ==LowFreqPos)
            sExtractedBits += "0";
        else
        {
            if(fftRes[HighFreqPos] > fftRes[HighFreqPos])
                sExtractedBits+="1";
            else
                sExtractedBits+="0";
        }
        startIndex = startIndex + numberOfFFTPoints;
        NumOfRuns--;
    }
}
CalculateEfft方法:

public double[] calculateFFT(double[] signalChunk)
{           
    double mMaxFFTSample;
    double temp;
    Complex[] y;
    Complex[] complexSignal = new Complex[numberOfFFTPoints];
    double[] absSignal = new double[numberOfFFTPoints/2];

    for(int i = 0; i < numberOfFFTPoints; i++)
    {
        temp = signalChunk[i];
        complexSignal[i] = new Complex(temp,0.0);
    }

    y = FFT.fft(complexSignal);

    mMaxFFTSample = 0.0;
    mPeakPos = 0;
    for(int i = 0; i < (numberOfFFTPoints/2); i++)
    {
         absSignal[i] = Math.sqrt(Math.pow(y[i].re(), 2) + Math.pow(y[i].im(), 2));
         if(absSignal[i] > mMaxFFTSample)
         {
             mMaxFFTSample = absSignal[i];
             mPeakPos = i;
         } 
    }
     return absSignal;
}

如前所述,使用基于FFT的方法进行此操作就像试图使用大锤敲碎核桃-您最终将陷入一片混乱。继续,当您准备好重新评估时,再看看更合适的方法。您希望iffftRes[HighFreqPos]>fftRes[HighFreqPos]行做什么?你是说iffftRes[HighFreqPos]>fftRes[LowFreqPos]吗?请注意,在这种情况下,使用ifmPeakPos>HighFreqPos+LowFreqPos/2可能会更好,但正如Paul提到的,还有其他更好的选择。您没有对信号加窗,fft可能是相邻位的重叠部分,一个目标是另一个目标的谐波,因此谐波失真可能导致错误结果,尤其是在没有良好窗口的情况下,您使用16k采样FFT来区分两个信号,这两个信号都只适合20个采样。看看Goertzel算法,如果你能调整频率,使一个不是另一个的整数倍。@SleuthEye谢谢你,我没有看到这个。为什么我要使用第二个条件?@Katie谢谢你的解释,我把频率改为934Hz和510Hz,我仍然得到一个比这两个更高的频率,它仍然被认为是谐波失真吗?