Friday, June 24, 2005

ADPCM beautiful solutions

Now it's the turn to rewrite my ADPCM codecs.

Couple things... these are lossless ADPCM codecs geared towards audio. My previous implementation accepted 8/16 bit, 1-256 independent channel inputs. It had plug-and-play delta strategies, and there were several more or less hard coded coding strategies.

Note to self: without knowing it, I experimented with Rice coding. What it does is to write 1 bit to tell if each delta you write has overflowed or not. But if your delta modeler is good, that means that most of the time there's no overflow, which means that most of the time you're penalizing each delta with 1 bit. B-b-b-b-bad to the bone!

It's much better to reserve the top and bottom values of your allowed delta interval to signal upper or lower overflow, and follow that with a special coding for the rest using the fact that you already know the minimum size of the overflow. Being able to represent 2^n - 2 values instead of 2^n is a much less expensive proposition than using 2^(n+1) values to represent 2^n values.

So how to reproduce all these features without writing a ton of messy code... first, I chose a 4 stage approach to coding/decoding. Coding consists of calculating a delta according to the delta strategy, then updating the coding strategy with the current delta strategy configuration, then encoding the delta using the coding strategy, followed by updating the delta strategy with the efficiency of the coding (this gives feedback to the delta strategy so it can avoid being too aggressive or too conservative). This means that an ADPCM codec has two strategies, which instantly means they are serializable objects which are written to disk via serializable parameters.

Decoding consists of reading a delta according to the coding strategy, calculating the original value and outputting to the destination, followed by updating the delta strategy with the observed coding efficiency. So far, so good.

To implement multiple channels, I decided to implement a mux / demux codec with a list of scheduled codecs (the list also becomes a parameter, its elements are serializable). To implement different bit depths, I decided to implement a stream splitter codec.

So a full ADPCM codec is a complex codec: stream splitter >> mux / demux >> basicAdpcm {with strategies}. Decoding is accomplished by directing data from the adpcm through the mux / demux through the splitter.

I like this stuff very very much.

No comments: