tags:

views:

935

answers:

3

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?

+11  A: 

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).

Vinko Vrsalovic
Great explanation. I was pondering how to best answer, but I'll vote this up instead.
Dave
Excellent answer Vinko! This combined with McWafflestix response below makes a perfect answer.
Just added the two extra bits (no pun intended) from McWafflestix's answer that weren't here.
Vinko Vrsalovic
+1  A: 

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.

McWafflestix
Excellent answer!
+2  A: 

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.

erickson
Great answer! Good to learn new things from language lawyers :-).
Vinko Vrsalovic