|
|
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.5 ! root 111: void sample16i_handler (void)
! 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.2 root 167: void sample8_handler (void)
1.1 root 168: {
169: BEGIN_BENCH
170:
171: uae_u32 data0 = audio_channel[0].current_sample;
172: uae_u32 data1 = audio_channel[1].current_sample;
173: uae_u32 data2 = audio_channel[2].current_sample;
174: uae_u32 data3 = audio_channel[3].current_sample;
175: DO_CHANNEL_1 (data0, 0);
176: DO_CHANNEL_1 (data1, 1);
177: DO_CHANNEL_1 (data2, 2);
178: DO_CHANNEL_1 (data3, 3);
179: data0 &= audio_channel[0].adk_mask;
180: data1 &= audio_channel[1].adk_mask;
181: data2 &= audio_channel[2].adk_mask;
182: data3 &= audio_channel[3].adk_mask;
183: data0 += data1;
184: data0 += data2;
185: data0 += data3;
186: {
187: uae_u32 data = SBASEVAL8(2) + data0;
188: FINISH_DATA(8, 2);
189: PUT_SOUND_BYTE (data);
190: }
191: END_BENCH
192:
193: check_sound_buffers ();
194: }
195:
196: #ifdef HAVE_STEREO_SUPPORT
1.1.1.2 root 197: void sample16s_handler (void)
1.1 root 198: {
199: BEGIN_BENCH
200:
201: uae_u32 data0 = audio_channel[0].current_sample;
202: uae_u32 data1 = audio_channel[1].current_sample;
203: uae_u32 data2 = audio_channel[2].current_sample;
204: uae_u32 data3 = audio_channel[3].current_sample;
205: DO_CHANNEL_1 (data0, 0);
206: DO_CHANNEL_1 (data1, 1);
207: DO_CHANNEL_1 (data2, 2);
208: DO_CHANNEL_1 (data3, 3);
209:
210: data0 &= audio_channel[0].adk_mask;
211: data1 &= audio_channel[1].adk_mask;
212: data2 &= audio_channel[2].adk_mask;
213: data3 &= audio_channel[3].adk_mask;
214:
215: data0 += data3;
216: {
217: uae_u32 data = SBASEVAL16(1) + data0;
218: FINISH_DATA (16, 1);
219: PUT_SOUND_WORD_RIGHT (data);
220: }
221:
222: data1 += data2;
223: {
224: uae_u32 data = SBASEVAL16(1) + data1;
225: FINISH_DATA (16, 1);
226: PUT_SOUND_WORD_LEFT (data);
227: }
228:
229: END_BENCH
230:
231: check_sound_buffers ();
232: }
233:
1.1.1.5 ! root 234: void sample16si_handler (void)
! 235: {
! 236: unsigned long delta, ratio;
! 237:
! 238: BEGIN_BENCH
! 239:
! 240: uae_u32 data0 = audio_channel[0].current_sample;
! 241: uae_u32 data1 = audio_channel[1].current_sample;
! 242: uae_u32 data2 = audio_channel[2].current_sample;
! 243: uae_u32 data3 = audio_channel[3].current_sample;
! 244: uae_u32 data0p = audio_channel[0].last_sample;
! 245: uae_u32 data1p = audio_channel[1].last_sample;
! 246: uae_u32 data2p = audio_channel[2].last_sample;
! 247: uae_u32 data3p = audio_channel[3].last_sample;
! 248:
! 249: DO_CHANNEL_1 (data0, 0);
! 250: DO_CHANNEL_1 (data1, 1);
! 251: DO_CHANNEL_1 (data2, 2);
! 252: DO_CHANNEL_1 (data3, 3);
! 253: DO_CHANNEL_1 (data0p, 0);
! 254: DO_CHANNEL_1 (data1p, 1);
! 255: DO_CHANNEL_1 (data2p, 2);
! 256: DO_CHANNEL_1 (data3p, 3);
! 257:
! 258: data0 &= audio_channel[0].adk_mask;
! 259: data0p &= audio_channel[0].adk_mask;
! 260: data1 &= audio_channel[1].adk_mask;
! 261: data1p &= audio_channel[1].adk_mask;
! 262: data2 &= audio_channel[2].adk_mask;
! 263: data2p &= audio_channel[2].adk_mask;
! 264: data3 &= audio_channel[3].adk_mask;
! 265: data3p &= audio_channel[3].adk_mask;
! 266:
! 267: # if 0
! 268: /* linear interpolation and summing up... */
! 269: delta = audio_channel[0].per;
! 270: ratio = ((audio_channel[0].evtime % delta) << 8) / delta;
! 271: data0 = (data0 * (256 - ratio) + data0p * ratio) >> 8;
! 272: delta = audio_channel[1].per;
! 273: ratio = ((audio_channel[1].evtime % delta) << 8) / delta;
! 274: data1 = (data1 * (256 - ratio) + data1p * ratio) >> 8;
! 275: delta = audio_channel[2].per;
! 276: ratio = ((audio_channel[2].evtime % delta) << 8) / delta;
! 277: data1 += (data2 * (256 - ratio) + data2p * ratio) >> 8;
! 278: delta = audio_channel[3].per;
! 279: ratio = ((audio_channel[3].evtime % delta) << 8) / delta;
! 280: data0 += (data3 * (256 - ratio) + data3p * ratio) >> 8;
! 281: #else
! 282: {
! 283: struct audio_channel_data *cdp;
! 284: int ratio, ratio1;
! 285: #define INTERVAL (sample_evtime)
! 286: cdp = audio_channel + 0;
! 287: ratio1 = cdp->per - cdp->evtime;
! 288: ratio = (ratio1 << 12) / INTERVAL;
! 289: if (cdp->evtime < sample_evtime || ratio1 >= INTERVAL)
! 290: ratio = 4096;
! 291: data0 = (data0 * ratio + data0p * (4096 - ratio)) >> 12;
! 292:
! 293: cdp = audio_channel + 1;
! 294: ratio1 = cdp->per - cdp->evtime;
! 295: ratio = (ratio1 << 12) / INTERVAL;
! 296: if (cdp->evtime < sample_evtime || ratio1 >= INTERVAL)
! 297: ratio = 4096;
! 298: data1 = (data1 * ratio + data1p * (4096 - ratio)) >> 12;
! 299:
! 300: cdp = audio_channel + 2;
! 301: ratio1 = cdp->per - cdp->evtime;
! 302: ratio = (ratio1 << 12) / INTERVAL;
! 303: if (cdp->evtime < sample_evtime || ratio1 >= INTERVAL)
! 304: ratio = 4096;
! 305: data2 = (data2 * ratio + data2p * (4096 - ratio)) >> 12;
! 306:
! 307: cdp = audio_channel + 3;
! 308: ratio1 = cdp->per - cdp->evtime;
! 309: ratio = (ratio1 << 12) / INTERVAL;
! 310: if (cdp->evtime < sample_evtime || ratio1 >= INTERVAL)
! 311: ratio = 4096;
! 312: data3 = (data3 * ratio + data3p * (4096 - ratio)) >> 12;
! 313: }
! 314: data1 += data2;
! 315: data0 += data3;
! 316: #endif
! 317: {
! 318: uae_u32 data = SBASEVAL16 (1) + data0;
! 319: FINISH_DATA (16, 1);
! 320: PUT_SOUND_WORD_RIGHT (data);
! 321: }
! 322:
! 323: {
! 324: uae_u32 data = SBASEVAL16 (1) + data1;
! 325: FINISH_DATA (16, 1);
! 326: PUT_SOUND_WORD_LEFT (data);
! 327: }
! 328:
! 329: END_BENCH
! 330:
! 331: check_sound_buffers ();
! 332: }
! 333:
1.1.1.2 root 334: void sample8s_handler (void)
1.1 root 335: {
336: BEGIN_BENCH
337:
338: uae_u32 data0 = audio_channel[0].current_sample;
339: uae_u32 data1 = audio_channel[1].current_sample;
340: uae_u32 data2 = audio_channel[2].current_sample;
341: uae_u32 data3 = audio_channel[3].current_sample;
342: DO_CHANNEL_1 (data0, 0);
343: DO_CHANNEL_1 (data1, 1);
344: DO_CHANNEL_1 (data2, 2);
345: DO_CHANNEL_1 (data3, 3);
346:
347: data0 &= audio_channel[0].adk_mask;
348: data1 &= audio_channel[1].adk_mask;
349: data2 &= audio_channel[2].adk_mask;
350: data3 &= audio_channel[3].adk_mask;
351:
352: data0 += data3;
353: {
354: uae_u32 data = SBASEVAL8(1) + data0;
355: FINISH_DATA (8, 1);
356: PUT_SOUND_BYTE_RIGHT (data);
357: }
358: data1 += data2;
359: {
360: uae_u32 data = SBASEVAL8(1) + data1;
361: FINISH_DATA (8, 1);
362: PUT_SOUND_BYTE_LEFT (data);
363: }
364:
365: END_BENCH
366:
367: check_sound_buffers ();
368: }
369: #else
1.1.1.2 root 370: void sample8s_handler (void)
1.1 root 371: {
372: sample8_handler();
373: }
1.1.1.2 root 374: void sample16s_handler (void)
1.1 root 375: {
376: sample16_handler();
377: }
378: #endif
379:
1.1.1.2 root 380: static uae_u8 int2ulaw (int ch)
1.1 root 381: {
382: int mask;
383:
384: if (ch < 0) {
385: ch = -ch;
386: mask = 0x7f;
387: }
388: else {
389: mask = 0xff;
390: }
391:
392: if (ch < 32) {
393: ch = 0xF0 | ( 15 - (ch/2) );
394: } else if (ch < 96) {
395: ch = 0xE0 | ( 15 - (ch-32)/4 );
396: } else if (ch < 224) {
397: ch = 0xD0 | ( 15 - (ch-96)/8 );
398: } else if (ch < 480) {
399: ch = 0xC0 | ( 15 - (ch-224)/16 );
400: } else if (ch < 992 ) {
401: ch = 0xB0 | ( 15 - (ch-480)/32 );
402: } else if (ch < 2016) {
403: ch = 0xA0 | ( 15 - (ch-992)/64 );
404: } else if (ch < 4064) {
405: ch = 0x90 | ( 15 - (ch-2016)/128 );
406: } else if (ch < 8160) {
407: ch = 0x80 | ( 15 - (ch-4064)/256 );
408: } else {
409: ch = 0x80;
410: }
411: return (uae_u8)(mask & ch);
412: }
413:
414: void sample_ulaw_handler (void)
415: {
416: int nr;
417: uae_u32 data = 0;
418:
419: for (nr = 0; nr < 4; nr++) {
420: if (!(adkcon & (0x11 << nr))) {
421: uae_u32 d = audio_channel[nr].current_sample;
422: DO_CHANNEL_1 (d, nr);
423: data += d;
424: }
425: }
426: PUT_SOUND_BYTE (int2ulaw (data));
427: check_sound_buffers ();
428: }
429:
430: static void audio_handler (int nr)
431: {
432: struct audio_channel_data *cdp = audio_channel + nr;
433:
434: switch (cdp->state) {
435: case 0:
436: fprintf(stderr, "Bug in sound code\n");
437: break;
438:
439: case 1:
440: /* We come here at the first hsync after DMA was turned on. */
1.1.1.2 root 441: cdp->evtime = maxhpos;
1.1 root 442:
443: cdp->state = 5;
444: INTREQ(0x8000 | (0x80 << nr));
445: if (cdp->wlen != 1)
446: cdp->wlen--;
447: cdp->nextdat = chipmem_bank.wget(cdp->pt);
448:
449: cdp->pt += 2;
450: break;
451:
452: case 5:
453: /* We come here at the second hsync after DMA was turned on. */
454: if (currprefs.produce_sound == 0)
455: cdp->per = 65535;
456:
1.1.1.2 root 457: cdp->evtime = cdp->per;
1.1 root 458: cdp->dat = cdp->nextdat;
1.1.1.5 ! root 459: cdp->last_sample = cdp->current_sample;
1.1 root 460: cdp->current_sample = (sample8_t)(cdp->dat >> 8);
461:
462: cdp->state = 2;
463: {
464: int audav = adkcon & (1 << nr);
465: int audap = adkcon & (16 << nr);
466: int napnav = (!audav && !audap) || audav;
467: if (napnav)
468: cdp->data_written = 2;
469: }
470: break;
471:
472: case 2:
473: /* We come here when a 2->3 transition occurs */
474: if (currprefs.produce_sound == 0)
475: cdp->per = 65535;
476:
1.1.1.5 ! root 477: cdp->last_sample = cdp->current_sample;
1.1 root 478: cdp->current_sample = (sample8_t)(cdp->dat & 0xFF);
1.1.1.2 root 479: cdp->evtime = cdp->per;
1.1 root 480:
481: cdp->state = 3;
482:
483: /* Period attachment? */
484: if (adkcon & (0x10 << nr)) {
485: if (cdp->intreq2 && cdp->dmaen)
486: INTREQ(0x8000 | (0x80 << nr));
487: cdp->intreq2 = 0;
488:
489: cdp->dat = cdp->nextdat;
490: if (cdp->dmaen)
491: cdp->data_written = 2;
492: if (nr < 3) {
493: if (cdp->dat == 0)
494: (cdp+1)->per = 65535;
495:
496: else if (cdp->dat < maxhpos/2 && currprefs.produce_sound < 3)
497: (cdp+1)->per = maxhpos/2;
498: else
499: (cdp+1)->per = cdp->dat;
500: }
501: }
502: break;
503:
504: case 3:
505: /* We come here when a 3->2 transition occurs */
506: if (currprefs.produce_sound == 0)
507: cdp->per = 65535;
508:
1.1.1.2 root 509: cdp->evtime = cdp->per;
1.1 root 510:
511: if ((INTREQR() & (0x80 << nr)) && !cdp->dmaen) {
512: cdp->state = 0;
1.1.1.5 ! root 513: cdp->last_sample = 0;
1.1 root 514: cdp->current_sample = 0;
515: break;
516: } else {
517: int audav = adkcon & (1 << nr);
518: int audap = adkcon & (16 << nr);
519: int napnav = (!audav && !audap) || audav;
520: cdp->state = 2;
521:
522: if ((cdp->intreq2 && cdp->dmaen && napnav)
523: || (napnav && !cdp->dmaen))
524: INTREQ(0x8000 | (0x80 << nr));
525: cdp->intreq2 = 0;
526:
527: cdp->dat = cdp->nextdat;
1.1.1.5 ! root 528: cdp->last_sample = cdp->current_sample;
1.1 root 529: cdp->current_sample = (sample8_t)(cdp->dat >> 8);
530:
531: if (cdp->dmaen && napnav)
532: cdp->data_written = 2;
533:
534: /* Volume attachment? */
535: if (audav) {
536: if (nr < 3) {
537: (cdp+1)->vol = cdp->dat;
538: #ifndef MULTIPLICATION_PROFITABLE
539: (cdp+1)->voltbl = sound_table[cdp->dat];
540: #endif
541: }
542: }
543: }
544: break;
545:
546: default:
547: cdp->state = 0;
548: break;
549: }
550: }
551:
552: void aud0_handler (void)
553: {
554: audio_handler (0);
555: }
556: void aud1_handler (void)
557: {
558: audio_handler (1);
559: }
560: void aud2_handler (void)
561: {
562: audio_handler (2);
563: }
564: void aud3_handler (void)
565: {
566: audio_handler (3);
567: }
568:
569: void audio_reset (void)
570: {
571: memset (audio_channel, 0, sizeof audio_channel);
572: audio_channel[0].per = 65535;
573: audio_channel[1].per = 65535;
574: audio_channel[2].per = 65535;
575: audio_channel[3].per = 65535;
576: audio_channel[0].voltbl = sound_table[0];
577: audio_channel[1].voltbl = sound_table[0];
578: audio_channel[2].voltbl = sound_table[0];
579: audio_channel[3].voltbl = sound_table[0];
1.1.1.2 root 580:
581: last_cycles = 0;
582: next_sample_evtime = sample_evtime;
583: }
584:
585: static __inline__ int sound_prefs_changed (void)
586: {
587: return (changed_prefs.produce_sound != currprefs.produce_sound
588: || changed_prefs.stereo != currprefs.stereo
1.1.1.4 root 589: || changed_prefs.sound_freq != currprefs.sound_freq
1.1.1.2 root 590: || changed_prefs.sound_bits != currprefs.sound_bits);
591: }
592:
593: void check_prefs_changed_audio (void)
594: {
595: if (! sound_available || ! sound_prefs_changed ())
596: return;
597:
598: close_sound ();
1.1.1.3 root 599:
1.1.1.2 root 600: currprefs.produce_sound = changed_prefs.produce_sound;
601: currprefs.stereo = changed_prefs.stereo;
602: currprefs.sound_bits = changed_prefs.sound_bits;
1.1.1.4 root 603: currprefs.sound_freq = changed_prefs.sound_freq;
1.1.1.2 root 604:
1.1.1.3 root 605: if (currprefs.produce_sound < 2)
606: return;
607:
608: if (init_sound ()) {
609: last_cycles = cycles - 1;
610: next_sample_evtime = sample_evtime;
611: return;
612: }
613: if (! sound_available) {
614: fprintf (stderr, "Sound is not supported.\n");
1.1.1.2 root 615: } else {
1.1.1.3 root 616: fprintf (stderr, "Sorry, can't initialize sound.\n");
617: currprefs.produce_sound = 0;
618: /* So we don't do this every frame */
619: changed_prefs.produce_sound = 0;
1.1.1.2 root 620: }
621: }
622:
623: void update_audio (void)
624: {
625: unsigned long int n_cycles;
626:
1.1.1.4 root 627: if (currprefs.produce_sound < 2)
1.1.1.2 root 628: return;
629:
630: n_cycles = cycles - last_cycles;
631: for (;;) {
632: int best = -1;
633: unsigned long int best_evtime = n_cycles + 1;
634: if (audio_channel[0].state != 0 && best_evtime > audio_channel[0].evtime)
635: best = 0, best_evtime = audio_channel[0].evtime;
636: if (audio_channel[1].state != 0 && best_evtime > audio_channel[1].evtime)
637: best = 1, best_evtime = audio_channel[1].evtime;
638: if (audio_channel[2].state != 0 && best_evtime > audio_channel[2].evtime)
639: best = 2, best_evtime = audio_channel[2].evtime;
640: if (audio_channel[3].state != 0 && best_evtime > audio_channel[3].evtime)
641: best = 3, best_evtime = audio_channel[3].evtime;
642: if (best_evtime > next_sample_evtime)
643: best_evtime = next_sample_evtime;
644:
645: if (best_evtime > n_cycles)
646: break;
647:
648: next_sample_evtime -= best_evtime;
649: audio_channel[0].evtime -= best_evtime;
650: audio_channel[1].evtime -= best_evtime;
651: audio_channel[2].evtime -= best_evtime;
652: audio_channel[3].evtime -= best_evtime;
653: n_cycles -= best_evtime;
1.1.1.3 root 654: if (next_sample_evtime == 0 && currprefs.produce_sound > 1) {
1.1.1.2 root 655: next_sample_evtime = sample_evtime;
656: (*sample_handler) ();
657: }
658: if (audio_channel[0].evtime == 0 && audio_channel[0].state != 0)
659: audio_handler (0);
660: if (audio_channel[1].evtime == 0 && audio_channel[1].state != 0)
661: audio_handler (1);
662: if (audio_channel[2].evtime == 0 && audio_channel[2].state != 0)
663: audio_handler (2);
664: if (audio_channel[3].evtime == 0 && audio_channel[3].state != 0)
665: audio_handler (3);
666: }
667: last_cycles = cycles - n_cycles;
668: }
669:
670: void AUDxDAT (int nr, uae_u16 v)
671: {
672: struct audio_channel_data *cdp = audio_channel + nr;
673:
674: update_audio ();
675:
676: cdp->dat = v;
677: if (cdp->state == 0 && !(INTREQR() & (0x80 << nr))) {
678: cdp->state = 2;
679: INTREQ(0x8000 | (0x80 << nr));
680: /* data_written = 2 ???? */
681: cdp->evtime = cdp->per;
682: }
683: }
684:
685: void AUDxLCH (int nr, uae_u16 v)
686: {
687: update_audio ();
688:
689: audio_channel[nr].lc = (audio_channel[nr].lc & 0xffff) | ((uae_u32)v << 16);
690: }
691:
692: void AUDxLCL (int nr, uae_u16 v)
693: {
694: update_audio ();
695:
696: audio_channel[nr].lc = (audio_channel[nr].lc & ~0xffff) | (v & 0xFFFE);
697: }
698:
699: void AUDxPER (int nr, uae_u16 v)
700: {
701: update_audio ();
702:
703: if (v == 0)
704: v = 65535;
705:
706: if (v < maxhpos/2 && currprefs.produce_sound < 3)
707: v = maxhpos/2;
708:
709: audio_channel[nr].per = v;
710: }
711:
712: void AUDxLEN (int nr, uae_u16 v)
713: {
714: update_audio ();
715:
716: audio_channel[nr].len = v;
717: }
718:
719: void AUDxVOL (int nr, uae_u16 v)
720: {
721: int v2 = v & 64 ? 63 : v & 63;
722:
723: update_audio ();
724:
725: audio_channel[nr].vol = v2;
726: #ifndef MULTIPLICATION_PROFITABLE
727: audio_channel[nr].voltbl = sound_table[v2];
728: #endif
1.1 root 729: }
730:
731: void dump_audio_bench (void)
732: {
733: #ifdef BENCHMARK_AUDIO
734: printf ("Average cycles per sample handler: %f\n", ((double)sh_time / sh_count));
735: #endif
736: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.