|
|
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:
1.1.1.17! root 17: #include <math.h>
! 18:
1.1 root 19: #include "options.h"
20: #include "memory.h"
21: #include "custom.h"
1.1.1.7 root 22: #include "newcpu.h"
23: #include "autoconf.h"
1.1 root 24: #include "gensound.h"
25: #include "sounddep/sound.h"
26: #include "events.h"
27: #include "audio.h"
1.1.1.8 root 28: #include "savestate.h"
1.1.1.16 root 29: #include "sinctable.h"
30: #include "gui.h"
31:
32: #define MAX_EV ~0ul
1.1 root 33:
1.1.1.16 root 34: /* periods less than this value are replaced by this value. */
35: #define MIN_ALLOWED_PERIOD 16
36: /* reserve ~20 extra slots in sinc queue for cpu volume or some such updates
37: * even at maximum period. This avoids sinc queue overflow on games like
38: * battle squadron that write these low period values and do cpu-based
39: * updates on paula registers, probably volume. */
40: #define NUMBER_OF_CPU_UPDATES_ALLOWED 20
41:
42: #define SINC_QUEUE_LENGTH (SINC_QUEUE_MAX_AGE / MIN_ALLOWED_PERIOD + NUMBER_OF_CPU_UPDATES_ALLOWED)
43:
44: typedef struct {
1.1.1.17! root 45: int age, output;
1.1.1.16 root 46: } sinc_queue_t;
47:
48: struct audio_channel_data {
49: unsigned long adk_mask;
50: unsigned long evtime;
51: unsigned long per;
52: uae_u8 dmaen, intreq2, data_written;
53: uaecptr lc, pt;
54: int state, wper;
55: unsigned int wlen;
56: int current_sample, last_sample;
57: int vol;
58: int *voltbl;
59: uae_u16 dat, nextdat, len;
1.1.1.17! root 60: int sample_accum, sample_accum_time;
1.1.1.16 root 61: int sinc_output_state;
62: sinc_queue_t sinc_queue[SINC_QUEUE_LENGTH];
63: int sinc_queue_length;
64: };
65:
66: static struct audio_channel_data audio_channel[4];
1.1.1.2 root 67: int sound_available = 0;
1.1 root 68: int sound_table[64][256];
1.1.1.2 root 69: void (*sample_handler) (void);
1.1.1.16 root 70: static void (*sample_prehandler) (unsigned long best_evtime);
1.1.1.7 root 71:
1.1.1.16 root 72: static unsigned long scaled_sample_evtime;
1.1.1.2 root 73: static unsigned long last_cycles, next_sample_evtime;
1.1 root 74:
1.1.1.16 root 75: unsigned int obtainedfreq;
76:
1.1.1.2 root 77: void init_sound_table16 (void)
1.1 root 78: {
79: int i,j;
80:
81: for (i = 0; i < 256; i++)
82: for (j = 0; j < 64; j++)
1.1.1.17! root 83: sound_table[j][i] = j * (uae_s8)i * (get_audio_ismono () ? 1 : 2);
1.1 root 84: }
85:
86: #ifdef MULTIPLICATION_PROFITABLE
87: typedef uae_s8 sample8_t;
88: #define DO_CHANNEL_1(v, c) do { (v) *= audio_channel[c].vol; } while (0)
89: #define SBASEVAL16(logn) ((logn) == 1 ? SOUND16_BASE_VAL >> 1 : SOUND16_BASE_VAL)
1.1.1.17! root 90: #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 91: #else
92: typedef uae_u8 sample8_t;
93: #define DO_CHANNEL_1(v, c) do { (v) = audio_channel[c].voltbl[(v)]; } while (0)
94: #define SBASEVAL16(logn) SOUND16_BASE_VAL
1.1.1.17! root 95: #define FINISH_DATA(data, b, logn)
1.1 root 96: #endif
97:
1.1.1.17! root 98: static uae_u32 right_word_saved[SOUND_MAX_DELAY_BUFFER];
! 99: static uae_u32 left_word_saved[SOUND_MAX_DELAY_BUFFER];
1.1.1.7 root 100: static int saved_ptr;
1.1 root 101:
1.1.1.17! root 102: static int mixed_on, mixed_stereo_size, mixed_mul1, mixed_mul2;
! 103: static int led_filter_forced, sound_use_filter, sound_use_filter_sinc, led_filter_on;
! 104:
! 105: /* denormals are very small floating point numbers that force FPUs into slow
! 106: mode. All lowpass filters using floats are suspectible to denormals unless
! 107: a small offset is added to avoid very small floating point numbers. */
! 108: #define DENORMAL_OFFSET (1E-10)
! 109:
! 110: static struct filter_state {
! 111: float rc1, rc2, rc3, rc4, rc5;
! 112: } sound_filter_state[4];
! 113:
! 114: static float a500e_filter1_a0;
! 115: static float a500e_filter2_a0;
! 116: static float filter_a0; /* a500 and a1200 use the same */
! 117:
! 118: enum {
! 119: FILTER_NONE = 0,
! 120: FILTER_MODEL_A500,
! 121: FILTER_MODEL_A1200
! 122: };
! 123:
! 124: /* Amiga has two separate filtering circuits per channel, a static RC filter
! 125: * on A500 and the LED filter. This code emulates both.
! 126: *
! 127: * The Amiga filtering circuitry depends on Amiga model. Older Amigas seem
! 128: * to have a 6 dB/oct RC filter with cutoff frequency such that the -6 dB
! 129: * point for filter is reached at 6 kHz, while newer Amigas have no filtering.
! 130: *
! 131: * The LED filter is complicated, and we are modelling it with a pair of
! 132: * RC filters, the other providing a highboost. The LED starts to cut
! 133: * into signal somewhere around 5-6 kHz, and there's some kind of highboost
! 134: * in effect above 12 kHz. Better measurements are required.
! 135: *
! 136: * The current filtering should be accurate to 2 dB with the filter on,
! 137: * and to 1 dB with the filter off.
! 138: */
! 139:
! 140: static int filter(int input, struct filter_state *fs)
! 141: {
! 142: int o;
! 143: float normal_output, led_output;
! 144:
! 145: input = (uae_s16)input;
! 146: switch (sound_use_filter) {
! 147: case FILTER_NONE:
! 148: return input;
! 149: case FILTER_MODEL_A500:
! 150: fs->rc1 = a500e_filter1_a0 * input + (1 - a500e_filter1_a0) * fs->rc1 + DENORMAL_OFFSET;
! 151: fs->rc2 = a500e_filter2_a0 * fs->rc1 + (1-a500e_filter2_a0) * fs->rc2;
! 152: normal_output = fs->rc2;
! 153:
! 154: fs->rc3 = filter_a0 * normal_output + (1 - filter_a0) * fs->rc3;
! 155: fs->rc4 = filter_a0 * fs->rc3 + (1 - filter_a0) * fs->rc4;
! 156: fs->rc5 = filter_a0 * fs->rc4 + (1 - filter_a0) * fs->rc5;
! 157:
! 158: led_output = fs->rc5;
! 159: break;
! 160:
! 161: case FILTER_MODEL_A1200:
! 162: normal_output = input;
! 163:
! 164: fs->rc2 = filter_a0 * normal_output + (1 - filter_a0) * fs->rc2 + DENORMAL_OFFSET;
! 165: fs->rc3 = filter_a0 * fs->rc2 + (1 - filter_a0) * fs->rc3;
! 166: fs->rc4 = filter_a0 * fs->rc3 + (1 - filter_a0) * fs->rc4;
! 167:
! 168: led_output = fs->rc4;
! 169: break;
! 170: }
! 171:
! 172: if (led_filter_on)
! 173: o = led_output;
! 174: else
! 175: o = normal_output;
! 176:
! 177: if (o > 32767)
! 178: o = 32767;
! 179: else if (o < -32768)
! 180: o = -32768;
! 181:
! 182: return o;
! 183: }
! 184:
! 185: /* This computes the 1st order low-pass filter term b0.
! 186: * The a1 term is 1.0 - b0. The center frequency marks the -3 dB point. */
! 187: #ifndef M_PI
! 188: #define M_PI 3.14159265358979323846
! 189: #endif
! 190: static float rc_calculate_a0 (int sample_rate, int cutoff_freq)
! 191: {
! 192: float omega;
! 193: /* The BLT correction formula below blows up if the cutoff is above nyquist. */
! 194: if (cutoff_freq >= sample_rate / 2)
! 195: return 1.0;
! 196:
! 197: omega = 2 * M_PI * cutoff_freq / sample_rate;
! 198: /* Compensate for the bilinear transformation. This allows us to specify the
! 199: * stop frequency more exactly, but the filter becomes less steep further
! 200: * from stopband. */
! 201: omega = tan (omega / 2) * 2;
! 202: return 1 / (1 + 1 / omega);
! 203: }
! 204:
! 205: /* Always put the right word before the left word. */
! 206:
1.1.1.7 root 207: STATIC_INLINE void put_sound_word_right (uae_u32 w)
1.1 root 208: {
1.1.1.17! root 209: if (mixed_on) {
1.1.1.7 root 210: right_word_saved[saved_ptr] = w;
211: return;
1.1 root 212: }
213:
1.1.1.7 root 214: PUT_SOUND_WORD_RIGHT (w);
1.1 root 215: }
216:
1.1.1.7 root 217: STATIC_INLINE void put_sound_word_left (uae_u32 w)
1.1.1.5 root 218: {
1.1.1.17! root 219: if (mixed_on) {
1.1.1.7 root 220: uae_u32 rold, lold, rnew, lnew, tmp;
1.1.1.5 root 221:
1.1.1.7 root 222: left_word_saved[saved_ptr] = w;
223: lnew = w - SOUND16_BASE_VAL;
224: rnew = right_word_saved[saved_ptr] - SOUND16_BASE_VAL;
1.1.1.5 root 225:
1.1.1.17! root 226: saved_ptr = (saved_ptr + 1) & mixed_stereo_size;
! 227:
1.1.1.7 root 228: lold = left_word_saved[saved_ptr] - SOUND16_BASE_VAL;
1.1.1.17! root 229: tmp = (rnew * mixed_mul2 + lold * mixed_mul1) / MIXED_STEREO_SCALE;
1.1.1.7 root 230: tmp += SOUND16_BASE_VAL;
231: PUT_SOUND_WORD_RIGHT (tmp);
1.1.1.5 root 232:
1.1.1.7 root 233: rold = right_word_saved[saved_ptr] - SOUND16_BASE_VAL;
1.1.1.17! root 234: w = (lnew * mixed_mul2 + rold * mixed_mul1) / MIXED_STEREO_SCALE;
1.1.1.7 root 235: }
236: PUT_SOUND_WORD_LEFT (w);
237: }
1.1.1.5 root 238:
1.1.1.7 root 239: #define DO_CHANNEL(v, c) do { (v) &= audio_channel[c].adk_mask; data += v; } while (0);
1.1.1.5 root 240:
1.1.1.17! root 241: static void anti_prehandler (unsigned long best_evtime)
! 242: {
! 243: int i, output;
! 244: struct audio_channel_data *acd;
! 245:
! 246: /* Handle accumulator antialiasiation */
! 247: for (i = 0; i < 4; i++) {
! 248: acd = &audio_channel[i];
! 249: output = (acd->current_sample * acd->vol) & acd->adk_mask;
! 250: acd->sample_accum += output * best_evtime;
! 251: acd->sample_accum_time += best_evtime;
! 252: }
! 253: }
! 254:
! 255: STATIC_INLINE void samplexx_anti_handler (int *datasp)
! 256: {
! 257: int i;
! 258: for (i = 0; i < 4; i++) {
! 259: datasp[i] = audio_channel[i].sample_accum_time ? (audio_channel[i].sample_accum / audio_channel[i].sample_accum_time) : 0;
! 260: audio_channel[i].sample_accum = 0;
! 261: audio_channel[i].sample_accum_time = 0;
! 262:
! 263: }
! 264: }
! 265:
1.1.1.16 root 266: static void sinc_prehandler (unsigned long best_evtime)
267: {
268: int i, j, output;
269: struct audio_channel_data *acd;
270:
271: for (i = 0; i < 4; i++) {
272: acd = &audio_channel[i];
273: output = (acd->current_sample * acd->vol) & acd->adk_mask;
274:
275: /* age the sinc queue and truncate it when necessary */
276: for (j = 0; j < acd->sinc_queue_length; j += 1) {
277: acd->sinc_queue[j].age += best_evtime;
278: if (acd->sinc_queue[j].age >= SINC_QUEUE_MAX_AGE) {
279: acd->sinc_queue_length = j;
280: break;
281: }
282: }
283: /* if output state changes, record the state change and also
284: * write data into sinc queue for mixing in the BLEP */
285: if (acd->sinc_output_state != output) {
286: if (acd->sinc_queue_length > SINC_QUEUE_LENGTH - 1) {
287: write_log ("warning: sinc queue truncated. Last age: %d.\n",
288: acd->sinc_queue[SINC_QUEUE_LENGTH-1].age);
289: acd->sinc_queue_length = SINC_QUEUE_LENGTH - 1;
290: }
291: /* make room for new and add the new value */
292: memmove (&acd->sinc_queue[1], &acd->sinc_queue[0],
293: sizeof(acd->sinc_queue[0]) * acd->sinc_queue_length);
294: acd->sinc_queue_length += 1;
295: acd->sinc_queue[0].age = best_evtime;
296: acd->sinc_queue[0].output = output - acd->sinc_output_state;
297: acd->sinc_output_state = output;
298: }
299: }
300: }
301:
302:
303: /* this interpolator performs BLEP mixing (bleps are shaped like integrated sinc
304: * functions) with a type of BLEP that matches the filtering configuration. */
305: STATIC_INLINE void samplexx_sinc_handler (int *datasp)
306: {
307: int i, n;
308: int const *winsinc;
309:
310: if (sound_use_filter_sinc) {
311: n = (sound_use_filter_sinc == FILTER_MODEL_A500) ? 0 : 2;
312: if (led_filter_on)
313: n += 1;
314: } else {
315: n = 4;
316: }
317: winsinc = winsinc_integral[n];
318:
319: for (i = 0; i < 4; i += 1) {
320: int j, v;
321: struct audio_channel_data *acd = &audio_channel[i];
322: /* The sum rings with harmonic components up to infinity... */
323: int sum = acd->sinc_output_state << 17;
324: /* ...but we cancel them through mixing in BLEPs instead */
325: for (j = 0; j < acd->sinc_queue_length; j += 1)
326: sum -= winsinc[acd->sinc_queue[j].age] * acd->sinc_queue[j].output;
327: v = sum >> 17;
328: if (v > 32767)
329: v = 32767;
330: else if (v < -32768)
331: v = -32768;
332: datasp[i] = v;
333: }
334: }
335:
336: static void sample16i_sinc_handler (void)
337: {
338: int datas[4], data1;
339:
340: samplexx_sinc_handler (datas);
341: data1 = datas[0] + datas[3] + datas[1] + datas[2];
342: FINISH_DATA (data1, 16, 2);
343: PUT_SOUND_WORD (data1);
344: check_sound_buffers ();
345: }
346:
1.1.1.7 root 347: void sample16_handler (void)
348: {
1.1.1.13 root 349: uae_u32 data0 = audio_channel[0].current_sample;
350: uae_u32 data1 = audio_channel[1].current_sample;
351: uae_u32 data2 = audio_channel[2].current_sample;
352: uae_u32 data3 = audio_channel[3].current_sample;
353: DO_CHANNEL_1 (data0, 0);
354: DO_CHANNEL_1 (data1, 1);
355: DO_CHANNEL_1 (data2, 2);
356: DO_CHANNEL_1 (data3, 3);
357: data0 &= audio_channel[0].adk_mask;
358: data1 &= audio_channel[1].adk_mask;
359: data2 &= audio_channel[2].adk_mask;
360: data3 &= audio_channel[3].adk_mask;
361: data0 += data1;
362: data0 += data2;
363: data0 += data3;
364: {
365: uae_u32 data = SBASEVAL16(2) + data0;
366: FINISH_DATA (data, 16, 2);
1.1.1.17! root 367: if (sound_use_filter)
! 368: data = filter (data, &sound_filter_state[0]);
1.1.1.13 root 369: PUT_SOUND_WORD (data);
1.1.1.5 root 370: }
371: check_sound_buffers ();
372: }
373:
1.1.1.17! root 374: /* This interpolator examines sample points when Paula switches the output
! 375: * voltage and computes the average of Paula's output */
! 376: static void sample16i_anti_handler (void)
! 377: {
! 378: int datas[4], data1;
! 379:
! 380: samplexx_anti_handler (datas);
! 381: data1 = datas[0] + datas[3] + datas[1] + datas[2];
! 382: FINISH_DATA (data1, 16, 2);
! 383: if (sound_use_filter)
! 384: data1 = filter (data1, &sound_filter_state[0]);
! 385: PUT_SOUND_WORD (data1);
! 386: check_sound_buffers ();
! 387: }
! 388:
1.1.1.16 root 389: static void sample16i_rh_handler (void)
1.1.1.6 root 390: {
1.1.1.13 root 391: unsigned long delta, ratio;
392:
393: uae_u32 data0 = audio_channel[0].current_sample;
394: uae_u32 data1 = audio_channel[1].current_sample;
395: uae_u32 data2 = audio_channel[2].current_sample;
396: uae_u32 data3 = audio_channel[3].current_sample;
397: uae_u32 data0p = audio_channel[0].last_sample;
398: uae_u32 data1p = audio_channel[1].last_sample;
399: uae_u32 data2p = audio_channel[2].last_sample;
400: uae_u32 data3p = audio_channel[3].last_sample;
401: DO_CHANNEL_1 (data0, 0);
402: DO_CHANNEL_1 (data1, 1);
403: DO_CHANNEL_1 (data2, 2);
404: DO_CHANNEL_1 (data3, 3);
405: DO_CHANNEL_1 (data0p, 0);
406: DO_CHANNEL_1 (data1p, 1);
407: DO_CHANNEL_1 (data2p, 2);
408: DO_CHANNEL_1 (data3p, 3);
1.1.1.6 root 409:
1.1.1.13 root 410: data0 &= audio_channel[0].adk_mask;
411: data0p &= audio_channel[0].adk_mask;
412: data1 &= audio_channel[1].adk_mask;
413: data1p &= audio_channel[1].adk_mask;
414: data2 &= audio_channel[2].adk_mask;
415: data2p &= audio_channel[2].adk_mask;
416: data3 &= audio_channel[3].adk_mask;
417: data3p &= audio_channel[3].adk_mask;
1.1.1.6 root 418:
1.1.1.13 root 419: /* linear interpolation and summing up... */
420: delta = audio_channel[0].per;
421: ratio = ((audio_channel[0].evtime % delta) << 8) / delta;
422: data0 = (data0 * (256 - ratio) + data0p * ratio) >> 8;
423: delta = audio_channel[1].per;
424: ratio = ((audio_channel[1].evtime % delta) << 8) / delta;
425: data0 += (data1 * (256 - ratio) + data1p * ratio) >> 8;
426: delta = audio_channel[2].per;
427: ratio = ((audio_channel[2].evtime % delta) << 8) / delta;
428: data0 += (data2 * (256 - ratio) + data2p * ratio) >> 8;
429: delta = audio_channel[3].per;
430: ratio = ((audio_channel[3].evtime % delta) << 8) / delta;
431: data0 += (data3 * (256 - ratio) + data3p * ratio) >> 8;
1.1.1.6 root 432:
1.1.1.13 root 433: {
434: uae_u32 data = SBASEVAL16(2) + data0;
435: FINISH_DATA (data, 16, 2);
1.1.1.17! root 436: if (sound_use_filter)
! 437: data = filter (data, &sound_filter_state[0]);
1.1.1.13 root 438: PUT_SOUND_WORD (data);
1.1.1.6 root 439: }
1.1.1.13 root 440:
441: check_sound_buffers ();
1.1.1.7 root 442: }
1.1.1.6 root 443:
1.1.1.16 root 444: static void sample16i_crux_handler (void)
1.1.1.7 root 445: {
1.1.1.13 root 446: uae_u32 data0 = audio_channel[0].current_sample;
447: uae_u32 data1 = audio_channel[1].current_sample;
448: uae_u32 data2 = audio_channel[2].current_sample;
449: uae_u32 data3 = audio_channel[3].current_sample;
450: uae_u32 data0p = audio_channel[0].last_sample;
451: uae_u32 data1p = audio_channel[1].last_sample;
452: uae_u32 data2p = audio_channel[2].last_sample;
453: uae_u32 data3p = audio_channel[3].last_sample;
454: DO_CHANNEL_1 (data0, 0);
455: DO_CHANNEL_1 (data1, 1);
456: DO_CHANNEL_1 (data2, 2);
457: DO_CHANNEL_1 (data3, 3);
458: DO_CHANNEL_1 (data0p, 0);
459: DO_CHANNEL_1 (data1p, 1);
460: DO_CHANNEL_1 (data2p, 2);
461: DO_CHANNEL_1 (data3p, 3);
462:
463: data0 &= audio_channel[0].adk_mask;
464: data0p &= audio_channel[0].adk_mask;
465: data1 &= audio_channel[1].adk_mask;
466: data1p &= audio_channel[1].adk_mask;
467: data2 &= audio_channel[2].adk_mask;
468: data2p &= audio_channel[2].adk_mask;
469: data3 &= audio_channel[3].adk_mask;
470: data3p &= audio_channel[3].adk_mask;
471:
1.1.1.15 root 472: {
1.1.1.13 root 473: struct audio_channel_data *cdp;
474: unsigned long ratio, ratio1;
1.1.1.7 root 475: #define INTERVAL (scaled_sample_evtime * 3)
1.1.1.13 root 476: cdp = audio_channel + 0;
477: ratio1 = cdp->per - cdp->evtime;
478: ratio = (ratio1 << 12) / INTERVAL;
479: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
480: ratio = 4096;
481: data0 = (data0 * ratio + data0p * (4096 - ratio)) >> 12;
482:
483: cdp = audio_channel + 1;
484: ratio1 = cdp->per - cdp->evtime;
485: ratio = (ratio1 << 12) / INTERVAL;
486: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
487: ratio = 4096;
488: data1 = (data1 * ratio + data1p * (4096 - ratio)) >> 12;
489:
490: cdp = audio_channel + 2;
491: ratio1 = cdp->per - cdp->evtime;
492: ratio = (ratio1 << 12) / INTERVAL;
493: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
494: ratio = 4096;
495: data2 = (data2 * ratio + data2p * (4096 - ratio)) >> 12;
496:
497: cdp = audio_channel + 3;
498: ratio1 = cdp->per - cdp->evtime;
499: ratio = (ratio1 << 12) / INTERVAL;
500: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
501: ratio = 4096;
502: data3 = (data3 * ratio + data3p * (4096 - ratio)) >> 12;
503: }
504: data1 += data2;
505: data0 += data3;
506: data0 += data1;
507: {
508: uae_u32 data = SBASEVAL16(2) + data0;
509: FINISH_DATA (data, 16, 2);
1.1.1.17! root 510: if (sound_use_filter)
! 511: data = filter (data, &sound_filter_state[0]);
1.1.1.13 root 512: PUT_SOUND_WORD (data);
1.1.1.7 root 513: }
1.1.1.6 root 514: check_sound_buffers ();
515: }
516:
1.1.1.16 root 517: #ifdef HAVE_STEREO_SUPPORT
1.1.1.17! root 518: static void sample16si_anti_handler (void)
! 519: {
! 520: int datas[4], data1, data2;
! 521:
! 522: samplexx_anti_handler (datas);
! 523: data1 = datas[0] + datas[3];
! 524: data2 = datas[1] + datas[2];
! 525: FINISH_DATA (data1, 16, 1);
! 526: if (sound_use_filter)
! 527: data1 = filter (data1, &sound_filter_state[0]);
! 528: put_sound_word_right (data1);
! 529: FINISH_DATA (data2, 16, 1);
! 530: if (sound_use_filter)
! 531: data2 = filter (data2, &sound_filter_state[1]);
! 532: put_sound_word_left (data2);
! 533: check_sound_buffers ();
! 534: }
! 535:
1.1.1.16 root 536: static void sample16si_sinc_handler (void)
1.1 root 537: {
1.1.1.16 root 538: int datas[4], data1, data2;
1.1 root 539:
1.1.1.16 root 540: samplexx_sinc_handler (datas);
541: data1 = datas[0] + datas[3];
542: data2 = datas[1] + datas[2];
543: FINISH_DATA (data1, 16, 1);
1.1.1.17! root 544: put_sound_word_right (data1);
1.1.1.16 root 545: FINISH_DATA (data2, 16, 1);
1.1.1.17! root 546: put_sound_word_left (data2);
1.1 root 547: check_sound_buffers ();
548: }
549:
1.1.1.2 root 550: void sample16s_handler (void)
1.1 root 551: {
1.1.1.13 root 552: uae_u32 data0 = audio_channel[0].current_sample;
553: uae_u32 data1 = audio_channel[1].current_sample;
554: uae_u32 data2 = audio_channel[2].current_sample;
555: uae_u32 data3 = audio_channel[3].current_sample;
556: DO_CHANNEL_1 (data0, 0);
557: DO_CHANNEL_1 (data1, 1);
558: DO_CHANNEL_1 (data2, 2);
559: DO_CHANNEL_1 (data3, 3);
560:
561: data0 &= audio_channel[0].adk_mask;
562: data1 &= audio_channel[1].adk_mask;
563: data2 &= audio_channel[2].adk_mask;
564: data3 &= audio_channel[3].adk_mask;
1.1.1.15 root 565:
1.1.1.13 root 566: data0 += data3;
567: {
568: uae_u32 data = SBASEVAL16(1) + data0;
569: FINISH_DATA (data, 16, 1);
1.1.1.17! root 570: if (sound_use_filter)
! 571: data = filter (data, &sound_filter_state[0]);
1.1.1.13 root 572: put_sound_word_right (data);
573: }
1.1 root 574:
1.1.1.13 root 575: data1 += data2;
576: {
1.1.1.15 root 577: uae_u32 data = SBASEVAL16(1) + data1;
1.1.1.13 root 578: FINISH_DATA (data, 16, 1);
1.1.1.17! root 579: if (sound_use_filter)
! 580: data = filter (data, &sound_filter_state[1]);
1.1.1.13 root 581: put_sound_word_left (data);
1.1 root 582: }
1.1.1.7 root 583:
1.1 root 584: check_sound_buffers ();
585: }
586:
1.1.1.16 root 587: static void sample16si_crux_handler (void)
1.1.1.5 root 588: {
1.1.1.13 root 589: uae_u32 data0 = audio_channel[0].current_sample;
590: uae_u32 data1 = audio_channel[1].current_sample;
591: uae_u32 data2 = audio_channel[2].current_sample;
592: uae_u32 data3 = audio_channel[3].current_sample;
593: uae_u32 data0p = audio_channel[0].last_sample;
594: uae_u32 data1p = audio_channel[1].last_sample;
595: uae_u32 data2p = audio_channel[2].last_sample;
596: uae_u32 data3p = audio_channel[3].last_sample;
597:
598: DO_CHANNEL_1 (data0, 0);
599: DO_CHANNEL_1 (data1, 1);
600: DO_CHANNEL_1 (data2, 2);
601: DO_CHANNEL_1 (data3, 3);
602: DO_CHANNEL_1 (data0p, 0);
603: DO_CHANNEL_1 (data1p, 1);
604: DO_CHANNEL_1 (data2p, 2);
605: DO_CHANNEL_1 (data3p, 3);
606:
607: data0 &= audio_channel[0].adk_mask;
608: data0p &= audio_channel[0].adk_mask;
609: data1 &= audio_channel[1].adk_mask;
610: data1p &= audio_channel[1].adk_mask;
611: data2 &= audio_channel[2].adk_mask;
612: data2p &= audio_channel[2].adk_mask;
613: data3 &= audio_channel[3].adk_mask;
614: data3p &= audio_channel[3].adk_mask;
615:
1.1.1.15 root 616: {
1.1.1.13 root 617: struct audio_channel_data *cdp;
618: unsigned long ratio, ratio1;
1.1.1.7 root 619: #define INTERVAL (scaled_sample_evtime * 3)
1.1.1.13 root 620: cdp = audio_channel + 0;
621: ratio1 = cdp->per - cdp->evtime;
622: ratio = (ratio1 << 12) / INTERVAL;
623: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
624: ratio = 4096;
625: data0 = (data0 * ratio + data0p * (4096 - ratio)) >> 12;
626:
627: cdp = audio_channel + 1;
628: ratio1 = cdp->per - cdp->evtime;
629: ratio = (ratio1 << 12) / INTERVAL;
630: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
631: ratio = 4096;
632: data1 = (data1 * ratio + data1p * (4096 - ratio)) >> 12;
633:
634: cdp = audio_channel + 2;
635: ratio1 = cdp->per - cdp->evtime;
636: ratio = (ratio1 << 12) / INTERVAL;
637: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
638: ratio = 4096;
639: data2 = (data2 * ratio + data2p * (4096 - ratio)) >> 12;
640:
641: cdp = audio_channel + 3;
642: ratio1 = cdp->per - cdp->evtime;
643: ratio = (ratio1 << 12) / INTERVAL;
644: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
645: ratio = 4096;
646: data3 = (data3 * ratio + data3p * (4096 - ratio)) >> 12;
647: }
648: data1 += data2;
649: data0 += data3;
650: {
651: uae_u32 data = SBASEVAL16 (1) + data0;
652: FINISH_DATA (data, 16, 1);
1.1.1.17! root 653: if (sound_use_filter)
! 654: data = filter (data, &sound_filter_state[0]);
1.1.1.13 root 655: put_sound_word_right (data);
656: }
1.1.1.6 root 657:
1.1.1.13 root 658: {
659: uae_u32 data = SBASEVAL16 (1) + data1;
660: FINISH_DATA (data, 16, 1);
1.1.1.17! root 661: if (sound_use_filter)
! 662: data = filter (data, &sound_filter_state[1]);
1.1.1.13 root 663: put_sound_word_left (data);
664: }
1.1.1.6 root 665: check_sound_buffers ();
666: }
667:
1.1.1.16 root 668: static void sample16si_rh_handler (void)
1.1.1.6 root 669: {
1.1.1.13 root 670: unsigned long delta, ratio;
1.1.1.6 root 671:
1.1.1.13 root 672: uae_u32 data0 = audio_channel[0].current_sample;
673: uae_u32 data1 = audio_channel[1].current_sample;
674: uae_u32 data2 = audio_channel[2].current_sample;
675: uae_u32 data3 = audio_channel[3].current_sample;
676: uae_u32 data0p = audio_channel[0].last_sample;
677: uae_u32 data1p = audio_channel[1].last_sample;
678: uae_u32 data2p = audio_channel[2].last_sample;
679: uae_u32 data3p = audio_channel[3].last_sample;
1.1.1.5 root 680:
1.1.1.13 root 681: DO_CHANNEL_1 (data0, 0);
682: DO_CHANNEL_1 (data1, 1);
683: DO_CHANNEL_1 (data2, 2);
684: DO_CHANNEL_1 (data3, 3);
685: DO_CHANNEL_1 (data0p, 0);
686: DO_CHANNEL_1 (data1p, 1);
687: DO_CHANNEL_1 (data2p, 2);
688: DO_CHANNEL_1 (data3p, 3);
689:
690: data0 &= audio_channel[0].adk_mask;
691: data0p &= audio_channel[0].adk_mask;
692: data1 &= audio_channel[1].adk_mask;
693: data1p &= audio_channel[1].adk_mask;
694: data2 &= audio_channel[2].adk_mask;
695: data2p &= audio_channel[2].adk_mask;
696: data3 &= audio_channel[3].adk_mask;
697: data3p &= audio_channel[3].adk_mask;
698:
699: /* linear interpolation and summing up... */
700: delta = audio_channel[0].per;
701: ratio = ((audio_channel[0].evtime % delta) << 8) / delta;
702: data0 = (data0 * (256 - ratio) + data0p * ratio) >> 8;
703: delta = audio_channel[1].per;
704: ratio = ((audio_channel[1].evtime % delta) << 8) / delta;
705: data1 = (data1 * (256 - ratio) + data1p * ratio) >> 8;
706: delta = audio_channel[2].per;
707: ratio = ((audio_channel[2].evtime % delta) << 8) / delta;
708: data1 += (data2 * (256 - ratio) + data2p * ratio) >> 8;
709: delta = audio_channel[3].per;
710: ratio = ((audio_channel[3].evtime % delta) << 8) / delta;
711: data0 += (data3 * (256 - ratio) + data3p * ratio) >> 8;
712: {
713: uae_u32 data = SBASEVAL16 (1) + data0;
714: FINISH_DATA (data, 16, 1);
1.1.1.17! root 715: if (sound_use_filter)
! 716: data = filter (data, &sound_filter_state[0]);
1.1.1.13 root 717: put_sound_word_right (data);
718: }
719:
720: {
721: uae_u32 data = SBASEVAL16 (1) + data1;
722: FINISH_DATA (data, 16, 1);
1.1.1.17! root 723: if (sound_use_filter)
! 724: data = filter (data, &sound_filter_state[1]);
1.1.1.13 root 725: put_sound_word_left (data);
726: }
1.1.1.5 root 727: check_sound_buffers ();
728: }
729:
1.1 root 730: #else
1.1.1.2 root 731: void sample16s_handler (void)
1.1 root 732: {
1.1.1.16 root 733: sample16_handler ();
1.1 root 734: }
1.1.1.16 root 735: static void sample16si_crux_handler (void)
1.1.1.6 root 736: {
1.1.1.16 root 737: sample16i_crux_handler ();
1.1.1.6 root 738: }
1.1.1.16 root 739: static void sample16si_rh_handler (void)
1.1.1.6 root 740: {
1.1.1.16 root 741: sample16i_rh_handler ();
1.1.1.6 root 742: }
1.1 root 743: #endif
744:
1.1.1.16 root 745: void switch_audio_interpol (void)
1.1 root 746: {
1.1.1.16 root 747: if (currprefs.sound_interpol == 0) {
748: changed_prefs.sound_interpol = 1;
749: write_log ("Interpol on: rh\n");
750: } else if (currprefs.sound_interpol == 1) {
751: changed_prefs.sound_interpol = 2;
752: write_log ("Interpol on: crux\n");
753: } else if (currprefs.sound_interpol == 2) {
754: changed_prefs.sound_interpol = 3;
755: write_log ("Interpol on: sinc\n");
1.1.1.17! root 756: } else if (currprefs.sound_interpol == 3) {
! 757: changed_prefs.sound_interpol = 4;
! 758: write_log ("Interpol on: anti\n");
1.1 root 759: } else {
1.1.1.16 root 760: changed_prefs.sound_interpol = 0;
761: write_log ("Interpol off\n");
1.1 root 762: }
1.1.1.16 root 763: return;
1.1 root 764: }
1.1.1.16 root 765:
1.1.1.7 root 766: void schedule_audio (void)
767: {
1.1.1.16 root 768: unsigned long best = MAX_EV;
1.1.1.7 root 769: int i;
770:
771: eventtab[ev_audio].active = 0;
772: eventtab[ev_audio].oldcycles = get_cycles ();
1.1.1.16 root 773: for (i = 0; i < 4; i++) {
1.1.1.7 root 774: struct audio_channel_data *cdp = audio_channel + i;
775:
1.1.1.16 root 776: if (cdp->evtime != MAX_EV) {
1.1.1.7 root 777: if (best > cdp->evtime) {
778: best = cdp->evtime;
779: eventtab[ev_audio].active = 1;
780: }
1.1.1.15 root 781: }
1.1.1.7 root 782: }
783: eventtab[ev_audio].evtime = get_cycles () + best;
784: }
785:
1.1.1.16 root 786: /*
787: * TODO: This function has been moved here from the audio back-end layer
788: * since it was common to all.
789: * Needs further cleaning up and a better name - or replacing entirely.
790: */
791: void update_sound (unsigned int freq)
792: {
793: if (obtainedfreq) {
1.1.1.17! root 794: if (currprefs.ntscmode)
! 795: scaled_sample_evtime = (unsigned long)(MAXHPOS_NTSC * MAXVPOS_NTSC * freq * CYCLE_UNIT + obtainedfreq - 1) / obtainedfreq;
! 796: else
! 797: scaled_sample_evtime = (unsigned long)(MAXHPOS_PAL * MAXVPOS_PAL * freq * CYCLE_UNIT + obtainedfreq - 1) / obtainedfreq;
1.1.1.16 root 798: }
799: }
800:
801: static void audio_handler (unsigned int nr)
1.1 root 802: {
803: struct audio_channel_data *cdp = audio_channel + nr;
804:
1.1.1.16 root 805: cdp->evtime = MAX_EV;
1.1 root 806: switch (cdp->state) {
807: case 0:
1.1.1.11 root 808: write_log ("Bug in sound code\n");
1.1 root 809: break;
810:
811: case 1:
812: /* We come here at the first hsync after DMA was turned on. */
1.1.1.7 root 813: cdp->evtime = maxhpos * CYCLE_UNIT;
1.1 root 814:
815: cdp->state = 5;
816: INTREQ(0x8000 | (0x80 << nr));
817: if (cdp->wlen != 1)
1.1.1.9 root 818: cdp->wlen = (cdp->wlen - 1) & 0xFFFF;
1.1.1.17! root 819: cdp->nextdat = chipmem_agnus_wget (cdp->pt);
1.1 root 820:
821: cdp->pt += 2;
822: break;
823:
824: case 5:
825: /* We come here at the second hsync after DMA was turned on. */
826: if (currprefs.produce_sound == 0)
1.1.1.7 root 827: cdp->per = PERIOD_MAX;
1.1 root 828:
1.1.1.2 root 829: cdp->evtime = cdp->per;
1.1 root 830: cdp->dat = cdp->nextdat;
1.1.1.5 root 831: cdp->last_sample = cdp->current_sample;
1.1 root 832: cdp->current_sample = (sample8_t)(cdp->dat >> 8);
833:
834: cdp->state = 2;
835: {
836: int audav = adkcon & (1 << nr);
837: int audap = adkcon & (16 << nr);
838: int napnav = (!audav && !audap) || audav;
839: if (napnav)
840: cdp->data_written = 2;
841: }
842: break;
843:
844: case 2:
845: /* We come here when a 2->3 transition occurs */
846: if (currprefs.produce_sound == 0)
1.1.1.7 root 847: cdp->per = PERIOD_MAX;
1.1 root 848:
1.1.1.5 root 849: cdp->last_sample = cdp->current_sample;
1.1 root 850: cdp->current_sample = (sample8_t)(cdp->dat & 0xFF);
1.1.1.2 root 851: cdp->evtime = cdp->per;
1.1 root 852:
853: cdp->state = 3;
854:
855: /* Period attachment? */
856: if (adkcon & (0x10 << nr)) {
857: if (cdp->intreq2 && cdp->dmaen)
1.1.1.9 root 858: INTREQ (0x8000 | (0x80 << nr));
1.1 root 859: cdp->intreq2 = 0;
860:
861: cdp->dat = cdp->nextdat;
862: if (cdp->dmaen)
863: cdp->data_written = 2;
864: if (nr < 3) {
865: if (cdp->dat == 0)
1.1.1.7 root 866: (cdp+1)->per = PERIOD_MAX;
867: else if (cdp->dat < maxhpos * CYCLE_UNIT / 2 && currprefs.produce_sound < 3)
868: (cdp+1)->per = maxhpos * CYCLE_UNIT / 2;
1.1 root 869: else
1.1.1.7 root 870: (cdp+1)->per = cdp->dat * CYCLE_UNIT;
1.1 root 871: }
872: }
873: break;
874:
875: case 3:
876: /* We come here when a 3->2 transition occurs */
877: if (currprefs.produce_sound == 0)
1.1.1.7 root 878: cdp->per = PERIOD_MAX;
1.1 root 879:
1.1.1.2 root 880: cdp->evtime = cdp->per;
1.1 root 881:
1.1.1.17! root 882: if ((INTREQR () & (0x80 << nr)) && !cdp->dmaen) {
1.1 root 883: cdp->state = 0;
1.1.1.16 root 884: cdp->evtime = MAX_EV;
1.1.1.5 root 885: cdp->last_sample = 0;
1.1 root 886: cdp->current_sample = 0;
887: break;
888: } else {
889: int audav = adkcon & (1 << nr);
890: int audap = adkcon & (16 << nr);
891: int napnav = (!audav && !audap) || audav;
892: cdp->state = 2;
893:
894: if ((cdp->intreq2 && cdp->dmaen && napnav)
895: || (napnav && !cdp->dmaen))
896: INTREQ(0x8000 | (0x80 << nr));
897: cdp->intreq2 = 0;
898:
899: cdp->dat = cdp->nextdat;
1.1.1.5 root 900: cdp->last_sample = cdp->current_sample;
1.1 root 901: cdp->current_sample = (sample8_t)(cdp->dat >> 8);
902:
903: if (cdp->dmaen && napnav)
904: cdp->data_written = 2;
905:
906: /* Volume attachment? */
907: if (audav) {
908: if (nr < 3) {
909: (cdp+1)->vol = cdp->dat;
910: #ifndef MULTIPLICATION_PROFITABLE
911: (cdp+1)->voltbl = sound_table[cdp->dat];
912: #endif
913: }
914: }
915: }
916: break;
917:
918: default:
919: cdp->state = 0;
920: break;
921: }
922: }
923:
1.1.1.16 root 924: static void audio_channel_enable_dma (struct audio_channel_data *cdp)
1.1.1.10 root 925: {
1.1.1.16 root 926: if (cdp->evtime == MAX_EV) {
1.1.1.10 root 927: cdp->state = 1;
928: cdp->pt = cdp->lc;
929: cdp->wper = cdp->per;
930: cdp->wlen = cdp->len;
931: cdp->data_written = 2;
932: cdp->evtime = eventtab[ev_hsync].evtime - get_cycles ();
933: }
934: }
935:
1.1.1.16 root 936: static void audio_channel_disable_dma (struct audio_channel_data *cdp)
1.1.1.10 root 937: {
938: if (cdp->state == 1 || cdp->state == 5) {
939: cdp->state = 0;
1.1.1.16 root 940: cdp->evtime = MAX_EV;
1.1.1.10 root 941: cdp->last_sample = 0;
942: cdp->current_sample = 0;
943: }
944: }
945:
1.1 root 946: void audio_reset (void)
947: {
1.1.1.8 root 948: int i;
1.1.1.16 root 949: struct audio_channel_data *cdp;
950:
1.1.1.17! root 951: memset (sound_filter_state, 0, sizeof sound_filter_state);
1.1.1.8 root 952: if (savestate_state != STATE_RESTORE) {
1.1.1.16 root 953: for (i = 0; i < 4; i++) {
954: cdp = &audio_channel[i];
955: memset (cdp, 0, sizeof *audio_channel);
956: cdp->per = PERIOD_MAX;
957: cdp->vol = 0;
958: cdp->evtime = MAX_EV;
959: }
1.1.1.8 root 960: } else
961: for (i = 0; i < 4; i++)
962: audio_channel[i].dmaen = (dmacon & 0x200) && (dmacon & (1 << i));
963:
964: #ifndef MULTIPLICATION_PROFITABLE
1.1.1.13 root 965: for (i = 0; i < 4; i++)
1.1.1.16 root 966: audio_channel[i].voltbl = sound_table[audio_channel[i].vol];
1.1.1.8 root 967: #endif
1.1.1.2 root 968:
1.1.1.16 root 969: last_cycles = get_cycles ();
1.1.1.7 root 970: next_sample_evtime = scaled_sample_evtime;
1.1.1.8 root 971: schedule_audio ();
1.1.1.16 root 972: events_schedule ();
1.1.1.2 root 973: }
974:
1.1.1.6 root 975: STATIC_INLINE int sound_prefs_changed (void)
1.1.1.2 root 976: {
977: return (changed_prefs.produce_sound != currprefs.produce_sound
1.1.1.13 root 978: || changed_prefs.sound_stereo != currprefs.sound_stereo
1.1.1.9 root 979: || changed_prefs.sound_maxbsiz != currprefs.sound_maxbsiz
1.1.1.17! root 980: || changed_prefs.sound_freq != currprefs.sound_freq);
1.1.1.2 root 981: }
982:
983: void check_prefs_changed_audio (void)
984: {
1.1.1.17! root 985: int old_mixed_on = mixed_on;
! 986: int old_mixed_size = mixed_stereo_size;
! 987: int sep, delay;
! 988:
! 989: /* Some options we can just apply without reinitializing the sound
! 990: backend. */
! 991: currprefs.sound_interpol = changed_prefs.sound_interpol;
! 992: currprefs.sound_filter = changed_prefs.sound_filter;
! 993: currprefs.sound_filter_type = changed_prefs.sound_filter_type;
! 994:
! 995: sep = currprefs.sound_stereo_separation = changed_prefs.sound_stereo_separation;
! 996: delay = currprefs.sound_mixed_stereo_delay = changed_prefs.sound_mixed_stereo_delay;
! 997: mixed_mul1 = MIXED_STEREO_SCALE / 2 - sep;
! 998: mixed_mul2 = MIXED_STEREO_SCALE / 2 + sep;
! 999: mixed_stereo_size = delay > 0 ? (1 << (delay - 1)) - 1 : 0;
! 1000: mixed_on = (sep > 0 && sep < MIXED_STEREO_MAX) || mixed_stereo_size > 0;
! 1001: if (mixed_on && old_mixed_size != mixed_stereo_size) {
! 1002: saved_ptr = 0;
! 1003: memset (right_word_saved, 0, sizeof right_word_saved);
! 1004: }
! 1005:
1.1.1.6 root 1006: if (sound_available && sound_prefs_changed ()) {
1.1.1.17! root 1007: if (currprefs.produce_sound >= 2)
! 1008: close_sound ();
1.1.1.2 root 1009:
1.1.1.6 root 1010: currprefs.produce_sound = changed_prefs.produce_sound;
1.1.1.13 root 1011: currprefs.sound_stereo = changed_prefs.sound_stereo;
1.1.1.6 root 1012: currprefs.sound_freq = changed_prefs.sound_freq;
1.1.1.9 root 1013: currprefs.sound_maxbsiz = changed_prefs.sound_maxbsiz;
1.1.1.6 root 1014: if (currprefs.produce_sound >= 2) {
1.1.1.17! root 1015: if (!init_audio ()) {
1.1.1.6 root 1016: if (! sound_available) {
1.1.1.11 root 1017: write_log ("Sound is not supported.\n");
1.1.1.6 root 1018: } else {
1.1.1.11 root 1019: write_log ("Sorry, can't initialize sound.\n");
1.1.1.6 root 1020: currprefs.produce_sound = 0;
1021: /* So we don't do this every frame */
1022: changed_prefs.produce_sound = 0;
1023: }
1.1.1.17! root 1024: }
! 1025: next_sample_evtime = scaled_sample_evtime;
! 1026: last_cycles = get_cycles () - 1;
! 1027: compute_vsynctime ();
! 1028: }
! 1029: if (currprefs.produce_sound == 0) {
! 1030: eventtab[ev_audio].active = 0;
! 1031: events_schedule ();
1.1.1.6 root 1032: }
1.1.1.2 root 1033: }
1.1.1.17! root 1034:
! 1035: led_filter_forced = -1; // always off
! 1036: sound_use_filter = sound_use_filter_sinc = 0;
! 1037: if (currprefs.sound_filter != FILTER_SOUND_OFF) {
! 1038: if (currprefs.sound_filter == FILTER_SOUND_ON)
! 1039: led_filter_forced = 1;
! 1040: if (currprefs.sound_filter == FILTER_SOUND_EMUL)
! 1041: led_filter_forced = 0;
! 1042: if (currprefs.sound_filter_type == FILTER_SOUND_TYPE_A500)
! 1043: sound_use_filter = FILTER_MODEL_A500;
! 1044: else if (currprefs.sound_filter_type == FILTER_SOUND_TYPE_A1200)
! 1045: sound_use_filter = FILTER_MODEL_A1200;
! 1046: }
! 1047: a500e_filter1_a0 = rc_calculate_a0(currprefs.sound_freq, 6200);
! 1048: a500e_filter2_a0 = rc_calculate_a0(currprefs.sound_freq, 20000);
! 1049: filter_a0 = rc_calculate_a0(currprefs.sound_freq, 7000);
! 1050: led_filter_audio();
! 1051:
1.1.1.6 root 1052: /* Select the right interpolation method. */
1053: if (sample_handler == sample16_handler
1054: || sample_handler == sample16i_crux_handler
1.1.1.16 root 1055: || sample_handler == sample16i_rh_handler
1.1.1.17! root 1056: || sample_handler == sample16i_sinc_handler
! 1057: || sample_handler == sample16i_anti_handler)
! 1058: {
1.1.1.6 root 1059: sample_handler = (currprefs.sound_interpol == 0 ? sample16_handler
1060: : currprefs.sound_interpol == 1 ? sample16i_rh_handler
1.1.1.16 root 1061: : currprefs.sound_interpol == 2 ? sample16i_crux_handler
1.1.1.17! root 1062: : currprefs.sound_interpol == 3 ? sample16i_sinc_handler
! 1063: : sample16i_anti_handler);
1.1.1.16 root 1064: } else if (sample_handler == sample16s_handler
1.1.1.17! root 1065: || sample_handler == sample16si_crux_handler
! 1066: || sample_handler == sample16si_rh_handler
! 1067: || sample_handler == sample16si_sinc_handler
! 1068: || sample_handler == sample16si_anti_handler)
1.1.1.6 root 1069: sample_handler = (currprefs.sound_interpol == 0 ? sample16s_handler
1070: : currprefs.sound_interpol == 1 ? sample16si_rh_handler
1.1.1.16 root 1071: : currprefs.sound_interpol == 2 ? sample16si_crux_handler
1.1.1.17! root 1072: : currprefs.sound_interpol == 3 ? sample16si_sinc_handler
! 1073: : sample16si_anti_handler);
1.1.1.16 root 1074: sample_prehandler = NULL;
1.1.1.17! root 1075: if (currprefs.sound_interpol == 3) {
! 1076: sound_use_filter_sinc = sound_use_filter;
! 1077: sound_use_filter = 0;
1.1.1.16 root 1078: sample_prehandler = sinc_prehandler;
1.1.1.17! root 1079: } else if (currprefs.sound_interpol == 4) {
! 1080: sample_prehandler = anti_prehandler;
1.1.1.7 root 1081: }
1.1.1.2 root 1082: }
1083:
1084: void update_audio (void)
1085: {
1086: unsigned long int n_cycles;
1087:
1.1.1.8 root 1088: if (currprefs.produce_sound == 0 || savestate_state == STATE_RESTORE)
1.1.1.2 root 1089: return;
1090:
1.1.1.7 root 1091: n_cycles = get_cycles () - last_cycles;
1.1.1.2 root 1092: for (;;) {
1093: unsigned long int best_evtime = n_cycles + 1;
1.1.1.16 root 1094: if (audio_channel[0].evtime != MAX_EV && best_evtime > audio_channel[0].evtime)
1.1.1.10 root 1095: best_evtime = audio_channel[0].evtime;
1.1.1.16 root 1096: if (audio_channel[1].evtime != MAX_EV && best_evtime > audio_channel[1].evtime)
1.1.1.10 root 1097: best_evtime = audio_channel[1].evtime;
1.1.1.16 root 1098: if (audio_channel[2].evtime != MAX_EV && best_evtime > audio_channel[2].evtime)
1.1.1.10 root 1099: best_evtime = audio_channel[2].evtime;
1.1.1.16 root 1100: if (audio_channel[3].evtime != MAX_EV && best_evtime > audio_channel[3].evtime)
1.1.1.10 root 1101: best_evtime = audio_channel[3].evtime;
1.1.1.7 root 1102: if (currprefs.produce_sound > 1 && best_evtime > next_sample_evtime)
1.1.1.2 root 1103: best_evtime = next_sample_evtime;
1104:
1105: if (best_evtime > n_cycles)
1106: break;
1107:
1.1.1.16 root 1108: if (audio_channel[0].evtime != MAX_EV)
1109: audio_channel[0].evtime -= best_evtime;
1110: if (audio_channel[1].evtime != MAX_EV)
1111: audio_channel[1].evtime -= best_evtime;
1112: if (audio_channel[2].evtime != MAX_EV)
1113: audio_channel[2].evtime -= best_evtime;
1114: if (audio_channel[3].evtime != MAX_EV)
1115: audio_channel[3].evtime -= best_evtime;
1.1.1.2 root 1116: n_cycles -= best_evtime;
1.1.1.16 root 1117: if (currprefs.produce_sound > 1) {
1118: next_sample_evtime -= best_evtime;
1119: if (sample_prehandler)
1120: sample_prehandler (best_evtime / CYCLE_UNIT);
1121: if (next_sample_evtime == 0) {
1122: next_sample_evtime = scaled_sample_evtime;
1123: (*sample_handler) ();
1124: }
1.1.1.2 root 1125: }
1.1.1.16 root 1126: if (audio_channel[0].evtime == 0)
1.1.1.2 root 1127: audio_handler (0);
1.1.1.16 root 1128: if (audio_channel[1].evtime == 0)
1.1.1.2 root 1129: audio_handler (1);
1.1.1.16 root 1130: if (audio_channel[2].evtime == 0)
1.1.1.2 root 1131: audio_handler (2);
1.1.1.16 root 1132: if (audio_channel[3].evtime == 0)
1.1.1.2 root 1133: audio_handler (3);
1134: }
1.1.1.7 root 1135: last_cycles = get_cycles () - n_cycles;
1136: }
1137:
1.1.1.16 root 1138: void update_audio_dmacon (void)
1139: {
1140: unsigned int i;
1141: update_audio ();
1142:
1143: for (i = 0; i < 4; i++) {
1144: struct audio_channel_data *cdp = audio_channel + i;
1145: int chan_ena = (dmacon & 0x200) && (dmacon & (1<<i));
1146: if (cdp->dmaen == chan_ena)
1147: continue;
1148: cdp->dmaen = chan_ena;
1149: if (cdp->dmaen)
1150: audio_channel_enable_dma (cdp);
1151: else
1152: audio_channel_disable_dma (cdp);
1153: }
1154: schedule_audio ();
1155: }
1156:
1.1.1.7 root 1157: void audio_evhandler (void)
1158: {
1159: if (currprefs.produce_sound == 0)
1160: abort ();
1161:
1162: update_audio ();
1163: schedule_audio ();
1.1.1.2 root 1164: }
1165:
1.1.1.15 root 1166: void audio_hsync (int dmaaction)
1167: {
1168: int nr;
1169:
1170: update_audio ();
1171:
1172: /* Sound data is fetched at the beginning of each line */
1173: for (nr = 0; nr < 4; nr++) {
1174: struct audio_channel_data *cdp = audio_channel + nr;
1175:
1176: if (cdp->data_written == 2) {
1177: cdp->data_written = 0;
1.1.1.17! root 1178: cdp->nextdat = chipmem_agnus_wget (cdp->pt);
1.1.1.15 root 1179: cdp->pt += 2;
1180: if (cdp->state == 2 || cdp->state == 3) {
1181: if (cdp->wlen == 1) {
1182: cdp->pt = cdp->lc;
1183: cdp->wlen = cdp->len;
1184: cdp->intreq2 = 1;
1185: } else
1186: cdp->wlen = (cdp->wlen - 1) & 0xFFFF;
1187: }
1188: }
1189: }
1190: }
1191:
1.1.1.17! root 1192: void AUDxDAT (int nr, uae_u16 v)
1.1.1.2 root 1193: {
1194: struct audio_channel_data *cdp = audio_channel + nr;
1195:
1.1.1.7 root 1196: if (currprefs.produce_sound == 0)
1197: return;
1198:
1.1.1.2 root 1199: update_audio ();
1200:
1201: cdp->dat = v;
1.1.1.17! root 1202: if (cdp->state == 0 && !(INTREQR () & (0x80 << nr))) {
1.1.1.2 root 1203: cdp->state = 2;
1.1.1.17! root 1204: INTREQ (0x8000 | (0x80 << nr));
1.1.1.2 root 1205: /* data_written = 2 ???? */
1206: cdp->evtime = cdp->per;
1.1.1.7 root 1207: schedule_audio ();
1208: events_schedule ();
1.1.1.2 root 1209: }
1210: }
1211:
1.1.1.17! root 1212: void AUDxLCH (int nr, uae_u16 v)
1.1.1.2 root 1213: {
1214: update_audio ();
1215:
1216: audio_channel[nr].lc = (audio_channel[nr].lc & 0xffff) | ((uae_u32)v << 16);
1217: }
1218:
1.1.1.17! root 1219: void AUDxLCL (int nr, uae_u16 v)
1.1.1.2 root 1220: {
1221: update_audio ();
1222:
1223: audio_channel[nr].lc = (audio_channel[nr].lc & ~0xffff) | (v & 0xFFFE);
1224: }
1225:
1.1.1.17! root 1226: void AUDxPER (int nr, uae_u16 v)
1.1.1.2 root 1227: {
1.1.1.7 root 1228: unsigned long per = v * CYCLE_UNIT;
1.1.1.2 root 1229: update_audio ();
1230:
1.1.1.7 root 1231: if (per == 0)
1232: per = PERIOD_MAX;
1.1.1.2 root 1233:
1.1.1.7 root 1234: if (per < maxhpos * CYCLE_UNIT / 2 && currprefs.produce_sound < 3)
1235: per = maxhpos * CYCLE_UNIT / 2;
1.1.1.16 root 1236: /* the sinc code registers paula output state changes, but has a finite
1237: * buffer in which to do so. Hence, we forbid very low values; this should
1238: * only limit the accurate rendering of supersonic sounds, which are
1239: * filtered away on the sinc output path anyway. */
1240: if (currprefs.produce_sound == 3 && sample_handler == sample16si_sinc_handler && per < MIN_ALLOWED_PERIOD * CYCLE_UNIT)
1241: per = MIN_ALLOWED_PERIOD * CYCLE_UNIT;
1.1.1.2 root 1242:
1.1.1.16 root 1243: if (audio_channel[nr].per == PERIOD_MAX && per != PERIOD_MAX
1244: && audio_channel[nr].evtime != MAX_EV) {
1.1.1.8 root 1245: audio_channel[nr].evtime = CYCLE_UNIT;
1.1.1.9 root 1246: if (currprefs.produce_sound > 0) {
1247: schedule_audio ();
1248: events_schedule ();
1249: }
1.1.1.8 root 1250: }
1.1.1.16 root 1251:
1.1.1.7 root 1252: audio_channel[nr].per = per;
1.1.1.2 root 1253: }
1254:
1.1.1.17! root 1255: void AUDxLEN (int nr, uae_u16 v)
1.1.1.2 root 1256: {
1257: update_audio ();
1258: audio_channel[nr].len = v;
1259: }
1260:
1.1.1.17! root 1261: void AUDxVOL (int nr, uae_u16 v)
1.1.1.2 root 1262: {
1263: int v2 = v & 64 ? 63 : v & 63;
1264:
1265: update_audio ();
1266:
1267: audio_channel[nr].vol = v2;
1268: #ifndef MULTIPLICATION_PROFITABLE
1269: audio_channel[nr].voltbl = sound_table[v2];
1270: #endif
1.1 root 1271: }
1272:
1.1.1.15 root 1273: void update_adkmasks (void)
1274: {
1275: unsigned long t;
1276:
1277: t = adkcon | (adkcon >> 4);
1278: audio_channel[0].adk_mask = (((t >> 0) & 1) - 1);
1279: audio_channel[1].adk_mask = (((t >> 1) & 1) - 1);
1280: audio_channel[2].adk_mask = (((t >> 2) & 1) - 1);
1281: audio_channel[3].adk_mask = (((t >> 3) & 1) - 1);
1282: }
1283:
1.1.1.7 root 1284: int init_audio (void)
1.1 root 1285: {
1.1.1.16 root 1286: int result = init_sound ();
1287: update_sound (vblank_hz);
1288: return result;
1.1.1.7 root 1289: }
1290:
1.1.1.17! root 1291: void led_filter_audio (void)
! 1292: {
! 1293: led_filter_on = 0;
! 1294: if (led_filter_forced > 0 || (gui_data.powerled && led_filter_forced >= 0))
! 1295: led_filter_on = 1;
! 1296: gui_led (0, gui_data.powerled);
! 1297: }
! 1298:
1.1.1.8 root 1299: /* audio save/restore code FIXME: not working correctly */
1300: /* help needed */
1301:
1.1.1.16 root 1302: const uae_u8 *restore_audio (int i, const uae_u8 *src)
1.1.1.8 root 1303: {
1304: struct audio_channel_data *acd;
1305: uae_u16 p;
1306:
1307: acd = audio_channel + i;
1308: acd->state = restore_u8 ();
1309: acd->vol = restore_u8 ();
1310: acd->intreq2 = restore_u8 ();
1311: acd->data_written = restore_u8 ();
1312: acd->len = restore_u16 ();
1313: acd->wlen = restore_u16 ();
1314: p = restore_u16 ();
1315: acd->per = p ? p * CYCLE_UNIT : PERIOD_MAX;
1316: p = restore_u16 ();
1317: acd->wper = p ? p * CYCLE_UNIT : PERIOD_MAX;
1318: acd->lc = restore_u32 ();
1319: acd->pt = restore_u32 ();
1320: acd->evtime = restore_u32 ();
1321:
1322: return src;
1323: }
1324:
1.1.1.15 root 1325: uae_u8 *save_audio (int i, int *len)
1.1.1.8 root 1326: {
1327: struct audio_channel_data *acd;
1328: uae_u8 *dst = malloc (100);
1329: uae_u8 *dstbak = dst;
1330: uae_u16 p;
1331:
1332: acd = audio_channel + i;
1333: save_u8 ((uae_u8)acd->state);
1334: save_u8 (acd->vol);
1335: save_u8 (acd->intreq2);
1336: save_u8 (acd->data_written);
1337: save_u16 (acd->len);
1338: save_u16 (acd->wlen);
1339: p = acd->per == PERIOD_MAX ? 0 : acd->per / CYCLE_UNIT;
1340: save_u16 (p);
1341: p = acd->per == PERIOD_MAX ? 0 : acd->wper / CYCLE_UNIT;
1342: save_u16 (p);
1343: save_u32 (acd->lc);
1344: save_u32 (acd->pt);
1345: save_u32 (acd->evtime);
1346: *len = dst - dstbak;
1347: return dstbak;
1348: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.