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 
S_AdpcmEncode(short indata[],char outdata[],int len,struct adpcm_state * state)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 
S_AdpcmDecode(const char indata[],short * outdata,int len,struct adpcm_state * state)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 */
S_AdpcmMemoryNeeded(const wavinfo_t * info)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 */
S_AdpcmGetSamples(sndBuffer * chunk,short * to)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((char *) out, to, SND_CHUNK_SIZE_BYTE*2, &state );
282 }
283 
284 
285 /*
286 ====================
287 S_AdpcmEncodeSound
288 ====================
289 */
S_AdpcmEncodeSound(sfx_t * sfx,short * samples)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 if (chunk != NULL) {
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, (char *) out, n, &state );
326 
327 		inOffset += n;
328 		count -= n;
329 	}
330 }
331