在分析 FSK 信号之前,我一直在这里问几个问题。我正在生成和记录一个采样率为 44100 的 fsk 信号,它包含两个频率,'1' 为 934Hz,'0' 为 510Hz,编码的消息是一个字符串,我将其转换为二进制表示,每个位使用2048 个样本。在代表数据本身的音调之前,我有一个频率为 440Hz 的初步音调。我使用以下代码来捕获音频字节,唯一的区别是我将它们写入 ByteArrayOutputStream https://stackoverflow.com/questions/23432398/audio-recorder-in-android-process-the-audio-bytes
我之前用的是8000的采样率,决定提高传输率,所以我改变了采样率。当我的记录器和发射器使用 8000 采样率时,我设法找到信号的起点并分析数据,由于某种原因,当我使用 44100 的采样率时,我的 fft 似乎无法正常工作,我找不到正确的频率,当我使用 8000 采样率时,我什至看不到我曾经看到的泛音,我使用这个类的 hann 窗口函数并将每个窗口相乘:https ://github.com/jpatanooga/Canova/blob/主/canova-data/canova-data-audio/src/main/java/org/canova/sound/musicg/dsp/WindowFunction.java。
现在,我只是在记录的数据中推进每个 2048 个样本来查看结果。我不太确定为什么 fft 不起作用,有什么想法吗?
我附上了一些我使用的功能:
将音频字节转换为表示归一化正弦波的 doule 数组的函数(发送的数据为小端格式):
private double[] convertBytes2SineWave(byte[] byteArray)
{
double[] doubleArray = new double[byteArray.length / 2];
short temp;
double normalizedVal;
for (int i=0; i<doubleArray.length; i++)
{
//The data send in little endian format - first byte is low order byte
byte bLow = byteArray[2*i];
byte bHigh = byteArray[2*i + 1];
temp = (short)(((bHigh & 0x00FF) << 8) | (bLow & 0x00FF));
normalizedVal = temp / 32767.0 ;
doubleArray[i] = normalizedVal;
}
return doubleArray;
}
fft函数:
public double[] calculateFFT(double[] signalChunk, int numFFTPoint)
{
double mMaxFFTSample;
double temp;
Complex[] y;
Complex[] complexSignal = new Complex[numFFTPoint];
double[] absSignal = new double[numFFTPoint/2];
for(int i = 0; i < numFFTPoint; 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 < (numFFTPoint/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;
}
提取数据位的函数:
private void ExtractDataBits()
{
byte[] byteArrayData = ByteArrayAudioData.toByteArray();
sExtractedBits= new StringBuilder();
double binSize =((double)sampleRate/numberOfFFTPoints);
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)
{
if(daOriginalSine.length - startIndex < numberOfFFTPoints)
break;
smallArray = new double[numberOfFFTPoints];
System.arraycopy(daOriginalSine, startIndex, smallArray, 0, numberOfFFTPoints);
smallArray = applyHannWindow(smallArray, numberOfFFTPoints);
double[]fftRes = calculateFFT(smallArray,numberOfFFTPoints);
if(fftRes[HighFreqPos] > fftRes[LowFreqPos])
sExtractedBits.append("1");
else
sExtractedBits.append("0");
startIndex = startIndex + numberOfFFTPoints;
NumOfRuns--;
}
}