snd_adpcm.c (8802B)
1 /*********************************************************** 2 Copyright 1992 by Stichting Mathematisch Centrum, Amsterdam, The 3 Netherlands. 4 5 All Rights Reserved 6 7 Permission to use, copy, modify, and distribute this software and its 8 documentation for any purpose and without fee is hereby granted, 9 provided that the above copyright notice appear in all copies and that 10 both that copyright notice and this permission notice appear in 11 supporting documentation, and that the names of Stichting Mathematisch 12 Centrum or CWI not be used in advertising or publicity pertaining to 13 distribution of the software without specific, written prior permission. 14 15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO 16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE 18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 23 ******************************************************************/ 24 25 /* 26 ** Intel/DVI ADPCM coder/decoder. 27 ** 28 ** The algorithm for this coder was taken from the IMA Compatability Project 29 ** proceedings, Vol 2, Number 2; May 1992. 30 ** 31 ** Version 1.2, 18-Dec-92. 32 */ 33 34 #include "snd_local.h" 35 36 37 /* Intel ADPCM step variation table */ 38 static int indexTable[16] = { 39 -1, -1, -1, -1, 2, 4, 6, 8, 40 -1, -1, -1, -1, 2, 4, 6, 8, 41 }; 42 43 static int stepsizeTable[89] = { 44 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 45 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 46 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 47 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, 48 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 49 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 50 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, 51 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 52 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 53 }; 54 55 56 void S_AdpcmEncode( short indata[], char outdata[], int len, struct adpcm_state *state ) { 57 short *inp; /* Input buffer pointer */ 58 signed char *outp; /* output buffer pointer */ 59 int val; /* Current input sample value */ 60 int sign; /* Current adpcm sign bit */ 61 int delta; /* Current adpcm output value */ 62 int diff; /* Difference between val and sample */ 63 int step; /* Stepsize */ 64 int valpred; /* Predicted output value */ 65 int vpdiff; /* Current change to valpred */ 66 int index; /* Current step change index */ 67 int outputbuffer; /* place to keep previous 4-bit value */ 68 int bufferstep; /* toggle between outputbuffer/output */ 69 70 outp = (signed char *)outdata; 71 inp = indata; 72 73 valpred = state->sample; 74 index = state->index; 75 step = stepsizeTable[index]; 76 77 outputbuffer = 0; // quiet a compiler warning 78 bufferstep = 1; 79 80 for ( ; len > 0 ; len-- ) { 81 val = *inp++; 82 83 /* Step 1 - compute difference with previous value */ 84 diff = val - valpred; 85 sign = (diff < 0) ? 8 : 0; 86 if ( sign ) diff = (-diff); 87 88 /* Step 2 - Divide and clamp */ 89 /* Note: 90 ** This code *approximately* computes: 91 ** delta = diff*4/step; 92 ** vpdiff = (delta+0.5)*step/4; 93 ** but in shift step bits are dropped. The net result of this is 94 ** that even if you have fast mul/div hardware you cannot put it to 95 ** good use since the fixup would be too expensive. 96 */ 97 delta = 0; 98 vpdiff = (step >> 3); 99 100 if ( diff >= step ) { 101 delta = 4; 102 diff -= step; 103 vpdiff += step; 104 } 105 step >>= 1; 106 if ( diff >= step ) { 107 delta |= 2; 108 diff -= step; 109 vpdiff += step; 110 } 111 step >>= 1; 112 if ( diff >= step ) { 113 delta |= 1; 114 vpdiff += step; 115 } 116 117 /* Step 3 - Update previous value */ 118 if ( sign ) 119 valpred -= vpdiff; 120 else 121 valpred += vpdiff; 122 123 /* Step 4 - Clamp previous value to 16 bits */ 124 if ( valpred > 32767 ) 125 valpred = 32767; 126 else if ( valpred < -32768 ) 127 valpred = -32768; 128 129 /* Step 5 - Assemble value, update index and step values */ 130 delta |= sign; 131 132 index += indexTable[delta]; 133 if ( index < 0 ) index = 0; 134 if ( index > 88 ) index = 88; 135 step = stepsizeTable[index]; 136 137 /* Step 6 - Output value */ 138 if ( bufferstep ) { 139 outputbuffer = (delta << 4) & 0xf0; 140 } else { 141 *outp++ = (delta & 0x0f) | outputbuffer; 142 } 143 bufferstep = !bufferstep; 144 } 145 146 /* Output last step, if needed */ 147 if ( !bufferstep ) 148 *outp++ = outputbuffer; 149 150 state->sample = valpred; 151 state->index = index; 152 } 153 154 155 /* static */ void S_AdpcmDecode( const char indata[], short *outdata, int len, struct adpcm_state *state ) { 156 signed char *inp; /* Input buffer pointer */ 157 int outp; /* output buffer pointer */ 158 int sign; /* Current adpcm sign bit */ 159 int delta; /* Current adpcm output value */ 160 int step; /* Stepsize */ 161 int valpred; /* Predicted value */ 162 int vpdiff; /* Current change to valpred */ 163 int index; /* Current step change index */ 164 int inputbuffer; /* place to keep next 4-bit value */ 165 int bufferstep; /* toggle between inputbuffer/input */ 166 167 outp = 0; 168 inp = (signed char *)indata; 169 170 valpred = state->sample; 171 index = state->index; 172 step = stepsizeTable[index]; 173 174 bufferstep = 0; 175 inputbuffer = 0; // quiet a compiler warning 176 for ( ; len > 0 ; len-- ) { 177 178 /* Step 1 - get the delta value */ 179 if ( bufferstep ) { 180 delta = inputbuffer & 0xf; 181 } else { 182 inputbuffer = *inp++; 183 delta = (inputbuffer >> 4) & 0xf; 184 } 185 bufferstep = !bufferstep; 186 187 /* Step 2 - Find new index value (for later) */ 188 index += indexTable[delta]; 189 if ( index < 0 ) index = 0; 190 if ( index > 88 ) index = 88; 191 192 /* Step 3 - Separate sign and magnitude */ 193 sign = delta & 8; 194 delta = delta & 7; 195 196 /* Step 4 - Compute difference and new predicted value */ 197 /* 198 ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment 199 ** in adpcm_coder. 200 */ 201 vpdiff = step >> 3; 202 if ( delta & 4 ) vpdiff += step; 203 if ( delta & 2 ) vpdiff += step>>1; 204 if ( delta & 1 ) vpdiff += step>>2; 205 206 if ( sign ) 207 valpred -= vpdiff; 208 else 209 valpred += vpdiff; 210 211 /* Step 5 - clamp output value */ 212 if ( valpred > 32767 ) 213 valpred = 32767; 214 else if ( valpred < -32768 ) 215 valpred = -32768; 216 217 /* Step 6 - Update step value */ 218 step = stepsizeTable[index]; 219 220 /* Step 7 - Output value */ 221 outdata[outp] = valpred; 222 outp++; 223 } 224 225 state->sample = valpred; 226 state->index = index; 227 } 228 229 230 /* 231 ==================== 232 S_AdpcmMemoryNeeded 233 234 Returns the amount of memory (in bytes) needed to store the samples in out internal adpcm format 235 ==================== 236 */ 237 int S_AdpcmMemoryNeeded( const wavinfo_t *info ) { 238 float scale; 239 int scaledSampleCount; 240 int sampleMemory; 241 int blockCount; 242 int headerMemory; 243 244 // determine scale to convert from input sampling rate to desired sampling rate 245 scale = (float)info->rate / dma.speed; 246 247 // calc number of samples at playback sampling rate 248 scaledSampleCount = info->samples / scale; 249 250 // calc memory need to store those samples using ADPCM at 4 bits per sample 251 sampleMemory = scaledSampleCount / 2; 252 253 // calc number of sample blocks needed of PAINTBUFFER_SIZE 254 blockCount = scaledSampleCount / PAINTBUFFER_SIZE; 255 if( scaledSampleCount % PAINTBUFFER_SIZE ) { 256 blockCount++; 257 } 258 259 // calc memory needed to store the block headers 260 headerMemory = blockCount * sizeof(adpcm_state_t); 261 262 return sampleMemory + headerMemory; 263 } 264 265 266 /* 267 ==================== 268 S_AdpcmGetSamples 269 ==================== 270 */ 271 void S_AdpcmGetSamples(sndBuffer *chunk, short *to) { 272 adpcm_state_t state; 273 byte *out; 274 275 // get the starting state from the block header 276 state.index = chunk->adpcm.index; 277 state.sample = chunk->adpcm.sample; 278 279 out = (byte *)chunk->sndChunk; 280 // get samples 281 S_AdpcmDecode( out, to, SND_CHUNK_SIZE_BYTE*2, &state ); 282 } 283 284 285 /* 286 ==================== 287 S_AdpcmEncodeSound 288 ==================== 289 */ 290 void S_AdpcmEncodeSound( sfx_t *sfx, short *samples ) { 291 adpcm_state_t state; 292 int inOffset; 293 int count; 294 int n; 295 sndBuffer *newchunk, *chunk; 296 byte *out; 297 298 inOffset = 0; 299 count = sfx->soundLength; 300 state.index = 0; 301 state.sample = samples[0]; 302 303 chunk = NULL; 304 while( count ) { 305 n = count; 306 if( n > SND_CHUNK_SIZE_BYTE*2 ) { 307 n = SND_CHUNK_SIZE_BYTE*2; 308 } 309 310 newchunk = SND_malloc(); 311 if (sfx->soundData == NULL) { 312 sfx->soundData = newchunk; 313 } else { 314 chunk->next = newchunk; 315 } 316 chunk = newchunk; 317 318 // output the header 319 chunk->adpcm.index = state.index; 320 chunk->adpcm.sample = state.sample; 321 322 out = (byte *)chunk->sndChunk; 323 324 // encode the samples 325 S_AdpcmEncode( samples + inOffset, out, n, &state ); 326 327 inOffset += n; 328 count -= n; 329 } 330 }