#175932 - Ruben - Fri Mar 04, 2011 1:01 pm
[this is more General Coding, but since it's targetted at the DS, I thought I'd put it here]
Hullo.
I recently got the idea to make a custom ADPCM format to play sequenced music on the DS by mixing on the ARM9 [SMLAxy ftw!] since I'm not fond of being limited to 16 channels. I've come up with a step table that, so far, appears to work great [may be tweaked later on].
The basic idea of the format is:
What that means is:
The sound wave starts off with a sample. When it's done with that sample, it reads the next by skipping through the delta step table, using the SIGNED nibble as its index (this allows it to go back/forth). Further, the step table is alternating positive/negative values so it won't have to make humongous leaps to reach the other side. The last nibble is reserved to not be zero as this allows an optimization to the decoder.
Another note is that the step table is 16.16, as the sample data is in the upper 16 bits anyway to use a saturating add.
Now, the problem I have at the moment is calculating the step values when encoding (the decoder is complete and works perfectly. Afaik, it is as optimized as it can get - and doesn't even take up the stack pointer =O).
DekuTree and I had tried to come up with a good way of calculating the index steps, but his method had a small flaw that caused BIG problems.
As such, I'm asking for help here.
Any tips/ideas how to calculate the steps?
The step table is 96 values - 48 positives, 48 negatives, all in the form of:
tab[x+0] = (x*x * 200h << 16) / (48*48);
tab[x+1] = -tab[x+0]
Hullo.
I recently got the idea to make a custom ADPCM format to play sequenced music on the DS by mixing on the ARM9 [SMLAxy ftw!] since I'm not fond of being limited to 16 channels. I've come up with a step table that, so far, appears to work great [may be tweaked later on].
The basic idea of the format is:
Code: |
//! when initializing
chan.sample = wave.firstSample; chan.sampPack = *(s32*)(wave.data)[0]; //! note the sign chan.sampNext = &(u32*)(wave.data)[1]; chan.stepTab = &stepTab[wave.firstIdx]; //! during mixing mixOut(chan.sample); if(needSkipSamples) { s32 indexStep = chan.sampPack >> 28; //! ASR 28 s32 delta = chan.stepTab[indexStep]; chan.stepTab += indexStep; chan.sample += delta; //! last nibble can't be 0 - 0 is reserved for 'end of word' if((chan.SampPack <<= 4) == 0) chan.SampPack = *chan.SampNext++; } |
What that means is:
The sound wave starts off with a sample. When it's done with that sample, it reads the next by skipping through the delta step table, using the SIGNED nibble as its index (this allows it to go back/forth). Further, the step table is alternating positive/negative values so it won't have to make humongous leaps to reach the other side. The last nibble is reserved to not be zero as this allows an optimization to the decoder.
Another note is that the step table is 16.16, as the sample data is in the upper 16 bits anyway to use a saturating add.
Now, the problem I have at the moment is calculating the step values when encoding (the decoder is complete and works perfectly. Afaik, it is as optimized as it can get - and doesn't even take up the stack pointer =O).
DekuTree and I had tried to come up with a good way of calculating the index steps, but his method had a small flaw that caused BIG problems.
As such, I'm asking for help here.
Any tips/ideas how to calculate the steps?
The step table is 96 values - 48 positives, 48 negatives, all in the form of:
tab[x+0] = (x*x * 200h << 16) / (48*48);
tab[x+1] = -tab[x+0]