Re: [linux-audio-dev] 24 bits, 2's complement - help!

New Message Reply About this list Date view Thread view Subject view Author view Other groups

Subject: Re: [linux-audio-dev] 24 bits, 2's complement - help!
From: Bill Gribble (grib_AT_cs.utexas.edu)
Date: la tammi  15 2000 - 11:41:37 EST


Paul Barton-Davis <pbd_AT_Op.Net> writes:
> the range of numbers we can represent with 24 bits (23 bits+sign bit)
> is 8388607 .. -8388607. yet with 2's complement, -9189120 is (bytes
> right to left):
> 0 c9 73 ff

You're thinking too hard :)

It might help to recall that every bit in an audio word is a bit of
PRECISION, not of increasing magnitude; you can think of all digital
audio word values, regardless of length, converting to values between
-1.0 and 1.0 rather than (with 24-bit) 8388607 .. -8388608 (note the
difference in positive and negative magnitude; with 2's complement you
get 1 more negative than positive value since 0 is positive). So the
most significant bit represents .5 (1/2^1), the next most significant
represents .25 (1/2^2), and so on. Adding another bit gives you
another factor of 2 (6 db) of dynamic range because you halve the size
of the smallest quantity you can represent.

Your example 0 c9 73 ff is 0xff73c900 in "C-style" hex. To convert to
16 bits, you want to drop the 8 least-significant bits of the 24-bit
word to get 0xff730000, or in memory-byte-order 00 00 73 ff. In
C it's as simple as a bit shift to the right:

int_u16
truncate_32_to_16(int_u32 in) {
  return (int_u16)(in >> 16);
}

If you want to continue to represent the number in a 32-bit
quantity but just eliminate the least-significant bits, you can
just leave the value alone and mask off the bits you don't want:

int_u32
lose_lower_16_bits(int_u32 in) {
  return in & 0xffff0000;
}

All this will do the trick, but remember that truncation for word
length reduction is considered a cardinal sin in digital audio.
You're throwing away useful information that you can demonstrate
mathematically can be at least partially preserved by the use of
dither.

Presumably you're doing this for the Hammerfall driver, under the
condition that it's opened for 16-bit reads by the user; how tough
would it be to put a very simple RPDF dither on there before
truncating? Maybe this could be an option settable via ioctl()?

No, now that I think about it, you don't want to dither in the driver.
That's an application issue; if you want high-quality audio, you'll
open the driver in 24-bit mode and do the dithering in your
application where you can do stuff like carefully managing the source
of your randomness (you can do big block reads from /dev/urandom and
have some "cached" randomness ready when you need it, and you can
reuse random blocks if you get in a real-time crunch).

Have fun!
Bill Gribble


New Message Reply About this list Date view Thread view Subject view Author view Other groups

This archive was generated by hypermail 2b28 : pe maalis 10 2000 - 07:23:26 EST