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