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