Re: Creative ADPCM?

Jim Leonard <[email protected]> Thu, 21 Oct 2004 19:55:49 -0500
Newsgroups gmane.comp.video.xine.codec.devel
Message-ID <[email protected]>
TJ Edmister wrote:

> &gt;- John Ratcliff's ACOMP (variable bit-depth per frame ADPCM)
> &gt;- Michael J. Mahon's 4-bit ADPCM adapted for 8-bit input (uses
> &gt;regular DVI values table but ends at the last value below 127)
> &gt;- 8svx fibonacci deltas (good for voice, bad for music)
> &gt;- Dumb raw convert from 8-bit to 6-bit (RealSound did this)
> 
> Where can I find details on these? 

ACOMP:  I have attached all the info I have on it.  In a nutshell, it's a 
variable bit-depth ADPCM method; each frame defaults to (IIRC) 128 samples and 
can consist of either 1-bit/2-bit/4-bit deltas or RLE silence.  It's possible 
to write a good encoder for it that would achieve 3:1 for music and 6:1 for 
speech, but doing so would require a brute-force exhaustive search of all frame 
sizes and bit depths -- PITA to write.  Also, decompression is more complex 
than it needs to be (his ASM source is good but not fantastic).

4-bit ADPCM adapted for 8-bit sound:  http://members.aol.com/MJMahon/

8svx fibonacci:  Attached at the end of this email.

Dumb raw convert:  Well, just like it says, you can go from unsigned 8-bit 
sound to unsigned 6-bit sound with little percievable loss as long as your 
sampling rate is high (22KHz or more) and you have a crappy output device like 
a Sound Blaster.

> I like to play around with audio and 
> video codecs (the not-so processor intensive, non-FPU kind which my 
> brain can more easily comprehend). 

Same here, because I'm still working on my video/audio process for an 8088. 
(BTW, did I ever mention I got something working?  It won first place at a 
programming competition, you can download it here: 
http://www.pouet.net/prod.php?which=13722 )

After going through the above schemes and coming up with a variable-frame 
method of my own, I believe DVI ADPCM offers the best quality/speed tradeoff. 
While I haven't implemented it yet, it should easily be possible on an 8088 and 
leave time left over for video (as long as I can work it into the compressor 
never to produce a value that needs clipping).

 > I'm sure most if not all my ideas
> were reinventing the wheel so I always like to check out what has been 
> done before. I wrote a couple programs for audio which stored the sign 
> of the difference and log base 2 of the magnitude. So I went from 16-bit 
> PCM to 5-bits per sample and the quality was good at high sample rates.

Look up the audio algorithm of RoQ and also mu-law and a-law companding.

-------------------------

This is Steve Hayes' Fibonacci Delta sound compression technique.  It's
like the traditional delta encoding but encodes each delta in a mere 4
bits.  The compressed data is half the size of the original data plus a
2-byte overhead for the initial value.  This much compression introduces
some distortion, so try it out and use it with discretion.

To achieve a reasonable slew rate, this algorithm looks up each stored
4-bit value in a table of Fibonacci numbers.  So very small deltas are
encoded precisely while larger deltas are approximated.  When it has to
make approximations, the compressor should adjust all the values (forwards
and backwards in time) for minimum overall distortion.

Here is the decompressor written in the C programming language.

     /* Fibonacci delta encoding for sound data. */
     BYTE codeToDelta[16] = {-34,-21,-13,-8,-5,-3,-2,-1,0,1,2,3,5,8,13,21};

     /* Unpack Fibonacci-delta encoded data from n byte source buffer into
      * 2*n byte dest buffer, given initial data value x.  It returns the
      * last data value x so you can call it several times to incrementally
      * decompress the data.                                             */
     short D1Unpack(source, n, dest, x)
         BYTE source[], dest[];
         LONG n;
         BYTE x;
         {
         BYTE d;
         LONG i, lim;

         lim = n << 1;
         for (i = 0; i < lim; ++i)
                 { /* Decode a data nybble; high nybble then low nybble. */
                 d = source[i >> 1];     /* get a pair of nybbles        */
                 if (i & 1)              /* select low or high nybble?   */
                         d &= 0xf;       /* mask to get the low nybble   */
                 else
                         d >>= 4;        /* shift to get the high nybble */
                 x += codeToDelta[d];    /* add in the decoded delta     */
                 dest[i] = x;            /* store a 1-byte sample        */
                 }
         return(x);
         }

     /* Unpack Fibonacci-delta encoded data from n byte source buffer into
      * 2*(n-2) byte dest buffer. Source buffer has a pad byte, an 8-bit
      * initial value, followed by n-2 bytes comprising 2*(n-2) 4-bit
      * encoded samples.                                                 */

     void DUnpack(source, n, dest)
         BYTE source[], dest[];
         LONG n;
         {
           D1Unpack(source + 2, n - 2, dest, source[1]);
         }





-- 
Jim Leonard ([email protected])                    http://www.oldskool.org/
Want to help an ambitious games project?             http://www.mobygames.com/
Or check out some trippy MindCandy at             http://www.mindcandydvd.com/
ACOMP.rar (application/octet-stream, 52.9 KB) - not displayed