有符号的16位PCM转换不起作用。为什么?

时间:2013-09-07 17:06:12

标签: java android audio pcm

在过去的两天里,我一直试图在Android上操纵16位PCM数据,但收效甚微。我目前正在使用WAV recorder来捕获音频。在使用onPeriodicNotification(AudioRecord recorder)写缓冲区之前的randomAccessWriter方法中,我将缓冲区发送到自定义类,操作样本,并将样本保存回缓冲区。我的自定义类中的方法如下:

由于缓冲区是一个字节数组,我首先将它们转换为短路,现在一个短路代表一个帧(只有一个通道)。我将实现FFT算法,一旦我越过这个障碍,需要输入为浮点数组 - 所以我将每个短路转换为浮点数。现在,将数据写入WAV文件的randomAccessWriter接受一个字节数组,并期望每个帧为2个字节。因此,我将每个float转换回short并使用ByteBuffer重建一个字节数组,然后返回该数组。当我运行我的录音机应用程序时,缓冲区通过上面的代码发送,一切都很好。

我尝试使用简单的语音调制算法来测试录音是否被修改,算法放在TODO评论的位置:

现在如果我在我的iPhone上使用上面的代码,音频样本将被转换,尽管数据本身是32位浮点数。但是,在我重新运行录音机应用程序的Android上,插入上面的代码后,产生的所有内容都是白噪声。在使用上述代码成功修改样本之前,我无法继续使用FFT算法。

为什么会这样?如果有关于该主题的知识的人能够阐明这一主题,我将不胜感激。

已解决 - 由Bjorn Roche

潜在原因:录制在Little Endian中提供数据,而Java短片在Big Endian中;当使用两种不同形式应用函数时,会产生白噪声。下面的代码显示了如何接收Little Endian字节数组,转换为Big Endian浮点数组并返回Little Endian字节数组。虽然浮动你可以随心所欲,我现在将使用我的FFT算法:

public byte[] manipulateSamples(byte[] data,
                                int samplingRate,
                                int numFrames,
                                short numChannels) {

    // Convert byte[] to short[] (16 bit) to float[] (32 bit) (End result: Big Endian)
    ShortBuffer sbuf = ByteBuffer.wrap(data).asShortBuffer();
    short[] audioShorts = new short[sbuf.capacity()];
    sbuf.get(audioShorts);

    float[] audioFloats = new float[audioShorts.length];

    for (int i = 0; i < audioShorts.length; i++) {
        audioFloats[i] = ((float)Short.reverseBytes(audioShorts[i])/0x8000);
    }

    // Do your tasks here.

    // Convert float[] to short[] to byte[] (End result: Little Endian)
    audioShorts = new short[audioFloats.length];
    for (int i = 0; i < audioFloats.length; i++) {
        audioShorts[i] = Short.reverseBytes((short) ((audioFloats[i])*0x8000));
    }

    byte byteArray[] = new byte[audioShorts.length * 2];
    ByteBuffer buffer = ByteBuffer.wrap(byteArray);
    sbuf = buffer.asShortBuffer();
    sbuf.put(audioShorts);
    data = buffer.array();

    return data;

}

1 个答案:

答案 0 :(得分:4)

你的问题是java中的short是bigendian,但如果从WAV文件中获取数据,那么数据就是小端。