1 /**********************************************************************************************
2 *
3 * Streaming singe channel ADPCM core for the ES8712 chip
4 * Chip is branded by Excellent Systems, probably OEM'd.
5 *
6 * Samples are currently looped, but whether they should and how, is unknown.
7 * Interface to the chip is also not 100% clear.
8 * Should there be any status signals signifying busy, end of sample - etc?
9 *
10 * Heavily borrowed from the OKI M6295 source
11 *
12 * Excellent Systems ADPCM Emulation
13 * Copyright Nicola Salmoria and the MAME Team
14 *
15 * From MAME 0.139u1. Modified for use in FBA Aug 23, 2010.
16 *
17 **********************************************************************************************/
18
19 #include "burnint.h"
20 #include "math.h"
21 #include "es8712.h"
22
23 #define MAX_ES8712_CHIPS 1
24
25 #define MAX_SAMPLE_CHUNK 10000
26
27 /* struct describing a playing ADPCM chip */
28 typedef struct _es8712_state es8712_state;
29 struct _es8712_state
30 {
31 UINT8 playing; /* 1 if we're actively playing */
32
33 UINT32 base_offset; /* pointer to the base memory location */
34 UINT32 sample; /* current sample number */
35 UINT32 count; /* total samples to play */
36
37 UINT32 signal; /* current ADPCM signal */
38 UINT32 step; /* current ADPCM step */
39
40 UINT32 start; /* starting address for the next loop */
41 UINT32 end; /* ending address for the next loop */
42 UINT8 repeat; /* Repeat current sample when 1 */
43
44 INT32 bank_offset;
45
46 // non volatile
47 UINT8 *region_base; /* pointer to the base of the region */
48
49 INT32 sample_rate; /* samples per frame */
50 double volume; /* set gain */
51 INT32 output_dir;
52 INT32 addSignal; /* add signal to stream? */
53 };
54
55 static INT16 *tbuf[MAX_ES8712_CHIPS] = { NULL };
56
57 static _es8712_state chips[MAX_ES8712_CHIPS];
58 static _es8712_state *chip;
59
60 static const INT32 index_shift[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
61 static INT32 diff_lookup[49*16];
62
63 /**********************************************************************************************
64
65 compute_tables -- compute the difference tables
66
67 ***********************************************************************************************/
68
compute_tables()69 static void compute_tables()
70 {
71 /* nibble to bit map */
72 static const INT32 nbl2bit[16][4] =
73 {
74 { 1, 0, 0, 0}, { 1, 0, 0, 1}, { 1, 0, 1, 0}, { 1, 0, 1, 1},
75 { 1, 1, 0, 0}, { 1, 1, 0, 1}, { 1, 1, 1, 0}, { 1, 1, 1, 1},
76 {-1, 0, 0, 0}, {-1, 0, 0, 1}, {-1, 0, 1, 0}, {-1, 0, 1, 1},
77 {-1, 1, 0, 0}, {-1, 1, 0, 1}, {-1, 1, 1, 0}, {-1, 1, 1, 1}
78 };
79
80 INT32 step, nib;
81
82 /* loop over all possible steps */
83 for (step = 0; step <= 48; step++)
84 {
85 /* compute the step value */
86 INT32 stepval = (INT32)(floor(16.0 * pow(11.0 / 10.0, (double)step)));
87
88 /* loop over all nibbles and compute the difference */
89 for (nib = 0; nib < 16; nib++)
90 {
91 diff_lookup[step*16 + nib] = nbl2bit[nib][0] *
92 (stepval * nbl2bit[nib][1] +
93 stepval/2 * nbl2bit[nib][2] +
94 stepval/4 * nbl2bit[nib][3] +
95 stepval/8);
96 }
97 }
98 }
99
100
101 /**********************************************************************************************
102
103 generate_adpcm -- general ADPCM decoding routine
104
105 ***********************************************************************************************/
106
generate_adpcm(INT16 * buffer,INT32 samples)107 static void generate_adpcm(INT16 *buffer, INT32 samples)
108 {
109 /* if this chip is active */
110 if (chip->playing)
111 {
112 UINT8 *base = chip->region_base + chip->bank_offset + chip->base_offset;
113 INT32 sample = chip->sample;
114 INT32 signal = chip->signal;
115 INT32 count = chip->count;
116 INT32 step = chip->step;
117 double volume = chip->volume;
118 INT32 val;
119
120 /* loop while we still have samples to generate */
121 while (samples)
122 {
123 /* compute the new amplitude and update the current step */
124 val = base[sample / 2] >> (((sample & 1) << 2) ^ 4);
125 signal += diff_lookup[step * 16 + (val & 15)];
126
127 /* clamp to the maximum */
128 if (signal > 2047)
129 signal = 2047;
130 else if (signal < -2048)
131 signal = -2048;
132
133 /* adjust the step size and clamp */
134 step += index_shift[val & 7];
135 if (step > 48)
136 step = 48;
137 else if (step < 0)
138 step = 0;
139
140 /* output to the buffer */
141 *buffer++ = (INT32)(signal * 16 * volume);
142 samples--;
143
144 /* next! */
145 if (++sample >= count)
146 {
147 if (chip->repeat)
148 {
149 sample = 0;
150 signal = -2;
151 step = 0;
152 }
153 else
154 {
155 chip->playing = 0;
156 break;
157 }
158 }
159 }
160
161 /* update the parameters */
162 chip->sample = sample;
163 chip->signal = signal;
164 chip->step = step;
165 }
166
167 /* fill the rest with silence */
168 while (samples--)
169 *buffer++ = 0;
170 }
171
172
173 /**********************************************************************************************
174
175 es8712Update -- update the sound chip so that it is in sync with CPU execution
176
177 ***********************************************************************************************/
178
es8712Update(INT32 device,INT16 * buffer,INT32 samples)179 void es8712Update(INT32 device, INT16 *buffer, INT32 samples)
180 {
181 #if defined FBA_DEBUG
182 if (!DebugSnd_ES8712Initted) bprintf(PRINT_ERROR, _T("es8712Update called without init\n"));
183 #endif
184
185 if (device >= MAX_ES8712_CHIPS) return;
186
187 chip = &chips[device];
188
189 INT32 sample_num = (INT32)((float)(((samples / nBurnSoundLen) * 1.0000) * chip->sample_rate));
190
191 float step = ((chip->sample_rate * 1.00000) / nBurnSoundLen);
192
193 INT16 *buf = tbuf[device];
194
195 generate_adpcm(buf, sample_num);
196
197 float r = 0;
198 for (INT32 i = 0; i < samples; i++, r += step, buffer+=2) {
199 INT32 nLeftSample = 0, nRightSample = 0;
200
201 if ((chip->output_dir & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
202 nLeftSample += (INT32)(buf[(INT32)r] * chip->volume);
203 }
204 if ((chip->output_dir & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
205 nRightSample += (INT32)(buf[(INT32)r] * chip->volume);
206 }
207
208 nLeftSample = BURN_SND_CLIP(nLeftSample);
209 nRightSample = BURN_SND_CLIP(nRightSample);
210
211 if (chip->addSignal) {
212 buffer[0] += nLeftSample;
213 buffer[1] += nRightSample;
214 } else {
215 buffer[0] = nLeftSample;
216 buffer[1] = nRightSample;
217 }
218 }
219
220 }
221
222
223 /**********************************************************************************************
224
225 es8712Init -- start emulation of an ES8712 chip
226
227 ***********************************************************************************************/
228
es8712Init(INT32 device,UINT8 * rom,INT32 sample_rate,INT32 addSignal)229 void es8712Init(INT32 device, UINT8 *rom, INT32 sample_rate, INT32 addSignal)
230 {
231 DebugSnd_ES8712Initted = 1;
232
233 if (device >= MAX_ES8712_CHIPS) return;
234
235 chip = &chips[device];
236
237 compute_tables();
238
239 chip->start = 0;
240 chip->end = 0;
241 chip->repeat = 0;
242
243 chip->bank_offset = 0;
244 chip->region_base = (UINT8*)rom;
245
246 /* initialize the rest of the structure */
247 chip->signal = (UINT32)-2;
248
249 chip->sample_rate = sample_rate;
250
251 chip->volume = 1.00;
252 chip->output_dir = BURN_SND_ROUTE_BOTH;
253 chip->addSignal = addSignal;
254
255 if (tbuf[device] == NULL) {
256 tbuf[device] = (INT16*)BurnMalloc(sample_rate * sizeof(INT16));
257 }
258 }
259
es8712SetRoute(INT32 device,double nVolume,INT32 nRouteDir)260 void es8712SetRoute(INT32 device, double nVolume, INT32 nRouteDir)
261 {
262 #if defined FBA_DEBUG
263 if (!DebugSnd_ES8712Initted) bprintf(PRINT_ERROR, _T("es8712SetRoute called without init\n"));
264 #endif
265
266 if (device >= MAX_ES8712_CHIPS) return;
267
268 chip = &chips[device];
269 chip->volume = nVolume;
270 chip->output_dir = nRouteDir;
271 }
272
273 /**********************************************************************************************
274
275 es8712Exit -- stop emulation of an ES8712 chip
276
277 ***********************************************************************************************/
278
es8712Exit(INT32 device)279 void es8712Exit(INT32 device)
280 {
281 #if defined FBA_DEBUG
282 if (!DebugSnd_ES8712Initted) bprintf(PRINT_ERROR, _T("es8712Exit called without init\n"));
283 #endif
284
285 if (!DebugSnd_ES8712Initted) return;
286
287 if (device >= MAX_ES8712_CHIPS) return;
288
289 chip = &chips[device];
290
291 memset (chip, 0, sizeof(_es8712_state));
292
293 BurnFree (tbuf[device]);
294
295 DebugSnd_ES8712Initted = 0;
296 }
297
298 /*************************************************************************************
299
300 es8712Reset -- stop emulation of an ES8712-compatible chip
301
302 **************************************************************************************/
303
es8712Reset(INT32 device)304 void es8712Reset(INT32 device)
305 {
306 #if defined FBA_DEBUG
307 if (!DebugSnd_ES8712Initted) bprintf(PRINT_ERROR, _T("es8712Reset called without init\n"));
308 #endif
309
310 if (device >= MAX_ES8712_CHIPS) return;
311
312 chip = &chips[device];
313
314 if (chip->playing)
315 {
316 /* update the stream, then turn it off */
317 chip->playing = 0;
318 chip->repeat = 0;
319 }
320 }
321
322
323 /****************************************************************************
324
325 es8712_set_bank_base -- set the base of the bank on a given chip
326
327 *****************************************************************************/
328
es8712SetBankBase(INT32 device,INT32 base)329 void es8712SetBankBase(INT32 device, INT32 base)
330 {
331 #if defined FBA_DEBUG
332 if (!DebugSnd_ES8712Initted) bprintf(PRINT_ERROR, _T("es8712SetBankBase called without init\n"));
333 #endif
334
335 if (device >= MAX_ES8712_CHIPS) return;
336
337 chip = &chips[device];
338
339 chip->bank_offset = base;
340 }
341
342
343 /**********************************************************************************************
344
345 es8712Play -- Begin playing the addressed sample
346
347 ***********************************************************************************************/
348
es8712Play(INT32 device)349 void es8712Play(INT32 device)
350 {
351 #if defined FBA_DEBUG
352 if (!DebugSnd_ES8712Initted) bprintf(PRINT_ERROR, _T("es8712Play called without init\n"));
353 #endif
354
355 if (device >= MAX_ES8712_CHIPS) return;
356
357 chip = &chips[device];
358
359 if (chip->start < chip->end)
360 {
361 if (!chip->playing)
362 {
363 chip->playing = 1;
364 chip->base_offset = chip->start;
365 chip->sample = 0;
366 chip->count = 2 * (chip->end - chip->start + 1);
367 chip->repeat = 0;//1;
368
369 /* also reset the ADPCM parameters */
370 chip->signal = (UINT32)-2;
371 chip->step = 0;
372 }
373 }
374 /* invalid samples go here */
375 else
376 {
377 if (chip->playing)
378 {
379 /* update the stream */
380 chip->playing = 0;
381 }
382 }
383 }
384
385
386 /**********************************************************************************************
387
388 es8712Write -- generic data write function
389
390 ***********************************************************************************************/
391
392 /**********************************************************************************************
393 *
394 * offset Start End
395 * 0hmmll - 0HMMLL
396 * 00 ----ll
397 * 01 --mm--
398 * 02 0h----
399 * 03 ----LL
400 * 04 --MM--
401 * 05 0H----
402 * 06 Go!
403 *
404 * Offsets are written in the order -> 00, 02, 01, 03, 05, 04, 06
405 * Offset 06 is written with the same value as offset 04.
406 *
407 ***********************************************************************************************/
408
es8712Write(INT32 device,INT32 offset,UINT8 data)409 void es8712Write(INT32 device, INT32 offset, UINT8 data)
410 {
411 #if defined FBA_DEBUG
412 if (!DebugSnd_ES8712Initted) bprintf(PRINT_ERROR, _T("es8712Write called without init\n"));
413 #endif
414
415 if (device >= MAX_ES8712_CHIPS) return;
416
417 chip = &chips[device];
418
419 switch (offset)
420 {
421 case 00: chip->start &= 0x000fff00;
422 chip->start |= ((data & 0xff) << 0); break;
423 case 01: chip->start &= 0x000f00ff;
424 chip->start |= ((data & 0xff) << 8); break;
425 case 02: chip->start &= 0x0000ffff;
426 chip->start |= ((data & 0x0f) << 16); break;
427 case 03: chip->end &= 0x000fff00;
428 chip->end |= ((data & 0xff) << 0); break;
429 case 04: chip->end &= 0x000f00ff;
430 chip->end |= ((data & 0xff) << 8); break;
431 case 05: chip->end &= 0x0000ffff;
432 chip->end |= ((data & 0x0f) << 16); break;
433 case 06:
434 es8712Play(device);
435 break;
436 default: break;
437 }
438
439 chip->start &= 0xfffff;
440 chip->end &= 0xfffff;
441 }
442
443
444 /**********************************************************************************************
445
446 es8712Scan -- save state function
447
448 ***********************************************************************************************/
449
es8712Scan(INT32 nAction,INT32 *)450 void es8712Scan(INT32 nAction, INT32 *)
451 {
452 #if defined FBA_DEBUG
453 if (!DebugSnd_ES8712Initted) bprintf(PRINT_ERROR, _T("es8712Scan called without init\n"));
454 #endif
455
456 if (nAction & ACB_DRIVER_DATA)
457 {
458 for (INT32 i = 0; i < MAX_ES8712_CHIPS; i++)
459 {
460 chip = &chips[i];
461
462 SCAN_VAR(chip->playing);
463 SCAN_VAR(chip->base_offset);
464 SCAN_VAR(chip->sample);
465 SCAN_VAR(chip->count);
466 SCAN_VAR(chip->signal);
467 SCAN_VAR(chip->step);
468 SCAN_VAR(chip->start);
469 SCAN_VAR(chip->end);
470 SCAN_VAR(chip->repeat);
471 SCAN_VAR(chip->bank_offset);
472 }
473 }
474 }
475