1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "ibm.h"
4 #include "device.h"
5
6 #include "cdrom-ioctl.h"
7 #include "cdrom-image.h"
8 #include "ide.h"
9
10 #include "filters.h"
11
12 #include "sound_opl.h"
13
14 #include "sound.h"
15 #include "sound_adlib.h"
16 #include "sound_adlibgold.h"
17 #include "sound_audiopci.h"
18 #include "sound_pas16.h"
19 #include "sound_sb.h"
20 #include "sound_sb_dsp.h"
21 #include "sound_wss.h"
22
23 #include "timer.h"
24 #include "thread.h"
25
26 int sound_card_current = 0;
27 static int sound_card_last = 0;
28
29 typedef struct
30 {
31 char name[64];
32 char internal_name[24];
33 device_t *device;
34 } SOUND_CARD;
35
36 static SOUND_CARD sound_cards[] =
37 {
38 {"None", "none", NULL},
39 {"Adlib", "adlib", &adlib_device},
40 {"Adlib", "adlib_mca", &adlib_mca_device},
41 {"Sound Blaster 1.0", "sb", &sb_1_device},
42 {"Sound Blaster 1.5", "sb1.5", &sb_15_device},
43 {"Sound Blaster MCV", "sbmcv", &sb_mcv_device},
44 {"Sound Blaster 2.0", "sb2.0", &sb_2_device},
45 {"Sound Blaster Pro v1", "sbprov1", &sb_pro_v1_device},
46 {"Sound Blaster Pro v2", "sbprov2", &sb_pro_v2_device},
47 {"Sound Blaster Pro MCV", "sbpromcv", &sb_pro_mcv_device},
48 {"Sound Blaster 16", "sb16", &sb_16_device},
49 {"Sound Blaster AWE32", "sbawe32", &sb_awe32_device},
50 {"Adlib Gold", "adlibgold", &adgold_device},
51 {"Windows Sound System", "wss", &wss_device},
52 {"Pro Audio Spectrum 16", "pas16", &pas16_device},
53 {"Ensoniq AudioPCI (ES1371)", "es1371", &es1371_device},
54 {"Sound Blaster PCI 128", "sbpci128", &es1371_device},
55 {"", "", NULL}
56 };
57
sound_card_available(int card)58 int sound_card_available(int card)
59 {
60 if (sound_cards[card].device)
61 return device_available(sound_cards[card].device);
62
63 return 1;
64 }
65
sound_card_getname(int card)66 char *sound_card_getname(int card)
67 {
68 return sound_cards[card].name;
69 }
70
sound_card_getdevice(int card)71 device_t *sound_card_getdevice(int card)
72 {
73 return sound_cards[card].device;
74 }
75
sound_card_has_config(int card)76 int sound_card_has_config(int card)
77 {
78 if (!sound_cards[card].device)
79 return 0;
80 return sound_cards[card].device->config ? 1 : 0;
81 }
82
sound_card_get_internal_name(int card)83 char *sound_card_get_internal_name(int card)
84 {
85 return sound_cards[card].internal_name;
86 }
87
sound_card_get_from_internal_name(char * s)88 int sound_card_get_from_internal_name(char *s)
89 {
90 int c = 0;
91
92 while (strlen(sound_cards[c].internal_name))
93 {
94 if (!strcmp(sound_cards[c].internal_name, s))
95 return c;
96 c++;
97 }
98
99 return 0;
100 }
101
sound_card_init()102 void sound_card_init()
103 {
104 if (sound_cards[sound_card_current].device)
105 device_add(sound_cards[sound_card_current].device);
106 sound_card_last = sound_card_current;
107 }
108
109 static struct
110 {
111 void (*get_buffer)(int32_t *buffer, int len, void *p);
112 void *priv;
113 } sound_handlers[8];
114
115 static int sound_handlers_num;
116
117 static int sound_poll_time = 0, sound_poll_latch;
118 int sound_pos_global = 0;
119
120 int soundon = 1;
121
122 static int16_t cd_buffer[CD_BUFLEN * 2];
123 static thread_t *sound_cd_thread_h;
124 static event_t *sound_cd_event;
125 static unsigned int cd_vol_l, cd_vol_r;
126
127 int sound_buf_len = 48000 / 10;
128 int sound_gain = 0;
129
sound_update_buf_length()130 void sound_update_buf_length()
131 {
132 int new_buf_len = (48000 / (1000 / sound_buf_len)) / 4;
133
134 if (new_buf_len > MAXSOUNDBUFLEN)
135 new_buf_len = MAXSOUNDBUFLEN;
136
137 SOUNDBUFLEN = new_buf_len;
138 }
139
sound_set_cd_volume(unsigned int vol_l,unsigned int vol_r)140 void sound_set_cd_volume(unsigned int vol_l, unsigned int vol_r)
141 {
142 cd_vol_l = vol_l;
143 cd_vol_r = vol_r;
144 }
145
sound_cd_thread(void * param)146 static void sound_cd_thread(void *param)
147 {
148 while (1)
149 {
150 int c;
151
152 thread_wait_event(sound_cd_event, -1);
153 thread_reset_event(sound_cd_event);
154 memset(cd_buffer, 0, CD_BUFLEN*2 * 2);
155 ioctl_audio_callback(cd_buffer, CD_BUFLEN*2);
156 image_audio_callback(cd_buffer, CD_BUFLEN*2);
157 if (soundon)
158 {
159 int32_t atapi_vol_l = atapi_get_cd_volume(0);
160 int32_t atapi_vol_r = atapi_get_cd_volume(1);
161 int channel_select[2];
162
163 channel_select[0] = atapi_get_cd_channel(0);
164 channel_select[1] = atapi_get_cd_channel(1);
165
166 for (c = 0; c < CD_BUFLEN*2; c += 2)
167 {
168 int32_t cd_buffer_temp[2] = {0, 0};
169
170 /*First, adjust input from drive according to ATAPI volume.*/
171 cd_buffer[c] = ((int32_t)cd_buffer[c] * atapi_vol_l) / 255;
172 cd_buffer[c+1] = ((int32_t)cd_buffer[c+1] * atapi_vol_r) / 255;
173
174 /*Apply ATAPI channel select*/
175 if (channel_select[0] & 1)
176 cd_buffer_temp[0] += cd_buffer[c];
177 if (channel_select[0] & 2)
178 cd_buffer_temp[1] += cd_buffer[c];
179 if (channel_select[1] & 1)
180 cd_buffer_temp[0] += cd_buffer[c+1];
181 if (channel_select[1] & 2)
182 cd_buffer_temp[1] += cd_buffer[c+1];
183
184 /*Apply sound card CD volume*/
185 cd_buffer_temp[0] = (cd_buffer_temp[0] * (int)cd_vol_l) / 65535;
186 cd_buffer_temp[1] = (cd_buffer_temp[1] * (int)cd_vol_r) / 65535;
187
188 if (cd_buffer_temp[0] > 32767)
189 cd_buffer_temp[0] = 32767;
190 if (cd_buffer_temp[0] < -32768)
191 cd_buffer_temp[0] = -32768;
192 if (cd_buffer_temp[1] > 32767)
193 cd_buffer_temp[1] = 32767;
194 if (cd_buffer_temp[1] < -32768)
195 cd_buffer_temp[1] = -32768;
196
197 cd_buffer[c] = cd_buffer_temp[0];
198 cd_buffer[c+1] = cd_buffer_temp[1];
199 }
200
201 givealbuffer_cd(cd_buffer);
202 }
203 }
204 }
205
206 static int32_t *outbuffer;
207
sound_init()208 void sound_init()
209 {
210 initalmain(0,NULL);
211 inital();
212
213 outbuffer = malloc(MAXSOUNDBUFLEN * 2 * sizeof(int32_t));
214
215 sound_cd_event = thread_create_event();
216 sound_cd_thread_h = thread_create(sound_cd_thread, NULL);
217 }
218
sound_add_handler(void (* get_buffer)(int32_t * buffer,int len,void * p),void * p)219 void sound_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *p), void *p)
220 {
221 sound_handlers[sound_handlers_num].get_buffer = get_buffer;
222 sound_handlers[sound_handlers_num].priv = p;
223 sound_handlers_num++;
224 }
225
226 static int cd_pos = 0;
sound_poll(void * priv)227 void sound_poll(void *priv)
228 {
229 sound_poll_time += sound_poll_latch;
230
231 cd_pos++;
232 if (cd_pos == (CD_BUFLEN * 48000) / CD_FREQ)
233 {
234 cd_pos = 0;
235 thread_set_event(sound_cd_event);
236 }
237
238 sound_pos_global++;
239 if (sound_pos_global == SOUNDBUFLEN)
240 {
241 int c;
242 /* int16_t buf16[SOUNDBUFLEN * 2 ];*/
243
244 memset(outbuffer, 0, SOUNDBUFLEN * 2 * sizeof(int32_t));
245
246 for (c = 0; c < sound_handlers_num; c++)
247 sound_handlers[c].get_buffer(outbuffer, SOUNDBUFLEN, sound_handlers[c].priv);
248
249
250 /* for (c=0;c<SOUNDBUFLEN*2;c++)
251 {
252 if (outbuffer[c] < -32768)
253 buf16[c] = -32768;
254 else if (outbuffer[c] > 32767)
255 buf16[c] = 32767;
256 else
257 buf16[c] = outbuffer[c];
258 }
259
260 if (!soundf) soundf=fopen("sound.pcm","wb");
261 fwrite(buf16,(SOUNDBUFLEN)*2*2,1,soundf);*/
262
263 if (soundon) givealbuffer(outbuffer);
264
265 sound_pos_global = 0;
266 sound_update_buf_length();
267 }
268 }
269
sound_speed_changed()270 void sound_speed_changed()
271 {
272 sound_poll_latch = (int)((double)TIMER_USEC * (1000000.0 / 48000.0));
273 }
274
sound_reset()275 void sound_reset()
276 {
277 timer_add(sound_poll, &sound_poll_time, TIMER_ALWAYS_ENABLED, NULL);
278
279 sound_handlers_num = 0;
280
281 sound_set_cd_volume(65535, 65535);
282 ioctl_audio_stop();
283 image_audio_stop();
284 }
285