Android - 计算FFT后频率不正确

时间:2013-10-30 16:24:14

标签: java android audio fft audiorecord

我开始使用一些参数从AudioRecord录制声音。

private static final int RECORDER_SAMPLERATE = 44100;
private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_STEREO;
private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
this.recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
            RECORDER_SAMPLERATE, RECORDER_CHANNELS,
            RECORDER_AUDIO_ENCODING, this.bufferSize);

我将数据存储到ArrayList< byte []> soundRecord;

while (this.isRecording) {
    read = this.recorder.read(data, 0, this.bufferSize);
    if (AudioRecord.ERROR_INVALID_OPERATION != read) {
        try {
            soundRecord.add(data);
            os.write(data);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

这是我将声音计算成复数阵列FFT的方法。在这之前,我将字节转换为double。

public ArrayList<double[]> computeFFT(byte[] audioSignal) {
    final int fftPoint = 65536;
    ArrayList<double[]> result;

    double tmp;
    Complex[] y;
    Complex[] complexAudioSignal = new Complex[fftPoint];
    double[] magnitude = new double[fftPoint / 2];

    for (int i = 0; i < fftPoint; i++) {
        if (i >= 22050) tmp = 0;
        else tmp = (double) ((audioSignal[2 * i] & 0xFF) | (audioSignal[2 * i + 1] << 8) / 32768.0F;
        complexAudioSignal[i] = new Complex(tmp, 0.0);
    }

    y = FFF.fft(complexAudioSignal);

    // Calculate magnitude values from fft[]
    for (int i = 0; (fftPoint / 2); i++) {
        magnitude[i] = y[i].abs();
    }

    // get only values over mid value
    result = showFrequencies(magnitude, fftPoint);
    return result;
}

我的问题是,我用440Hz(钢琴A4)测试一个恒定的声音。 我的阵列“幅度”是一个峰值,但这个峰值的频率是220Hz。 每当我尝试只有一个频率的样本声音时(我使用n轨道),频率就是实际频率/ 2.

我知道频率是f = index * SAMPLE_RATE / fftPoint。

有人可以帮助我。我这个问题从3天开始......


编辑一个:

我按照你的建议修改我的转换循环。看起来像这样:

int bytePerSample =2;
int j = 0;
for (int i = 0; i < audioSignal.length / 2; i++) {
    if (( i % 8 == 0 || i % 8 == 2 ) && i < 22050) {
        tmp = (double) ((audioSignal[bytesPerSample * i] & 0xFF) | audioSignal[bytePerSample * i + 1] << 8)) / 32768.0F;
        complexAudioSignal[j] = new Complex(tmp, 0.0);
        j++;
    }
}

现在的问题是FrequencyIWant = FreqIObtain / 2。 我真的不知道现在该做什么:'(。

1 个答案:

答案 0 :(得分:2)

您正在将两个立体声通道复制到FFT中,而不仅仅是左声道或右声道。尝试在整数解包和转换循环中每4个字节中使用2个连续字节。