|
|
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"
18: #include "gensound.h"
19: #include "sounddep/sound.h"
20: #include "events.h"
21: #include "audio.h"
22:
23: #undef BENCHMARK_AUDIO
24:
25: #ifdef BENCHMARK_AUDIO
26:
27: #define BEGIN_BENCH frame_time_t audbench = read_processor_time ();
28: #define END_BENCH sh_time += read_processor_time () - audbench; sh_count++;
29: static frame_time_t sh_time = 0;
30: unsigned long sh_count = 0;
31:
32: #else
33:
34: #define BEGIN_BENCH
35: #define END_BENCH
36:
37: #endif
38:
39: struct audio_channel_data audio_channel[4];
1.1.1.2 root 40: int sound_available = 0;
1.1 root 41: int sound_table[64][256];
1.1.1.2 root 42: void (*sample_handler) (void);
1.1 root 43: unsigned long int sample_evtime;
1.1.1.2 root 44: static unsigned long last_cycles, next_sample_evtime;
1.1 root 45:
1.1.1.2 root 46: void init_sound_table16 (void)
1.1 root 47: {
48: int i,j;
49:
50: for (i = 0; i < 256; i++)
51: for (j = 0; j < 64; j++)
52: sound_table[j][i] = j * (uae_s8)i * (currprefs.stereo ? 2 : 1);
53: }
54:
55: void init_sound_table8 (void)
56: {
57: int i,j;
58:
59: for (i = 0; i < 256; i++)
60: for (j = 0; j < 64; j++)
61: sound_table[j][i] = (j * (uae_s8)i * (currprefs.stereo ? 2 : 1)) / 256;
62: }
63:
64: #define MULTIPLICATION_PROFITABLE
65:
66: #ifdef MULTIPLICATION_PROFITABLE
67: typedef uae_s8 sample8_t;
68: #define DO_CHANNEL_1(v, c) do { (v) *= audio_channel[c].vol; } while (0)
69: #define SBASEVAL8(logn) ((logn) == 1 ? SOUND8_BASE_VAL << 7 : SOUND8_BASE_VAL << 8)
70: #define SBASEVAL16(logn) ((logn) == 1 ? SOUND16_BASE_VAL >> 1 : SOUND16_BASE_VAL)
71: #define FINISH_DATA(b,logn) do { if (14 - (b) + (logn) > 0) data >>= 14 - (b) + (logn); else data <<= (b) - 14 - (logn); } while (0);
72: #else
73: typedef uae_u8 sample8_t;
74: #define DO_CHANNEL_1(v, c) do { (v) = audio_channel[c].voltbl[(v)]; } while (0)
75: #define SBASEVAL8(logn) SOUND8_BASE_VAL
76: #define SBASEVAL16(logn) SOUND16_BASE_VAL
77: #define FINISH_DATA(b,logn)
78: #endif
79:
80: #define DO_CHANNEL(v, c) do { (v) &= audio_channel[c].adk_mask; data += v; } while (0);
81:
1.1.1.2 root 82: void sample16_handler (void)
1.1 root 83: {
84: BEGIN_BENCH
85:
86: uae_u32 data0 = audio_channel[0].current_sample;
87: uae_u32 data1 = audio_channel[1].current_sample;
88: uae_u32 data2 = audio_channel[2].current_sample;
89: uae_u32 data3 = audio_channel[3].current_sample;
90: DO_CHANNEL_1 (data0, 0);
91: DO_CHANNEL_1 (data1, 1);
92: DO_CHANNEL_1 (data2, 2);
93: DO_CHANNEL_1 (data3, 3);
94: data0 &= audio_channel[0].adk_mask;
95: data1 &= audio_channel[1].adk_mask;
96: data2 &= audio_channel[2].adk_mask;
97: data3 &= audio_channel[3].adk_mask;
98: data0 += data1;
99: data0 += data2;
100: data0 += data3;
101: {
102: uae_u32 data = SBASEVAL16(2) + data0;
103: FINISH_DATA(16, 2);
104: PUT_SOUND_WORD (data);
105: }
106: END_BENCH
107:
108: check_sound_buffers ();
109: }
110:
1.1.1.6 ! root 111: void sample16i_rh_handler (void)
1.1.1.5 root 112: {
113: unsigned long delta, ratio;
114:
115: BEGIN_BENCH
116:
117: uae_u32 data0 = audio_channel[0].current_sample;
118: uae_u32 data1 = audio_channel[1].current_sample;
119: uae_u32 data2 = audio_channel[2].current_sample;
120: uae_u32 data3 = audio_channel[3].current_sample;
121: uae_u32 data0p = audio_channel[0].last_sample;
122: uae_u32 data1p = audio_channel[1].last_sample;
123: uae_u32 data2p = audio_channel[2].last_sample;
124: uae_u32 data3p = audio_channel[3].last_sample;
125: DO_CHANNEL_1 (data0, 0);
126: DO_CHANNEL_1 (data1, 1);
127: DO_CHANNEL_1 (data2, 2);
128: DO_CHANNEL_1 (data3, 3);
129: DO_CHANNEL_1 (data0p, 0);
130: DO_CHANNEL_1 (data1p, 1);
131: DO_CHANNEL_1 (data2p, 2);
132: DO_CHANNEL_1 (data3p, 3);
133:
134: data0 &= audio_channel[0].adk_mask;
135: data0p &= audio_channel[0].adk_mask;
136: data1 &= audio_channel[1].adk_mask;
137: data1p &= audio_channel[1].adk_mask;
138: data2 &= audio_channel[2].adk_mask;
139: data2p &= audio_channel[2].adk_mask;
140: data3 &= audio_channel[3].adk_mask;
141: data3p &= audio_channel[3].adk_mask;
142:
143: /* linear interpolation and summing up... */
144: delta = audio_channel[0].per;
145: ratio = ((audio_channel[0].evtime % delta) << 8) / delta;
146: data0 = (data0 * (256 - ratio) + data0p * ratio) >> 8;
147: delta = audio_channel[1].per;
148: ratio = ((audio_channel[1].evtime % delta) << 8) / delta;
149: data0 += (data1 * (256 - ratio) + data1p * ratio) >> 8;
150: delta = audio_channel[2].per;
151: ratio = ((audio_channel[2].evtime % delta) << 8) / delta;
152: data0 += (data2 * (256 - ratio) + data2p * ratio) >> 8;
153: delta = audio_channel[3].per;
154: ratio = ((audio_channel[3].evtime % delta) << 8) / delta;
155: data0 += (data3 * (256 - ratio) + data3p * ratio) >> 8;
156:
157: {
158: uae_u32 data = SBASEVAL16(2) + data0;
159: FINISH_DATA(16, 2);
160: PUT_SOUND_WORD (data);
161: }
162: END_BENCH
163:
164: check_sound_buffers ();
165: }
166:
1.1.1.6 ! root 167: void sample16i_crux_handler (void)
! 168: {
! 169: unsigned long delta, ratio;
! 170:
! 171: BEGIN_BENCH
! 172:
! 173: uae_u32 data0 = audio_channel[0].current_sample;
! 174: uae_u32 data1 = audio_channel[1].current_sample;
! 175: uae_u32 data2 = audio_channel[2].current_sample;
! 176: uae_u32 data3 = audio_channel[3].current_sample;
! 177: uae_u32 data0p = audio_channel[0].last_sample;
! 178: uae_u32 data1p = audio_channel[1].last_sample;
! 179: uae_u32 data2p = audio_channel[2].last_sample;
! 180: uae_u32 data3p = audio_channel[3].last_sample;
! 181: DO_CHANNEL_1 (data0, 0);
! 182: DO_CHANNEL_1 (data1, 1);
! 183: DO_CHANNEL_1 (data2, 2);
! 184: DO_CHANNEL_1 (data3, 3);
! 185: DO_CHANNEL_1 (data0p, 0);
! 186: DO_CHANNEL_1 (data1p, 1);
! 187: DO_CHANNEL_1 (data2p, 2);
! 188: DO_CHANNEL_1 (data3p, 3);
! 189:
! 190: data0 &= audio_channel[0].adk_mask;
! 191: data0p &= audio_channel[0].adk_mask;
! 192: data1 &= audio_channel[1].adk_mask;
! 193: data1p &= audio_channel[1].adk_mask;
! 194: data2 &= audio_channel[2].adk_mask;
! 195: data2p &= audio_channel[2].adk_mask;
! 196: data3 &= audio_channel[3].adk_mask;
! 197: data3p &= audio_channel[3].adk_mask;
! 198:
! 199: {
! 200: struct audio_channel_data *cdp;
! 201: int ratio, ratio1;
! 202: #define INTERVAL (sample_evtime * 3)
! 203: cdp = audio_channel + 0;
! 204: ratio1 = cdp->per - cdp->evtime;
! 205: ratio = (ratio1 << 12) / INTERVAL;
! 206: if (cdp->evtime < sample_evtime || ratio1 >= INTERVAL)
! 207: ratio = 4096;
! 208: data0 = (data0 * ratio + data0p * (4096 - ratio)) >> 12;
! 209:
! 210: cdp = audio_channel + 1;
! 211: ratio1 = cdp->per - cdp->evtime;
! 212: ratio = (ratio1 << 12) / INTERVAL;
! 213: if (cdp->evtime < sample_evtime || ratio1 >= INTERVAL)
! 214: ratio = 4096;
! 215: data1 = (data1 * ratio + data1p * (4096 - ratio)) >> 12;
! 216:
! 217: cdp = audio_channel + 2;
! 218: ratio1 = cdp->per - cdp->evtime;
! 219: ratio = (ratio1 << 12) / INTERVAL;
! 220: if (cdp->evtime < sample_evtime || ratio1 >= INTERVAL)
! 221: ratio = 4096;
! 222: data2 = (data2 * ratio + data2p * (4096 - ratio)) >> 12;
! 223:
! 224: cdp = audio_channel + 3;
! 225: ratio1 = cdp->per - cdp->evtime;
! 226: ratio = (ratio1 << 12) / INTERVAL;
! 227: if (cdp->evtime < sample_evtime || ratio1 >= INTERVAL)
! 228: ratio = 4096;
! 229: data3 = (data3 * ratio + data3p * (4096 - ratio)) >> 12;
! 230: }
! 231: data1 += data2;
! 232: data0 += data3;
! 233: data0 += data1;
! 234: {
! 235: uae_u32 data = SBASEVAL16(2) + data0;
! 236: FINISH_DATA(16, 2);
! 237: PUT_SOUND_WORD (data);
! 238: }
! 239: END_BENCH
! 240:
! 241: check_sound_buffers ();
! 242: }
! 243:
1.1.1.2 root 244: void sample8_handler (void)
1.1 root 245: {
246: BEGIN_BENCH
247:
248: uae_u32 data0 = audio_channel[0].current_sample;
249: uae_u32 data1 = audio_channel[1].current_sample;
250: uae_u32 data2 = audio_channel[2].current_sample;
251: uae_u32 data3 = audio_channel[3].current_sample;
252: DO_CHANNEL_1 (data0, 0);
253: DO_CHANNEL_1 (data1, 1);
254: DO_CHANNEL_1 (data2, 2);
255: DO_CHANNEL_1 (data3, 3);
256: data0 &= audio_channel[0].adk_mask;
257: data1 &= audio_channel[1].adk_mask;
258: data2 &= audio_channel[2].adk_mask;
259: data3 &= audio_channel[3].adk_mask;
260: data0 += data1;
261: data0 += data2;
262: data0 += data3;
263: {
264: uae_u32 data = SBASEVAL8(2) + data0;
265: FINISH_DATA(8, 2);
266: PUT_SOUND_BYTE (data);
267: }
268: END_BENCH
269:
270: check_sound_buffers ();
271: }
272:
273: #ifdef HAVE_STEREO_SUPPORT
1.1.1.2 root 274: void sample16s_handler (void)
1.1 root 275: {
276: BEGIN_BENCH
277:
278: uae_u32 data0 = audio_channel[0].current_sample;
279: uae_u32 data1 = audio_channel[1].current_sample;
280: uae_u32 data2 = audio_channel[2].current_sample;
281: uae_u32 data3 = audio_channel[3].current_sample;
282: DO_CHANNEL_1 (data0, 0);
283: DO_CHANNEL_1 (data1, 1);
284: DO_CHANNEL_1 (data2, 2);
285: DO_CHANNEL_1 (data3, 3);
286:
287: data0 &= audio_channel[0].adk_mask;
288: data1 &= audio_channel[1].adk_mask;
289: data2 &= audio_channel[2].adk_mask;
290: data3 &= audio_channel[3].adk_mask;
291:
292: data0 += data3;
293: {
294: uae_u32 data = SBASEVAL16(1) + data0;
295: FINISH_DATA (16, 1);
296: PUT_SOUND_WORD_RIGHT (data);
297: }
298:
299: data1 += data2;
300: {
301: uae_u32 data = SBASEVAL16(1) + data1;
302: FINISH_DATA (16, 1);
303: PUT_SOUND_WORD_LEFT (data);
304: }
305:
306: END_BENCH
307:
308: check_sound_buffers ();
309: }
310:
1.1.1.6 ! root 311: void sample16si_crux_handler (void)
1.1.1.5 root 312: {
313: unsigned long delta, ratio;
314:
315: BEGIN_BENCH
316:
317: uae_u32 data0 = audio_channel[0].current_sample;
318: uae_u32 data1 = audio_channel[1].current_sample;
319: uae_u32 data2 = audio_channel[2].current_sample;
320: uae_u32 data3 = audio_channel[3].current_sample;
321: uae_u32 data0p = audio_channel[0].last_sample;
322: uae_u32 data1p = audio_channel[1].last_sample;
323: uae_u32 data2p = audio_channel[2].last_sample;
324: uae_u32 data3p = audio_channel[3].last_sample;
325:
326: DO_CHANNEL_1 (data0, 0);
327: DO_CHANNEL_1 (data1, 1);
328: DO_CHANNEL_1 (data2, 2);
329: DO_CHANNEL_1 (data3, 3);
330: DO_CHANNEL_1 (data0p, 0);
331: DO_CHANNEL_1 (data1p, 1);
332: DO_CHANNEL_1 (data2p, 2);
333: DO_CHANNEL_1 (data3p, 3);
334:
335: data0 &= audio_channel[0].adk_mask;
336: data0p &= audio_channel[0].adk_mask;
337: data1 &= audio_channel[1].adk_mask;
338: data1p &= audio_channel[1].adk_mask;
339: data2 &= audio_channel[2].adk_mask;
340: data2p &= audio_channel[2].adk_mask;
341: data3 &= audio_channel[3].adk_mask;
342: data3p &= audio_channel[3].adk_mask;
343:
344: {
345: struct audio_channel_data *cdp;
346: int ratio, ratio1;
1.1.1.6 ! root 347: #define INTERVAL (sample_evtime * 3)
1.1.1.5 root 348: cdp = audio_channel + 0;
349: ratio1 = cdp->per - cdp->evtime;
350: ratio = (ratio1 << 12) / INTERVAL;
351: if (cdp->evtime < sample_evtime || ratio1 >= INTERVAL)
352: ratio = 4096;
353: data0 = (data0 * ratio + data0p * (4096 - ratio)) >> 12;
354:
355: cdp = audio_channel + 1;
356: ratio1 = cdp->per - cdp->evtime;
357: ratio = (ratio1 << 12) / INTERVAL;
358: if (cdp->evtime < sample_evtime || ratio1 >= INTERVAL)
359: ratio = 4096;
360: data1 = (data1 * ratio + data1p * (4096 - ratio)) >> 12;
361:
362: cdp = audio_channel + 2;
363: ratio1 = cdp->per - cdp->evtime;
364: ratio = (ratio1 << 12) / INTERVAL;
365: if (cdp->evtime < sample_evtime || ratio1 >= INTERVAL)
366: ratio = 4096;
367: data2 = (data2 * ratio + data2p * (4096 - ratio)) >> 12;
368:
369: cdp = audio_channel + 3;
370: ratio1 = cdp->per - cdp->evtime;
371: ratio = (ratio1 << 12) / INTERVAL;
372: if (cdp->evtime < sample_evtime || ratio1 >= INTERVAL)
373: ratio = 4096;
374: data3 = (data3 * ratio + data3p * (4096 - ratio)) >> 12;
375: }
376: data1 += data2;
377: data0 += data3;
1.1.1.6 ! root 378: {
! 379: uae_u32 data = SBASEVAL16 (1) + data0;
! 380: FINISH_DATA (16, 1);
! 381: PUT_SOUND_WORD_RIGHT (data);
! 382: }
! 383:
! 384: {
! 385: uae_u32 data = SBASEVAL16 (1) + data1;
! 386: FINISH_DATA (16, 1);
! 387: PUT_SOUND_WORD_LEFT (data);
! 388: }
! 389:
! 390: END_BENCH
! 391:
! 392: check_sound_buffers ();
! 393: }
! 394:
! 395: void sample16si_rh_handler (void)
! 396: {
! 397: unsigned long delta, ratio;
! 398:
! 399: BEGIN_BENCH
! 400:
! 401: uae_u32 data0 = audio_channel[0].current_sample;
! 402: uae_u32 data1 = audio_channel[1].current_sample;
! 403: uae_u32 data2 = audio_channel[2].current_sample;
! 404: uae_u32 data3 = audio_channel[3].current_sample;
! 405: uae_u32 data0p = audio_channel[0].last_sample;
! 406: uae_u32 data1p = audio_channel[1].last_sample;
! 407: uae_u32 data2p = audio_channel[2].last_sample;
! 408: uae_u32 data3p = audio_channel[3].last_sample;
! 409:
! 410: DO_CHANNEL_1 (data0, 0);
! 411: DO_CHANNEL_1 (data1, 1);
! 412: DO_CHANNEL_1 (data2, 2);
! 413: DO_CHANNEL_1 (data3, 3);
! 414: DO_CHANNEL_1 (data0p, 0);
! 415: DO_CHANNEL_1 (data1p, 1);
! 416: DO_CHANNEL_1 (data2p, 2);
! 417: DO_CHANNEL_1 (data3p, 3);
! 418:
! 419: data0 &= audio_channel[0].adk_mask;
! 420: data0p &= audio_channel[0].adk_mask;
! 421: data1 &= audio_channel[1].adk_mask;
! 422: data1p &= audio_channel[1].adk_mask;
! 423: data2 &= audio_channel[2].adk_mask;
! 424: data2p &= audio_channel[2].adk_mask;
! 425: data3 &= audio_channel[3].adk_mask;
! 426: data3p &= audio_channel[3].adk_mask;
! 427:
! 428: /* linear interpolation and summing up... */
! 429: delta = audio_channel[0].per;
! 430: ratio = ((audio_channel[0].evtime % delta) << 8) / delta;
! 431: data0 = (data0 * (256 - ratio) + data0p * ratio) >> 8;
! 432: delta = audio_channel[1].per;
! 433: ratio = ((audio_channel[1].evtime % delta) << 8) / delta;
! 434: data1 = (data1 * (256 - ratio) + data1p * ratio) >> 8;
! 435: delta = audio_channel[2].per;
! 436: ratio = ((audio_channel[2].evtime % delta) << 8) / delta;
! 437: data1 += (data2 * (256 - ratio) + data2p * ratio) >> 8;
! 438: delta = audio_channel[3].per;
! 439: ratio = ((audio_channel[3].evtime % delta) << 8) / delta;
! 440: data0 += (data3 * (256 - ratio) + data3p * ratio) >> 8;
1.1.1.5 root 441: {
442: uae_u32 data = SBASEVAL16 (1) + data0;
443: FINISH_DATA (16, 1);
444: PUT_SOUND_WORD_RIGHT (data);
445: }
446:
447: {
448: uae_u32 data = SBASEVAL16 (1) + data1;
449: FINISH_DATA (16, 1);
450: PUT_SOUND_WORD_LEFT (data);
451: }
452:
453: END_BENCH
454:
455: check_sound_buffers ();
456: }
457:
1.1.1.2 root 458: void sample8s_handler (void)
1.1 root 459: {
460: BEGIN_BENCH
461:
462: uae_u32 data0 = audio_channel[0].current_sample;
463: uae_u32 data1 = audio_channel[1].current_sample;
464: uae_u32 data2 = audio_channel[2].current_sample;
465: uae_u32 data3 = audio_channel[3].current_sample;
466: DO_CHANNEL_1 (data0, 0);
467: DO_CHANNEL_1 (data1, 1);
468: DO_CHANNEL_1 (data2, 2);
469: DO_CHANNEL_1 (data3, 3);
470:
471: data0 &= audio_channel[0].adk_mask;
472: data1 &= audio_channel[1].adk_mask;
473: data2 &= audio_channel[2].adk_mask;
474: data3 &= audio_channel[3].adk_mask;
475:
476: data0 += data3;
477: {
478: uae_u32 data = SBASEVAL8(1) + data0;
479: FINISH_DATA (8, 1);
480: PUT_SOUND_BYTE_RIGHT (data);
481: }
482: data1 += data2;
483: {
484: uae_u32 data = SBASEVAL8(1) + data1;
485: FINISH_DATA (8, 1);
486: PUT_SOUND_BYTE_LEFT (data);
487: }
488:
489: END_BENCH
490:
491: check_sound_buffers ();
492: }
493: #else
1.1.1.2 root 494: void sample8s_handler (void)
1.1 root 495: {
496: sample8_handler();
497: }
1.1.1.2 root 498: void sample16s_handler (void)
1.1 root 499: {
500: sample16_handler();
501: }
1.1.1.6 ! root 502: void sample16si_crux_handler (void)
! 503: {
! 504: sample16i_crux_handler();
! 505: }
! 506: void sample16si_rh_handler (void)
! 507: {
! 508: sample16i_rh_handler();
! 509: }
1.1 root 510: #endif
511:
1.1.1.2 root 512: static uae_u8 int2ulaw (int ch)
1.1 root 513: {
514: int mask;
515:
516: if (ch < 0) {
517: ch = -ch;
518: mask = 0x7f;
519: }
520: else {
521: mask = 0xff;
522: }
523:
524: if (ch < 32) {
525: ch = 0xF0 | ( 15 - (ch/2) );
526: } else if (ch < 96) {
527: ch = 0xE0 | ( 15 - (ch-32)/4 );
528: } else if (ch < 224) {
529: ch = 0xD0 | ( 15 - (ch-96)/8 );
530: } else if (ch < 480) {
531: ch = 0xC0 | ( 15 - (ch-224)/16 );
532: } else if (ch < 992 ) {
533: ch = 0xB0 | ( 15 - (ch-480)/32 );
534: } else if (ch < 2016) {
535: ch = 0xA0 | ( 15 - (ch-992)/64 );
536: } else if (ch < 4064) {
537: ch = 0x90 | ( 15 - (ch-2016)/128 );
538: } else if (ch < 8160) {
539: ch = 0x80 | ( 15 - (ch-4064)/256 );
540: } else {
541: ch = 0x80;
542: }
543: return (uae_u8)(mask & ch);
544: }
545:
546: void sample_ulaw_handler (void)
547: {
548: int nr;
549: uae_u32 data = 0;
550:
551: for (nr = 0; nr < 4; nr++) {
552: if (!(adkcon & (0x11 << nr))) {
553: uae_u32 d = audio_channel[nr].current_sample;
554: DO_CHANNEL_1 (d, nr);
555: data += d;
556: }
557: }
558: PUT_SOUND_BYTE (int2ulaw (data));
559: check_sound_buffers ();
560: }
561:
562: static void audio_handler (int nr)
563: {
564: struct audio_channel_data *cdp = audio_channel + nr;
565:
566: switch (cdp->state) {
567: case 0:
568: fprintf(stderr, "Bug in sound code\n");
569: break;
570:
571: case 1:
572: /* We come here at the first hsync after DMA was turned on. */
1.1.1.2 root 573: cdp->evtime = maxhpos;
1.1 root 574:
575: cdp->state = 5;
576: INTREQ(0x8000 | (0x80 << nr));
577: if (cdp->wlen != 1)
578: cdp->wlen--;
579: cdp->nextdat = chipmem_bank.wget(cdp->pt);
580:
581: cdp->pt += 2;
582: break;
583:
584: case 5:
585: /* We come here at the second hsync after DMA was turned on. */
586: if (currprefs.produce_sound == 0)
587: cdp->per = 65535;
588:
1.1.1.2 root 589: cdp->evtime = cdp->per;
1.1 root 590: cdp->dat = cdp->nextdat;
1.1.1.5 root 591: cdp->last_sample = cdp->current_sample;
1.1 root 592: cdp->current_sample = (sample8_t)(cdp->dat >> 8);
593:
594: cdp->state = 2;
595: {
596: int audav = adkcon & (1 << nr);
597: int audap = adkcon & (16 << nr);
598: int napnav = (!audav && !audap) || audav;
599: if (napnav)
600: cdp->data_written = 2;
601: }
602: break;
603:
604: case 2:
605: /* We come here when a 2->3 transition occurs */
606: if (currprefs.produce_sound == 0)
607: cdp->per = 65535;
608:
1.1.1.5 root 609: cdp->last_sample = cdp->current_sample;
1.1 root 610: cdp->current_sample = (sample8_t)(cdp->dat & 0xFF);
1.1.1.2 root 611: cdp->evtime = cdp->per;
1.1 root 612:
613: cdp->state = 3;
614:
615: /* Period attachment? */
616: if (adkcon & (0x10 << nr)) {
617: if (cdp->intreq2 && cdp->dmaen)
618: INTREQ(0x8000 | (0x80 << nr));
619: cdp->intreq2 = 0;
620:
621: cdp->dat = cdp->nextdat;
622: if (cdp->dmaen)
623: cdp->data_written = 2;
624: if (nr < 3) {
625: if (cdp->dat == 0)
626: (cdp+1)->per = 65535;
627:
628: else if (cdp->dat < maxhpos/2 && currprefs.produce_sound < 3)
629: (cdp+1)->per = maxhpos/2;
630: else
631: (cdp+1)->per = cdp->dat;
632: }
633: }
634: break;
635:
636: case 3:
637: /* We come here when a 3->2 transition occurs */
638: if (currprefs.produce_sound == 0)
639: cdp->per = 65535;
640:
1.1.1.2 root 641: cdp->evtime = cdp->per;
1.1 root 642:
643: if ((INTREQR() & (0x80 << nr)) && !cdp->dmaen) {
644: cdp->state = 0;
1.1.1.5 root 645: cdp->last_sample = 0;
1.1 root 646: cdp->current_sample = 0;
647: break;
648: } else {
649: int audav = adkcon & (1 << nr);
650: int audap = adkcon & (16 << nr);
651: int napnav = (!audav && !audap) || audav;
652: cdp->state = 2;
653:
654: if ((cdp->intreq2 && cdp->dmaen && napnav)
655: || (napnav && !cdp->dmaen))
656: INTREQ(0x8000 | (0x80 << nr));
657: cdp->intreq2 = 0;
658:
659: cdp->dat = cdp->nextdat;
1.1.1.5 root 660: cdp->last_sample = cdp->current_sample;
1.1 root 661: cdp->current_sample = (sample8_t)(cdp->dat >> 8);
662:
663: if (cdp->dmaen && napnav)
664: cdp->data_written = 2;
665:
666: /* Volume attachment? */
667: if (audav) {
668: if (nr < 3) {
669: (cdp+1)->vol = cdp->dat;
670: #ifndef MULTIPLICATION_PROFITABLE
671: (cdp+1)->voltbl = sound_table[cdp->dat];
672: #endif
673: }
674: }
675: }
676: break;
677:
678: default:
679: cdp->state = 0;
680: break;
681: }
682: }
683:
684: void aud0_handler (void)
685: {
686: audio_handler (0);
687: }
688: void aud1_handler (void)
689: {
690: audio_handler (1);
691: }
692: void aud2_handler (void)
693: {
694: audio_handler (2);
695: }
696: void aud3_handler (void)
697: {
698: audio_handler (3);
699: }
700:
701: void audio_reset (void)
702: {
703: memset (audio_channel, 0, sizeof audio_channel);
704: audio_channel[0].per = 65535;
705: audio_channel[1].per = 65535;
706: audio_channel[2].per = 65535;
707: audio_channel[3].per = 65535;
708: audio_channel[0].voltbl = sound_table[0];
709: audio_channel[1].voltbl = sound_table[0];
710: audio_channel[2].voltbl = sound_table[0];
711: audio_channel[3].voltbl = sound_table[0];
1.1.1.2 root 712:
713: last_cycles = 0;
714: next_sample_evtime = sample_evtime;
715: }
716:
1.1.1.6 ! root 717: STATIC_INLINE int sound_prefs_changed (void)
1.1.1.2 root 718: {
719: return (changed_prefs.produce_sound != currprefs.produce_sound
720: || changed_prefs.stereo != currprefs.stereo
1.1.1.4 root 721: || changed_prefs.sound_freq != currprefs.sound_freq
1.1.1.2 root 722: || changed_prefs.sound_bits != currprefs.sound_bits);
723: }
724:
725: void check_prefs_changed_audio (void)
726: {
1.1.1.6 ! root 727: if (sound_available && sound_prefs_changed ()) {
! 728: close_sound ();
1.1.1.2 root 729:
1.1.1.6 ! root 730: currprefs.produce_sound = changed_prefs.produce_sound;
! 731: currprefs.stereo = changed_prefs.stereo;
! 732: currprefs.sound_bits = changed_prefs.sound_bits;
! 733: currprefs.sound_freq = changed_prefs.sound_freq;
! 734:
! 735: if (currprefs.produce_sound >= 2) {
! 736: if (init_sound ()) {
! 737: last_cycles = cycles - 1;
! 738: next_sample_evtime = sample_evtime;
! 739: } else
! 740: if (! sound_available) {
! 741: fprintf (stderr, "Sound is not supported.\n");
! 742: } else {
! 743: fprintf (stderr, "Sorry, can't initialize sound.\n");
! 744: currprefs.produce_sound = 0;
! 745: /* So we don't do this every frame */
! 746: changed_prefs.produce_sound = 0;
! 747: }
! 748: }
1.1.1.2 root 749: }
1.1.1.6 ! root 750: /* Select the right interpolation method. */
! 751: if (sample_handler == sample16_handler
! 752: || sample_handler == sample16i_crux_handler
! 753: || sample_handler == sample16i_rh_handler)
! 754: sample_handler = (currprefs.sound_interpol == 0 ? sample16_handler
! 755: : currprefs.sound_interpol == 1 ? sample16i_rh_handler
! 756: : sample16i_crux_handler);
! 757: else if (sample_handler == sample16s_handler
! 758: || sample_handler == sample16si_crux_handler
! 759: || sample_handler == sample16si_rh_handler)
! 760: sample_handler = (currprefs.sound_interpol == 0 ? sample16s_handler
! 761: : currprefs.sound_interpol == 1 ? sample16si_rh_handler
! 762: : sample16si_crux_handler);
1.1.1.2 root 763: }
764:
765: void update_audio (void)
766: {
767: unsigned long int n_cycles;
768:
1.1.1.4 root 769: if (currprefs.produce_sound < 2)
1.1.1.2 root 770: return;
771:
772: n_cycles = cycles - last_cycles;
773: for (;;) {
774: int best = -1;
775: unsigned long int best_evtime = n_cycles + 1;
776: if (audio_channel[0].state != 0 && best_evtime > audio_channel[0].evtime)
777: best = 0, best_evtime = audio_channel[0].evtime;
778: if (audio_channel[1].state != 0 && best_evtime > audio_channel[1].evtime)
779: best = 1, best_evtime = audio_channel[1].evtime;
780: if (audio_channel[2].state != 0 && best_evtime > audio_channel[2].evtime)
781: best = 2, best_evtime = audio_channel[2].evtime;
782: if (audio_channel[3].state != 0 && best_evtime > audio_channel[3].evtime)
783: best = 3, best_evtime = audio_channel[3].evtime;
784: if (best_evtime > next_sample_evtime)
785: best_evtime = next_sample_evtime;
786:
787: if (best_evtime > n_cycles)
788: break;
789:
790: next_sample_evtime -= best_evtime;
791: audio_channel[0].evtime -= best_evtime;
792: audio_channel[1].evtime -= best_evtime;
793: audio_channel[2].evtime -= best_evtime;
794: audio_channel[3].evtime -= best_evtime;
795: n_cycles -= best_evtime;
1.1.1.3 root 796: if (next_sample_evtime == 0 && currprefs.produce_sound > 1) {
1.1.1.2 root 797: next_sample_evtime = sample_evtime;
798: (*sample_handler) ();
799: }
800: if (audio_channel[0].evtime == 0 && audio_channel[0].state != 0)
801: audio_handler (0);
802: if (audio_channel[1].evtime == 0 && audio_channel[1].state != 0)
803: audio_handler (1);
804: if (audio_channel[2].evtime == 0 && audio_channel[2].state != 0)
805: audio_handler (2);
806: if (audio_channel[3].evtime == 0 && audio_channel[3].state != 0)
807: audio_handler (3);
808: }
809: last_cycles = cycles - n_cycles;
810: }
811:
812: void AUDxDAT (int nr, uae_u16 v)
813: {
814: struct audio_channel_data *cdp = audio_channel + nr;
815:
816: update_audio ();
817:
818: cdp->dat = v;
819: if (cdp->state == 0 && !(INTREQR() & (0x80 << nr))) {
820: cdp->state = 2;
821: INTREQ(0x8000 | (0x80 << nr));
822: /* data_written = 2 ???? */
823: cdp->evtime = cdp->per;
824: }
825: }
826:
827: void AUDxLCH (int nr, uae_u16 v)
828: {
829: update_audio ();
830:
831: audio_channel[nr].lc = (audio_channel[nr].lc & 0xffff) | ((uae_u32)v << 16);
832: }
833:
834: void AUDxLCL (int nr, uae_u16 v)
835: {
836: update_audio ();
837:
838: audio_channel[nr].lc = (audio_channel[nr].lc & ~0xffff) | (v & 0xFFFE);
839: }
840:
841: void AUDxPER (int nr, uae_u16 v)
842: {
843: update_audio ();
844:
845: if (v == 0)
846: v = 65535;
847:
848: if (v < maxhpos/2 && currprefs.produce_sound < 3)
849: v = maxhpos/2;
850:
851: audio_channel[nr].per = v;
852: }
853:
854: void AUDxLEN (int nr, uae_u16 v)
855: {
856: update_audio ();
857:
858: audio_channel[nr].len = v;
859: }
860:
861: void AUDxVOL (int nr, uae_u16 v)
862: {
863: int v2 = v & 64 ? 63 : v & 63;
864:
865: update_audio ();
866:
867: audio_channel[nr].vol = v2;
868: #ifndef MULTIPLICATION_PROFITABLE
869: audio_channel[nr].voltbl = sound_table[v2];
870: #endif
1.1 root 871: }
872:
873: void dump_audio_bench (void)
874: {
875: #ifdef BENCHMARK_AUDIO
876: printf ("Average cycles per sample handler: %f\n", ((double)sh_time / sh_count));
877: #endif
878: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.