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