Reputation: 7310
To put it as simply as I can.
Is there any scaling value? For example when I wanted to cast [24 bit signed int] to [24 bit signed double] I did it like this:
for (int i=0; i<256; i++) {
bufferInDouble = *((int*)bufferRawData[currentPan]+i) / (double)0x7fffffff;
}
Any similar method could be there?
Upvotes: 3
Views: 6265
Reputation: 106096
The general answer is to divide by 256. Note that bit-shifting right won't work portably with signed int
s (which are specified in your question): 5.8/3 in the C++ Standard says behaviour of E1 >> E2
, where E1
is a negative signed value, is implementation defined.
An alternative that may retain higher audio quality is to find the highest amplitude values in the existing data (so you can only do this if you receive all the data before starting scaling) - let's call it M - then work out a scaling factor F such that that highest value has a new amplitude that's as high as 16 bit signed values can go: i.e. 32767.
M / F = 32767.0, so
F = M / 32767.0
Upvotes: 0
Reputation: 9341
The method is going to vary depending on whether you're 24-bit data is packed or is just 24-bits stored in a 32-bit word. I'm going to assume it is not packed and is left justified within the integer because that is most common.
The technique is to simply shift the data down into a 16-bit data type
ABCDEFxx => ABCD
Here I've shown the nibbles of a 32-bit integer where ABCDEF
contain the 24-bit audio data and the xx
byte contains nothing of value. Shifting right by 16 will discard the EFxx
.
short outBuffer[256]
int* inBuffer = ((int*)bufferRawData);
for (int i = 0 ; i < 256 ; ++i)
{
outBuffer[i] = (short)(inBuffer[i] >> 16);
}
On a side note, it is often desirable when reducing the bit-depth to add some low level noise in the LSB to reduce the quantization distortion. This is known as dither. For information refer to this article on wikipedia Dither
Upvotes: 3