问题
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;
}
回答1:
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;
}
回答2:
You may try using the ByteBuffer API. http://developer.android.com/reference/java/nio/ByteBuffer.html#asFloatBuffer()
回答3:
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;
}
来源:https://stackoverflow.com/questions/4630221/correct-way-to-convert-16bit-pcm-wave-data-to-float