1 #include "mix.h"
2 
3 #if defined(SDL)
4 #include <SDL_audio.h>
5 
6 #if defined(LINUX) || defined(FREEBSD)
7   #include "osd_linux_sdl_machine.h"
8 #elif defined(SOLARIS)
9   #include "osd_unix_sdl_machine.h"
10 #elif defined(WIN32)
11   #include "osd_win_sdl_machine.h"
12 #else
13   #warning no machine defined for SDL audio include
14 #endif
15 
16 #endif
17 
update_sound_null(void)18 void update_sound_null(void)
19 {
20 }
21 
22 
update_sound_allegro(void)23 void update_sound_allegro(void)
24 {
25 #ifdef ALLEGRO
26   int dum;
27   char ch;
28 
29   static where_to_fill = 0;
30   static remaining_to_fill = 0;
31   static remaining_to_read = 0;
32 
33 #ifndef FINAL_RELEASE
34   // Log("Entering %s\n",__FUNCTION__);
35 #endif
36 
37   // fill each channel specific buffer
38   for (ch = 0; ch < 6; ch++)
39     write_psg (ch);
40 
41   write_adpcm ();
42 
43   // Log("%d/%d\n", dwNewPos, SBUF_SIZE_BYTE);
44 
45   if (dwNewPos > SBUF_SIZE_BYTE)
46     dwNewPos = SBUF_SIZE_BYTE;
47 
48   if (remaining_to_fill)
49     {
50       memcpy (big_buf, main_buf + remaining_to_read, remaining_to_fill);
51       where_to_fill = remaining_to_fill;
52       remaining_to_fill = 0;
53       remaining_to_read = 0;
54     }
55 
56   // do a simplistic mixing (should be hard instead of this one)
57   /* TEST */
58   if (io.adpcm_psize > 1)
59     for (dum = 0; dum < dwNewPos; dum++)
60       main_buf[dum] = (
61 		       (
62 			(sbuf[0][dum]
63 			 + sbuf[1][dum]
64 			 + sbuf[2][dum]
65 			 + sbuf[3][dum]
66 			 + sbuf[4][dum]
67 			 + sbuf[5][dum] + adpcmbuf[dum]) >> 2)) ^ 0x80;
68   // main_buf[dum] = (adpcmbuf[dum])^0x80;
69   else
70     for (dum = 0; dum < dwNewPos; dum++)
71       main_buf[dum] =
72 	((sbuf[0][dum] + sbuf[1][dum] + sbuf[2][dum] + sbuf[3][dum] +
73 	  sbuf[4][dum] + sbuf[5][dum]) >> 2) ^ 0x80;
74 
75   {
76 
77     int size;
78     unsigned char *p;
79 
80 #if defined(LINUX) || defined(MSDOS)
81     if (MP3_playing)
82       run_amp ();
83 #endif
84 
85     size = dwNewPos;
86 
87     if (where_to_fill + size < sbuf_size)
88       {
89 	memcpy (big_buf + where_to_fill, main_buf, size);
90 	where_to_fill += size;
91       }
92     else
93       {
94 	memcpy (big_buf + where_to_fill, main_buf, sbuf_size - where_to_fill);
95 	remaining_to_read = sbuf_size - where_to_fill;
96 	remaining_to_fill = size - remaining_to_read;
97 	where_to_fill = 0;
98 
99 	// if dump asked, write in a file
100 	if (dump_snd)
101 	  fwrite (big_buf, 1, sbuf_size, out_snd);
102 
103 	while (!(p = get_audio_stream_buffer (PCM_stream)));
104 
105 	memcpy (p, big_buf, sbuf_size);
106 
107 	free_audio_stream_buffer (PCM_stream);
108 
109       }
110 
111   }
112 #endif
113 }
114 
115 
116 #ifndef MSDOS
117 
118 void (*update_sound[4])() =
119 {
120   update_sound_null, update_sound_allegro, update_sound_allegro, update_sound_null
121 };
122 
123 /* SDL Audio Stuff */
124 
125 unsigned char old;
126 Uint32 audio_len=0;
127 
128 /* Callback for SDL Audio */
sdl_fill_audio(void * data,Uint8 * stream,int len)129 void sdl_fill_audio(void *data, Uint8 *stream, int len)
130 {
131   UChar lvol, rvol;
132   int i;
133   UChar center;
134 #ifdef SOUND_DEBUG
135   UChar first_chan;
136 
137 //IXION
138   if ((first_chan = ((io.psg_lfo_ctrl & 3) == 0) ? 0 : 2) == 2)
139     ;
140 //    printf("first_chan = 2\n");
141 
142   for (i = first_chan; i < 6; i++)
143 #else
144   for (i = 0; i < 6; i++)
145 #endif
146     WriteBuffer(sbuf[i], i, len);
147 
148   write_adpcm();
149 
150   /*
151    * Adjust the final post-mixed left/right volumes.  0-15 * 1.22 comes out to
152    * (0..18) which when multiplied by the ((-127..127) * 7) we get in the final
153    * stream mix below we have (-16002..16002) which we then divide by 128 to get
154    * a nice unsigned 8-bit value of 128 + (-125..125).
155    */
156   if (host.sound.stereo)
157   {
158     lvol = (io.psg_volume >> 4) * 1.22;
159     rvol = (io.psg_volume & 0x0F) * 1.22;
160   }
161   else
162   {
163     /*
164      * Use the average of the two channels for mono
165      */
166     lvol = rvol = (((io.psg_volume >> 4) * 1.22) + ((io.psg_volume & 0x0F) * 1.22)) / 2;
167   }
168 
169   SDL_LockAudio();
170 
171   center = (host.sound.signed_sound?0:128);
172 
173   /*
174    * Mix streams and apply master volume.
175    */
176   for (i = 0; i < len ; i++)
177     stream[i] = center + ((UInt32) ((sbuf[0][i] + sbuf[1][i] + sbuf[2][i] + sbuf[3][i] + sbuf[4][i] + sbuf[5][i] +
178                 adpcmbuf[i]) * (!(i % 2) ? lvol : rvol)) >> 7);
179 
180   SDL_UnlockAudio();
181 
182 	if (dump_snd) // We also have to write data into a file
183 		{
184 			dump_audio_chunck(stream, len);
185 		}
186 
187 }
188 
189 #else /* MSDOS */
190 
update_sound_seal(void)191 void update_sound_seal(void)
192 {
193   int dum;
194   char ch;
195   static int old = 0;
196 
197   // fill each channel specific buffer
198   for (ch = 0; ch < 6; ch++)
199     write_psg (ch);
200 
201   write_adpcm ();
202 
203   // do a simplistic mixing (should be hard instead of this one)
204   /* TEST */
205 
206   // Log("new pos = %d\n", dwNewPos);
207 
208   /* TEST */
209   if (io.adpcm_psize > 1)
210     for (dum = 0; dum < dwNewPos; dum++)
211       main_buf[dum] = (
212 		       (
213 			(sbuf[0][dum]
214 			 + sbuf[1][dum]
215 			 + sbuf[2][dum]
216 			 + sbuf[3][dum]
217 			 + sbuf[4][dum]
218 			 + sbuf[5][dum] + adpcmbuf[dum]) >> 2));
219    main_buf[dum] = (adpcmbuf[dum])^0x80;
220   else
221     for (dum = 0; dum < dwNewPos; dum++)
222       main_buf[dum] =
223 	((sbuf
224 	  [0][dum] + sbuf[1][dum] + sbuf[2][dum] + sbuf[3][dum] +
225 	  sbuf[4][dum] + sbuf[5][dum]) >> 2);
226 
227 // for (dum=0;dum<dwNewPos;dum++)
228   // main_buf[dum]=((sbuf[0][dum]+sbuf[1][dum]+sbuf[2][dum]+sbuf[3][dum]+sbuf[4][dum]+sbuf[5][dum])>>2 );
229   //     main_buf[dum]=adpcmbuf[dum] << 2;
230 
231 #if defined(DOUBLE_BUFFER)
232 
233   memcpy (lpWave->lpData + old_snd_pos, main_buf,
234 	  lpWave->dwLength - old_snd_pos);
235 
236   if (old_snd_pos)
237     {
238 
239 #ifndef FINAL_RELEASE
240       fprintf (stderr, "set loop end to %d\n", old_snd_pos + dwNewPos);
241 #endif
242       lpWave->dwLoopEnd = old_snd_pos + dwNewPos;
243       // set the loop end to the end of the sample
244 
245       //ASetVoicePosition(hVoice,0);
246       AWriteAudioData (lpWave, 0L, lpWave->dwLength);
247 
248       {
249 	long dum;
250 	do
251 	  {
252 	    AGetVoicePosition (hVoice, &dum);
253 
254 #ifndef FINAL_RELEASE
255 	    fprintf (stderr, "%d / %d\n", dum, old_snd_pos + dwNewPos);
256 #endif
257 
258 	    AUpdateAudio ();
259 	  }
260 	while (dum > old_snd_pos);
261       }
262 
263       old_snd_pos = 0;
264     }
265   else
266     {
267 
268 #ifndef FINAL_RELEASE
269       fprintf (stderr, "i've not set loop end\n");
270 #endif
271       old_snd_pos = dwNewPos;
272       AWriteAudioData (lpWave, 0L, lpWave->dwLength);
273 
274       {
275 	long dum;
276 	do
277 	  {
278 	    AGetVoicePosition (hVoice, &dum);
279 
280 #ifndef FINAL_RELEASE
281 	    fprintf (stderr, "%d / %d\n", dum, old_snd_pos);
282 #endif
283 
284 	    AUpdateAudio ();
285 	  }
286 	while (dum < old_snd_pos);
287       }
288 
289 
290     }
291 
292   //memcpy(lpWave->lpData,main_buf,lpWave->dwLength);
293   //memcpy(lpWave->lpData,sbuf[2],lpWave->dwLength);
294   //lpWave->dwLoopEnd = dwNewPos;
295   //AWriteAudioData(lpWave, 0L, lpWave->dwLength);
296 
297   //ASetVoicePosition(hVoice,0);
298   //old=dwNewPos;
299   //       }
300 
301   AUpdateAudio ();
302 
303 
304 #else /* not double buffer */
305   {
306     long dum;
307     do
308       {
309 	AGetVoicePosition (hVoice, &dum);
310 
311 	AUpdateAudio ();
312       }
313     while (dum < old - 10);
314   }
315 
316   memcpy (lpWave->lpData, main_buf, lpWave->dwLength);
317   //memcpy(lpWave->lpData,sbuf[2],lpWave->dwLength);
318   lpWave->dwLoopEnd = dwNewPos;
319   AWriteAudioData (lpWave, 0L, lpWave->dwLength);
320 
321   // if dump asked, write in a file
322   if (dump_snd)
323     fwrite (lpWave->lpData, 1, dwNewPos, out_snd);
324 
325   ASetVoicePosition (hVoice, 0);
326   old = dwNewPos;
327   //       }
328 
329   AUpdateAudio ();
330 
331 #endif /* else double buffer */
332 
333 }
334 
335 void (*update_sound[4])() =
336 {
337   update_sound_null, update_sound_allegro, update_sound_seal, update_sound_null
338 };
339 
340 #endif
341 
342 
mseq(UInt32 * rand_val)343 int mseq(UInt32 *rand_val)
344 {
345   if (*rand_val & 0x00080000)
346   {
347     *rand_val = ((*rand_val ^ 0x0004) << 1) + 1;
348     return 1;
349   }
350   else
351   {
352     *rand_val <<= 1;
353     return 0;
354   }
355 }
356 
357 
358 /*
359  *
360  * Lookup tables for IMA ADPCM format
361  *
362  */
363 int AdpcmIndexAdjustTable[16] =
364 {
365   -1, -1, -1, -1,		/* +0 - +3, decrease the step size */
366   2, 4, 6, 8,			/* +4 - +7, increase the step size */
367   -1, -1, -1, -1,		/* -0 - -3, decrease the step size */
368   2, 4, 6, 8,			/* -4 - -7, increase the step size */
369 };
370 
371 #define ADPCM_MAX_INDEX 48
372 
373 int AdpcmStepSizeTable[ADPCM_MAX_INDEX + 1] =
374 {
375   16, 17, 19, 21, 23, 25, 28,
376   31, 34, 37, 41, 45, 50, 55,
377   60, 66, 73, 80, 88, 97, 107,
378   118, 130, 143, 157, 173, 190,
379   209, 230, 253, 279, 307, 337,
380   371, 408, 449, 494, 544, 598,
381   658, 724, 796, 876, 963, 1060,
382   1166, 1282, 1411, 1552
383 };
384 
385 /* TODO : improve pointer in adpcm buffer maybe using fixed type */
WriteBufferAdpcm8(UChar * buf,UInt32 begin,UInt32 size,SChar * Index,SInt32 * PreviousValue)386 UInt32 WriteBufferAdpcm8 (UChar *buf, UInt32 begin, UInt32 size, SChar *Index, SInt32 *PreviousValue)
387 {
388   UInt32 ret_val = 0;
389 
390   /* TODO: use something else than ALLEGRO's fixed to make this portable */
391 #ifdef ALLEGRO
392   SInt32 step, difference, deltaCode;
393   SChar index = *Index;
394   SInt32 previousValue = *PreviousValue;
395   fixed FixedIndex = 0, FixedInc;
396 
397 
398   if (io.adpcm_rate)
399     FixedInc = ftofix ((float) io.adpcm_rate * 1000 / (float) host.sound.freq);
400   else
401     return 0;
402 
403   while (size)
404     {
405 
406       FixedIndex += FixedInc;
407 
408       while (FixedIndex > itofix (1))
409 	{
410 
411 	  FixedIndex -= itofix (1);
412 
413 	  ret_val++;
414 
415 	  deltaCode = PCM[begin >> 1];
416 
417 	  if (begin & 1)
418 	    deltaCode >>= 4;
419 	  else
420 	    deltaCode &= 0xF;
421 
422 	  step = AdpcmStepSizeTable[index];
423 
424 	  begin++;
425 
426 	  begin &= 0x1FFFF;
427 	  // Make the adpcm repeat from beginning once finished
428 
429 	  /* Construct the difference by scaling the current step size */
430 	  /* This is approximately: difference = (deltaCode+.5)*step/4 */
431 	  difference = step >> 3;
432 	  if (deltaCode & 1)
433 	    difference += step >> 2;
434 	  if (deltaCode & 2)
435 	    difference += step >> 1;
436 	  if (deltaCode & 4)
437 	    difference += step;
438 
439 	  if (deltaCode & 8)
440 	    difference = -difference;
441 
442 	  /* Build the new sample */
443 	  previousValue += difference;
444 
445 	  if (previousValue > 32767)
446 	    previousValue = 32767;
447 	  else if (previousValue < -32768)
448 	    previousValue = -32768;
449 
450 	  index += AdpcmIndexAdjustTable[deltaCode];
451 	  if (index < 0)
452 	    index = 0;
453 	  else if (index > ADPCM_MAX_INDEX)
454 	    index = ADPCM_MAX_INDEX;
455 
456 	}
457       /* TEST, was 5 */
458       *(buf++) = (previousValue << 6) >> 8;
459 
460       size--;
461 
462     }
463 
464   *Index = index;
465   *PreviousValue = previousValue;
466 
467 #else
468   memset(buf, 0, host.sound.sample_size);
469 #endif
470 
471   return ret_val;
472 }
473 
474 
WriteBuffer(char * buf,int ch,unsigned dwSize)475 void WriteBuffer(char *buf, int ch, unsigned dwSize)
476 {
477   static UInt32 fixed_n[6] = { 0, 0, 0, 0, 0, 0 };
478   UInt32 fixed_inc;
479   static UInt32 k[6] = { 0, 0, 0, 0, 0, 0 };
480   static UInt32 t; // used to know how much we got to advance in the ring buffer
481   static UInt32 r[6];
482   static UInt32 rand_val[6] = { 0, 0, 0, 0, 0x51F631E4, 0x51F631E4 }; // random seed for 'noise' generation
483   UInt16 dwPos = 0;
484   SInt32 vol;
485   UInt32 Tp;
486   static char vol_tbl[32] =
487   {
488     /*
489      * Funky stuff everywhere!  I'm quite sure there was a reason to use an array
490      * of constant values divided by constant values and having the host machine figure
491      * it all out . . . that's why I'm leaving the original formula here within the
492      * comment.
493      *    100 / 256, 451 / 256, 508 / 256, 573 / 256, 646 / 256, 728 / 256,
494      *    821 / 256, 925 / 256,
495      *    1043 / 256, 1175 / 256, 1325 / 256, 1493 / 256, 1683 / 256, 1898 / 256,
496      *    2139 / 256, 2411 / 256,
497      *    2718 / 256, 3064 / 256, 3454 / 256, 3893 / 256, 4388 / 256, 4947 / 256,
498      *    5576 / 256, 6285 / 256,
499      *    7085 / 256, 7986 / 256, 9002 / 256, 10148 / 256, 11439 / 256, 12894 / 256,
500      *    14535 / 256, 16384 / 256
501      */
502     0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 21, 24, 27, 31, 35, 39, 44, 50, 56, 64
503   };
504   UInt16 lbal, rbal;
505   SChar sample;
506 
507   if (!(io.PSG[ch][PSG_DDA_REG] & PSG_DDA_ENABLE) || io.psg_channel_disabled[ch])
508   {
509     /*
510      * There is no audio to be played on this channel.
511      */
512     fixed_n[ch] = 0;
513     memset(buf, 0, dwSize);
514     return;
515   }
516 
517   if ((io.PSG[ch][PSG_DDA_REG] & PSG_DDA_DIRECT_ACCESS) || io.psg_da_count[ch])
518   {
519     /*
520      * There is 'direct access' audio to be played.
521      */
522     static UInt32 da_index[6] = { 0, 0, 0, 0, 0, 0 };
523     UInt16 index = da_index[ch] >> 16;
524 
525     /*
526      * For this direct audio stuff there is no frequency provided via PSG registers 3
527      * and 4.  I'm not sure if this is normal behaviour or if it's something wrong in
528      * the emulation but I'm leaning toward the former.
529      *
530      * The 0x1FF divisor is completely arbitrary.  I adjusted it by listening to the voices
531      * in Street Fighter 2 CE.  If anyone has information to improve my "seat of the pants"
532      * calculations then by all means *does finger quotes* "throw me a frikkin` bone here".
533      *
534      * See the big comment in the final else clause for an explanation of this value
535      * to the best of my knowledge.
536      */
537     fixed_inc = ((UInt32) (3580000 / host.sound.freq) << 16) / 0x1FF;
538 
539     /*
540      * Volume handling changed 2-24-03.
541      * I believe io.psg_volume should only be used to compute the final sample
542      * volume after all the buffers have been mixed together.  Alright, it's what
543      * other people have already stated, and I believe them :)
544      */
545 
546     if (host.sound.stereo)
547     {
548       /*
549        * We multiply the 4-bit balance values by 1.1 to get a result from (0..16.5).
550        * This multiplied by the 5-bit channel volume (0..31) gives us a result of
551        * (0..511).
552        */
553       lbal = ((io.PSG[ch][5] >> 4) * 1.1) * (io.PSG[ch][4] & PSG_DDA_VOICE_VOLUME);
554       rbal = ((io.PSG[ch][5] & 0x0F) * 1.1) * (io.PSG[ch][4] & PSG_DDA_VOICE_VOLUME);
555     }
556     else
557     {
558       /*
559        * Use an average of the two channels for mono.
560        */
561       lbal = ((((io.PSG[ch][5] >> 4) * 1.1) * (io.PSG[ch][4] & PSG_DDA_VOICE_VOLUME)) +
562               (((io.PSG[ch][5] & 0x0F) * 1.1) * (io.PSG[ch][4] & PSG_DDA_VOICE_VOLUME))) / 2;
563     }
564 
565     while ((dwPos < dwSize) && io.psg_da_count[ch])
566     {
567       /*
568        * Make our sample data signed (-16..15) and then increment a non-negative
569        * result otherwise a sample with a value of 10000b will not be reproduced,
570        * which I do not believe is the correct behaviour.  Plus the increment
571        * insures matching values on both sides of the wave.
572        */
573       if ((sample = io.psg_da_data[ch][index] - 16) >= 0)
574         sample++;
575 
576       /*
577        * Left channel, or main channel in mono mode.  Multiply our sample value
578        * (-16..16) by our balance (0..511) and then divide by 64 to get a final
579        * 8-bit output sample of (-127..127)
580        */
581       *buf++ = (char) ((SInt32) (sample * lbal) >> 6);
582 
583       if (host.sound.stereo)
584       {
585         /*
586          * Same as above but for right channel.
587          */
588         *buf++ = (char) ((SInt32) (sample * rbal) >> 6);
589         dwPos += 2;
590       }
591       else
592       {
593         dwPos++;
594       }
595 
596       da_index[ch] += fixed_inc;
597       da_index[ch] &= 0x3FFFFFF; /* (1023 << 16) + 0xFFFF */
598       if ((da_index[ch] >> 16) != index)
599       {
600         index = da_index[ch] >> 16;
601         io.psg_da_count[ch]--;
602       }
603     }
604 
605     if ((dwPos != dwSize) && (io.PSG[ch][PSG_DDA_REG] & PSG_DDA_DIRECT_ACCESS))
606     {
607       memset(buf, 0, dwSize - dwPos);
608       return;
609     }
610   }
611 
612   if ((ch > 3) && (io.PSG[ch][7] & 0x80))
613   {
614     UInt32 Np = (io.PSG[ch][7] & 0x1F);
615 
616     /*
617      * PSG Noise generation, for nifty little effects like space ships taking off or blowing up.
618      * Only available to PSG channels 5 and 6.
619      */
620 //                      if (ds_nChannels == 2) // STEREO DISABLED
621 //                      {
622 //                              lvol = ((io.psg_volume>>3)&0x1E) + (io.PSG[ch][4] & PSG_DDA_VOICE_VOLUME) + ((io.PSG[ch][5]>>3)&0x1E);
623 //                              lvol = lvol-60;
624 //                              if (lvol < 0) lvol = 0;
625 //                              lvol = vol_tbl[lvol];
626 //                              rvol = ((io.psg_volume<<1)&0x1E) + (io.PSG[ch][4] & PSG_DDA_VOICE_VOLUME) + ((io.PSG[ch][5]<<1)&0x1E);
627 //                              rvol = rvol-60;
628 //                              if (rvol < 0) rvol = 0;
629 //                              rvol = vol_tbl[rvol];
630 //                              for (dwPos = 0; dwPos < dwSize; dwPos += 2)
631 //                              {
632 //                                      k[ch] += 3000+Np*512;
633 //                                      t = k[ch] / (DWORD) host.sound.freq;
634 //                                      if (t >= 1)
635 //                                      {
636 //                                              r[ch] = mseq(&rand_val[ch]);
637 //                                              k[ch] -= host.sound.freq * t;
638 //                                      }
639 //                                      *buf++ = (WORD)((r[ch] ? 10*702 : -10*702)*lvol/64);
640 //                                      *buf++ = (WORD)((r[ch] ? 10*702 : -10*702)*rvol/64);
641 //                              }
642 //                      }
643 //                      else  // MONO
644 
645     vol = max((io.psg_volume >> 3) & 0x1E, (io.psg_volume << 1) & 0x1E) +
646           (io.PSG[ch][4] & PSG_DDA_VOICE_VOLUME) +
647           max((io.PSG[ch][5] >> 3) & 0x1E, (io.PSG[ch][5] << 1) & 0x1E);
648     //average sound level
649 
650     if ((vol -= 60) < 0)
651       vol = 0;
652 
653     vol = vol_tbl[vol];
654     // get cooked volume
655 
656     while (dwPos < dwSize)
657     {
658       k[ch] += 3000 + Np * 512;
659 
660       if ((t = (k[ch] / (UInt32) host.sound.freq)) >= 1)
661       {
662         r[ch] = mseq(&rand_val[ch]);
663         k[ch] -= host.sound.freq * t;
664       }
665 
666       *buf++ = (signed char) ((r[ch] ? 10 * 702 : -10 * 702) * vol / 256 / 16); // Level 0
667       //sbuf[ch][dum++] = (WORD)((r[ch] ? 10*702 : -10*702)*lvol/64/256);
668       //*buf++ = (r[ch] ? 32 : -32) * lvol / 24;
669       dwPos++;
670     }
671   }
672   else if ((Tp = (io.PSG[ch][PSG_FREQ_LSB_REG] + (io.PSG[ch][PSG_FREQ_MSB_REG] << 8))) == 0)
673   {
674     /*
675      * 12-bit pseudo frequency value stored in PSG registers 2 (all 8 bits) and 3
676      * (lower nibble).  If we get to this point and the value is 0 then there's no
677      * sound to be played.
678      *
679      * dwPos will either be 0 as initialized at the beginning of the function or a value
680      * left over from the direct audio stuff.  If left over then buf will already be at
681      * (buf + dwPos) from the beginning of the function.
682      */
683      memset(buf, 0, dwSize);
684   }
685   else
686   {
687     /*
688      * Thank god for well commented code!  The original line of code read:
689      * fixed_inc = ((UInt32) (3.2 * 1118608 / host.sound.freq) << 16) / Tp;
690      * and had nary a comment to be found.  It took a little head scratching to get
691      * it figured out.  The 3.2 * 1118608 comes out to 3574595.6 which is obviously
692      * meant to represent the 3.58mhz cpu clock speed used in the pc engine to
693      * decrement the sound 'frequency'.  I haven't figured out why the original
694      * author had the two numbers multiplied together to get the odd value instead of
695      * just using 3580000.  I did some checking and the value will compute the same
696      * using either value divided by any standard soundcard samplerate.  The
697      * host.sound.freq is our soundcard's samplerate which is quite a bit slower than
698      * the pce's cpu (3580000 vs. 22050/44100 typically).
699      *
700      * Taken from the PSG doc written by Paul Clifford (paul@plasma.demon.co.uk)
701      * <in reference to the 12 bit frequency value in PSG registers 2 and 3>
702      * "For waveform output, a copy of this value is, in effect, decremented 3,580,000
703      *  times a second until zero is reached.  When this happens the PSG advances an
704      *  internal pointer into the channel's waveform buffer by one."
705      *
706      * So all we need to do to emulate original pc engine behaviour is take our soundcard's
707      * sampling rate into consideration with regard to the 3580000 effective pc engine
708      * samplerate.  We use 16.16 fixed arithmetic for speed.
709      */
710     fixed_inc = ((UInt32) (3580000 / host.sound.freq) << 16) / Tp;
711 
712     if (host.sound.stereo)
713     {
714       /*
715        * See the direct audio code above if you're curious why we're multiplying by 1.1
716        */
717       lbal = ((io.PSG[ch][5] >> 4) * 1.1) * (io.PSG[ch][4] & PSG_DDA_VOICE_VOLUME);
718       rbal = ((io.PSG[ch][5] & 0x0F) * 1.1) * (io.PSG[ch][4] & PSG_DDA_VOICE_VOLUME);
719     }
720     else
721     {
722       lbal = ((((io.PSG[ch][5] >> 4) * 1.1) * (io.PSG[ch][4] & PSG_DDA_VOICE_VOLUME)) +
723               (((io.PSG[ch][5] & 0x0F) * 1.1) * (io.PSG[ch][4] & PSG_DDA_VOICE_VOLUME))) / 2;
724     }
725 
726     while (dwPos < dwSize)
727     {
728       /*
729        * See the direct audio stuff a little above for an explanation of everything
730        * within this loop.
731        */
732       if ((sample = (io.wave[ch][io.PSG[ch][PSG_DATA_INDEX_REG]] - 16)) >= 0)
733         sample++;
734 
735       *buf++ = (char) ((SInt16) (sample * lbal) >> 6);
736 
737       if (host.sound.stereo)
738       {
739         *buf++ = (char) ((SInt32) (sample * rbal) >> 6);
740         dwPos += 2;
741       }
742       else
743       {
744         dwPos++;
745       }
746 
747       fixed_n[ch] += fixed_inc;
748       fixed_n[ch] &= 0x1FFFFF; /* (31 << 16) + 0xFFFF */
749       io.PSG[ch][PSG_DATA_INDEX_REG] = fixed_n[ch] >> 16;
750     }
751   }
752 }
753