2

I've found here on stackoverflow.com a great example that actually works for playing sounds. Everything works smoothly but I'd like to know what happen in PCM generation. Here is the code:

int idx = 0;
for (final double dVal : sample) {
    final short val = (short) ((dVal * 32767));

    generatedSnd[idx++] = (byte) (val & 0x00ff);
    generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);
}

where sample is a double array that holds a sine computed with all required parameters in this case (frequency, hertz, so on and so forth), and generatedSnd is a byte array. Everything I know is that val & 0xff translates an int into a byte, but here what is precisely done? Why do there is the shift >>> 8?

Community
  • 1
  • 1
Andrea
  • 4,262
  • 4
  • 37
  • 56
  • 1
    Just guessing...It saves lowest 8-bit in the first byte, then it saves the higher 8-bit (from 9 to 16) in the second byte? Is it correct? Then what dVal * 32676 means? – Andrea Apr 18 '13 at 14:14

1 Answers1

4

You don't mention in your question what the input to this function is, but I'm going to guess that the elements in sample have a range of -1.0 to +1.0.

16-bit signed PCM data has a range of -32768 to +32767. So what's happening in this method is that each floating point sample is scaled by 32767 to get a value in the range -32767 to +32767, which is then truncated to a short.

This short is then stored in generatedSnd (which I assume to be a byte[]) by first writing the low byteof the short (the least significant 8 bits), followed by the high byte (shifting the short 8 bits to the right takes what originally was the high byte and places it in the low byte).

Michael
  • 57,169
  • 9
  • 80
  • 125
  • Your guess was right, sample's elements have the range you mentioned. Thank you very much for the good explanation! EDIT: generateSnd was byte[numSamples*2], as you said – Andrea Apr 20 '13 at 09:30