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