1 
2 /*
3  *   O2EM Free Odyssey2 / Videopac+ Emulator
4  *
5  *   Created by Daniel Boris <dboris@comcast.net>  (c) 1997,1998
6  *
7  *   Developed by Andre de la Rocha   <adlroc@users.sourceforge.net>
8  *             Arlindo M. de Oliveira <dgtec@users.sourceforge.net>
9  *
10  *   http://o2em.sourceforge.net
11  *
12  *
13  *
14  *   O2 audio emulation
15  */
16 
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include "cpu.h"
22 #include "types.h"
23 #include "config.h"
24 #include "vmachine.h"
25 #include "audio.h"
26 #include "allegro.h"
27 
28 #define SAMPLE_RATE 44100
29 #define PERIOD1 11
30 #define PERIOD2 44
31 
32 #define SOUND_BUFFER_LEN 1056
33 
34 #define AUD_CTRL  0xAA
35 #define AUD_D0	  0xA7
36 #define AUD_D1	  0xA8
37 #define AUD_D2	  0xA9
38 
39 
40 int sound_IRQ;
41 static AUDIOSTREAM *stream=NULL;
42 FILE *sndlog=NULL;
43 
44 static double flt_a=0.0, flt_b=0.0;
45 static unsigned char flt_prv = 0;
46 
47 
48 static void filter(unsigned char *buf, unsigned long len);
49 
50 
audio_process(unsigned char * buffer)51 void audio_process(unsigned char *buffer){
52 	unsigned long aud_data;
53 	int volume, re_circ, noise, enabled, intena, period, pnt, cnt, rndbit, pos;
54 
55 	aud_data = (VDCwrite[AUD_D2] | (VDCwrite[AUD_D1] << 8) | (VDCwrite[AUD_D0] << 16));
56 
57 	intena = VDCwrite[0xA0] & 0x04;
58 
59 	pnt = cnt = 0;
60 
61 	noise = VDCwrite[AUD_CTRL] & 0x10;
62 	enabled = VDCwrite[AUD_CTRL] & 0x80;
63 	rndbit = (enabled && noise) ? (rand()%2) : 0;
64 
65 	while (pnt < SOUND_BUFFER_LEN) {
66 		pos = (tweakedaudio) ? (pnt/3) : (MAXLINES-1);
67 		volume = AudioVector[pos] & 0x0F;
68 		enabled = AudioVector[pos] & 0x80;
69 		period = (AudioVector[pos] & 0x20) ? PERIOD1 : PERIOD2;
70 		re_circ = AudioVector[pos] & 0x40;
71 
72 		buffer[pnt++] = (enabled) ? ((aud_data & 0x01)^rndbit) * (0x10 * volume) : 0;
73 		cnt++;
74 
75 		if (cnt >= period) {
76 			cnt=0;
77 			aud_data = (re_circ) ? ((aud_data >> 1) | ((aud_data & 1) << 23)) : (aud_data >> 1);
78 			rndbit = (enabled && noise) ? (rand()%2) : 0;
79 
80 			if (enabled && intena && (!sound_IRQ)) {
81 				sound_IRQ = 1;
82 				ext_IRQ();
83 			}
84 		}
85 	}
86 
87 	if (app_data.filter) filter(buffer, SOUND_BUFFER_LEN);
88 }
89 
90 
update_audio(void)91 void update_audio(void) {
92 	unsigned char *p;
93 	if (app_data.sound_en) {
94 		p = (unsigned char *)get_audio_stream_buffer(stream);
95 		if (p) {
96 			audio_process(p);
97 			if (sndlog) fwrite(p,1,SOUND_BUFFER_LEN,sndlog);
98 			free_audio_stream_buffer(stream);
99 		}
100    	}
101 }
102 
103 
init_audio(void)104 void init_audio(void) {
105 	int i;
106 
107 	sound_IRQ=0;
108 	if ((app_data.sound_en) || (app_data.voice)) {
109 		printf("Initializing sound system...\n");
110 		i = install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL);
111 		if (i != 0) {
112 		   printf("  ERROR: could not initialize sound card\n   %s\n",allegro_error);
113 		   printf("  Sound system disabled\n");
114 		   app_data.sound_en = 0;
115 		   app_data.voice = 0;
116 		}
117 		else {
118 			if (digi_driver->name && (strlen(digi_driver->name)>0)){
119 				printf("  Sound system initialized ok\n");
120 				printf("  Sound driver [%s] detected\n",digi_driver->name);
121 				set_volume(-1,-1);
122 				init_sound_stream();
123 			} else {
124 				printf("  ERROR: could not initialize sound card\n");
125 				printf("  Sound system disabled\n");
126 				app_data.sound_en = 0;
127 				app_data.voice = 0;
128 			}
129 		}
130 	}
131 
132 	sndlog = NULL;
133 }
134 
135 
init_sound_stream(void)136 void init_sound_stream(void){
137 	int vol;
138 	if (app_data.sound_en){
139 		if (app_data.filter)
140 			vol = (255*app_data.svolume)/100;
141 		else
142 			vol = (255*app_data.svolume)/200;
143 		stream = play_audio_stream(SOUND_BUFFER_LEN,8,0,SAMPLE_RATE,vol,128);
144 		if (!stream) {
145 			printf("Error creating audio stream!\n");
146 			app_data.sound_en=0;
147 		}
148 		flt_a = flt_b = 0.0;
149 		flt_prv = 0;
150 	}
151 }
152 
153 
mute_audio(void)154 void mute_audio(void){
155 	if (app_data.sound_en && stream){
156 		stop_audio_stream(stream);
157 		stream=NULL;
158 	}
159 }
160 
161 
close_audio(void)162 void close_audio(void) {
163 	if (app_data.sound_en && stream) {
164 		stop_audio_stream(stream);
165 	}
166 	if (sndlog) fclose(sndlog);
167 	app_data.sound_en=0;
168 }
169 
170 
filter(unsigned char * buffer,unsigned long len)171 static void filter(unsigned char *buffer, unsigned long len){
172 	static unsigned char buf[SOUND_BUFFER_LEN];
173 	int t;
174 	unsigned long i;
175 	if (len>SOUND_BUFFER_LEN) return;
176 	memcpy(buf,buffer,len);
177 	for (i=0; i<len; i++){
178 		t = (i==0)?(buf[0]-flt_prv):(buf[i]-buf[i-1]);
179 		if (t) flt_b = (double)t;
180 		flt_a += flt_b/4.0 - flt_a/80.0;
181 		flt_b -= flt_b/4.0;
182 		if ((flt_a>255.0)||(flt_a<-255.0)) flt_a=0.0;
183 		buffer[i] = (unsigned char)((flt_a+255.0)/2.0);
184 	}
185 	flt_prv = buf[len-1];
186 }
187 
188 
189