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