|
|
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.18 root 9: * Copyright 2005 Heikki Orsila
1.1.1.16 root 10: * Copyright 2006 Toni Wilen
11: *
12: * new filter algorithm and anti&sinc interpolators by Antti S. Lankila
1.1 root 13: */
14:
15: #include "sysconfig.h"
16: #include "sysdeps.h"
17:
1.1.1.17 root 18: #include <math.h>
19:
1.1 root 20: #include "options.h"
21: #include "memory.h"
22: #include "custom.h"
1.1.1.7 root 23: #include "newcpu.h"
24: #include "autoconf.h"
1.1 root 25: #include "gensound.h"
26: #include "sounddep/sound.h"
27: #include "events.h"
28: #include "audio.h"
1.1.1.8 root 29: #include "savestate.h"
1.1.1.16 root 30: #include "sinctable.h"
31: #include "gui.h"
32:
33: #define MAX_EV ~0ul
1.1 root 34:
1.1.1.16 root 35: /* periods less than this value are replaced by this value. */
36: #define MIN_ALLOWED_PERIOD 16
37: /* reserve ~20 extra slots in sinc queue for cpu volume or some such updates
38: * even at maximum period. This avoids sinc queue overflow on games like
39: * battle squadron that write these low period values and do cpu-based
40: * updates on paula registers, probably volume. */
41: #define NUMBER_OF_CPU_UPDATES_ALLOWED 20
42:
43: #define SINC_QUEUE_LENGTH (SINC_QUEUE_MAX_AGE / MIN_ALLOWED_PERIOD + NUMBER_OF_CPU_UPDATES_ALLOWED)
44:
45: typedef struct {
1.1.1.17 root 46: int age, output;
1.1.1.16 root 47: } sinc_queue_t;
48:
49: struct audio_channel_data {
50: unsigned long adk_mask;
51: unsigned long evtime;
52: unsigned long per;
53: uae_u8 dmaen, intreq2, data_written;
54: uaecptr lc, pt;
55: int state, wper;
56: unsigned int wlen;
57: int current_sample, last_sample;
58: int vol;
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.18 root 83: sound_table[j][i] = j * (uae_s8)i * 2;
1.1 root 84: }
85:
86: typedef uae_s8 sample8_t;
87: #define DO_CHANNEL_1(v, c) do { (v) *= audio_channel[c].vol; } while (0)
88: #define SBASEVAL16(logn) ((logn) == 1 ? SOUND16_BASE_VAL >> 1 : SOUND16_BASE_VAL)
1.1.1.17 root 89: #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 90:
1.1.1.17 root 91: static uae_u32 right_word_saved[SOUND_MAX_DELAY_BUFFER];
92: static uae_u32 left_word_saved[SOUND_MAX_DELAY_BUFFER];
1.1.1.7 root 93: static int saved_ptr;
1.1 root 94:
1.1.1.17 root 95: static int mixed_on, mixed_stereo_size, mixed_mul1, mixed_mul2;
96: static int led_filter_forced, sound_use_filter, sound_use_filter_sinc, led_filter_on;
97:
98: /* denormals are very small floating point numbers that force FPUs into slow
99: mode. All lowpass filters using floats are suspectible to denormals unless
100: a small offset is added to avoid very small floating point numbers. */
101: #define DENORMAL_OFFSET (1E-10)
102:
103: static struct filter_state {
104: float rc1, rc2, rc3, rc4, rc5;
105: } sound_filter_state[4];
106:
107: static float a500e_filter1_a0;
108: static float a500e_filter2_a0;
109: static float filter_a0; /* a500 and a1200 use the same */
110:
111: enum {
112: FILTER_NONE = 0,
113: FILTER_MODEL_A500,
114: FILTER_MODEL_A1200
115: };
116:
117: /* Amiga has two separate filtering circuits per channel, a static RC filter
118: * on A500 and the LED filter. This code emulates both.
119: *
120: * The Amiga filtering circuitry depends on Amiga model. Older Amigas seem
121: * to have a 6 dB/oct RC filter with cutoff frequency such that the -6 dB
122: * point for filter is reached at 6 kHz, while newer Amigas have no filtering.
123: *
124: * The LED filter is complicated, and we are modelling it with a pair of
125: * RC filters, the other providing a highboost. The LED starts to cut
126: * into signal somewhere around 5-6 kHz, and there's some kind of highboost
127: * in effect above 12 kHz. Better measurements are required.
128: *
129: * The current filtering should be accurate to 2 dB with the filter on,
130: * and to 1 dB with the filter off.
131: */
132:
133: static int filter(int input, struct filter_state *fs)
134: {
135: int o;
136: float normal_output, led_output;
137:
138: input = (uae_s16)input;
139: switch (sound_use_filter) {
140: case FILTER_NONE:
141: return input;
142: case FILTER_MODEL_A500:
143: fs->rc1 = a500e_filter1_a0 * input + (1 - a500e_filter1_a0) * fs->rc1 + DENORMAL_OFFSET;
144: fs->rc2 = a500e_filter2_a0 * fs->rc1 + (1-a500e_filter2_a0) * fs->rc2;
145: normal_output = fs->rc2;
146:
147: fs->rc3 = filter_a0 * normal_output + (1 - filter_a0) * fs->rc3;
148: fs->rc4 = filter_a0 * fs->rc3 + (1 - filter_a0) * fs->rc4;
149: fs->rc5 = filter_a0 * fs->rc4 + (1 - filter_a0) * fs->rc5;
150:
151: led_output = fs->rc5;
152: break;
153:
154: case FILTER_MODEL_A1200:
155: normal_output = input;
156:
157: fs->rc2 = filter_a0 * normal_output + (1 - filter_a0) * fs->rc2 + DENORMAL_OFFSET;
158: fs->rc3 = filter_a0 * fs->rc2 + (1 - filter_a0) * fs->rc3;
159: fs->rc4 = filter_a0 * fs->rc3 + (1 - filter_a0) * fs->rc4;
160:
161: led_output = fs->rc4;
162: break;
163: }
164:
165: if (led_filter_on)
166: o = led_output;
167: else
168: o = normal_output;
169:
170: if (o > 32767)
171: o = 32767;
172: else if (o < -32768)
173: o = -32768;
174:
175: return o;
176: }
177:
178: /* This computes the 1st order low-pass filter term b0.
179: * The a1 term is 1.0 - b0. The center frequency marks the -3 dB point. */
180: #ifndef M_PI
181: #define M_PI 3.14159265358979323846
182: #endif
183: static float rc_calculate_a0 (int sample_rate, int cutoff_freq)
184: {
185: float omega;
186: /* The BLT correction formula below blows up if the cutoff is above nyquist. */
187: if (cutoff_freq >= sample_rate / 2)
188: return 1.0;
189:
190: omega = 2 * M_PI * cutoff_freq / sample_rate;
191: /* Compensate for the bilinear transformation. This allows us to specify the
192: * stop frequency more exactly, but the filter becomes less steep further
193: * from stopband. */
194: omega = tan (omega / 2) * 2;
195: return 1 / (1 + 1 / omega);
196: }
197:
198: /* Always put the right word before the left word. */
199:
1.1.1.7 root 200: STATIC_INLINE void put_sound_word_right (uae_u32 w)
1.1 root 201: {
1.1.1.17 root 202: if (mixed_on) {
1.1.1.7 root 203: right_word_saved[saved_ptr] = w;
204: return;
1.1 root 205: }
206:
1.1.1.7 root 207: PUT_SOUND_WORD_RIGHT (w);
1.1 root 208: }
209:
1.1.1.7 root 210: STATIC_INLINE void put_sound_word_left (uae_u32 w)
1.1.1.5 root 211: {
1.1.1.17 root 212: if (mixed_on) {
1.1.1.7 root 213: uae_u32 rold, lold, rnew, lnew, tmp;
1.1.1.5 root 214:
1.1.1.7 root 215: left_word_saved[saved_ptr] = w;
216: lnew = w - SOUND16_BASE_VAL;
217: rnew = right_word_saved[saved_ptr] - SOUND16_BASE_VAL;
1.1.1.5 root 218:
1.1.1.17 root 219: saved_ptr = (saved_ptr + 1) & mixed_stereo_size;
220:
1.1.1.7 root 221: lold = left_word_saved[saved_ptr] - SOUND16_BASE_VAL;
1.1.1.17 root 222: tmp = (rnew * mixed_mul2 + lold * mixed_mul1) / MIXED_STEREO_SCALE;
1.1.1.7 root 223: tmp += SOUND16_BASE_VAL;
224: PUT_SOUND_WORD_RIGHT (tmp);
1.1.1.5 root 225:
1.1.1.7 root 226: rold = right_word_saved[saved_ptr] - SOUND16_BASE_VAL;
1.1.1.17 root 227: w = (lnew * mixed_mul2 + rold * mixed_mul1) / MIXED_STEREO_SCALE;
1.1.1.7 root 228: }
229: PUT_SOUND_WORD_LEFT (w);
230: }
1.1.1.5 root 231:
1.1.1.7 root 232: #define DO_CHANNEL(v, c) do { (v) &= audio_channel[c].adk_mask; data += v; } while (0);
1.1.1.5 root 233:
1.1.1.17 root 234: static void anti_prehandler (unsigned long best_evtime)
235: {
236: int i, output;
237: struct audio_channel_data *acd;
238:
239: /* Handle accumulator antialiasiation */
240: for (i = 0; i < 4; i++) {
241: acd = &audio_channel[i];
242: output = (acd->current_sample * acd->vol) & acd->adk_mask;
243: acd->sample_accum += output * best_evtime;
244: acd->sample_accum_time += best_evtime;
245: }
246: }
247:
248: STATIC_INLINE void samplexx_anti_handler (int *datasp)
249: {
250: int i;
251: for (i = 0; i < 4; i++) {
252: datasp[i] = audio_channel[i].sample_accum_time ? (audio_channel[i].sample_accum / audio_channel[i].sample_accum_time) : 0;
253: audio_channel[i].sample_accum = 0;
254: audio_channel[i].sample_accum_time = 0;
255:
256: }
257: }
258:
1.1.1.16 root 259: static void sinc_prehandler (unsigned long best_evtime)
260: {
261: int i, j, output;
262: struct audio_channel_data *acd;
263:
264: for (i = 0; i < 4; i++) {
265: acd = &audio_channel[i];
266: output = (acd->current_sample * acd->vol) & acd->adk_mask;
267:
268: /* age the sinc queue and truncate it when necessary */
269: for (j = 0; j < acd->sinc_queue_length; j += 1) {
270: acd->sinc_queue[j].age += best_evtime;
271: if (acd->sinc_queue[j].age >= SINC_QUEUE_MAX_AGE) {
272: acd->sinc_queue_length = j;
273: break;
274: }
275: }
276: /* if output state changes, record the state change and also
277: * write data into sinc queue for mixing in the BLEP */
278: if (acd->sinc_output_state != output) {
279: if (acd->sinc_queue_length > SINC_QUEUE_LENGTH - 1) {
280: write_log ("warning: sinc queue truncated. Last age: %d.\n",
281: acd->sinc_queue[SINC_QUEUE_LENGTH-1].age);
282: acd->sinc_queue_length = SINC_QUEUE_LENGTH - 1;
283: }
284: /* make room for new and add the new value */
285: memmove (&acd->sinc_queue[1], &acd->sinc_queue[0],
286: sizeof(acd->sinc_queue[0]) * acd->sinc_queue_length);
287: acd->sinc_queue_length += 1;
288: acd->sinc_queue[0].age = best_evtime;
289: acd->sinc_queue[0].output = output - acd->sinc_output_state;
290: acd->sinc_output_state = output;
291: }
292: }
293: }
294:
295:
296: /* this interpolator performs BLEP mixing (bleps are shaped like integrated sinc
297: * functions) with a type of BLEP that matches the filtering configuration. */
298: STATIC_INLINE void samplexx_sinc_handler (int *datasp)
299: {
300: int i, n;
301: int const *winsinc;
302:
303: if (sound_use_filter_sinc) {
304: n = (sound_use_filter_sinc == FILTER_MODEL_A500) ? 0 : 2;
305: if (led_filter_on)
306: n += 1;
307: } else {
308: n = 4;
309: }
310: winsinc = winsinc_integral[n];
311:
312: for (i = 0; i < 4; i += 1) {
313: int j, v;
314: struct audio_channel_data *acd = &audio_channel[i];
315: /* The sum rings with harmonic components up to infinity... */
316: int sum = acd->sinc_output_state << 17;
317: /* ...but we cancel them through mixing in BLEPs instead */
318: for (j = 0; j < acd->sinc_queue_length; j += 1)
319: sum -= winsinc[acd->sinc_queue[j].age] * acd->sinc_queue[j].output;
320: v = sum >> 17;
321: if (v > 32767)
322: v = 32767;
323: else if (v < -32768)
324: v = -32768;
325: datasp[i] = v;
326: }
327: }
328:
1.1.1.17 root 329: static void sample16si_anti_handler (void)
330: {
331: int datas[4], data1, data2;
332:
333: samplexx_anti_handler (datas);
334: data1 = datas[0] + datas[3];
335: data2 = datas[1] + datas[2];
336: FINISH_DATA (data1, 16, 1);
337: if (sound_use_filter)
338: data1 = filter (data1, &sound_filter_state[0]);
339: put_sound_word_right (data1);
340: FINISH_DATA (data2, 16, 1);
341: if (sound_use_filter)
342: data2 = filter (data2, &sound_filter_state[1]);
343: put_sound_word_left (data2);
344: check_sound_buffers ();
345: }
346:
1.1.1.16 root 347: static void sample16si_sinc_handler (void)
1.1 root 348: {
1.1.1.16 root 349: int datas[4], data1, data2;
1.1 root 350:
1.1.1.16 root 351: samplexx_sinc_handler (datas);
352: data1 = datas[0] + datas[3];
353: data2 = datas[1] + datas[2];
354: FINISH_DATA (data1, 16, 1);
1.1.1.17 root 355: put_sound_word_right (data1);
1.1.1.16 root 356: FINISH_DATA (data2, 16, 1);
1.1.1.17 root 357: put_sound_word_left (data2);
1.1 root 358: check_sound_buffers ();
359: }
360:
1.1.1.2 root 361: void sample16s_handler (void)
1.1 root 362: {
1.1.1.13 root 363: uae_u32 data0 = audio_channel[0].current_sample;
364: uae_u32 data1 = audio_channel[1].current_sample;
365: uae_u32 data2 = audio_channel[2].current_sample;
366: uae_u32 data3 = audio_channel[3].current_sample;
367: DO_CHANNEL_1 (data0, 0);
368: DO_CHANNEL_1 (data1, 1);
369: DO_CHANNEL_1 (data2, 2);
370: DO_CHANNEL_1 (data3, 3);
371:
372: data0 &= audio_channel[0].adk_mask;
373: data1 &= audio_channel[1].adk_mask;
374: data2 &= audio_channel[2].adk_mask;
375: data3 &= audio_channel[3].adk_mask;
1.1.1.15 root 376:
1.1.1.13 root 377: data0 += data3;
378: {
379: uae_u32 data = SBASEVAL16(1) + data0;
380: FINISH_DATA (data, 16, 1);
1.1.1.17 root 381: if (sound_use_filter)
382: data = filter (data, &sound_filter_state[0]);
1.1.1.13 root 383: put_sound_word_right (data);
384: }
1.1 root 385:
1.1.1.13 root 386: data1 += data2;
387: {
1.1.1.15 root 388: uae_u32 data = SBASEVAL16(1) + data1;
1.1.1.13 root 389: FINISH_DATA (data, 16, 1);
1.1.1.17 root 390: if (sound_use_filter)
391: data = filter (data, &sound_filter_state[1]);
1.1.1.13 root 392: put_sound_word_left (data);
1.1 root 393: }
1.1.1.7 root 394:
1.1 root 395: check_sound_buffers ();
396: }
397:
1.1.1.16 root 398: void switch_audio_interpol (void)
1.1 root 399: {
1.1.1.16 root 400: if (currprefs.sound_interpol == 0) {
401: changed_prefs.sound_interpol = 1;
1.1.1.18 root 402: write_log ("Resampler on: sinc\n");
1.1.1.16 root 403: } else if (currprefs.sound_interpol == 1) {
404: changed_prefs.sound_interpol = 2;
1.1.1.18 root 405: write_log ("Resampler on: anti\n");
1.1 root 406: } else {
1.1.1.16 root 407: changed_prefs.sound_interpol = 0;
1.1.1.18 root 408: write_log ("Resampler off\n");
1.1 root 409: }
1.1.1.16 root 410: return;
1.1 root 411: }
1.1.1.16 root 412:
1.1.1.7 root 413: void schedule_audio (void)
414: {
1.1.1.16 root 415: unsigned long best = MAX_EV;
1.1.1.7 root 416: int i;
417:
418: eventtab[ev_audio].active = 0;
419: eventtab[ev_audio].oldcycles = get_cycles ();
1.1.1.16 root 420: for (i = 0; i < 4; i++) {
1.1.1.7 root 421: struct audio_channel_data *cdp = audio_channel + i;
422:
1.1.1.16 root 423: if (cdp->evtime != MAX_EV) {
1.1.1.7 root 424: if (best > cdp->evtime) {
425: best = cdp->evtime;
426: eventtab[ev_audio].active = 1;
427: }
1.1.1.15 root 428: }
1.1.1.7 root 429: }
430: eventtab[ev_audio].evtime = get_cycles () + best;
431: }
432:
1.1.1.16 root 433: /*
434: * TODO: This function has been moved here from the audio back-end layer
435: * since it was common to all.
436: * Needs further cleaning up and a better name - or replacing entirely.
437: */
438: void update_sound (unsigned int freq)
439: {
440: if (obtainedfreq) {
1.1.1.17 root 441: if (currprefs.ntscmode)
442: scaled_sample_evtime = (unsigned long)(MAXHPOS_NTSC * MAXVPOS_NTSC * freq * CYCLE_UNIT + obtainedfreq - 1) / obtainedfreq;
443: else
444: scaled_sample_evtime = (unsigned long)(MAXHPOS_PAL * MAXVPOS_PAL * freq * CYCLE_UNIT + obtainedfreq - 1) / obtainedfreq;
1.1.1.16 root 445: }
446: }
447:
448: static void audio_handler (unsigned int nr)
1.1 root 449: {
450: struct audio_channel_data *cdp = audio_channel + nr;
451:
1.1.1.16 root 452: cdp->evtime = MAX_EV;
1.1 root 453: switch (cdp->state) {
454: case 0:
1.1.1.11 root 455: write_log ("Bug in sound code\n");
1.1 root 456: break;
457:
458: case 1:
459: /* We come here at the first hsync after DMA was turned on. */
1.1.1.7 root 460: cdp->evtime = maxhpos * CYCLE_UNIT;
1.1 root 461:
462: cdp->state = 5;
463: INTREQ(0x8000 | (0x80 << nr));
464: if (cdp->wlen != 1)
1.1.1.9 root 465: cdp->wlen = (cdp->wlen - 1) & 0xFFFF;
1.1.1.17 root 466: cdp->nextdat = chipmem_agnus_wget (cdp->pt);
1.1 root 467:
468: cdp->pt += 2;
469: break;
470:
471: case 5:
472: /* We come here at the second hsync after DMA was turned on. */
473: if (currprefs.produce_sound == 0)
1.1.1.7 root 474: cdp->per = PERIOD_MAX;
1.1 root 475:
1.1.1.2 root 476: cdp->evtime = cdp->per;
1.1 root 477: cdp->dat = cdp->nextdat;
1.1.1.5 root 478: cdp->last_sample = cdp->current_sample;
1.1 root 479: cdp->current_sample = (sample8_t)(cdp->dat >> 8);
480:
481: cdp->state = 2;
482: {
483: int audav = adkcon & (1 << nr);
484: int audap = adkcon & (16 << nr);
485: int napnav = (!audav && !audap) || audav;
486: if (napnav)
487: cdp->data_written = 2;
488: }
489: break;
490:
491: case 2:
492: /* We come here when a 2->3 transition occurs */
493: if (currprefs.produce_sound == 0)
1.1.1.7 root 494: cdp->per = PERIOD_MAX;
1.1 root 495:
1.1.1.5 root 496: cdp->last_sample = cdp->current_sample;
1.1 root 497: cdp->current_sample = (sample8_t)(cdp->dat & 0xFF);
1.1.1.2 root 498: cdp->evtime = cdp->per;
1.1 root 499:
500: cdp->state = 3;
501:
502: /* Period attachment? */
503: if (adkcon & (0x10 << nr)) {
504: if (cdp->intreq2 && cdp->dmaen)
1.1.1.9 root 505: INTREQ (0x8000 | (0x80 << nr));
1.1 root 506: cdp->intreq2 = 0;
507:
508: cdp->dat = cdp->nextdat;
509: if (cdp->dmaen)
510: cdp->data_written = 2;
511: if (nr < 3) {
512: if (cdp->dat == 0)
1.1.1.7 root 513: (cdp+1)->per = PERIOD_MAX;
514: else if (cdp->dat < maxhpos * CYCLE_UNIT / 2 && currprefs.produce_sound < 3)
515: (cdp+1)->per = maxhpos * CYCLE_UNIT / 2;
1.1 root 516: else
1.1.1.7 root 517: (cdp+1)->per = cdp->dat * CYCLE_UNIT;
1.1 root 518: }
519: }
520: break;
521:
522: case 3:
523: /* We come here when a 3->2 transition occurs */
524: if (currprefs.produce_sound == 0)
1.1.1.7 root 525: cdp->per = PERIOD_MAX;
1.1 root 526:
1.1.1.2 root 527: cdp->evtime = cdp->per;
1.1 root 528:
1.1.1.17 root 529: if ((INTREQR () & (0x80 << nr)) && !cdp->dmaen) {
1.1 root 530: cdp->state = 0;
1.1.1.16 root 531: cdp->evtime = MAX_EV;
1.1.1.5 root 532: cdp->last_sample = 0;
1.1 root 533: cdp->current_sample = 0;
534: break;
535: } else {
536: int audav = adkcon & (1 << nr);
537: int audap = adkcon & (16 << nr);
538: int napnav = (!audav && !audap) || audav;
539: cdp->state = 2;
540:
541: if ((cdp->intreq2 && cdp->dmaen && napnav)
542: || (napnav && !cdp->dmaen))
543: INTREQ(0x8000 | (0x80 << nr));
544: cdp->intreq2 = 0;
545:
546: cdp->dat = cdp->nextdat;
1.1.1.5 root 547: cdp->last_sample = cdp->current_sample;
1.1 root 548: cdp->current_sample = (sample8_t)(cdp->dat >> 8);
549:
550: if (cdp->dmaen && napnav)
551: cdp->data_written = 2;
552:
553: /* Volume attachment? */
554: if (audav) {
1.1.1.19! root 555: if (nr < 3)
1.1 root 556: (cdp+1)->vol = cdp->dat;
557: }
558: }
559: break;
560:
561: default:
562: cdp->state = 0;
563: break;
564: }
565: }
566:
1.1.1.16 root 567: static void audio_channel_enable_dma (struct audio_channel_data *cdp)
1.1.1.10 root 568: {
1.1.1.16 root 569: if (cdp->evtime == MAX_EV) {
1.1.1.10 root 570: cdp->state = 1;
571: cdp->pt = cdp->lc;
572: cdp->wper = cdp->per;
573: cdp->wlen = cdp->len;
574: cdp->data_written = 2;
575: cdp->evtime = eventtab[ev_hsync].evtime - get_cycles ();
576: }
577: }
578:
1.1.1.16 root 579: static void audio_channel_disable_dma (struct audio_channel_data *cdp)
1.1.1.10 root 580: {
581: if (cdp->state == 1 || cdp->state == 5) {
582: cdp->state = 0;
1.1.1.16 root 583: cdp->evtime = MAX_EV;
1.1.1.10 root 584: cdp->last_sample = 0;
585: cdp->current_sample = 0;
586: }
587: }
588:
1.1 root 589: void audio_reset (void)
590: {
1.1.1.8 root 591: int i;
1.1.1.16 root 592: struct audio_channel_data *cdp;
593:
1.1.1.17 root 594: memset (sound_filter_state, 0, sizeof sound_filter_state);
1.1.1.8 root 595: if (savestate_state != STATE_RESTORE) {
1.1.1.16 root 596: for (i = 0; i < 4; i++) {
597: cdp = &audio_channel[i];
598: memset (cdp, 0, sizeof *audio_channel);
599: cdp->per = PERIOD_MAX;
600: cdp->vol = 0;
601: cdp->evtime = MAX_EV;
602: }
1.1.1.8 root 603: } else
604: for (i = 0; i < 4; i++)
605: audio_channel[i].dmaen = (dmacon & 0x200) && (dmacon & (1 << i));
606:
1.1.1.16 root 607: last_cycles = get_cycles ();
1.1.1.7 root 608: next_sample_evtime = scaled_sample_evtime;
1.1.1.8 root 609: schedule_audio ();
1.1.1.16 root 610: events_schedule ();
1.1.1.2 root 611: }
612:
1.1.1.6 root 613: STATIC_INLINE int sound_prefs_changed (void)
1.1.1.2 root 614: {
615: return (changed_prefs.produce_sound != currprefs.produce_sound
1.1.1.13 root 616: || changed_prefs.sound_stereo != currprefs.sound_stereo
1.1.1.9 root 617: || changed_prefs.sound_maxbsiz != currprefs.sound_maxbsiz
1.1.1.17 root 618: || changed_prefs.sound_freq != currprefs.sound_freq);
1.1.1.2 root 619: }
620:
621: void check_prefs_changed_audio (void)
622: {
1.1.1.17 root 623: int old_mixed_on = mixed_on;
624: int old_mixed_size = mixed_stereo_size;
625: int sep, delay;
626:
627: /* Some options we can just apply without reinitializing the sound
628: backend. */
629: currprefs.sound_interpol = changed_prefs.sound_interpol;
630: currprefs.sound_filter = changed_prefs.sound_filter;
631: currprefs.sound_filter_type = changed_prefs.sound_filter_type;
632:
633: sep = currprefs.sound_stereo_separation = changed_prefs.sound_stereo_separation;
634: delay = currprefs.sound_mixed_stereo_delay = changed_prefs.sound_mixed_stereo_delay;
635: mixed_mul1 = MIXED_STEREO_SCALE / 2 - sep;
636: mixed_mul2 = MIXED_STEREO_SCALE / 2 + sep;
637: mixed_stereo_size = delay > 0 ? (1 << (delay - 1)) - 1 : 0;
638: mixed_on = (sep > 0 && sep < MIXED_STEREO_MAX) || mixed_stereo_size > 0;
639: if (mixed_on && old_mixed_size != mixed_stereo_size) {
640: saved_ptr = 0;
641: memset (right_word_saved, 0, sizeof right_word_saved);
642: }
643:
1.1.1.6 root 644: if (sound_available && sound_prefs_changed ()) {
1.1.1.17 root 645: if (currprefs.produce_sound >= 2)
646: close_sound ();
1.1.1.2 root 647:
1.1.1.6 root 648: currprefs.produce_sound = changed_prefs.produce_sound;
1.1.1.13 root 649: currprefs.sound_stereo = changed_prefs.sound_stereo;
1.1.1.6 root 650: currprefs.sound_freq = changed_prefs.sound_freq;
1.1.1.9 root 651: currprefs.sound_maxbsiz = changed_prefs.sound_maxbsiz;
1.1.1.6 root 652: if (currprefs.produce_sound >= 2) {
1.1.1.17 root 653: if (!init_audio ()) {
1.1.1.6 root 654: if (! sound_available) {
1.1.1.11 root 655: write_log ("Sound is not supported.\n");
1.1.1.6 root 656: } else {
1.1.1.11 root 657: write_log ("Sorry, can't initialize sound.\n");
1.1.1.6 root 658: currprefs.produce_sound = 0;
659: /* So we don't do this every frame */
660: changed_prefs.produce_sound = 0;
661: }
1.1.1.17 root 662: }
663: next_sample_evtime = scaled_sample_evtime;
664: last_cycles = get_cycles () - 1;
665: compute_vsynctime ();
666: }
667: if (currprefs.produce_sound == 0) {
668: eventtab[ev_audio].active = 0;
669: events_schedule ();
1.1.1.6 root 670: }
1.1.1.2 root 671: }
1.1.1.17 root 672:
673: led_filter_forced = -1; // always off
674: sound_use_filter = sound_use_filter_sinc = 0;
675: if (currprefs.sound_filter != FILTER_SOUND_OFF) {
676: if (currprefs.sound_filter == FILTER_SOUND_ON)
677: led_filter_forced = 1;
678: if (currprefs.sound_filter == FILTER_SOUND_EMUL)
679: led_filter_forced = 0;
680: if (currprefs.sound_filter_type == FILTER_SOUND_TYPE_A500)
681: sound_use_filter = FILTER_MODEL_A500;
682: else if (currprefs.sound_filter_type == FILTER_SOUND_TYPE_A1200)
683: sound_use_filter = FILTER_MODEL_A1200;
684: }
685: a500e_filter1_a0 = rc_calculate_a0(currprefs.sound_freq, 6200);
686: a500e_filter2_a0 = rc_calculate_a0(currprefs.sound_freq, 20000);
687: filter_a0 = rc_calculate_a0(currprefs.sound_freq, 7000);
688: led_filter_audio();
689:
1.1.1.6 root 690: /* Select the right interpolation method. */
1.1.1.18 root 691: if (sample_handler == sample16s_handler
692: || sample_handler == sample16si_sinc_handler
693: || sample_handler == sample16si_anti_handler)
1.1.1.17 root 694: {
1.1.1.6 root 695: sample_handler = (currprefs.sound_interpol == 0 ? sample16s_handler
1.1.1.18 root 696: : currprefs.sound_interpol == 1 ? sample16si_sinc_handler
1.1.1.17 root 697: : sample16si_anti_handler);
1.1.1.18 root 698: }
1.1.1.16 root 699: sample_prehandler = NULL;
1.1.1.18 root 700: if (currprefs.sound_interpol == 1) {
1.1.1.17 root 701: sound_use_filter_sinc = sound_use_filter;
702: sound_use_filter = 0;
1.1.1.16 root 703: sample_prehandler = sinc_prehandler;
1.1.1.18 root 704: } else if (currprefs.sound_interpol == 2) {
1.1.1.17 root 705: sample_prehandler = anti_prehandler;
1.1.1.7 root 706: }
1.1.1.2 root 707: }
708:
709: void update_audio (void)
710: {
711: unsigned long int n_cycles;
712:
1.1.1.8 root 713: if (currprefs.produce_sound == 0 || savestate_state == STATE_RESTORE)
1.1.1.2 root 714: return;
715:
1.1.1.7 root 716: n_cycles = get_cycles () - last_cycles;
1.1.1.2 root 717: for (;;) {
718: unsigned long int best_evtime = n_cycles + 1;
1.1.1.16 root 719: if (audio_channel[0].evtime != MAX_EV && best_evtime > audio_channel[0].evtime)
1.1.1.10 root 720: best_evtime = audio_channel[0].evtime;
1.1.1.16 root 721: if (audio_channel[1].evtime != MAX_EV && best_evtime > audio_channel[1].evtime)
1.1.1.10 root 722: best_evtime = audio_channel[1].evtime;
1.1.1.16 root 723: if (audio_channel[2].evtime != MAX_EV && best_evtime > audio_channel[2].evtime)
1.1.1.10 root 724: best_evtime = audio_channel[2].evtime;
1.1.1.16 root 725: if (audio_channel[3].evtime != MAX_EV && best_evtime > audio_channel[3].evtime)
1.1.1.10 root 726: best_evtime = audio_channel[3].evtime;
1.1.1.7 root 727: if (currprefs.produce_sound > 1 && best_evtime > next_sample_evtime)
1.1.1.2 root 728: best_evtime = next_sample_evtime;
729:
730: if (best_evtime > n_cycles)
731: break;
732:
1.1.1.16 root 733: if (audio_channel[0].evtime != MAX_EV)
734: audio_channel[0].evtime -= best_evtime;
735: if (audio_channel[1].evtime != MAX_EV)
736: audio_channel[1].evtime -= best_evtime;
737: if (audio_channel[2].evtime != MAX_EV)
738: audio_channel[2].evtime -= best_evtime;
739: if (audio_channel[3].evtime != MAX_EV)
740: audio_channel[3].evtime -= best_evtime;
1.1.1.2 root 741: n_cycles -= best_evtime;
1.1.1.16 root 742: if (currprefs.produce_sound > 1) {
743: next_sample_evtime -= best_evtime;
744: if (sample_prehandler)
745: sample_prehandler (best_evtime / CYCLE_UNIT);
746: if (next_sample_evtime == 0) {
747: next_sample_evtime = scaled_sample_evtime;
748: (*sample_handler) ();
749: }
1.1.1.2 root 750: }
1.1.1.16 root 751: if (audio_channel[0].evtime == 0)
1.1.1.2 root 752: audio_handler (0);
1.1.1.16 root 753: if (audio_channel[1].evtime == 0)
1.1.1.2 root 754: audio_handler (1);
1.1.1.16 root 755: if (audio_channel[2].evtime == 0)
1.1.1.2 root 756: audio_handler (2);
1.1.1.16 root 757: if (audio_channel[3].evtime == 0)
1.1.1.2 root 758: audio_handler (3);
759: }
1.1.1.7 root 760: last_cycles = get_cycles () - n_cycles;
761: }
762:
1.1.1.16 root 763: void update_audio_dmacon (void)
764: {
765: unsigned int i;
766: update_audio ();
767:
768: for (i = 0; i < 4; i++) {
769: struct audio_channel_data *cdp = audio_channel + i;
770: int chan_ena = (dmacon & 0x200) && (dmacon & (1<<i));
771: if (cdp->dmaen == chan_ena)
772: continue;
773: cdp->dmaen = chan_ena;
774: if (cdp->dmaen)
775: audio_channel_enable_dma (cdp);
776: else
777: audio_channel_disable_dma (cdp);
778: }
779: schedule_audio ();
780: }
781:
1.1.1.7 root 782: void audio_evhandler (void)
783: {
784: if (currprefs.produce_sound == 0)
785: abort ();
786:
787: update_audio ();
788: schedule_audio ();
1.1.1.2 root 789: }
790:
1.1.1.15 root 791: void audio_hsync (int dmaaction)
792: {
793: int nr;
794:
795: update_audio ();
796:
797: /* Sound data is fetched at the beginning of each line */
798: for (nr = 0; nr < 4; nr++) {
799: struct audio_channel_data *cdp = audio_channel + nr;
800:
801: if (cdp->data_written == 2) {
802: cdp->data_written = 0;
1.1.1.17 root 803: cdp->nextdat = chipmem_agnus_wget (cdp->pt);
1.1.1.15 root 804: cdp->pt += 2;
805: if (cdp->state == 2 || cdp->state == 3) {
806: if (cdp->wlen == 1) {
807: cdp->pt = cdp->lc;
808: cdp->wlen = cdp->len;
809: cdp->intreq2 = 1;
810: } else
811: cdp->wlen = (cdp->wlen - 1) & 0xFFFF;
812: }
813: }
814: }
815: }
816:
1.1.1.17 root 817: void AUDxDAT (int nr, uae_u16 v)
1.1.1.2 root 818: {
819: struct audio_channel_data *cdp = audio_channel + nr;
820:
1.1.1.7 root 821: if (currprefs.produce_sound == 0)
822: return;
823:
1.1.1.2 root 824: update_audio ();
825:
826: cdp->dat = v;
1.1.1.17 root 827: if (cdp->state == 0 && !(INTREQR () & (0x80 << nr))) {
1.1.1.2 root 828: cdp->state = 2;
1.1.1.17 root 829: INTREQ (0x8000 | (0x80 << nr));
1.1.1.2 root 830: /* data_written = 2 ???? */
831: cdp->evtime = cdp->per;
1.1.1.7 root 832: schedule_audio ();
833: events_schedule ();
1.1.1.2 root 834: }
835: }
836:
1.1.1.17 root 837: void AUDxLCH (int nr, uae_u16 v)
1.1.1.2 root 838: {
839: update_audio ();
840:
841: audio_channel[nr].lc = (audio_channel[nr].lc & 0xffff) | ((uae_u32)v << 16);
842: }
843:
1.1.1.17 root 844: void AUDxLCL (int nr, uae_u16 v)
1.1.1.2 root 845: {
846: update_audio ();
847:
848: audio_channel[nr].lc = (audio_channel[nr].lc & ~0xffff) | (v & 0xFFFE);
849: }
850:
1.1.1.17 root 851: void AUDxPER (int nr, uae_u16 v)
1.1.1.2 root 852: {
1.1.1.7 root 853: unsigned long per = v * CYCLE_UNIT;
1.1.1.2 root 854: update_audio ();
855:
1.1.1.7 root 856: if (per == 0)
857: per = PERIOD_MAX;
1.1.1.2 root 858:
1.1.1.7 root 859: if (per < maxhpos * CYCLE_UNIT / 2 && currprefs.produce_sound < 3)
860: per = maxhpos * CYCLE_UNIT / 2;
1.1.1.16 root 861: /* the sinc code registers paula output state changes, but has a finite
862: * buffer in which to do so. Hence, we forbid very low values; this should
863: * only limit the accurate rendering of supersonic sounds, which are
864: * filtered away on the sinc output path anyway. */
865: if (currprefs.produce_sound == 3 && sample_handler == sample16si_sinc_handler && per < MIN_ALLOWED_PERIOD * CYCLE_UNIT)
866: per = MIN_ALLOWED_PERIOD * CYCLE_UNIT;
1.1.1.2 root 867:
1.1.1.16 root 868: if (audio_channel[nr].per == PERIOD_MAX && per != PERIOD_MAX
869: && audio_channel[nr].evtime != MAX_EV) {
1.1.1.8 root 870: audio_channel[nr].evtime = CYCLE_UNIT;
1.1.1.9 root 871: if (currprefs.produce_sound > 0) {
872: schedule_audio ();
873: events_schedule ();
874: }
1.1.1.8 root 875: }
1.1.1.16 root 876:
1.1.1.7 root 877: audio_channel[nr].per = per;
1.1.1.2 root 878: }
879:
1.1.1.17 root 880: void AUDxLEN (int nr, uae_u16 v)
1.1.1.2 root 881: {
882: update_audio ();
883: audio_channel[nr].len = v;
884: }
885:
1.1.1.17 root 886: void AUDxVOL (int nr, uae_u16 v)
1.1.1.2 root 887: {
888: int v2 = v & 64 ? 63 : v & 63;
889:
890: update_audio ();
891:
892: audio_channel[nr].vol = v2;
1.1 root 893: }
894:
1.1.1.15 root 895: void update_adkmasks (void)
896: {
897: unsigned long t;
898:
899: t = adkcon | (adkcon >> 4);
900: audio_channel[0].adk_mask = (((t >> 0) & 1) - 1);
901: audio_channel[1].adk_mask = (((t >> 1) & 1) - 1);
902: audio_channel[2].adk_mask = (((t >> 2) & 1) - 1);
903: audio_channel[3].adk_mask = (((t >> 3) & 1) - 1);
904: }
905:
1.1.1.7 root 906: int init_audio (void)
1.1 root 907: {
1.1.1.16 root 908: int result = init_sound ();
909: update_sound (vblank_hz);
910: return result;
1.1.1.7 root 911: }
912:
1.1.1.17 root 913: void led_filter_audio (void)
914: {
915: led_filter_on = 0;
916: if (led_filter_forced > 0 || (gui_data.powerled && led_filter_forced >= 0))
917: led_filter_on = 1;
918: gui_led (0, gui_data.powerled);
919: }
920:
1.1.1.8 root 921: /* audio save/restore code FIXME: not working correctly */
922: /* help needed */
923:
1.1.1.16 root 924: const uae_u8 *restore_audio (int i, const uae_u8 *src)
1.1.1.8 root 925: {
926: struct audio_channel_data *acd;
927: uae_u16 p;
928:
929: acd = audio_channel + i;
930: acd->state = restore_u8 ();
931: acd->vol = restore_u8 ();
932: acd->intreq2 = restore_u8 ();
933: acd->data_written = restore_u8 ();
934: acd->len = restore_u16 ();
935: acd->wlen = restore_u16 ();
936: p = restore_u16 ();
937: acd->per = p ? p * CYCLE_UNIT : PERIOD_MAX;
938: p = restore_u16 ();
939: acd->wper = p ? p * CYCLE_UNIT : PERIOD_MAX;
940: acd->lc = restore_u32 ();
941: acd->pt = restore_u32 ();
942: acd->evtime = restore_u32 ();
943:
944: return src;
945: }
946:
1.1.1.15 root 947: uae_u8 *save_audio (int i, int *len)
1.1.1.8 root 948: {
949: struct audio_channel_data *acd;
950: uae_u8 *dst = malloc (100);
951: uae_u8 *dstbak = dst;
952: uae_u16 p;
953:
954: acd = audio_channel + i;
955: save_u8 ((uae_u8)acd->state);
956: save_u8 (acd->vol);
957: save_u8 (acd->intreq2);
958: save_u8 (acd->data_written);
959: save_u16 (acd->len);
960: save_u16 (acd->wlen);
961: p = acd->per == PERIOD_MAX ? 0 : acd->per / CYCLE_UNIT;
962: save_u16 (p);
963: p = acd->per == PERIOD_MAX ? 0 : acd->wper / CYCLE_UNIT;
964: save_u16 (p);
965: save_u32 (acd->lc);
966: save_u32 (acd->pt);
967: save_u32 (acd->evtime);
968: *len = dst - dstbak;
969: return dstbak;
970: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.