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