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