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 <stdint.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include "cpu.h"
22 #include "config.h"
23 #include "vmachine.h"
24 #include "audio.h"
25 
26 #define SAMPLE_RATE 44100
27 #define PERIOD1 11
28 #define PERIOD2 44
29 
30 #define SOUND_BUFFER_LEN 1056
31 
32 #define AUD_CTRL  0xAA
33 #define AUD_D0	  0xA7
34 #define AUD_D1	  0xA8
35 #define AUD_D2	  0xA9
36 
37 extern int SND;
38 extern uint8_t soundBuffer[SOUND_BUFFER_LEN];
39 
40 int sound_IRQ;
41 
42 static double flt_a=0.0, flt_b=0.0;
43 static unsigned char flt_prv = 0;
44 
45 
filter(unsigned char * buffer,unsigned long len)46 static void filter(unsigned char *buffer, unsigned long len)
47 {
48 	static unsigned char buf[SOUND_BUFFER_LEN];
49 	unsigned long i;
50 	if (len>SOUND_BUFFER_LEN)
51       return;
52 
53 	memcpy(buf,buffer,len);
54 
55 	for (i=0; i<len; i++)
56    {
57 		int t = (i==0)?(buf[0]-flt_prv):(buf[i]-buf[i-1]);
58 		if (t) flt_b = (double)t;
59 		flt_a += flt_b/4.0 - flt_a/80.0;
60 		flt_b -= flt_b/4.0;
61 		if ((flt_a>255.0)||(flt_a<-255.0))
62          flt_a=0.0;
63 		buffer[i] = (unsigned char)((flt_a+255.0)/2.0);
64 	}
65 	flt_prv = buf[len-1];
66 }
67 
audio_process(unsigned char * buffer)68 void audio_process(unsigned char *buffer)
69 {
70    unsigned long aud_data = (VDCwrite[AUD_D2] |
71          (VDCwrite[AUD_D1] << 8) | (VDCwrite[AUD_D0] << 16));
72 
73    int intena = VDCwrite[0xA0] & 0x04;
74    int pnt    = 0;
75    int cnt    = 0;
76 
77    int noise = VDCwrite[AUD_CTRL] & 0x10;
78    int enabled = VDCwrite[AUD_CTRL] & 0x80;
79    int rndbit = (enabled && noise) ? (rand()%2) : 0;
80 
81    while (pnt < SOUND_BUFFER_LEN)
82    {
83       int period, re_circ;
84 
85       int pos = (tweakedaudio) ? (pnt/3) : (MAXLINES-1);
86       int volume = AudioVector[pos] & 0x0F;
87       enabled = AudioVector[pos] & 0x80;
88       period = (AudioVector[pos] & 0x20) ? PERIOD1 : PERIOD2;
89       re_circ = AudioVector[pos] & 0x40;
90 
91       buffer[pnt++] = (enabled) ? ((aud_data & 0x01)^rndbit) * (0x10 * volume) : 0;
92       cnt++;
93 
94       if (cnt >= period)
95       {
96          cnt=0;
97          aud_data = (re_circ) ? ((aud_data >> 1) | ((aud_data & 1) << 23)) : (aud_data >> 1);
98          rndbit = (enabled && noise) ? (rand()%2) : 0;
99 
100          if (enabled && intena && (!sound_IRQ))
101          {
102             sound_IRQ = 1;
103             ext_IRQ();
104          }
105       }
106    }
107 
108    if (app_data.filter)
109       filter(buffer, SOUND_BUFFER_LEN);
110 }
111 
112 
113 
update_audio(void)114 void update_audio(void)
115 {
116    audio_process(soundBuffer);
117 }
118 
119 
init_audio(void)120 void init_audio(void)
121 {
122    sound_IRQ=0;
123    if ((app_data.sound_en) || (app_data.voice))
124       init_sound_stream();
125 }
126 
127 
init_sound_stream(void)128 void init_sound_stream(void)
129 {
130 #if 0
131    int vol;
132 #endif
133    if (app_data.sound_en)
134    {
135 #if 0
136       if (app_data.filter)
137          vol = (255*app_data.svolume)/100;
138       else
139          vol = (255*app_data.svolume)/200;
140 #endif
141       flt_a = flt_b = 0.0;
142       flt_prv = 0;
143    }
144 }
145 
146 
mute_audio(void)147 void mute_audio(void)
148 {
149 	SND=0;
150 }
151 
close_audio(void)152 void close_audio(void)
153 {
154 	app_data.sound_en=0;
155 }
156 
157 
158