Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

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 }