Reputation:
In converting from short to a byte array I found the following solution on the web but could not quite understand the logic involved.
//buffer is an array of bytes, bytes[]
buffer[position] = (byte)(sample & 0xff);
buffer[position+1] = (byte)((sample >> 8) & 0xff);
Can someone tell me why 0xff (256) is being anded to the sample which is a short?
Upvotes: 3
Views: 1969
Reputation: 11
buffer[position] = (byte)(sample & 0xff);
buffer[position+1] = (byte)((sample >> 8) & 0xff);
must be :
buffer[position] = (byte)((sample >> 8) & 0xff);
buffer[position+1] = (byte)(sample & 0xff);
Upvotes: 1
Reputation: 340486
This code probably comes from C code (or was written by a C programmer who don't parse Java as well as erickson does). This is because in Java a cast from a type with more information to a type with less information will discard the higher order bits and thus the & 0xff is unnecessary in both cases.
A short has 16 bits, two bytes. So it needs to take two slots in the byte array, because if we just casted a short into a byte one byte would be lost.
So, the code you have does
1110001100001111 sample
0000000011111111 0xff
0000000000001111 sample & 0xff => first byte`
Then, displaces the sample to get the second byte
0000000011100011 sample >> 8
0000000011111111 0xff
0000000011100011 (sample >> 8 ) & 0xff => second byte
Which can be a lot better written as erickson shows below (hopefully it'll be above soon).
Upvotes: 11
Reputation: 269877
The other answers have some good information, but unfortunately, they both promote an incorrect idea about the cast to byte.
The & 0xFF
is unnecessary in both cases in your original code.
A narrowing cast discards the high-order bits that don't fit into the narrower type. In fact, the & 0xFF
actually first causes the short to be promoted to an int
with the most significant 24 bits cleared, which is then chopped down and stuffed in a byte by the cast. See the Java Language Specification Section §5.1.3 for details.
buffer[position] = (byte) sample;
buffer[position+1] = (byte) (sample >>> 8);
Also, note my use of the right shift with zero extension, rather than sign extension. In this case, since you're immediately casting the result of the shift to a byte, it doesn't matter. In general, however, the operators give different results, and you should be deliberate in what you choose.
Upvotes: 2
Reputation: 39520
It makes sure there's no overflow; specifically, the first line there is taking the LSByte of "sample" and masking OUT your upper 8 bits, giving you only values in the range of 0-255; the second line there is taking the MSByte of "sample" (by performing the right-shift) and doing the same thing. It shouldn't be necessary on the second line, since the right-shift by 8 should drop out the 8 least significant bits, but it does make the code a little bit more symmetric.
I would assume that this is because since sample is a short (2 bytes) any values in the range of 256-6553 would be interpreted as 255 by the byte conversion.
Upvotes: 1