/********************************************************************************************** clock_adpcm -- clock the next ADPCM byte ***********************************************************************************************/ public short clock_adpcm(adpcm_state state, byte nibble) { // System.Console.Write("nibble={0} diff_lookup[{1}]={2}\n", nibble, state.step * 16 + (nibble & 15), diff_lookup[state.step * 16 + (nibble & 15)]); // System.Console.Write("1state.signal={0}\n", state.signal); state.signal += diff_lookup[state.step * 16 + (nibble & 15)]; /* clamp to the maximum */ if (state.signal > 2047) state.signal = 2047; else if (state.signal < -2048) state.signal = -2048; // System.Console.Write("2state.signal={0}\n", state.signal); /* adjust the step size and clamp */ state.step += index_shift[nibble & 7]; // System.Console.Write("3state.signal={0}\n", state.signal); if (state.step > 48) state.step = 48; else if (state.step < 0) state.step = 0; // System.Console.Write("4state.signal={0}\n", state.signal); /* return the signal */ return (short)state.signal; }
/********************************************************************************************** reset_adpcm -- reset the ADPCM stream ***********************************************************************************************/ public void reset_adpcm(adpcm_state state) { /* make sure we have our tables */ if (tables_computed == 0) compute_tables(); /* reset the signal/step */ state.signal = -2; state.step = 0; }
static unsafe void adpcm_coder(short *indata, byte *outdata, int len, adpcm_state *state, int cBits, bool fPreClamp) { short *inp; /* Input buffer pointer */ byte *outp; /* output buffer pointer */ int val; /* Current input sample value */ int sign; /* Current adpcm sign bit */ int delta; /* Current adpcm output value */ int diff; /* Difference between val and valprev */ int step; /* Stepsize */ int valpred; /* Predicted output value */ int vpdiff; /* Current change to valpred */ int index; /* Current step change index */ int outputbuffer; /* place to keep previous 4-bit value */ int bufferstep; /* toggle between outputbuffer/output */ outp = outdata; inp = indata; valpred = state->valprev; index = state->index; step = stepsizeTable[index]; outputbuffer = 0; bufferstep = 1; for ( ; len > 0 ; len-- ) { val = *inp++; /* Step 1 - compute difference with previous value */ diff = val - valpred; sign = (diff < 0) ? 8 : 0; if (sign != 0) diff = (-diff); // If we preclamp, then at decode time we don't need to clamp // at all. It results in some quantization error however, but // it is so slight it fails the blind test. int vpdiffMax = int.MaxValue; if (fPreClamp) { if (sign != 0) { vpdiffMax = valpred - -32768; } else { vpdiffMax = 32767 - valpred; } } /* Step 2 - Divide and clamp */ /* Note: ** This code *approximately* computes: ** delta = diff*4/step; ** vpdiff = (delta+0.5)*step/4; ** but in shift step bits are dropped. The net result of this is ** that even if you have fast mul/div hardware you cannot put it to ** good use since the fixup would be too expensive. */ delta = 0; if (fPreClamp) { vpdiff = 0; } else { vpdiff = (step >> 3); } if ( diff >= step ) { delta = 4; diff -= step; vpdiff += step; if (vpdiff > vpdiffMax) { vpdiff -= step; delta &= ~4; } } if (cBits > 2) { step >>= 1; if ( diff >= step ) { delta |= 2; diff -= step; vpdiff += step; if (vpdiff > vpdiffMax) { vpdiff -= step; delta &= ~2; } } } if (cBits > 3) { step >>= 1; if ( diff >= step ) { delta |= 1; vpdiff += step; if (vpdiff > vpdiffMax) { vpdiff -= step; delta &= ~1; } } } /* Step 3 - Update previous value */ if (sign != 0) valpred -= vpdiff; else valpred += vpdiff; /* Step 4 - Clamp previous value to 16 bits */ if ( valpred > 32767 ) { valpred = 32767; Debug.Assert(!fPreClamp); } else if ( valpred < -32768 ) { valpred = -32768; Debug.Assert(!fPreClamp); } /* Step 5 - Assemble value, update index and step values */ delta |= sign; index += indexTable[delta]; if ( index < 0 ) index = 0; if ( index > 88 ) index = 88; step = stepsizeTable[index]; /* Step 6 - Output value */ if (bufferstep != 0 ) { outputbuffer = (delta << 4) & 0xf0; } else { *outp++ = (byte)((delta & 0x0f) | outputbuffer); } bufferstep ^= 1; } /* Output last step, if needed */ if (bufferstep == 0) *outp++ = (byte)outputbuffer; state->valprev = valpred; state->index = index; }
static unsafe void adpcm_decoder(byte *indata, short *outdata, int len, adpcm_state *state, bool fPreClamp) { byte *inp; /* Input buffer pointer */ short *outp; /* output buffer pointer */ int sign; /* Current adpcm sign bit */ int delta; /* Current adpcm output value */ int step; /* Stepsize */ int valpred; /* Predicted value */ int vpdiff; /* Current change to valpred */ int index; /* Current step change index */ int inputbuffer; /* place to keep next 4-bit value */ int bufferstep; /* toggle between inputbuffer/input */ outp = outdata; inp = indata; valpred = state->valprev; index = state->index; step = stepsizeTable[index]; inputbuffer = 0; bufferstep = 0; for ( ; len > 0 ; len-- ) { /* Step 1 - get the delta value */ if (bufferstep != 0) { delta = inputbuffer & 0xf; } else { inputbuffer = *inp++; delta = (inputbuffer >> 4) & 0xf; } bufferstep ^= 1; /* Step 2 - Find new index value (for later) */ index += indexTable[delta]; if ( index < 0 ) index = 0; if ( index > 88 ) index = 88; /* Step 3 - Separate sign and magnitude */ sign = delta & 8; delta = delta & 7; /* Step 4 - Compute difference and new predicted value */ /* ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment ** in adpcm_coder. */ if (fPreClamp) { vpdiff = 0; } else { vpdiff = step >> 3; } if ((delta & 4) != 0) vpdiff += step; if ((delta & 2) != 0) vpdiff += step>>1; if ((delta & 1) != 0) vpdiff += step>>2; if (sign != 0) valpred -= vpdiff; else valpred += vpdiff; /* Step 5 - clamp output value */ if (!fPreClamp) { if ( valpred > 32767 ) valpred = 32767; else if ( valpred < -32768 ) valpred = -32768; } /* Step 6 - Update step value */ step = stepsizeTable[index]; /* Step 7 - Output value */ *outp++ = (short)valpred; } state->valprev = valpred; state->index = index; }