1
2 /*
3 sound.c
4
5 Gameboy sound emulation support for Linux.
6
7 *****************************************************
8 EXPERIMENTAL !!!!!
9 SOUNDS TERRIBLE !!!!!!!!
10 *****************************************************
11
12 */
13
14
15 #ifdef SOUND
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <fcntl.h>
21 #include <sys/ioctl.h>
22 #include <pthread.h>
23
24 #ifndef AUDIO
25 #include <sys/soundcard.h>
26 #else
27 #include <sys/audioio.h>
28 #endif
29
30 #include "globals.h"
31 #include "gameboy.h"
32
33
34 int sd; /* dsp/audio device descriptor */
35
36 int gain;
37 int snd_count1,snd_count2,snd_count3,snd_count4;
38 int snd_reload1,snd_init1,snd_length1,snd_count1,snd1_st,snd1_str;
39 int snd_reload2,snd_init2,snd_length2,snd_count2;
40 int snd_reload3,snd_init3,snd_length3,snd_count3,snd_shr;
41 int snd_reload4,snd_init4,snd_length4,snd4_rand;
42
43 #define FIXPOINT_SHIFT 16
44 #define FIXPOINT_MASK ((1L<<FIXPOINT_SHIFT)-1)
45 #define FIXPOINT_HALF (1L<<(FIXPOINT_SHIFT-1))
46
47 /* current sound rate (set it higher, if you dare) */
48
49 int sound_frequency=22050;
50 int frequency_div256;
51
52 char *dspdev="/dev/dsp";
53 char *audiodev="/dev/audio";
54
55 int *pattern[4];
56 int chn3_tab[16]; /*={-32,-28,-24,-20,-16,-12,-8,-4,
57 0,4,8,12,16,20,24,28}*/
58
59 #define SND4_RNDPATTERNLEN 16384
60 int snd4_rndpattern[SND4_RNDPATTERNLEN];
61
62 int gbfreq(unsigned short int);
63 void outsample(int s);
64 /*void* processSound(void *);*/
65
66
67 /* sound initialisation */
68
initsound(void)69 int initsound(void)
70 {
71 /* pthread_t tid;*/
72 int value;
73
74 #ifdef AUDIO
75 audio_info_t audio;
76 #endif
77
78 #ifndef AUDIO
79 if ((sd=open(dspdev,O_WRONLY))<0) {
80 fprintf(OUTSTREAM,"Error opening %s\n",dspdev);
81 return 0;
82 }
83
84 value=AFMT_U8;
85 if (ioctl(sd,SNDCTL_DSP_SETFMT,&value)<0) {
86 fprintf(OUTSTREAM,"Error: SNDCLT_DSP_SETFMT\n");
87 close(sd);
88 return 0;
89 }
90
91 value=sound_frequency;
92 if (ioctl(sd,SNDCTL_DSP_SPEED,&value)<0) {
93 fprintf(OUTSTREAM,"Error: SNDCLT_DSP_SPEED\n");
94 close(sd);
95 return 0;
96 }
97
98 value=0x0003000a; /* 3 bufs, 2^8 bytes */
99 if (ioctl(sd,SNDCTL_DSP_SETFRAGMENT,&value)<0) {
100 fprintf(OUTSTREAM,"Error: SNDCLT_DSP_SETFRAGMENT\n");
101 close(sd);
102 return 0;
103 }
104 #else
105 if ((sd=open(audiodev,O_WRONLY))<0) {
106 fprintf(OUTSTREAM,"Error opening %s\n",audiodev);
107 close(sd);
108 return 0;
109 }
110
111 AUDIO_INITINFO (&audio);
112 audio.play.sample_rate = sound_frequency;
113 audio.play.channels = 1;
114 audio.play.precision = 8;
115 audio.play.encoding = AUDIO_ENCODING_LINEAR;
116
117 if (ioctl (sd, AUDIO_SETINFO, &audio)<0) {
118 fprintf(OUTSTREAM,"Failed to set %s.\n",audiodev);
119 return 0;
120 }
121 if (ioctl (sd, AUDIO_GETINFO, &audio) != 0) return (0);
122 #endif
123
124 fprintf(OUTSTREAM,"Allocating sound pattern memory 4x%lu bytes.\n",
125 (long unsigned int)sound_frequency*sizeof(int));
126 for (value=0;value<4;value++) {
127 if ((pattern[value]=malloc(sound_frequency*sizeof(int)))==NULL) {
128 fprintf(OUTSTREAM,"Error allocating sound pattern memory.\n");
129 close(sd);
130 return 0;
131 }
132 }
133
134 snd_updateclks=(4096*1024)/sound_frequency;
135
136 snd_init1=snd_length1=snd_count1=0;
137 snd_init2=snd_length2=snd_count2=0;
138 snd_init3=snd_length3=snd_count3=0;
139 snd_init4=snd_length4=snd_count4=0;
140
141 fprintf(OUTSTREAM,"Initializing sound pattern memory.\n");
142 for (value=0;value<sound_frequency;value++) {
143 /* pattern[2][value]=sin((float)value/DSP_FREQ*2*M_PI)*128+128;
144 if (value>=DSP_FREQ/2)
145 pattern[1][value]=sin((float)value/DSP_FREQ*4*M_PI)*128+128;
146 else pattern[1][value]=0;
147 if (value>=DSP_FREQ/4)
148 pattern[0][value]=sin((float)value/DSP_FREQ*8*M_PI)*128+128;
149 else pattern[0][value]=0;
150 if (value>=3*DSP_FREQ/4)
151 pattern[3][value]=sin((float)value/DSP_FREQ*1.5*M_PI)*128+128;
152 else pattern[3][value]=0;
153 pattern[value]=255-((float)value/DSP_FREQ*255.0);*/
154 if (value>=sound_frequency/2) pattern[2][value]=128-32;
155 else pattern[2][value]=128+32;
156 if (value>=sound_frequency/4) pattern[1][value]=128-32;
157 else pattern[1][value]=128+32;
158 if (value>=sound_frequency/8) pattern[0][value]=128-32;
159 else pattern[0][value]=128+32;
160 if (value>=sound_frequency/4) pattern[3][value]=128+32;
161 else pattern[3][value]=128-32;
162 }
163
164 srand(time(NULL));
165 for (value=0;value<SND4_RNDPATTERNLEN;value++) {
166
167 snd4_rndpattern[value]=(rand()>>26)+128-32;
168 if (value<16) {
169 snd4_rndpattern[value]*=(value/16.0);
170 }
171 /* printf("%d\n",snd4_rndpattern[value]);*/
172 }
173
174 for (value=0;value<16;value++)
175 chn3_tab[value]=(value-8)*4+128;
176
177 fprintf(OUTSTREAM,"Sound pattern memory OK.\n");
178
179 frequency_div256=sound_frequency/256;
180
181 /* value=pthread_create(&tid,NULL,processSound,NULL);
182 fprintf(OUTSTREAM,"Sound thread initialized %s.\n", value==0 ? "OK" : "FAILED");
183 if (value!=0) {
184 fprintf(OUTSTREAM,"Failed with value %d.\n",value);
185 }*/
186
187 return 1; /* sound will be emulated */
188 }
189
190 /* closing sound */
donesound(void)191 void donesound(void)
192 {
193 int value;
194
195 for (value=0;value<4;value++) free(pattern[value]);
196 if (sd>0) close(sd);
197 }
198
199 #if 0
200 #ifdef USE_LITTLE_ENDIAN
201 #define SND_BUFSIZE 1024
202 #define SND_BUFCOUNT 3
203 static int snd_bufptr=0;
204 static int snd_bufnr=0;
205 static char snd_buffer[SND_BUFCOUNT][SND_BUFSIZE];
206 #endif
207 #endif
208
outsample(int s)209 void outsample(int s)
210 {
211 #if 0
212 #ifdef USE_LITTLE_ENDIAN
213
214 snd_buffer[snd_bufnr][snd_bufptr++]=(char)s;
215
216 if (snd_bufptr>=SND_BUFSIZE) {
217 int playbuf=snd_bufnr-1;
218 if (playbuf<0) playbuf=SND_BUFCOUNT-1;
219
220 write(sd,snd_buffer[playbuf],SND_BUFSIZE);
221 snd_bufnr++;
222 snd_bufptr=0;
223 if (snd_bufnr>=SND_BUFCOUNT) snd_bufnr=0;
224 }
225 #else
226 #endif
227 #endif
228 char lf;
229 lf=(char)s;
230
231 write(sd,&lf,1);
232
233 /* printf("%d",s);*/
234 }
235
mixsample(int s1,int s2)236 int mixsample(int s1,int s2)
237 {
238 register int s;
239
240 s=((s1-128)+(s2-128))+128;
241
242 return s<=0 ? 0 :
243 s>=255 ? 255 : s;
244 }
245
processSound(void)246 void processSound(void)
247 {
248
249 /* while (1) {*/
250
251 int sample=128,gain=128,pos;
252
253 /* usleep(1);*/
254
255 /*printf("THREAD\n");*/
256 /*while (Z80_CPUCLKS & 0x03);*/
257
258 if (((NR50&0x77)==0)||((NR52&0x80)==0)) {
259 if (producesound) outsample(sample);
260 else outsample(0);
261 }
262
263 #if 1
264 if (NR51&0x11 && NR12&0xF8) {
265 if (snd_init1) {
266 snd_init1=0;
267 snd_count1=frequency_div256;
268 }
269
270 if ((snd_reload1>0)&&(snd_length1>0)) {
271 if (snd_count1--<=0) {
272 snd_length1--;
273 snd_count1=frequency_div256;
274
275 /* sweep */
276 if (snd1_str>0) {
277 if (--snd1_st==0) {
278 snd1_st=snd1_str;
279
280 pos=((NR14&7)<<8)|NR13;
281 if (NR10&8)
282 pos-=pos>>(NR10&7);
283 else
284 pos+=pos>>(NR10&7);
285
286 NR14=(NR14&0xF8)|((pos>>8)&7);
287 NR13=pos&0xFF;
288
289 snd_reload1=gbfreq(pos);
290 }
291 }
292 }
293
294 snd_count1+=snd_reload1;
295 /* if (snd_count1>=sound_frequency) snd_count1-=sound_frequency;
296 gain=pattern[NR11>>6][snd_count1];*/
297
298 gain=((snd_count1&FIXPOINT_MASK)>FIXPOINT_HALF) ? 128-32 : 128+32;
299
300 sample=gain;
301 } else {
302 gain=128;
303 NR52&=0xFE;
304 }
305 }
306 #endif
307
308 #if 1
309 if (NR51&0x22) {
310 if (snd_init2) {
311 snd_init2=0;
312 snd_count2=frequency_div256;
313 }
314
315 if ((snd_reload2>0)&&(snd_length2>0)) {
316 if (snd_count2--<=0) {
317 snd_length2--;
318 snd_count2=frequency_div256;
319 }
320
321 snd_count2+=snd_reload2;
322 /* if (snd_count2>=sound_frequency) snd_count2-=sound_frequency;
323 gain=pattern[NR21>>6][snd_count2];*/
324
325 gain=((snd_count2&FIXPOINT_MASK)>FIXPOINT_HALF) ? 128-32 : 128+32;
326
327 sample=mixsample(gain,sample);
328 } else {
329 gain=128;
330 NR52&=0xFD;
331 }
332 }
333 #endif
334
335 #if 1
336 if (NR51&0x44 && NR30&0x80 && NR32&60) {
337 if (snd_init3) {
338 snd_init3=0;
339 snd_count3=frequency_div256;
340 }
341
342 if ((snd_reload3>0)&&(snd_length3>0)) {
343 if (snd_count3--<=0) {
344 snd_length3--;
345 snd_count3=frequency_div256;
346 }
347
348 snd_count3+=snd_reload3;
349 /* if (snd_count3>=sound_frequency) snd_count3-=sound_frequency;*/
350
351 pos=((snd_count3<<5)>>FIXPOINT_SHIFT)&0x1F;
352
353 if (pos&1) gain=chn3_tab[(io[0x30+(pos>>1)]&0x0F)>>snd_shr];
354 else gain=chn3_tab[(io[0x30+(pos>>1)]>>4)>>snd_shr];
355
356 sample=mixsample(gain,sample);
357 } else {
358 gain=128;
359 NR52&=0xFB;
360 }
361 }
362 #endif
363
364 #if 1
365 if (NR51&0x88) {
366 if (snd_init4) {
367 snd_init4=0;
368 snd_count4=frequency_div256;
369 }
370
371 if (snd_length4>0) {
372 /* snd_reload4=0;*/
373 if (snd_count4--<=0) {
374 snd_length4--;
375 snd_count4=frequency_div256;
376 }
377 /* printf("sound4 (i:%d,l:%d,c:%d)\n",snd_init4,snd_length4,snd_count4);*/
378
379 if (snd4_rand>=SND4_RNDPATTERNLEN) snd4_rand=0;
380 gain=snd4_rndpattern[snd4_rand++];
381
382 /* snd4_rand=snd4_rand*0x111163+0x3211234;
383 gain=rand()>>24;*/
384
385 /* printf("sample: %d\n",gain);*/
386
387 sample=mixsample(gain,sample);
388 } else {
389 gain=128;
390 NR52&=0xF7;
391 }
392 }
393 #endif
394
395 if (producesound) outsample(sample);
396 else outsample(128);
397 /* }*/
398 }
399
gbfreq(unsigned short int value)400 int gbfreq(unsigned short int value)
401 {
402 /*int freq;*/
403
404 /* printf("%09f\n",(float)((131072<<13)/((2048L-value)<<13))); */
405
406 return value>0 ? ((((131072<<13)/(2048L-value))<<3)/sound_frequency) : 0;
407
408 /* freq=value>0 ? 131072/(2048-value) : 0;
409 if (freq>=sound_frequency/2) freq=0;
410 return freq;*/
411 }
412
413 #endif
414