> I've found that I've been forced to use an if statement to read 24-bit
> audio. I'm doing this with the following code:
>
>
> //-------------------------------------------------
> long data24;
>
> fread(&data24,sampleSize,1,file_In);
> if(data24 > 8388607)
> array1[i] = (data24)/8388608.0 - 2.0;
> if(data24 <= 8388607)
> array1[i] = (data24)/8388608.0;
> //-----------------------------------------------
>
>
> The strange thing is that I've been able to write it without using an if
> statement. I've done this using the following code:
>
>
> //------------------------------------------------
> long signed data24;
>
> data24 = (long)floor((array2[i])*8388608.0+0.5);
> fwrite(&data24,sampleSize,1,file_out);
> //-----------------------------------------------
>
>
> This makes no sense to me. How can it require an if statement to read,
> but not one to write? Is there a way around this?
You are using a long data type, which is 32-bits on many systems.
Your reader will work whether or not the upper 8 bits are all ones.
Your writer will always fill the upper 8 bits with ones (given full
range signals), which may not be symmetric and might fool some
readers which assume the upper 8 bits have some other meaning.
If you only write out the bottom 24 bits, then whether or not the
upper 8 bits are correct or not may be irrelevant.
IMHO. YMMV.
--
rhn A.T nicholson d.0.t C-o-M
Reply by Chris Barrett●January 21, 20072007-01-21
I've found that I've been forced to use an if statement to read 24-bit
audio. I'm doing this with the following code:
//-------------------------------------------------
long data24;
fread(&data24,sampleSize,1,file_In);
if(data24 > 8388607)
array1[i] = (data24)/8388608.0 - 2.0;
if(data24 <= 8388607)
array1[i] = (data24)/8388608.0;
//-----------------------------------------------
The strange thing is that I've been able to write it without using an if
statement. I've done this using the following code:
//------------------------------------------------
long signed data24;
data24 = (long)floor((array2[i])*8388608.0+0.5);
fwrite(&data24,sampleSize,1,file_out);
//-----------------------------------------------
This makes no sense to me. How can it require an if statement to read,
but not one to write? Is there a way around this?
Reply by robert bristow-johnson●January 20, 20072007-01-20
Carlos Moreno wrote:
> Chris Barrett wrote:
>
> >>> Why do you add 128.5 to the eight bit data, but only 0.5 to 16 bit data?
> >>
> >> Because 8-bit audio is scaled from -128 to 127, and 16-bit audio is
> >> scaled from -32768 to 32767. The compiled code always rounds down
> >> when converting floating point numbers to integers. Adding the extra
> >> 0.5 will cause half of them to effectively be rounded up.
> >
> > I made an error. The 8-bit audio is scaled from 0 to 256.
actually, in keeping with your previous statement (-128 to 127), 8-bit
audio in WAV files has a range of 0 to 255 (not 256). and this format
is often called "offset binary" as opposed to "2's complement". and
the only difference between the two is the inversion of the MSB.
>
> My question would be "why the 0.5 ?" --- correct me if I'm wrong, but I
> believe that in the 2's complement format, the 0V of the input analog
> signal maps to a 0.
>
> For the 8-bit unsigned format, I'm not sure, but I would find it
> severely wrong that the 0V does not map to an exact, integer value
> (such as 128, I would guess). If the 0V maps to something-point-five,
> then when you have a very weak signal, you're bound to have a very
> annoying and gratuitous +/- 1 bit noise. For very weak signals, you're
> amplifying the floor noise, instead of just thresholding it out (when
> the signal, or the floor noise, is lower than +/- 0.5 bits, then you
> make it 0 to completely eliminate it)
the addition of 0.5 to a floating-point representation of integer
values *almost* makes sense just before quantization by rounding down
causing it to round-to-nearest. it's a small DC offset if you don't
and rounding to nearest is a problem if you are within 1/2 LSB from the
positive rail because you are rounding to a value (+128 or +32768) that
is outside of your range. despite the DC bias, i might recommend just
dropping the bits or the low-order portion (which is rounding down).
then it is clear that every long word maps unambiguously to an
appropriate short word and there are no funny exceptions (clipping at
the +rails but no clipping at the -rail). if you're dithering are
doing something else that may extend the signal out of range and
clipping is possible, might as well add the bias (causing
round-to-nearest) to the dither and deal with the possibility of
clipping on either upper or lower rail.
r b-j
Reply by Erik de Castro Lopo●January 20, 20072007-01-20
Chris Barrett wrote:
> I made an error. The 8-bit audio is scaled from 0 to 256.
WAV files store 8 bit samples as unsigned while AIFF and AU
files store 8 bit samples as signed values.
HTH,
Erik
--
+-----------------------------------------------------------+
Erik de Castro Lopo
+-----------------------------------------------------------+
"It is forbidden for a Muslim to be a loyal friend to someone who does
not believe in God and His Prophet, or someone who fights the religion
of Islam." -- Fifth grade text book from Saudi Arabia
http://www.washingtonpost.com/wp-dyn/content/article/2006/05/19/AR2006051901769_pf.html
Reply by Carlos Moreno●January 20, 20072007-01-20
Chris Barrett wrote:
>>> Why do you add 128.5 to the eight bit data, but only 0.5 to 16 bit data?
>>
>> Because 8-bit audio is scaled from -128 to 127, and 16-bit audio is
>> scaled from -32768 to 32767. The compiled code always rounds down
>> when converting floating point numbers to integers. Adding the extra
>> 0.5 will cause half of them to effectively be rounded up.
>
> I made an error. The 8-bit audio is scaled from 0 to 256.
My question would be "why the 0.5 ?" --- correct me if I'm wrong, but I
believe that in the 2's complement format, the 0V of the input analog
signal maps to a 0.
For the 8-bit unsigned format, I'm not sure, but I would find it
severely wrong that the 0V does not map to an exact, integer value
(such as 128, I would guess). If the 0V maps to something-point-five,
then when you have a very weak signal, you're bound to have a very
annoying and gratuitous +/- 1 bit noise. For very weak signals, you're
amplifying the floor noise, instead of just thresholding it out (when
the signal, or the floor noise, is lower than +/- 0.5 bits, then you
make it 0 to completely eliminate it)
Right?
Carlos
--
Reply by Christen Fihl●January 20, 20072007-01-20
In your case, it seems to me like you can do whatever you like yourself,
also do -128..127 for internal use.
But if you are planning to save data into a specific format (on disk)
like G711 a-Law or u-Law (8 bit), then you need to follow the rules for
that format.
The 16 bit data you make is pcm format, as saved in a wav file in
Windows.
Saving G711 in Windows, you need to convert each 16 bit value using a
function like pcm2ulaw()
g711Byte := pcm2ulaw ( pcm_word )
or
g711Byte := pcm2ulaw ( array[i]*32000 )
g711 format is 0 to 255 based, but that is not something you really need
to think about in most cases.
I do a lot of VoIP handling using G711,ulaw on the IP connection, and as
diskfiles if needed.
Internal I keep g711 as strings for easy passing along between
functions.
When I do look at data (or generate tones), I use 16bit pcm.
I have 2 function between those 2 worlds, pcm2ulaw and ulaw2pcm.
--
Christen Fihl
http://HSPascal.Fihl.net/
Reply by Chris Barrett●January 20, 20072007-01-20
Chris Barrett wrote:
> glen herrmannsfeldt wrote:
>
>> Chris Barrett wrote:
>>
>>> I've been working on this problem for some time now, and I can't seem
>>> to understand what's going on. I have data in the range of -1.0 to
>>> 1.0. For 8-bit audio I scale it to range of 0 to 256 and for 16-bit
>>> audio I scale it to the range of -32768 to 32767. Why can't I scale
>>> 8-bit audio to the range of -128 to 127? Why does it appear that
>>> 8-bit audio is not signed?
>>
>>
>>
>> (snip)
>>
>>> if (bits2 == 8)
>>> data32 = (long)( array[i]*127.0+128.5 );
>>> if (bits2 == 16)
>>> data32 = (long)( array[i]*32767.0+0.5 );
>>
>>
>>
>> Why do you add 128.5 to the eight bit data, but only 0.5 to 16 bit data?
>>
>> -- glen
>>
>
> Because 8-bit audio is scaled from -128 to 127, and 16-bit audio is
> scaled from -32768 to 32767. The compiled code always rounds down when
> converting floating point numbers to integers. Adding the extra 0.5
> will cause half of them to effectively be rounded up.
I made an error. The 8-bit audio is scaled from 0 to 256.
Reply by Chris Barrett●January 20, 20072007-01-20
glen herrmannsfeldt wrote:
> Chris Barrett wrote:
>
>> I've been working on this problem for some time now, and I can't seem
>> to understand what's going on. I have data in the range of -1.0 to
>> 1.0. For 8-bit audio I scale it to range of 0 to 256 and for 16-bit
>> audio I scale it to the range of -32768 to 32767. Why can't I scale
>> 8-bit audio to the range of -128 to 127? Why does it appear that 8-bit
>> audio is not signed?
>
>
> (snip)
>
>> if (bits2 == 8)
>> data32 = (long)( array[i]*127.0+128.5 );
>> if (bits2 == 16)
>> data32 = (long)( array[i]*32767.0+0.5 );
>
>
> Why do you add 128.5 to the eight bit data, but only 0.5 to 16 bit data?
>
> -- glen
>
Because 8-bit audio is scaled from -128 to 127, and 16-bit audio is
scaled from -32768 to 32767. The compiled code always rounds down when
converting floating point numbers to integers. Adding the extra 0.5
will cause half of them to effectively be rounded up.
Reply by glen herrmannsfeldt●January 20, 20072007-01-20
Chris Barrett wrote:
> I've been working on this problem for some time now, and I can't seem to
> understand what's going on. I have data in the range of -1.0 to 1.0.
> For 8-bit audio I scale it to range of 0 to 256 and for 16-bit audio I
> scale it to the range of -32768 to 32767. Why can't I scale 8-bit audio
> to the range of -128 to 127? Why does it appear that 8-bit audio is not
> signed?
Why do you add 128.5 to the eight bit data, but only 0.5 to 16 bit data?
-- glen
Reply by Vladimir Vassilevsky●January 19, 20072007-01-19
Chris Barrett wrote:
> I've been working on this problem for some time now, and I can't seem to
> understand what's going on. I have data in the range of -1.0 to 1.0.
> For 8-bit audio I scale it to range of 0 to 256 and for 16-bit audio I
> scale it to the range of -32768 to 32767. Why can't I scale 8-bit audio
> to the range of -128 to 127? Why does it appear that 8-bit audio is not
> signed?
Yes, this is correct. The 8 bit wave audio is binary unsigned, whereas
all other formats are twos complement. Why? Because Bill Gates did it
that way.
Vladimir Vassilevsky
DSP and Mixed Signal Design Consultant
http://www.abvolt.com