|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
1.1.1.16! root 4: * Paula audio emulation
1.1 root 5: *
6: * Copyright 1995, 1996, 1997 Bernd Schmidt
7: * Copyright 1996 Marcus Sundberg
8: * Copyright 1996 Manfred Thole
1.1.1.16! root 9: * Copyright 2006 Toni Wilen
! 10: *
! 11: * new filter algorithm and anti&sinc interpolators by Antti S. Lankila
1.1 root 12: */
13:
14: #include "sysconfig.h"
15: #include "sysdeps.h"
16:
17: #include "options.h"
18: #include "memory.h"
19: #include "custom.h"
1.1.1.7 root 20: #include "newcpu.h"
21: #include "autoconf.h"
1.1 root 22: #include "gensound.h"
23: #include "sounddep/sound.h"
24: #include "events.h"
25: #include "audio.h"
1.1.1.8 root 26: #include "savestate.h"
1.1.1.16! root 27: #include "sinctable.h"
! 28: #include "gui.h"
! 29:
! 30: #define MAX_EV ~0ul
1.1 root 31:
1.1.1.16! root 32: /* periods less than this value are replaced by this value. */
! 33: #define MIN_ALLOWED_PERIOD 16
! 34: /* reserve ~20 extra slots in sinc queue for cpu volume or some such updates
! 35: * even at maximum period. This avoids sinc queue overflow on games like
! 36: * battle squadron that write these low period values and do cpu-based
! 37: * updates on paula registers, probably volume. */
! 38: #define NUMBER_OF_CPU_UPDATES_ALLOWED 20
! 39:
! 40: #define SINC_QUEUE_LENGTH (SINC_QUEUE_MAX_AGE / MIN_ALLOWED_PERIOD + NUMBER_OF_CPU_UPDATES_ALLOWED)
! 41:
! 42: typedef struct {
! 43: int age;
! 44: int output;
! 45: } sinc_queue_t;
! 46:
! 47: struct audio_channel_data {
! 48: unsigned long adk_mask;
! 49: unsigned long evtime;
! 50: unsigned long per;
! 51: uae_u8 dmaen, intreq2, data_written;
! 52: uaecptr lc, pt;
! 53: int state, wper;
! 54: unsigned int wlen;
! 55: int current_sample, last_sample;
! 56: int vol;
! 57: int *voltbl;
! 58: uae_u16 dat, nextdat, len;
! 59: int sinc_output_state;
! 60: sinc_queue_t sinc_queue[SINC_QUEUE_LENGTH];
! 61: int sinc_queue_length;
! 62: };
! 63:
! 64: static struct audio_channel_data audio_channel[4];
1.1.1.2 root 65: int sound_available = 0;
1.1 root 66: int sound_table[64][256];
1.1.1.2 root 67: void (*sample_handler) (void);
1.1.1.16! root 68: static void (*sample_prehandler) (unsigned long best_evtime);
1.1.1.7 root 69:
1.1.1.16! root 70: static unsigned long scaled_sample_evtime;
1.1.1.2 root 71: static unsigned long last_cycles, next_sample_evtime;
1.1 root 72:
1.1.1.16! root 73: unsigned int obtainedfreq;
! 74:
1.1.1.2 root 75: void init_sound_table16 (void)
1.1 root 76: {
77: int i,j;
78:
79: for (i = 0; i < 256; i++)
80: for (j = 0; j < 64; j++)
1.1.1.13 root 81: sound_table[j][i] = j * (uae_s8)i * (currprefs.sound_stereo ? 2 : 1);
1.1 root 82: }
83:
84: #ifdef MULTIPLICATION_PROFITABLE
85: typedef uae_s8 sample8_t;
86: #define DO_CHANNEL_1(v, c) do { (v) *= audio_channel[c].vol; } while (0)
87: #define SBASEVAL16(logn) ((logn) == 1 ? SOUND16_BASE_VAL >> 1 : SOUND16_BASE_VAL)
1.1.1.7 root 88: #define FINISH_DATA(data,b,logn) do { if (14 - (b) + (logn) > 0) (data) >>= 14 - (b) + (logn); else (data) <<= (b) - 14 - (logn); } while (0);
1.1 root 89: #else
90: typedef uae_u8 sample8_t;
91: #define DO_CHANNEL_1(v, c) do { (v) = audio_channel[c].voltbl[(v)]; } while (0)
92: #define SBASEVAL16(logn) SOUND16_BASE_VAL
1.1.1.16! root 93: #define FINISH_DATA(data,b,logn)
1.1 root 94: #endif
95:
1.1.1.7 root 96: /* Always put the right word before the left word. */
97: #define DELAY_BUFFER 32
98: static uae_u32 right_word_saved[DELAY_BUFFER];
99: static uae_u32 left_word_saved[DELAY_BUFFER];
100: static int saved_ptr;
1.1 root 101:
1.1.1.7 root 102: STATIC_INLINE void put_sound_word_right (uae_u32 w)
1.1 root 103: {
1.1.1.7 root 104: if (currprefs.mixed_stereo) {
105: right_word_saved[saved_ptr] = w;
106: return;
1.1 root 107: }
108:
1.1.1.7 root 109: PUT_SOUND_WORD_RIGHT (w);
1.1 root 110: }
111:
1.1.1.7 root 112: STATIC_INLINE void put_sound_word_left (uae_u32 w)
1.1.1.5 root 113: {
1.1.1.7 root 114: if (currprefs.mixed_stereo) {
115: uae_u32 rold, lold, rnew, lnew, tmp;
1.1.1.5 root 116:
1.1.1.7 root 117: left_word_saved[saved_ptr] = w;
118: lnew = w - SOUND16_BASE_VAL;
119: rnew = right_word_saved[saved_ptr] - SOUND16_BASE_VAL;
1.1.1.5 root 120:
1.1.1.7 root 121: saved_ptr = (saved_ptr + 1) & (DELAY_BUFFER - 1);
122: lold = left_word_saved[saved_ptr] - SOUND16_BASE_VAL;
123: tmp = (rnew * 5 + lold * 3) >> 3;
124: tmp += SOUND16_BASE_VAL;
125: PUT_SOUND_WORD_RIGHT (tmp);
1.1.1.5 root 126:
1.1.1.7 root 127: rold = right_word_saved[saved_ptr] - SOUND16_BASE_VAL;
128: w = (lnew * 5 + rold * 3) >> 3;
129: }
130: PUT_SOUND_WORD_LEFT (w);
131: }
1.1.1.5 root 132:
1.1.1.7 root 133: #define DO_CHANNEL(v, c) do { (v) &= audio_channel[c].adk_mask; data += v; } while (0);
1.1.1.5 root 134:
1.1.1.16! root 135: static void sinc_prehandler (unsigned long best_evtime)
! 136: {
! 137: int i, j, output;
! 138: struct audio_channel_data *acd;
! 139:
! 140: for (i = 0; i < 4; i++) {
! 141: acd = &audio_channel[i];
! 142: output = (acd->current_sample * acd->vol) & acd->adk_mask;
! 143:
! 144: /* age the sinc queue and truncate it when necessary */
! 145: for (j = 0; j < acd->sinc_queue_length; j += 1) {
! 146: acd->sinc_queue[j].age += best_evtime;
! 147: if (acd->sinc_queue[j].age >= SINC_QUEUE_MAX_AGE) {
! 148: acd->sinc_queue_length = j;
! 149: break;
! 150: }
! 151: }
! 152: /* if output state changes, record the state change and also
! 153: * write data into sinc queue for mixing in the BLEP */
! 154: if (acd->sinc_output_state != output) {
! 155: if (acd->sinc_queue_length > SINC_QUEUE_LENGTH - 1) {
! 156: write_log ("warning: sinc queue truncated. Last age: %d.\n",
! 157: acd->sinc_queue[SINC_QUEUE_LENGTH-1].age);
! 158: acd->sinc_queue_length = SINC_QUEUE_LENGTH - 1;
! 159: }
! 160: /* make room for new and add the new value */
! 161: memmove (&acd->sinc_queue[1], &acd->sinc_queue[0],
! 162: sizeof(acd->sinc_queue[0]) * acd->sinc_queue_length);
! 163: acd->sinc_queue_length += 1;
! 164: acd->sinc_queue[0].age = best_evtime;
! 165: acd->sinc_queue[0].output = output - acd->sinc_output_state;
! 166: acd->sinc_output_state = output;
! 167: }
! 168: }
! 169: }
! 170:
! 171:
! 172: /* this interpolator performs BLEP mixing (bleps are shaped like integrated sinc
! 173: * functions) with a type of BLEP that matches the filtering configuration. */
! 174: STATIC_INLINE void samplexx_sinc_handler (int *datasp)
! 175: {
! 176: int i, n;
! 177: int const *winsinc;
! 178:
! 179: #if 1
! 180: /* Amiga 500 filter model is default for now. Put n=2 for A1200. */
! 181: n = 0;
! 182: if (gui_ledstate & 1) /* power led */
! 183: n += 1;
! 184: #else
! 185: if (sound_use_filter_sinc) {
! 186: n = (sound_use_filter_sinc == FILTER_MODEL_A500) ? 0 : 2;
! 187: if (led_filter_on)
! 188: n += 1;
! 189: } else {
! 190: n = 4;
! 191: }
! 192: #endif
! 193: winsinc = winsinc_integral[n];
! 194:
! 195: for (i = 0; i < 4; i += 1) {
! 196: int j, v;
! 197: struct audio_channel_data *acd = &audio_channel[i];
! 198: /* The sum rings with harmonic components up to infinity... */
! 199: int sum = acd->sinc_output_state << 17;
! 200: /* ...but we cancel them through mixing in BLEPs instead */
! 201: for (j = 0; j < acd->sinc_queue_length; j += 1)
! 202: sum -= winsinc[acd->sinc_queue[j].age] * acd->sinc_queue[j].output;
! 203: v = sum >> 17;
! 204: if (v > 32767)
! 205: v = 32767;
! 206: else if (v < -32768)
! 207: v = -32768;
! 208: datasp[i] = v;
! 209: }
! 210: }
! 211:
! 212: static void sample16i_sinc_handler (void)
! 213: {
! 214: int datas[4], data1;
! 215:
! 216: samplexx_sinc_handler (datas);
! 217: data1 = datas[0] + datas[3] + datas[1] + datas[2];
! 218: FINISH_DATA (data1, 16, 2);
! 219: PUT_SOUND_WORD (data1);
! 220: check_sound_buffers ();
! 221: }
! 222:
1.1.1.7 root 223: void sample16_handler (void)
224: {
1.1.1.13 root 225: uae_u32 data0 = audio_channel[0].current_sample;
226: uae_u32 data1 = audio_channel[1].current_sample;
227: uae_u32 data2 = audio_channel[2].current_sample;
228: uae_u32 data3 = audio_channel[3].current_sample;
229: DO_CHANNEL_1 (data0, 0);
230: DO_CHANNEL_1 (data1, 1);
231: DO_CHANNEL_1 (data2, 2);
232: DO_CHANNEL_1 (data3, 3);
233: data0 &= audio_channel[0].adk_mask;
234: data1 &= audio_channel[1].adk_mask;
235: data2 &= audio_channel[2].adk_mask;
236: data3 &= audio_channel[3].adk_mask;
237: data0 += data1;
238: data0 += data2;
239: data0 += data3;
240: {
241: uae_u32 data = SBASEVAL16(2) + data0;
242: FINISH_DATA (data, 16, 2);
243: PUT_SOUND_WORD (data);
1.1.1.5 root 244: }
245: check_sound_buffers ();
246: }
247:
1.1.1.16! root 248: static void sample16i_rh_handler (void)
1.1.1.6 root 249: {
1.1.1.13 root 250: unsigned long delta, ratio;
251:
252: uae_u32 data0 = audio_channel[0].current_sample;
253: uae_u32 data1 = audio_channel[1].current_sample;
254: uae_u32 data2 = audio_channel[2].current_sample;
255: uae_u32 data3 = audio_channel[3].current_sample;
256: uae_u32 data0p = audio_channel[0].last_sample;
257: uae_u32 data1p = audio_channel[1].last_sample;
258: uae_u32 data2p = audio_channel[2].last_sample;
259: uae_u32 data3p = audio_channel[3].last_sample;
260: DO_CHANNEL_1 (data0, 0);
261: DO_CHANNEL_1 (data1, 1);
262: DO_CHANNEL_1 (data2, 2);
263: DO_CHANNEL_1 (data3, 3);
264: DO_CHANNEL_1 (data0p, 0);
265: DO_CHANNEL_1 (data1p, 1);
266: DO_CHANNEL_1 (data2p, 2);
267: DO_CHANNEL_1 (data3p, 3);
1.1.1.6 root 268:
1.1.1.13 root 269: data0 &= audio_channel[0].adk_mask;
270: data0p &= audio_channel[0].adk_mask;
271: data1 &= audio_channel[1].adk_mask;
272: data1p &= audio_channel[1].adk_mask;
273: data2 &= audio_channel[2].adk_mask;
274: data2p &= audio_channel[2].adk_mask;
275: data3 &= audio_channel[3].adk_mask;
276: data3p &= audio_channel[3].adk_mask;
1.1.1.6 root 277:
1.1.1.13 root 278: /* linear interpolation and summing up... */
279: delta = audio_channel[0].per;
280: ratio = ((audio_channel[0].evtime % delta) << 8) / delta;
281: data0 = (data0 * (256 - ratio) + data0p * ratio) >> 8;
282: delta = audio_channel[1].per;
283: ratio = ((audio_channel[1].evtime % delta) << 8) / delta;
284: data0 += (data1 * (256 - ratio) + data1p * ratio) >> 8;
285: delta = audio_channel[2].per;
286: ratio = ((audio_channel[2].evtime % delta) << 8) / delta;
287: data0 += (data2 * (256 - ratio) + data2p * ratio) >> 8;
288: delta = audio_channel[3].per;
289: ratio = ((audio_channel[3].evtime % delta) << 8) / delta;
290: data0 += (data3 * (256 - ratio) + data3p * ratio) >> 8;
1.1.1.6 root 291:
1.1.1.13 root 292: {
293: uae_u32 data = SBASEVAL16(2) + data0;
294: FINISH_DATA (data, 16, 2);
295: PUT_SOUND_WORD (data);
1.1.1.6 root 296: }
1.1.1.13 root 297:
298: check_sound_buffers ();
1.1.1.7 root 299: }
1.1.1.6 root 300:
1.1.1.16! root 301: static void sample16i_crux_handler (void)
1.1.1.7 root 302: {
1.1.1.13 root 303: uae_u32 data0 = audio_channel[0].current_sample;
304: uae_u32 data1 = audio_channel[1].current_sample;
305: uae_u32 data2 = audio_channel[2].current_sample;
306: uae_u32 data3 = audio_channel[3].current_sample;
307: uae_u32 data0p = audio_channel[0].last_sample;
308: uae_u32 data1p = audio_channel[1].last_sample;
309: uae_u32 data2p = audio_channel[2].last_sample;
310: uae_u32 data3p = audio_channel[3].last_sample;
311: DO_CHANNEL_1 (data0, 0);
312: DO_CHANNEL_1 (data1, 1);
313: DO_CHANNEL_1 (data2, 2);
314: DO_CHANNEL_1 (data3, 3);
315: DO_CHANNEL_1 (data0p, 0);
316: DO_CHANNEL_1 (data1p, 1);
317: DO_CHANNEL_1 (data2p, 2);
318: DO_CHANNEL_1 (data3p, 3);
319:
320: data0 &= audio_channel[0].adk_mask;
321: data0p &= audio_channel[0].adk_mask;
322: data1 &= audio_channel[1].adk_mask;
323: data1p &= audio_channel[1].adk_mask;
324: data2 &= audio_channel[2].adk_mask;
325: data2p &= audio_channel[2].adk_mask;
326: data3 &= audio_channel[3].adk_mask;
327: data3p &= audio_channel[3].adk_mask;
328:
1.1.1.15 root 329: {
1.1.1.13 root 330: struct audio_channel_data *cdp;
331: unsigned long ratio, ratio1;
1.1.1.7 root 332: #define INTERVAL (scaled_sample_evtime * 3)
1.1.1.13 root 333: cdp = audio_channel + 0;
334: ratio1 = cdp->per - cdp->evtime;
335: ratio = (ratio1 << 12) / INTERVAL;
336: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
337: ratio = 4096;
338: data0 = (data0 * ratio + data0p * (4096 - ratio)) >> 12;
339:
340: cdp = audio_channel + 1;
341: ratio1 = cdp->per - cdp->evtime;
342: ratio = (ratio1 << 12) / INTERVAL;
343: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
344: ratio = 4096;
345: data1 = (data1 * ratio + data1p * (4096 - ratio)) >> 12;
346:
347: cdp = audio_channel + 2;
348: ratio1 = cdp->per - cdp->evtime;
349: ratio = (ratio1 << 12) / INTERVAL;
350: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
351: ratio = 4096;
352: data2 = (data2 * ratio + data2p * (4096 - ratio)) >> 12;
353:
354: cdp = audio_channel + 3;
355: ratio1 = cdp->per - cdp->evtime;
356: ratio = (ratio1 << 12) / INTERVAL;
357: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
358: ratio = 4096;
359: data3 = (data3 * ratio + data3p * (4096 - ratio)) >> 12;
360: }
361: data1 += data2;
362: data0 += data3;
363: data0 += data1;
364: {
365: uae_u32 data = SBASEVAL16(2) + data0;
366: FINISH_DATA (data, 16, 2);
367: PUT_SOUND_WORD (data);
1.1.1.7 root 368: }
1.1.1.6 root 369: check_sound_buffers ();
370: }
371:
1.1.1.16! root 372: #ifdef HAVE_STEREO_SUPPORT
! 373: static void sample16si_sinc_handler (void)
1.1 root 374: {
1.1.1.16! root 375: int datas[4], data1, data2;
1.1 root 376:
1.1.1.16! root 377: samplexx_sinc_handler (datas);
! 378: data1 = datas[0] + datas[3];
! 379: data2 = datas[1] + datas[2];
! 380: FINISH_DATA (data1, 16, 1);
! 381: put_sound_word_left (data1);
! 382: FINISH_DATA (data2, 16, 1);
! 383: put_sound_word_right (data2);
1.1 root 384: check_sound_buffers ();
385: }
386:
1.1.1.2 root 387: void sample16s_handler (void)
1.1 root 388: {
1.1.1.13 root 389: uae_u32 data0 = audio_channel[0].current_sample;
390: uae_u32 data1 = audio_channel[1].current_sample;
391: uae_u32 data2 = audio_channel[2].current_sample;
392: uae_u32 data3 = audio_channel[3].current_sample;
393: DO_CHANNEL_1 (data0, 0);
394: DO_CHANNEL_1 (data1, 1);
395: DO_CHANNEL_1 (data2, 2);
396: DO_CHANNEL_1 (data3, 3);
397:
398: data0 &= audio_channel[0].adk_mask;
399: data1 &= audio_channel[1].adk_mask;
400: data2 &= audio_channel[2].adk_mask;
401: data3 &= audio_channel[3].adk_mask;
1.1.1.15 root 402:
1.1.1.13 root 403: data0 += data3;
404: {
405: uae_u32 data = SBASEVAL16(1) + data0;
406: FINISH_DATA (data, 16, 1);
407: put_sound_word_right (data);
408: }
1.1 root 409:
1.1.1.13 root 410: data1 += data2;
411: {
1.1.1.15 root 412: uae_u32 data = SBASEVAL16(1) + data1;
1.1.1.13 root 413: FINISH_DATA (data, 16, 1);
414: put_sound_word_left (data);
1.1 root 415: }
1.1.1.7 root 416:
1.1 root 417: check_sound_buffers ();
418: }
419:
1.1.1.16! root 420: static void sample16si_crux_handler (void)
1.1.1.5 root 421: {
1.1.1.13 root 422: uae_u32 data0 = audio_channel[0].current_sample;
423: uae_u32 data1 = audio_channel[1].current_sample;
424: uae_u32 data2 = audio_channel[2].current_sample;
425: uae_u32 data3 = audio_channel[3].current_sample;
426: uae_u32 data0p = audio_channel[0].last_sample;
427: uae_u32 data1p = audio_channel[1].last_sample;
428: uae_u32 data2p = audio_channel[2].last_sample;
429: uae_u32 data3p = audio_channel[3].last_sample;
430:
431: DO_CHANNEL_1 (data0, 0);
432: DO_CHANNEL_1 (data1, 1);
433: DO_CHANNEL_1 (data2, 2);
434: DO_CHANNEL_1 (data3, 3);
435: DO_CHANNEL_1 (data0p, 0);
436: DO_CHANNEL_1 (data1p, 1);
437: DO_CHANNEL_1 (data2p, 2);
438: DO_CHANNEL_1 (data3p, 3);
439:
440: data0 &= audio_channel[0].adk_mask;
441: data0p &= audio_channel[0].adk_mask;
442: data1 &= audio_channel[1].adk_mask;
443: data1p &= audio_channel[1].adk_mask;
444: data2 &= audio_channel[2].adk_mask;
445: data2p &= audio_channel[2].adk_mask;
446: data3 &= audio_channel[3].adk_mask;
447: data3p &= audio_channel[3].adk_mask;
448:
1.1.1.15 root 449: {
1.1.1.13 root 450: struct audio_channel_data *cdp;
451: unsigned long ratio, ratio1;
1.1.1.7 root 452: #define INTERVAL (scaled_sample_evtime * 3)
1.1.1.13 root 453: cdp = audio_channel + 0;
454: ratio1 = cdp->per - cdp->evtime;
455: ratio = (ratio1 << 12) / INTERVAL;
456: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
457: ratio = 4096;
458: data0 = (data0 * ratio + data0p * (4096 - ratio)) >> 12;
459:
460: cdp = audio_channel + 1;
461: ratio1 = cdp->per - cdp->evtime;
462: ratio = (ratio1 << 12) / INTERVAL;
463: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
464: ratio = 4096;
465: data1 = (data1 * ratio + data1p * (4096 - ratio)) >> 12;
466:
467: cdp = audio_channel + 2;
468: ratio1 = cdp->per - cdp->evtime;
469: ratio = (ratio1 << 12) / INTERVAL;
470: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
471: ratio = 4096;
472: data2 = (data2 * ratio + data2p * (4096 - ratio)) >> 12;
473:
474: cdp = audio_channel + 3;
475: ratio1 = cdp->per - cdp->evtime;
476: ratio = (ratio1 << 12) / INTERVAL;
477: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
478: ratio = 4096;
479: data3 = (data3 * ratio + data3p * (4096 - ratio)) >> 12;
480: }
481: data1 += data2;
482: data0 += data3;
483: {
484: uae_u32 data = SBASEVAL16 (1) + data0;
485: FINISH_DATA (data, 16, 1);
486: put_sound_word_right (data);
487: }
1.1.1.6 root 488:
1.1.1.13 root 489: {
490: uae_u32 data = SBASEVAL16 (1) + data1;
491: FINISH_DATA (data, 16, 1);
492: put_sound_word_left (data);
493: }
1.1.1.6 root 494: check_sound_buffers ();
495: }
496:
1.1.1.16! root 497: static void sample16si_rh_handler (void)
1.1.1.6 root 498: {
1.1.1.13 root 499: unsigned long delta, ratio;
1.1.1.6 root 500:
1.1.1.13 root 501: uae_u32 data0 = audio_channel[0].current_sample;
502: uae_u32 data1 = audio_channel[1].current_sample;
503: uae_u32 data2 = audio_channel[2].current_sample;
504: uae_u32 data3 = audio_channel[3].current_sample;
505: uae_u32 data0p = audio_channel[0].last_sample;
506: uae_u32 data1p = audio_channel[1].last_sample;
507: uae_u32 data2p = audio_channel[2].last_sample;
508: uae_u32 data3p = audio_channel[3].last_sample;
1.1.1.5 root 509:
1.1.1.13 root 510: DO_CHANNEL_1 (data0, 0);
511: DO_CHANNEL_1 (data1, 1);
512: DO_CHANNEL_1 (data2, 2);
513: DO_CHANNEL_1 (data3, 3);
514: DO_CHANNEL_1 (data0p, 0);
515: DO_CHANNEL_1 (data1p, 1);
516: DO_CHANNEL_1 (data2p, 2);
517: DO_CHANNEL_1 (data3p, 3);
518:
519: data0 &= audio_channel[0].adk_mask;
520: data0p &= audio_channel[0].adk_mask;
521: data1 &= audio_channel[1].adk_mask;
522: data1p &= audio_channel[1].adk_mask;
523: data2 &= audio_channel[2].adk_mask;
524: data2p &= audio_channel[2].adk_mask;
525: data3 &= audio_channel[3].adk_mask;
526: data3p &= audio_channel[3].adk_mask;
527:
528: /* linear interpolation and summing up... */
529: delta = audio_channel[0].per;
530: ratio = ((audio_channel[0].evtime % delta) << 8) / delta;
531: data0 = (data0 * (256 - ratio) + data0p * ratio) >> 8;
532: delta = audio_channel[1].per;
533: ratio = ((audio_channel[1].evtime % delta) << 8) / delta;
534: data1 = (data1 * (256 - ratio) + data1p * ratio) >> 8;
535: delta = audio_channel[2].per;
536: ratio = ((audio_channel[2].evtime % delta) << 8) / delta;
537: data1 += (data2 * (256 - ratio) + data2p * ratio) >> 8;
538: delta = audio_channel[3].per;
539: ratio = ((audio_channel[3].evtime % delta) << 8) / delta;
540: data0 += (data3 * (256 - ratio) + data3p * ratio) >> 8;
541: {
542: uae_u32 data = SBASEVAL16 (1) + data0;
543: FINISH_DATA (data, 16, 1);
544: put_sound_word_right (data);
545: }
546:
547: {
548: uae_u32 data = SBASEVAL16 (1) + data1;
549: FINISH_DATA (data, 16, 1);
550: put_sound_word_left (data);
551: }
1.1.1.5 root 552: check_sound_buffers ();
553: }
554:
1.1 root 555: #else
1.1.1.2 root 556: void sample16s_handler (void)
1.1 root 557: {
1.1.1.16! root 558: sample16_handler ();
1.1 root 559: }
1.1.1.16! root 560: static void sample16si_crux_handler (void)
1.1.1.6 root 561: {
1.1.1.16! root 562: sample16i_crux_handler ();
1.1.1.6 root 563: }
1.1.1.16! root 564: static void sample16si_rh_handler (void)
1.1.1.6 root 565: {
1.1.1.16! root 566: sample16i_rh_handler ();
1.1.1.6 root 567: }
1.1 root 568: #endif
569:
1.1.1.16! root 570: void switch_audio_interpol (void)
1.1 root 571: {
1.1.1.16! root 572: #if defined HAVE_8BIT_AUDIO_SUPPORT || defined HAVE_ULAW_AUDIO_SUPPORT
! 573: if (currprefs.sound_bits == 8)
! 574: /* only supported for 16-bit audio */
! 575: return;
! 576: #endif
1.1 root 577:
1.1.1.16! root 578: if (currprefs.sound_interpol == 0) {
! 579: changed_prefs.sound_interpol = 1;
! 580: write_log ("Interpol on: rh\n");
! 581: } else if (currprefs.sound_interpol == 1) {
! 582: changed_prefs.sound_interpol = 2;
! 583: write_log ("Interpol on: crux\n");
! 584: } else if (currprefs.sound_interpol == 2) {
! 585: changed_prefs.sound_interpol = 3;
! 586: write_log ("Interpol on: sinc\n");
1.1 root 587: } else {
1.1.1.16! root 588: changed_prefs.sound_interpol = 0;
! 589: write_log ("Interpol off\n");
1.1 root 590: }
1.1.1.16! root 591: return;
1.1 root 592: }
1.1.1.16! root 593:
1.1.1.7 root 594: void schedule_audio (void)
595: {
1.1.1.16! root 596: unsigned long best = MAX_EV;
1.1.1.7 root 597: int i;
598:
599: eventtab[ev_audio].active = 0;
600: eventtab[ev_audio].oldcycles = get_cycles ();
1.1.1.16! root 601: for (i = 0; i < 4; i++) {
1.1.1.7 root 602: struct audio_channel_data *cdp = audio_channel + i;
603:
1.1.1.16! root 604: if (cdp->evtime != MAX_EV) {
1.1.1.7 root 605: if (best > cdp->evtime) {
606: best = cdp->evtime;
607: eventtab[ev_audio].active = 1;
608: }
1.1.1.15 root 609: }
1.1.1.7 root 610: }
611: eventtab[ev_audio].evtime = get_cycles () + best;
612: }
613:
1.1.1.16! root 614: /*
! 615: * TODO: This function has been moved here from the audio back-end layer
! 616: * since it was common to all.
! 617: * Needs further cleaning up and a better name - or replacing entirely.
! 618: */
! 619: void update_sound (unsigned int freq)
! 620: {
! 621: if (obtainedfreq) {
! 622: if (0 /*is_vsync ()*/) {
! 623: if (currprefs.ntscmode)
! 624: scaled_sample_evtime = (unsigned long)(MAXHPOS_NTSC * MAXVPOS_NTSC * freq * CYCLE_UNIT + obtainedfreq - 1) / obtainedfreq;
! 625: else
! 626: scaled_sample_evtime = (unsigned long)(MAXHPOS_PAL * MAXVPOS_PAL * freq * CYCLE_UNIT + obtainedfreq - 1) / obtainedfreq;
! 627: } else {
! 628: scaled_sample_evtime = (unsigned long)(312.0 * 50 * CYCLE_UNIT / (obtainedfreq / 227.0));
! 629: }
! 630: }
! 631: }
! 632:
! 633: static void audio_handler (unsigned int nr)
1.1 root 634: {
635: struct audio_channel_data *cdp = audio_channel + nr;
636:
1.1.1.16! root 637: cdp->evtime = MAX_EV;
1.1 root 638: switch (cdp->state) {
639: case 0:
1.1.1.11 root 640: write_log ("Bug in sound code\n");
1.1 root 641: break;
642:
643: case 1:
644: /* We come here at the first hsync after DMA was turned on. */
1.1.1.7 root 645: cdp->evtime = maxhpos * CYCLE_UNIT;
1.1 root 646:
647: cdp->state = 5;
648: INTREQ(0x8000 | (0x80 << nr));
649: if (cdp->wlen != 1)
1.1.1.9 root 650: cdp->wlen = (cdp->wlen - 1) & 0xFFFF;
1.1.1.10 root 651: cdp->nextdat = chipmem_wget (cdp->pt);
1.1 root 652:
653: cdp->pt += 2;
654: break;
655:
656: case 5:
657: /* We come here at the second hsync after DMA was turned on. */
658: if (currprefs.produce_sound == 0)
1.1.1.7 root 659: cdp->per = PERIOD_MAX;
1.1 root 660:
1.1.1.2 root 661: cdp->evtime = cdp->per;
1.1 root 662: cdp->dat = cdp->nextdat;
1.1.1.5 root 663: cdp->last_sample = cdp->current_sample;
1.1 root 664: cdp->current_sample = (sample8_t)(cdp->dat >> 8);
665:
666: cdp->state = 2;
667: {
668: int audav = adkcon & (1 << nr);
669: int audap = adkcon & (16 << nr);
670: int napnav = (!audav && !audap) || audav;
671: if (napnav)
672: cdp->data_written = 2;
673: }
674: break;
675:
676: case 2:
677: /* We come here when a 2->3 transition occurs */
678: if (currprefs.produce_sound == 0)
1.1.1.7 root 679: cdp->per = PERIOD_MAX;
1.1 root 680:
1.1.1.5 root 681: cdp->last_sample = cdp->current_sample;
1.1 root 682: cdp->current_sample = (sample8_t)(cdp->dat & 0xFF);
1.1.1.2 root 683: cdp->evtime = cdp->per;
1.1 root 684:
685: cdp->state = 3;
686:
687: /* Period attachment? */
688: if (adkcon & (0x10 << nr)) {
689: if (cdp->intreq2 && cdp->dmaen)
1.1.1.9 root 690: INTREQ (0x8000 | (0x80 << nr));
1.1 root 691: cdp->intreq2 = 0;
692:
693: cdp->dat = cdp->nextdat;
694: if (cdp->dmaen)
695: cdp->data_written = 2;
696: if (nr < 3) {
697: if (cdp->dat == 0)
1.1.1.7 root 698: (cdp+1)->per = PERIOD_MAX;
699: else if (cdp->dat < maxhpos * CYCLE_UNIT / 2 && currprefs.produce_sound < 3)
700: (cdp+1)->per = maxhpos * CYCLE_UNIT / 2;
1.1 root 701: else
1.1.1.7 root 702: (cdp+1)->per = cdp->dat * CYCLE_UNIT;
1.1 root 703: }
704: }
705: break;
706:
707: case 3:
708: /* We come here when a 3->2 transition occurs */
709: if (currprefs.produce_sound == 0)
1.1.1.7 root 710: cdp->per = PERIOD_MAX;
1.1 root 711:
1.1.1.2 root 712: cdp->evtime = cdp->per;
1.1 root 713:
714: if ((INTREQR() & (0x80 << nr)) && !cdp->dmaen) {
715: cdp->state = 0;
1.1.1.16! root 716: cdp->evtime = MAX_EV;
1.1.1.5 root 717: cdp->last_sample = 0;
1.1 root 718: cdp->current_sample = 0;
719: break;
720: } else {
721: int audav = adkcon & (1 << nr);
722: int audap = adkcon & (16 << nr);
723: int napnav = (!audav && !audap) || audav;
724: cdp->state = 2;
725:
726: if ((cdp->intreq2 && cdp->dmaen && napnav)
727: || (napnav && !cdp->dmaen))
728: INTREQ(0x8000 | (0x80 << nr));
729: cdp->intreq2 = 0;
730:
731: cdp->dat = cdp->nextdat;
1.1.1.5 root 732: cdp->last_sample = cdp->current_sample;
1.1 root 733: cdp->current_sample = (sample8_t)(cdp->dat >> 8);
734:
735: if (cdp->dmaen && napnav)
736: cdp->data_written = 2;
737:
738: /* Volume attachment? */
739: if (audav) {
740: if (nr < 3) {
741: (cdp+1)->vol = cdp->dat;
742: #ifndef MULTIPLICATION_PROFITABLE
743: (cdp+1)->voltbl = sound_table[cdp->dat];
744: #endif
745: }
746: }
747: }
748: break;
749:
750: default:
751: cdp->state = 0;
752: break;
753: }
754: }
755:
1.1.1.16! root 756: static void audio_channel_enable_dma (struct audio_channel_data *cdp)
1.1.1.10 root 757: {
1.1.1.16! root 758: if (cdp->evtime == MAX_EV) {
1.1.1.10 root 759: cdp->state = 1;
760: cdp->pt = cdp->lc;
761: cdp->wper = cdp->per;
762: cdp->wlen = cdp->len;
763: cdp->data_written = 2;
764: cdp->evtime = eventtab[ev_hsync].evtime - get_cycles ();
765: }
766: }
767:
1.1.1.16! root 768: static void audio_channel_disable_dma (struct audio_channel_data *cdp)
1.1.1.10 root 769: {
770: if (cdp->state == 1 || cdp->state == 5) {
771: cdp->state = 0;
1.1.1.16! root 772: cdp->evtime = MAX_EV;
1.1.1.10 root 773: cdp->last_sample = 0;
774: cdp->current_sample = 0;
775: }
776: }
777:
1.1 root 778: void audio_reset (void)
779: {
1.1.1.8 root 780: int i;
1.1.1.16! root 781: struct audio_channel_data *cdp;
! 782:
1.1.1.8 root 783: if (savestate_state != STATE_RESTORE) {
1.1.1.16! root 784: for (i = 0; i < 4; i++) {
! 785: cdp = &audio_channel[i];
! 786: memset (cdp, 0, sizeof *audio_channel);
! 787: cdp->per = PERIOD_MAX;
! 788: cdp->vol = 0;
! 789: cdp->evtime = MAX_EV;
! 790: }
1.1.1.8 root 791: } else
792: for (i = 0; i < 4; i++)
793: audio_channel[i].dmaen = (dmacon & 0x200) && (dmacon & (1 << i));
794:
795: #ifndef MULTIPLICATION_PROFITABLE
1.1.1.13 root 796: for (i = 0; i < 4; i++)
1.1.1.16! root 797: audio_channel[i].voltbl = sound_table[audio_channel[i].vol];
1.1.1.8 root 798: #endif
1.1.1.2 root 799:
1.1.1.16! root 800: last_cycles = get_cycles ();
1.1.1.7 root 801: next_sample_evtime = scaled_sample_evtime;
1.1.1.8 root 802:
803: schedule_audio ();
1.1.1.16! root 804: events_schedule ();
1.1.1.2 root 805: }
806:
1.1.1.6 root 807: STATIC_INLINE int sound_prefs_changed (void)
1.1.1.2 root 808: {
809: return (changed_prefs.produce_sound != currprefs.produce_sound
1.1.1.13 root 810: || changed_prefs.sound_stereo != currprefs.sound_stereo
1.1.1.7 root 811: || changed_prefs.mixed_stereo != currprefs.mixed_stereo
1.1.1.9 root 812: || changed_prefs.sound_maxbsiz != currprefs.sound_maxbsiz
1.1.1.4 root 813: || changed_prefs.sound_freq != currprefs.sound_freq
1.1.1.16! root 814: || changed_prefs.sound_bits != currprefs.sound_bits
! 815: || changed_prefs.sound_interpol != currprefs.sound_interpol);
1.1.1.2 root 816: }
817:
818: void check_prefs_changed_audio (void)
819: {
1.1.1.6 root 820: if (sound_available && sound_prefs_changed ()) {
821: close_sound ();
1.1.1.2 root 822:
1.1.1.6 root 823: currprefs.produce_sound = changed_prefs.produce_sound;
1.1.1.13 root 824: currprefs.sound_stereo = changed_prefs.sound_stereo;
1.1.1.7 root 825: currprefs.mixed_stereo = changed_prefs.mixed_stereo;
1.1.1.6 root 826: currprefs.sound_bits = changed_prefs.sound_bits;
827: currprefs.sound_freq = changed_prefs.sound_freq;
1.1.1.16! root 828: currprefs.sound_interpol = changed_prefs.sound_interpol;
1.1.1.9 root 829: currprefs.sound_maxbsiz = changed_prefs.sound_maxbsiz;
1.1.1.6 root 830: if (currprefs.produce_sound >= 2) {
1.1.1.7 root 831: if (init_audio ()) {
832: last_cycles = get_cycles () - 1;
833: next_sample_evtime = scaled_sample_evtime;
1.1.1.6 root 834: } else
835: if (! sound_available) {
1.1.1.11 root 836: write_log ("Sound is not supported.\n");
1.1.1.6 root 837: } else {
1.1.1.11 root 838: write_log ("Sorry, can't initialize sound.\n");
1.1.1.6 root 839: currprefs.produce_sound = 0;
840: /* So we don't do this every frame */
841: changed_prefs.produce_sound = 0;
842: }
843: }
1.1.1.12 root 844: compute_vsynctime ();
1.1.1.2 root 845: }
1.1.1.6 root 846: /* Select the right interpolation method. */
847: if (sample_handler == sample16_handler
848: || sample_handler == sample16i_crux_handler
1.1.1.16! root 849: || sample_handler == sample16i_rh_handler
! 850: || sample_handler == sample16i_sinc_handler) {
1.1.1.6 root 851: sample_handler = (currprefs.sound_interpol == 0 ? sample16_handler
852: : currprefs.sound_interpol == 1 ? sample16i_rh_handler
1.1.1.16! root 853: : currprefs.sound_interpol == 2 ? sample16i_crux_handler
! 854: : sample16i_sinc_handler);
! 855: } else if (sample_handler == sample16s_handler
1.1.1.6 root 856: || sample_handler == sample16si_crux_handler
1.1.1.16! root 857: || sample_handler == sample16si_rh_handler
! 858: || sample_handler == sample16si_sinc_handler)
1.1.1.6 root 859: sample_handler = (currprefs.sound_interpol == 0 ? sample16s_handler
860: : currprefs.sound_interpol == 1 ? sample16si_rh_handler
1.1.1.16! root 861: : currprefs.sound_interpol == 2 ? sample16si_crux_handler
! 862: : sample16si_sinc_handler);
! 863: sample_prehandler = NULL;
! 864: if (sample_handler == sample16si_sinc_handler || sample_handler == sample16i_sinc_handler)
! 865: sample_prehandler = sinc_prehandler;
1.1.1.7 root 866: if (currprefs.produce_sound == 0) {
867: eventtab[ev_audio].active = 0;
868: events_schedule ();
869: }
1.1.1.2 root 870: }
871:
872: void update_audio (void)
873: {
874: unsigned long int n_cycles;
875:
1.1.1.8 root 876: if (currprefs.produce_sound == 0 || savestate_state == STATE_RESTORE)
1.1.1.2 root 877: return;
878:
1.1.1.7 root 879: n_cycles = get_cycles () - last_cycles;
1.1.1.2 root 880: for (;;) {
881: unsigned long int best_evtime = n_cycles + 1;
1.1.1.16! root 882: if (audio_channel[0].evtime != MAX_EV && best_evtime > audio_channel[0].evtime)
1.1.1.10 root 883: best_evtime = audio_channel[0].evtime;
1.1.1.16! root 884: if (audio_channel[1].evtime != MAX_EV && best_evtime > audio_channel[1].evtime)
1.1.1.10 root 885: best_evtime = audio_channel[1].evtime;
1.1.1.16! root 886: if (audio_channel[2].evtime != MAX_EV && best_evtime > audio_channel[2].evtime)
1.1.1.10 root 887: best_evtime = audio_channel[2].evtime;
1.1.1.16! root 888: if (audio_channel[3].evtime != MAX_EV && best_evtime > audio_channel[3].evtime)
1.1.1.10 root 889: best_evtime = audio_channel[3].evtime;
1.1.1.7 root 890: if (currprefs.produce_sound > 1 && best_evtime > next_sample_evtime)
1.1.1.2 root 891: best_evtime = next_sample_evtime;
892:
893: if (best_evtime > n_cycles)
894: break;
895:
1.1.1.16! root 896: if (audio_channel[0].evtime != MAX_EV)
! 897: audio_channel[0].evtime -= best_evtime;
! 898: if (audio_channel[1].evtime != MAX_EV)
! 899: audio_channel[1].evtime -= best_evtime;
! 900: if (audio_channel[2].evtime != MAX_EV)
! 901: audio_channel[2].evtime -= best_evtime;
! 902: if (audio_channel[3].evtime != MAX_EV)
! 903: audio_channel[3].evtime -= best_evtime;
1.1.1.2 root 904: n_cycles -= best_evtime;
1.1.1.16! root 905: if (currprefs.produce_sound > 1) {
! 906: next_sample_evtime -= best_evtime;
! 907: if (sample_prehandler)
! 908: sample_prehandler (best_evtime / CYCLE_UNIT);
! 909: if (next_sample_evtime == 0) {
! 910: next_sample_evtime = scaled_sample_evtime;
! 911: (*sample_handler) ();
! 912: }
1.1.1.2 root 913: }
1.1.1.16! root 914: if (audio_channel[0].evtime == 0)
1.1.1.2 root 915: audio_handler (0);
1.1.1.16! root 916: if (audio_channel[1].evtime == 0)
1.1.1.2 root 917: audio_handler (1);
1.1.1.16! root 918: if (audio_channel[2].evtime == 0)
1.1.1.2 root 919: audio_handler (2);
1.1.1.16! root 920: if (audio_channel[3].evtime == 0)
1.1.1.2 root 921: audio_handler (3);
922: }
1.1.1.7 root 923: last_cycles = get_cycles () - n_cycles;
924: }
925:
1.1.1.16! root 926: void update_audio_dmacon (void)
! 927: {
! 928: unsigned int i;
! 929: update_audio ();
! 930:
! 931: for (i = 0; i < 4; i++) {
! 932: struct audio_channel_data *cdp = audio_channel + i;
! 933: int chan_ena = (dmacon & 0x200) && (dmacon & (1<<i));
! 934: if (cdp->dmaen == chan_ena)
! 935: continue;
! 936: cdp->dmaen = chan_ena;
! 937: if (cdp->dmaen)
! 938: audio_channel_enable_dma (cdp);
! 939: else
! 940: audio_channel_disable_dma (cdp);
! 941: }
! 942: schedule_audio ();
! 943: }
! 944:
1.1.1.7 root 945: void audio_evhandler (void)
946: {
947: if (currprefs.produce_sound == 0)
948: abort ();
949:
950: update_audio ();
951: schedule_audio ();
1.1.1.2 root 952: }
953:
1.1.1.15 root 954: void audio_hsync (int dmaaction)
955: {
956: int nr;
957:
958: update_audio ();
959:
960: /* Sound data is fetched at the beginning of each line */
961: for (nr = 0; nr < 4; nr++) {
962: struct audio_channel_data *cdp = audio_channel + nr;
963:
964: if (cdp->data_written == 2) {
965: cdp->data_written = 0;
966: cdp->nextdat = chipmem_wget (cdp->pt);
967: cdp->pt += 2;
968: if (cdp->state == 2 || cdp->state == 3) {
969: if (cdp->wlen == 1) {
970: cdp->pt = cdp->lc;
971: cdp->wlen = cdp->len;
972: cdp->intreq2 = 1;
973: } else
974: cdp->wlen = (cdp->wlen - 1) & 0xFFFF;
975: }
976: }
977: }
978: }
979:
1.1.1.16! root 980: void AUDxDAT (unsigned int nr, uae_u16 v)
1.1.1.2 root 981: {
982: struct audio_channel_data *cdp = audio_channel + nr;
983:
1.1.1.7 root 984: if (currprefs.produce_sound == 0)
985: return;
986:
1.1.1.2 root 987: update_audio ();
988:
989: cdp->dat = v;
990: if (cdp->state == 0 && !(INTREQR() & (0x80 << nr))) {
991: cdp->state = 2;
992: INTREQ(0x8000 | (0x80 << nr));
993: /* data_written = 2 ???? */
994: cdp->evtime = cdp->per;
1.1.1.7 root 995: schedule_audio ();
996: events_schedule ();
1.1.1.2 root 997: }
998: }
999:
1.1.1.16! root 1000: void AUDxLCH (unsigned int nr, uae_u16 v)
1.1.1.2 root 1001: {
1002: update_audio ();
1003:
1004: audio_channel[nr].lc = (audio_channel[nr].lc & 0xffff) | ((uae_u32)v << 16);
1005: }
1006:
1.1.1.16! root 1007: void AUDxLCL (unsigned int nr, uae_u16 v)
1.1.1.2 root 1008: {
1009: update_audio ();
1010:
1011: audio_channel[nr].lc = (audio_channel[nr].lc & ~0xffff) | (v & 0xFFFE);
1012: }
1013:
1.1.1.16! root 1014: void AUDxPER (unsigned int nr, uae_u16 v)
1.1.1.2 root 1015: {
1.1.1.7 root 1016: unsigned long per = v * CYCLE_UNIT;
1.1.1.2 root 1017: update_audio ();
1018:
1.1.1.7 root 1019: if (per == 0)
1020: per = PERIOD_MAX;
1.1.1.2 root 1021:
1.1.1.7 root 1022: if (per < maxhpos * CYCLE_UNIT / 2 && currprefs.produce_sound < 3)
1023: per = maxhpos * CYCLE_UNIT / 2;
1.1.1.16! root 1024: /* the sinc code registers paula output state changes, but has a finite
! 1025: * buffer in which to do so. Hence, we forbid very low values; this should
! 1026: * only limit the accurate rendering of supersonic sounds, which are
! 1027: * filtered away on the sinc output path anyway. */
! 1028: if (currprefs.produce_sound == 3 && sample_handler == sample16si_sinc_handler && per < MIN_ALLOWED_PERIOD * CYCLE_UNIT)
! 1029: per = MIN_ALLOWED_PERIOD * CYCLE_UNIT;
1.1.1.2 root 1030:
1.1.1.16! root 1031: if (audio_channel[nr].per == PERIOD_MAX && per != PERIOD_MAX
! 1032: && audio_channel[nr].evtime != MAX_EV) {
1.1.1.8 root 1033: audio_channel[nr].evtime = CYCLE_UNIT;
1.1.1.9 root 1034: if (currprefs.produce_sound > 0) {
1035: schedule_audio ();
1036: events_schedule ();
1037: }
1.1.1.8 root 1038: }
1.1.1.16! root 1039:
1.1.1.7 root 1040: audio_channel[nr].per = per;
1.1.1.2 root 1041: }
1042:
1.1.1.16! root 1043: void AUDxLEN (unsigned int nr, uae_u16 v)
1.1.1.2 root 1044: {
1045: update_audio ();
1046: audio_channel[nr].len = v;
1047: }
1048:
1.1.1.16! root 1049: void AUDxVOL (unsigned int nr, uae_u16 v)
1.1.1.2 root 1050: {
1051: int v2 = v & 64 ? 63 : v & 63;
1052:
1053: update_audio ();
1054:
1055: audio_channel[nr].vol = v2;
1056: #ifndef MULTIPLICATION_PROFITABLE
1057: audio_channel[nr].voltbl = sound_table[v2];
1058: #endif
1.1 root 1059: }
1060:
1.1.1.15 root 1061: void update_adkmasks (void)
1062: {
1063: unsigned long t;
1064:
1065: t = adkcon | (adkcon >> 4);
1066: audio_channel[0].adk_mask = (((t >> 0) & 1) - 1);
1067: audio_channel[1].adk_mask = (((t >> 1) & 1) - 1);
1068: audio_channel[2].adk_mask = (((t >> 2) & 1) - 1);
1069: audio_channel[3].adk_mask = (((t >> 3) & 1) - 1);
1070: }
1071:
1.1.1.7 root 1072: int init_audio (void)
1.1 root 1073: {
1.1.1.16! root 1074: int result = init_sound ();
! 1075: update_sound (vblank_hz);
! 1076: return result;
1.1.1.7 root 1077: }
1078:
1.1.1.8 root 1079: /* audio save/restore code FIXME: not working correctly */
1080: /* help needed */
1081:
1.1.1.16! root 1082: const uae_u8 *restore_audio (int i, const uae_u8 *src)
1.1.1.8 root 1083: {
1084: struct audio_channel_data *acd;
1085: uae_u16 p;
1086:
1087: acd = audio_channel + i;
1088: acd->state = restore_u8 ();
1089: acd->vol = restore_u8 ();
1090: acd->intreq2 = restore_u8 ();
1091: acd->data_written = restore_u8 ();
1092: acd->len = restore_u16 ();
1093: acd->wlen = restore_u16 ();
1094: p = restore_u16 ();
1095: acd->per = p ? p * CYCLE_UNIT : PERIOD_MAX;
1096: p = restore_u16 ();
1097: acd->wper = p ? p * CYCLE_UNIT : PERIOD_MAX;
1098: acd->lc = restore_u32 ();
1099: acd->pt = restore_u32 ();
1100: acd->evtime = restore_u32 ();
1101:
1102: return src;
1103: }
1104:
1.1.1.15 root 1105: uae_u8 *save_audio (int i, int *len)
1.1.1.8 root 1106: {
1107: struct audio_channel_data *acd;
1108: uae_u8 *dst = malloc (100);
1109: uae_u8 *dstbak = dst;
1110: uae_u16 p;
1111:
1112: acd = audio_channel + i;
1113: save_u8 ((uae_u8)acd->state);
1114: save_u8 (acd->vol);
1115: save_u8 (acd->intreq2);
1116: save_u8 (acd->data_written);
1117: save_u16 (acd->len);
1118: save_u16 (acd->wlen);
1119: p = acd->per == PERIOD_MAX ? 0 : acd->per / CYCLE_UNIT;
1120: save_u16 (p);
1121: p = acd->per == PERIOD_MAX ? 0 : acd->wper / CYCLE_UNIT;
1122: save_u16 (p);
1123: save_u32 (acd->lc);
1124: save_u32 (acd->pt);
1125: save_u32 (acd->evtime);
1126: *len = dst - dstbak;
1127: return dstbak;
1128: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.