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