|
|
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:
82: /* Templates! I want templates! */
1.1.1.2 root 83: void sample16_handler (void)
1.1 root 84: {
85: BEGIN_BENCH
86:
87: uae_u32 data0 = audio_channel[0].current_sample;
88: uae_u32 data1 = audio_channel[1].current_sample;
89: uae_u32 data2 = audio_channel[2].current_sample;
90: uae_u32 data3 = audio_channel[3].current_sample;
91: DO_CHANNEL_1 (data0, 0);
92: DO_CHANNEL_1 (data1, 1);
93: DO_CHANNEL_1 (data2, 2);
94: DO_CHANNEL_1 (data3, 3);
95: data0 &= audio_channel[0].adk_mask;
96: data1 &= audio_channel[1].adk_mask;
97: data2 &= audio_channel[2].adk_mask;
98: data3 &= audio_channel[3].adk_mask;
99: data0 += data1;
100: data0 += data2;
101: data0 += data3;
102: {
103: uae_u32 data = SBASEVAL16(2) + data0;
104: FINISH_DATA(16, 2);
105: PUT_SOUND_WORD (data);
106: }
107: END_BENCH
108:
109: check_sound_buffers ();
110: }
111:
1.1.1.2 root 112: void sample8_handler (void)
1.1 root 113: {
114: BEGIN_BENCH
115:
116: uae_u32 data0 = audio_channel[0].current_sample;
117: uae_u32 data1 = audio_channel[1].current_sample;
118: uae_u32 data2 = audio_channel[2].current_sample;
119: uae_u32 data3 = audio_channel[3].current_sample;
120: DO_CHANNEL_1 (data0, 0);
121: DO_CHANNEL_1 (data1, 1);
122: DO_CHANNEL_1 (data2, 2);
123: DO_CHANNEL_1 (data3, 3);
124: data0 &= audio_channel[0].adk_mask;
125: data1 &= audio_channel[1].adk_mask;
126: data2 &= audio_channel[2].adk_mask;
127: data3 &= audio_channel[3].adk_mask;
128: data0 += data1;
129: data0 += data2;
130: data0 += data3;
131: {
132: uae_u32 data = SBASEVAL8(2) + data0;
133: FINISH_DATA(8, 2);
134: PUT_SOUND_BYTE (data);
135: }
136: END_BENCH
137:
138: check_sound_buffers ();
139: }
140:
141: #ifdef HAVE_STEREO_SUPPORT
1.1.1.2 root 142: void sample16s_handler (void)
1.1 root 143: {
144: BEGIN_BENCH
145:
146: uae_u32 data0 = audio_channel[0].current_sample;
147: uae_u32 data1 = audio_channel[1].current_sample;
148: uae_u32 data2 = audio_channel[2].current_sample;
149: uae_u32 data3 = audio_channel[3].current_sample;
150: DO_CHANNEL_1 (data0, 0);
151: DO_CHANNEL_1 (data1, 1);
152: DO_CHANNEL_1 (data2, 2);
153: DO_CHANNEL_1 (data3, 3);
154:
155: data0 &= audio_channel[0].adk_mask;
156: data1 &= audio_channel[1].adk_mask;
157: data2 &= audio_channel[2].adk_mask;
158: data3 &= audio_channel[3].adk_mask;
159:
160: data0 += data3;
161: {
162: uae_u32 data = SBASEVAL16(1) + data0;
163: FINISH_DATA (16, 1);
164: PUT_SOUND_WORD_RIGHT (data);
165: }
166:
167: data1 += data2;
168: {
169: uae_u32 data = SBASEVAL16(1) + data1;
170: FINISH_DATA (16, 1);
171: PUT_SOUND_WORD_LEFT (data);
172: }
173:
174: END_BENCH
175:
176: check_sound_buffers ();
177: }
178:
1.1.1.2 root 179: void sample8s_handler (void)
1.1 root 180: {
181: BEGIN_BENCH
182:
183: uae_u32 data0 = audio_channel[0].current_sample;
184: uae_u32 data1 = audio_channel[1].current_sample;
185: uae_u32 data2 = audio_channel[2].current_sample;
186: uae_u32 data3 = audio_channel[3].current_sample;
187: DO_CHANNEL_1 (data0, 0);
188: DO_CHANNEL_1 (data1, 1);
189: DO_CHANNEL_1 (data2, 2);
190: DO_CHANNEL_1 (data3, 3);
191:
192: data0 &= audio_channel[0].adk_mask;
193: data1 &= audio_channel[1].adk_mask;
194: data2 &= audio_channel[2].adk_mask;
195: data3 &= audio_channel[3].adk_mask;
196:
197: data0 += data3;
198: {
199: uae_u32 data = SBASEVAL8(1) + data0;
200: FINISH_DATA (8, 1);
201: PUT_SOUND_BYTE_RIGHT (data);
202: }
203: data1 += data2;
204: {
205: uae_u32 data = SBASEVAL8(1) + data1;
206: FINISH_DATA (8, 1);
207: PUT_SOUND_BYTE_LEFT (data);
208: }
209:
210: END_BENCH
211:
212: check_sound_buffers ();
213: }
214: #else
1.1.1.2 root 215: void sample8s_handler (void)
1.1 root 216: {
217: sample8_handler();
218: }
1.1.1.2 root 219: void sample16s_handler (void)
1.1 root 220: {
221: sample16_handler();
222: }
223: #endif
224:
1.1.1.2 root 225: static uae_u8 int2ulaw (int ch)
1.1 root 226: {
227: int mask;
228:
229: if (ch < 0) {
230: ch = -ch;
231: mask = 0x7f;
232: }
233: else {
234: mask = 0xff;
235: }
236:
237: if (ch < 32) {
238: ch = 0xF0 | ( 15 - (ch/2) );
239: } else if (ch < 96) {
240: ch = 0xE0 | ( 15 - (ch-32)/4 );
241: } else if (ch < 224) {
242: ch = 0xD0 | ( 15 - (ch-96)/8 );
243: } else if (ch < 480) {
244: ch = 0xC0 | ( 15 - (ch-224)/16 );
245: } else if (ch < 992 ) {
246: ch = 0xB0 | ( 15 - (ch-480)/32 );
247: } else if (ch < 2016) {
248: ch = 0xA0 | ( 15 - (ch-992)/64 );
249: } else if (ch < 4064) {
250: ch = 0x90 | ( 15 - (ch-2016)/128 );
251: } else if (ch < 8160) {
252: ch = 0x80 | ( 15 - (ch-4064)/256 );
253: } else {
254: ch = 0x80;
255: }
256: return (uae_u8)(mask & ch);
257: }
258:
259: void sample_ulaw_handler (void)
260: {
261: int nr;
262: uae_u32 data = 0;
263:
264: for (nr = 0; nr < 4; nr++) {
265: if (!(adkcon & (0x11 << nr))) {
266: uae_u32 d = audio_channel[nr].current_sample;
267: DO_CHANNEL_1 (d, nr);
268: data += d;
269: }
270: }
271: PUT_SOUND_BYTE (int2ulaw (data));
272: check_sound_buffers ();
273: }
274:
275: static void audio_handler (int nr)
276: {
277: struct audio_channel_data *cdp = audio_channel + nr;
278:
279: switch (cdp->state) {
280: case 0:
281: fprintf(stderr, "Bug in sound code\n");
282: break;
283:
284: case 1:
285: /* We come here at the first hsync after DMA was turned on. */
1.1.1.2 root 286: cdp->evtime = maxhpos;
1.1 root 287:
288: cdp->state = 5;
289: INTREQ(0x8000 | (0x80 << nr));
290: if (cdp->wlen != 1)
291: cdp->wlen--;
292: cdp->nextdat = chipmem_bank.wget(cdp->pt);
293:
294: cdp->pt += 2;
295: break;
296:
297: case 5:
298: /* We come here at the second hsync after DMA was turned on. */
299: if (currprefs.produce_sound == 0)
300: cdp->per = 65535;
301:
1.1.1.2 root 302: cdp->evtime = cdp->per;
1.1 root 303: cdp->dat = cdp->nextdat;
304: cdp->current_sample = (sample8_t)(cdp->dat >> 8);
305:
306: cdp->state = 2;
307: {
308: int audav = adkcon & (1 << nr);
309: int audap = adkcon & (16 << nr);
310: int napnav = (!audav && !audap) || audav;
311: if (napnav)
312: cdp->data_written = 2;
313: }
314: break;
315:
316: case 2:
317: /* We come here when a 2->3 transition occurs */
318: if (currprefs.produce_sound == 0)
319: cdp->per = 65535;
320:
321: cdp->current_sample = (sample8_t)(cdp->dat & 0xFF);
1.1.1.2 root 322: cdp->evtime = cdp->per;
1.1 root 323:
324: cdp->state = 3;
325:
326: /* Period attachment? */
327: if (adkcon & (0x10 << nr)) {
328: if (cdp->intreq2 && cdp->dmaen)
329: INTREQ(0x8000 | (0x80 << nr));
330: cdp->intreq2 = 0;
331:
332: cdp->dat = cdp->nextdat;
333: if (cdp->dmaen)
334: cdp->data_written = 2;
335: if (nr < 3) {
336: if (cdp->dat == 0)
337: (cdp+1)->per = 65535;
338:
339: else if (cdp->dat < maxhpos/2 && currprefs.produce_sound < 3)
340: (cdp+1)->per = maxhpos/2;
341: else
342: (cdp+1)->per = cdp->dat;
343: }
344: }
345: break;
346:
347: case 3:
348: /* We come here when a 3->2 transition occurs */
349: if (currprefs.produce_sound == 0)
350: cdp->per = 65535;
351:
1.1.1.2 root 352: cdp->evtime = cdp->per;
1.1 root 353:
354: if ((INTREQR() & (0x80 << nr)) && !cdp->dmaen) {
355: cdp->state = 0;
356: cdp->current_sample = 0;
357: break;
358: } else {
359: int audav = adkcon & (1 << nr);
360: int audap = adkcon & (16 << nr);
361: int napnav = (!audav && !audap) || audav;
362: cdp->state = 2;
363:
364: if ((cdp->intreq2 && cdp->dmaen && napnav)
365: || (napnav && !cdp->dmaen))
366: INTREQ(0x8000 | (0x80 << nr));
367: cdp->intreq2 = 0;
368:
369: cdp->dat = cdp->nextdat;
370: cdp->current_sample = (sample8_t)(cdp->dat >> 8);
371:
372: if (cdp->dmaen && napnav)
373: cdp->data_written = 2;
374:
375: /* Volume attachment? */
376: if (audav) {
377: if (nr < 3) {
378: (cdp+1)->vol = cdp->dat;
379: #ifndef MULTIPLICATION_PROFITABLE
380: (cdp+1)->voltbl = sound_table[cdp->dat];
381: #endif
382: }
383: }
384: }
385: break;
386:
387: default:
388: cdp->state = 0;
389: break;
390: }
391: }
392:
393: void aud0_handler (void)
394: {
395: audio_handler (0);
396: }
397: void aud1_handler (void)
398: {
399: audio_handler (1);
400: }
401: void aud2_handler (void)
402: {
403: audio_handler (2);
404: }
405: void aud3_handler (void)
406: {
407: audio_handler (3);
408: }
409:
410: void audio_reset (void)
411: {
412: memset (audio_channel, 0, sizeof audio_channel);
413: audio_channel[0].per = 65535;
414: audio_channel[1].per = 65535;
415: audio_channel[2].per = 65535;
416: audio_channel[3].per = 65535;
417: audio_channel[0].voltbl = sound_table[0];
418: audio_channel[1].voltbl = sound_table[0];
419: audio_channel[2].voltbl = sound_table[0];
420: audio_channel[3].voltbl = sound_table[0];
1.1.1.2 root 421:
422: last_cycles = 0;
423: next_sample_evtime = sample_evtime;
424: }
425:
426: static __inline__ int sound_prefs_changed (void)
427: {
428: return (changed_prefs.produce_sound != currprefs.produce_sound
429: || changed_prefs.stereo != currprefs.stereo
430: || changed_prefs.sound_bits != currprefs.sound_bits);
431: }
432:
433: void check_prefs_changed_audio (void)
434: {
435: if (! sound_available || ! sound_prefs_changed ())
436: return;
437:
438: close_sound ();
1.1.1.3 ! root 439:
1.1.1.2 root 440: currprefs.produce_sound = changed_prefs.produce_sound;
441: currprefs.stereo = changed_prefs.stereo;
442: currprefs.sound_bits = changed_prefs.sound_bits;
443:
1.1.1.3 ! root 444: if (currprefs.produce_sound < 2)
! 445: return;
! 446:
! 447: if (init_sound ()) {
! 448: last_cycles = cycles - 1;
! 449: next_sample_evtime = sample_evtime;
! 450: return;
! 451: }
! 452: if (! sound_available) {
! 453: fprintf (stderr, "Sound is not supported.\n");
1.1.1.2 root 454: } else {
1.1.1.3 ! root 455: fprintf (stderr, "Sorry, can't initialize sound.\n");
! 456: currprefs.produce_sound = 0;
! 457: /* So we don't do this every frame */
! 458: changed_prefs.produce_sound = 0;
1.1.1.2 root 459: }
460: }
461:
462: void update_audio (void)
463: {
464: unsigned long int n_cycles;
465:
466: if (currprefs.produce_sound == 0)
467: return;
468:
469: n_cycles = cycles - last_cycles;
470: for (;;) {
471: int best = -1;
472: unsigned long int best_evtime = n_cycles + 1;
473: if (audio_channel[0].state != 0 && best_evtime > audio_channel[0].evtime)
474: best = 0, best_evtime = audio_channel[0].evtime;
475: if (audio_channel[1].state != 0 && best_evtime > audio_channel[1].evtime)
476: best = 1, best_evtime = audio_channel[1].evtime;
477: if (audio_channel[2].state != 0 && best_evtime > audio_channel[2].evtime)
478: best = 2, best_evtime = audio_channel[2].evtime;
479: if (audio_channel[3].state != 0 && best_evtime > audio_channel[3].evtime)
480: best = 3, best_evtime = audio_channel[3].evtime;
481: if (best_evtime > next_sample_evtime)
482: best_evtime = next_sample_evtime;
483:
484: if (best_evtime > n_cycles)
485: break;
486:
487: next_sample_evtime -= best_evtime;
488: audio_channel[0].evtime -= best_evtime;
489: audio_channel[1].evtime -= best_evtime;
490: audio_channel[2].evtime -= best_evtime;
491: audio_channel[3].evtime -= best_evtime;
492: n_cycles -= best_evtime;
1.1.1.3 ! root 493: if (next_sample_evtime == 0 && currprefs.produce_sound > 1) {
1.1.1.2 root 494: next_sample_evtime = sample_evtime;
495: (*sample_handler) ();
496: }
497: if (audio_channel[0].evtime == 0 && audio_channel[0].state != 0)
498: audio_handler (0);
499: if (audio_channel[1].evtime == 0 && audio_channel[1].state != 0)
500: audio_handler (1);
501: if (audio_channel[2].evtime == 0 && audio_channel[2].state != 0)
502: audio_handler (2);
503: if (audio_channel[3].evtime == 0 && audio_channel[3].state != 0)
504: audio_handler (3);
505: }
506: last_cycles = cycles - n_cycles;
507: }
508:
509: void AUDxDAT (int nr, uae_u16 v)
510: {
511: struct audio_channel_data *cdp = audio_channel + nr;
512:
513: update_audio ();
514:
515: cdp->dat = v;
516: if (cdp->state == 0 && !(INTREQR() & (0x80 << nr))) {
517: cdp->state = 2;
518: INTREQ(0x8000 | (0x80 << nr));
519: /* data_written = 2 ???? */
520: cdp->evtime = cdp->per;
521: }
522: }
523:
524: void AUDxLCH (int nr, uae_u16 v)
525: {
526: update_audio ();
527:
528: audio_channel[nr].lc = (audio_channel[nr].lc & 0xffff) | ((uae_u32)v << 16);
529: }
530:
531: void AUDxLCL (int nr, uae_u16 v)
532: {
533: update_audio ();
534:
535: audio_channel[nr].lc = (audio_channel[nr].lc & ~0xffff) | (v & 0xFFFE);
536: }
537:
538: void AUDxPER (int nr, uae_u16 v)
539: {
540: update_audio ();
541:
542: if (v == 0)
543: v = 65535;
544:
545: if (v < maxhpos/2 && currprefs.produce_sound < 3)
546: v = maxhpos/2;
547:
548: audio_channel[nr].per = v;
549: }
550:
551: void AUDxLEN (int nr, uae_u16 v)
552: {
553: update_audio ();
554:
555: audio_channel[nr].len = v;
556: }
557:
558: void AUDxVOL (int nr, uae_u16 v)
559: {
560: int v2 = v & 64 ? 63 : v & 63;
561:
562: update_audio ();
563:
564: audio_channel[nr].vol = v2;
565: #ifndef MULTIPLICATION_PROFITABLE
566: audio_channel[nr].voltbl = sound_table[v2];
567: #endif
1.1 root 568: }
569:
570: void dump_audio_bench (void)
571: {
572: #ifdef BENCHMARK_AUDIO
573: printf ("Average cycles per sample handler: %f\n", ((double)sh_time / sh_count));
574: #endif
575: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.