将WAVE PCM字节数组传递给FFT进行音高检测

3

我已经完成了从音频文件中获取PCM数据的代码。如何将这些数据应用于快速傅里叶变换算法?在将字节数组应用于FFT算法之前,还有其他需要考虑的事情吗?

public static void main(String[] args) throws FileNotFoundException, IOException {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    BufferedInputStream in = new BufferedInputStream(new FileInputStream("adios.wav"));

    int read;
    byte[] buff = new byte[1024];
        while ((read = in.read(buff)) > 0)
        {
            out.write(buff, 0, read);
        }
        out.flush();
        byte[] audioBytes = out.toByteArray();

        for(int i=0; i<audioBytes.length;i++){
            System.out.println(audioBytes[i]);
        }
}

首先:使用您刚刚存储的代码,将 adios.wav 的内容存储到一个数组中,但这并不意味着您已经成功地将文件转换为数字数组。为了做到这一点,您需要首先读取文件头,然后根据头数据类型(int、float、8-16位)和可能的压缩方式对文件内容进行解码。其次,您想使用哪个 FFT 类?请先尝试使用它,然后告诉我们它出了什么问题(如果有的话)。 - lCapp
1个回答

3

你需要跳过wav头并将PCM采样转换为介于-1和1之间的浮点值。例如,对于具有16位每个采样和小端的PCM wav的字节数组,需要进行以下转换(来自com.sun.media.sound.AudioFloatConverter):

public float[] toFloatArray(byte[] in_buff, int in_offset,
  float[] out_buff, int out_offset, int out_len) {
        int ix = in_offset;
        int len = out_offset + out_len;
        for (int ox = out_offset; ox < len; ox++) {
            out_buff[ox] = ((short) ((in_buff[ix++] & 0xFF) | 
                       (in_buff[ix++] << 8))) * (1.0f / 32767.0f);
        }
        return out_buff;
    }

调用此函数后,您将拥有一个可以用于FFT分析的float[]

为了使这更简单,JVM包括AudioSystemAudioInputStream类。

TarsosDSP是一个Java音频处理库,其源代码充满了示例。 TarosDSP手册解释了PCM数据和可处理样本之间的关系。


1
我应该向这个方法传递哪些值?我手头唯一的值是 in_buff,它是一个字节数组。我应该传递什么给 int in_offset, float[] out_buff, int out_offset, int out_len - user3805160

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接