The Right Way to Convert 16-Bit PCM Wave Data to Swim

I have a wave file in 16 bit PCM form. I have the source data in byte[] and the method for extracting samples, and I need them in float format, i.e. A float[] for the Fourier transform. Here is my code, does it look right? I am working on Android, so javax.sound.sampled etc. 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; } 
+4
source share
3 answers

I had a similar solution, but IMHO is a bit cleaner. Unfortunately, there is no good library method as far as I know: * This assumes that even bytes are 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; } 
+6
source
+3
source

As indicated by hertzsprung, the answer is jk. only works for unsigned PCM. A large font is signed on Android-PCM16, so you need to consider the potentially negative value encoded in the two add-ons . This means that we need to check if the high byte is greater than 127, and if so subtract 256 from it 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; } 
+2
source

Source: https://habr.com/ru/post/1334709/


All Articles