Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct way to Convert 16bit PCM Wave data to float

I have a wave file in 16bit PCM form. I've got the raw data in a byte[] and a method for extracting samples, and I need them in float format, i.e. a float[] to do a Fourier Transform. Here's my code, does this look right? I'm working on Android so javax.sound.sampled etc. is not available.

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;
  }
like image 591
fredley Avatar asked Jan 07 '11 20:01

fredley


3 Answers

I had a similar solution, but IMHO a little cleaner. Unfortunately, there's no good library method as far as I'm aware: *This assumes the even bytes are the lower bytes

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;
}
like image 99
jk. Avatar answered Oct 21 '22 09:10

jk.


You may try using the ByteBuffer API. http://developer.android.com/reference/java/nio/ByteBuffer.html#asFloatBuffer()

like image 39
Dennis C Avatar answered Oct 21 '22 10:10

Dennis C


As indicated by hertzsprung the answer by jk. only works for unsigned PCM. On Android PCM16 is big-endian signed, so you need to account for the potentially negative value, encoded in two's complement. This means we need to check whether the high byte is greater than 127 and if so subtract 256 from it first before multiplying it by 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;
}
like image 2
Christian Fritz Avatar answered Oct 21 '22 08:10

Christian Fritz