将16位PCM Wave数据转换为float的正确方法

时间:2011-01-07 20:58:01

标签: java android pcm audio-processing

我有一个16位PCM形式的波形文件。我有byte[]中的原始数据和提取样本的方法,我需要浮点格式,即float[]进行傅里叶变换。这是我的代码,这看起来不错吗?我正在使用Android,因此无法使用javax.sound.sampled等。

private static short getSample(byte[] buffer, int position) {
  return (short) (((buffer[position + 1] & 0xff) << 8) | (buffer[position] & 0xff));
}

...

float[] samples = new float[samplesLength];
  for (int i = 0;i<input.length/2;i+=2){
    samples[i/2] = (float)getSample(input,i) / (float)Short.MAX_VALUE;
  }

3 个答案:

答案 0 :(得分:6)

我有一个类似的解决方案,但恕我直言有点清洁。不幸的是,据我所知,没有好的库方法:*这假设偶数字节是较低的字节

private static float[] bytesToFloats(byte[] bytes) {
    float[] floats = new float[bytes.length / 2];
    for(int i=0; i < bytes.length; i+=2) {
        floats[i/2] = bytes[i] | (bytes[i+1] << 8);
    }
    return floats;
}

答案 1 :(得分:3)

答案 2 :(得分:2)

正如hertzsprung所说,jk的回答。仅适用于未签名的PCM。在Android PCM16上签名是big-endian,因此您需要考虑two's complement中编码的潜在负值。这意味着我们需要检查高字节是否大于127,如果是,那么在将它乘以256之前先从它中减去256.

private static float[] bytesToFloats(byte[] bytes) {
    float[] floats = new float[bytes.length / 2];
    for(int i=0; i < bytes.length; i+=2) {
        floats[i/2] = bytes[i] | (bytes[i+1] < 128 ? (bytes[i+1] << 8) : ((bytes[i+1] - 256) << 8));
    }
    return floats;
}