|
|
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: int sound_available = 0;
40:
41: struct audio_channel_data audio_channel[4];
42:
43: int sound_table[64][256];
44: unsigned long int sample_evtime;
45:
46: void init_sound_table16(void)
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: void AUDxDAT(int nr, uae_u16 v)
65: {
66: struct audio_channel_data *cdp = audio_channel + nr;
67: cdp->dat = v;
68: if (cdp->state == 0 && !(INTREQR() & (0x80 << nr))) {
69: cdp->state = 2;
70: INTREQ(0x8000 | (0x80 << nr));
71: /* data_written = 2 ???? */
72: eventtab[ev_aud0 + nr].evtime = cycles + cdp->per;
73: eventtab[ev_aud0 + nr].oldcycles = cycles;
74: eventtab[ev_aud0 + nr].active = 1;
75: events_schedule();
76: }
77: }
78:
79: void AUDxLCH(int nr, uae_u16 v) { audio_channel[nr].lc = (audio_channel[nr].lc & 0xffff) | ((uae_u32)v << 16); }
80: void AUDxLCL(int nr, uae_u16 v) { audio_channel[nr].lc = (audio_channel[nr].lc & ~0xffff) | (v & 0xFFFE); }
81: void AUDxPER(int nr, uae_u16 v)
82: {
83: if (v <= 0) {
84: #if 0 /* v == 0 is rather common, and harmless, and the value isn't signed anyway */
85: static int warned = 0;
86: if (!warned)
87: write_log ("Broken program accessing the sound hardware\n"), warned++;
88: #endif
89: v = 65535;
90: }
91: if (v < maxhpos/2 && currprefs.produce_sound < 3)
92: v = maxhpos/2;
93:
94: audio_channel[nr].per = v;
95: }
96:
97: void AUDxLEN(int nr, uae_u16 v) { audio_channel[nr].len = v; }
98:
99: #define MULTIPLICATION_PROFITABLE
100:
101: #ifdef MULTIPLICATION_PROFITABLE
102: typedef uae_s8 sample8_t;
103: #define DO_CHANNEL_1(v, c) do { (v) *= audio_channel[c].vol; } while (0)
104: #define SBASEVAL8(logn) ((logn) == 1 ? SOUND8_BASE_VAL << 7 : SOUND8_BASE_VAL << 8)
105: #define SBASEVAL16(logn) ((logn) == 1 ? SOUND16_BASE_VAL >> 1 : SOUND16_BASE_VAL)
106: #define FINISH_DATA(b,logn) do { if (14 - (b) + (logn) > 0) data >>= 14 - (b) + (logn); else data <<= (b) - 14 - (logn); } while (0);
107: #else
108: typedef uae_u8 sample8_t;
109: #define DO_CHANNEL_1(v, c) do { (v) = audio_channel[c].voltbl[(v)]; } while (0)
110: #define SBASEVAL8(logn) SOUND8_BASE_VAL
111: #define SBASEVAL16(logn) SOUND16_BASE_VAL
112: #define FINISH_DATA(b,logn)
113: #endif
114:
115: void AUDxVOL(int nr, uae_u16 v)
116: {
117: int v2 = v & 64 ? 63 : v & 63;
118: audio_channel[nr].vol = v2;
119: #ifndef MULTIPLICATION_PROFITABLE
120: audio_channel[nr].voltbl = sound_table[v2];
121: #endif
122: }
123:
124: #define DO_CHANNEL(v, c) do { (v) &= audio_channel[c].adk_mask; data += v; } while (0);
125:
126: /* Templates! I want templates! */
127: void sample16_handler(void)
128: {
129: BEGIN_BENCH
130:
131: uae_u32 data0 = audio_channel[0].current_sample;
132: uae_u32 data1 = audio_channel[1].current_sample;
133: uae_u32 data2 = audio_channel[2].current_sample;
134: uae_u32 data3 = audio_channel[3].current_sample;
135: DO_CHANNEL_1 (data0, 0);
136: DO_CHANNEL_1 (data1, 1);
137: DO_CHANNEL_1 (data2, 2);
138: DO_CHANNEL_1 (data3, 3);
139: data0 &= audio_channel[0].adk_mask;
140: data1 &= audio_channel[1].adk_mask;
141: data2 &= audio_channel[2].adk_mask;
142: data3 &= audio_channel[3].adk_mask;
143: data0 += data1;
144: data0 += data2;
145: data0 += data3;
146: {
147: uae_u32 data = SBASEVAL16(2) + data0;
148: FINISH_DATA(16, 2);
149: PUT_SOUND_WORD (data);
150: }
151: END_BENCH
152:
153: check_sound_buffers ();
154:
155: eventtab[ev_sample].evtime = cycles + sample_evtime;
156: eventtab[ev_sample].oldcycles = cycles;
157: }
158:
159: void sample8_handler(void)
160: {
161: BEGIN_BENCH
162:
163: uae_u32 data0 = audio_channel[0].current_sample;
164: uae_u32 data1 = audio_channel[1].current_sample;
165: uae_u32 data2 = audio_channel[2].current_sample;
166: uae_u32 data3 = audio_channel[3].current_sample;
167: DO_CHANNEL_1 (data0, 0);
168: DO_CHANNEL_1 (data1, 1);
169: DO_CHANNEL_1 (data2, 2);
170: DO_CHANNEL_1 (data3, 3);
171: data0 &= audio_channel[0].adk_mask;
172: data1 &= audio_channel[1].adk_mask;
173: data2 &= audio_channel[2].adk_mask;
174: data3 &= audio_channel[3].adk_mask;
175: data0 += data1;
176: data0 += data2;
177: data0 += data3;
178: {
179: uae_u32 data = SBASEVAL8(2) + data0;
180: FINISH_DATA(8, 2);
181: PUT_SOUND_BYTE (data);
182: }
183: END_BENCH
184:
185: check_sound_buffers ();
186:
187: eventtab[ev_sample].evtime = cycles + sample_evtime;
188: eventtab[ev_sample].oldcycles = cycles;
189: }
190:
191: #ifdef HAVE_STEREO_SUPPORT
192: void sample16s_handler(void)
193: {
194: BEGIN_BENCH
195:
196: uae_u32 data0 = audio_channel[0].current_sample;
197: uae_u32 data1 = audio_channel[1].current_sample;
198: uae_u32 data2 = audio_channel[2].current_sample;
199: uae_u32 data3 = audio_channel[3].current_sample;
200: DO_CHANNEL_1 (data0, 0);
201: DO_CHANNEL_1 (data1, 1);
202: DO_CHANNEL_1 (data2, 2);
203: DO_CHANNEL_1 (data3, 3);
204:
205: data0 &= audio_channel[0].adk_mask;
206: data1 &= audio_channel[1].adk_mask;
207: data2 &= audio_channel[2].adk_mask;
208: data3 &= audio_channel[3].adk_mask;
209:
210: data0 += data3;
211: {
212: uae_u32 data = SBASEVAL16(1) + data0;
213: FINISH_DATA (16, 1);
214: PUT_SOUND_WORD_RIGHT (data);
215: }
216:
217: data1 += data2;
218: {
219: uae_u32 data = SBASEVAL16(1) + data1;
220: FINISH_DATA (16, 1);
221: PUT_SOUND_WORD_LEFT (data);
222: }
223:
224: END_BENCH
225:
226: check_sound_buffers ();
227:
228: eventtab[ev_sample].evtime = cycles + sample_evtime;
229: eventtab[ev_sample].oldcycles = cycles;
230: }
231:
232: void sample8s_handler(void)
233: {
234: BEGIN_BENCH
235:
236: uae_u32 data0 = audio_channel[0].current_sample;
237: uae_u32 data1 = audio_channel[1].current_sample;
238: uae_u32 data2 = audio_channel[2].current_sample;
239: uae_u32 data3 = audio_channel[3].current_sample;
240: DO_CHANNEL_1 (data0, 0);
241: DO_CHANNEL_1 (data1, 1);
242: DO_CHANNEL_1 (data2, 2);
243: DO_CHANNEL_1 (data3, 3);
244:
245: data0 &= audio_channel[0].adk_mask;
246: data1 &= audio_channel[1].adk_mask;
247: data2 &= audio_channel[2].adk_mask;
248: data3 &= audio_channel[3].adk_mask;
249:
250: data0 += data3;
251: {
252: uae_u32 data = SBASEVAL8(1) + data0;
253: FINISH_DATA (8, 1);
254: PUT_SOUND_BYTE_RIGHT (data);
255: }
256: data1 += data2;
257: {
258: uae_u32 data = SBASEVAL8(1) + data1;
259: FINISH_DATA (8, 1);
260: PUT_SOUND_BYTE_LEFT (data);
261: }
262:
263: END_BENCH
264:
265: check_sound_buffers ();
266:
267: eventtab[ev_sample].evtime = cycles + sample_evtime;
268: eventtab[ev_sample].oldcycles = cycles;
269: }
270: #else
271: void sample8s_handler(void)
272: {
273: sample8_handler();
274: }
275: void sample16s_handler(void)
276: {
277: sample16_handler();
278: }
279: #endif
280:
281: static uae_u8 int2ulaw(int ch)
282: {
283: int mask;
284:
285: if (ch < 0) {
286: ch = -ch;
287: mask = 0x7f;
288: }
289: else {
290: mask = 0xff;
291: }
292:
293: if (ch < 32) {
294: ch = 0xF0 | ( 15 - (ch/2) );
295: } else if (ch < 96) {
296: ch = 0xE0 | ( 15 - (ch-32)/4 );
297: } else if (ch < 224) {
298: ch = 0xD0 | ( 15 - (ch-96)/8 );
299: } else if (ch < 480) {
300: ch = 0xC0 | ( 15 - (ch-224)/16 );
301: } else if (ch < 992 ) {
302: ch = 0xB0 | ( 15 - (ch-480)/32 );
303: } else if (ch < 2016) {
304: ch = 0xA0 | ( 15 - (ch-992)/64 );
305: } else if (ch < 4064) {
306: ch = 0x90 | ( 15 - (ch-2016)/128 );
307: } else if (ch < 8160) {
308: ch = 0x80 | ( 15 - (ch-4064)/256 );
309: } else {
310: ch = 0x80;
311: }
312: return (uae_u8)(mask & ch);
313: }
314:
315: void sample_ulaw_handler (void)
316: {
317: int nr;
318: uae_u32 data = 0;
319:
320: eventtab[ev_sample].evtime += cycles - eventtab[ev_sample].oldcycles;
321: eventtab[ev_sample].oldcycles = cycles;
322:
323: for (nr = 0; nr < 4; nr++) {
324: if (!(adkcon & (0x11 << nr))) {
325: uae_u32 d = audio_channel[nr].current_sample;
326: DO_CHANNEL_1 (d, nr);
327: data += d;
328: }
329: }
330: PUT_SOUND_BYTE (int2ulaw (data));
331: check_sound_buffers ();
332: }
333:
334: static void audio_handler (int nr)
335: {
336: struct audio_channel_data *cdp = audio_channel + nr;
337:
338: switch (cdp->state) {
339: case 0:
340: fprintf(stderr, "Bug in sound code\n");
341: break;
342:
343: case 1:
344: /* We come here at the first hsync after DMA was turned on. */
345: eventtab[ev_aud0 + nr].evtime += maxhpos;
346: eventtab[ev_aud0 + nr].oldcycles += maxhpos;
347:
348: cdp->state = 5;
349: INTREQ(0x8000 | (0x80 << nr));
350: if (cdp->wlen != 1)
351: cdp->wlen--;
352: cdp->nextdat = chipmem_bank.wget(cdp->pt);
353:
354: cdp->pt += 2;
355: break;
356:
357: case 5:
358: /* We come here at the second hsync after DMA was turned on. */
359: if (currprefs.produce_sound == 0)
360: cdp->per = 65535;
361:
362: eventtab[ev_aud0 + nr].evtime = cycles + cdp->per;
363: eventtab[ev_aud0 + nr].oldcycles = cycles;
364: cdp->dat = cdp->nextdat;
365: cdp->current_sample = (sample8_t)(cdp->dat >> 8);
366:
367: cdp->state = 2;
368: {
369: int audav = adkcon & (1 << nr);
370: int audap = adkcon & (16 << nr);
371: int napnav = (!audav && !audap) || audav;
372: if (napnav)
373: cdp->data_written = 2;
374: }
375: break;
376:
377: case 2:
378: /* We come here when a 2->3 transition occurs */
379: if (currprefs.produce_sound == 0)
380: cdp->per = 65535;
381:
382: cdp->current_sample = (sample8_t)(cdp->dat & 0xFF);
383: eventtab[ev_aud0 + nr].evtime = cycles + cdp->per;
384: eventtab[ev_aud0 + nr].oldcycles = cycles;
385:
386: cdp->state = 3;
387:
388: /* Period attachment? */
389: if (adkcon & (0x10 << nr)) {
390: if (cdp->intreq2 && cdp->dmaen)
391: INTREQ(0x8000 | (0x80 << nr));
392: cdp->intreq2 = 0;
393:
394: cdp->dat = cdp->nextdat;
395: if (cdp->dmaen)
396: cdp->data_written = 2;
397: if (nr < 3) {
398: if (cdp->dat == 0)
399: (cdp+1)->per = 65535;
400:
401: else if (cdp->dat < maxhpos/2 && currprefs.produce_sound < 3)
402: (cdp+1)->per = maxhpos/2;
403: else
404: (cdp+1)->per = cdp->dat;
405: }
406: }
407: break;
408:
409: case 3:
410: /* We come here when a 3->2 transition occurs */
411: if (currprefs.produce_sound == 0)
412: cdp->per = 65535;
413:
414: eventtab[ev_aud0 + nr].evtime = cycles + cdp->per;
415: eventtab[ev_aud0 + nr].oldcycles = cycles;
416:
417: if ((INTREQR() & (0x80 << nr)) && !cdp->dmaen) {
418: cdp->state = 0;
419: cdp->current_sample = 0;
420: eventtab[ev_aud0 + nr].active = 0;
421: break;
422: } else {
423: int audav = adkcon & (1 << nr);
424: int audap = adkcon & (16 << nr);
425: int napnav = (!audav && !audap) || audav;
426: cdp->state = 2;
427:
428: if ((cdp->intreq2 && cdp->dmaen && napnav)
429: || (napnav && !cdp->dmaen))
430: INTREQ(0x8000 | (0x80 << nr));
431: cdp->intreq2 = 0;
432:
433: cdp->dat = cdp->nextdat;
434: cdp->current_sample = (sample8_t)(cdp->dat >> 8);
435:
436: if (cdp->dmaen && napnav)
437: cdp->data_written = 2;
438:
439: /* Volume attachment? */
440: if (audav) {
441: if (nr < 3) {
442: (cdp+1)->vol = cdp->dat;
443: #ifndef MULTIPLICATION_PROFITABLE
444: (cdp+1)->voltbl = sound_table[cdp->dat];
445: #endif
446: }
447: }
448: }
449: break;
450:
451: default:
452: cdp->state = 0;
453: eventtab[ev_aud0 + nr].active = 0;
454: break;
455: }
456: }
457:
458: void aud0_handler (void)
459: {
460: audio_handler (0);
461: }
462: void aud1_handler (void)
463: {
464: audio_handler (1);
465: }
466: void aud2_handler (void)
467: {
468: audio_handler (2);
469: }
470: void aud3_handler (void)
471: {
472: audio_handler (3);
473: }
474:
475: void audio_reset (void)
476: {
477: memset (audio_channel, 0, sizeof audio_channel);
478: audio_channel[0].per = 65535;
479: audio_channel[1].per = 65535;
480: audio_channel[2].per = 65535;
481: audio_channel[3].per = 65535;
482: audio_channel[0].voltbl = sound_table[0];
483: audio_channel[1].voltbl = sound_table[0];
484: audio_channel[2].voltbl = sound_table[0];
485: audio_channel[3].voltbl = sound_table[0];
486: }
487:
488: void dump_audio_bench (void)
489: {
490: #ifdef BENCHMARK_AUDIO
491: printf ("Average cycles per sample handler: %f\n", ((double)sh_time / sh_count));
492: #endif
493: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.