sound.cpp
  1  #include "dcastaway.h"
  2  
  3  #ifndef NO_SOUND
  4  
  5  #include<stdio.h>
  6  #include<stdlib.h>
  7  #include<string.h>
  8  
  9  #include<Arduino.h>
 10  
 11  #include "st.h"
 12  #include "mem.h"
 13  #include "m68k_intrf.h"
 14  
 15  #include "sound.h"
 16  
 17  #define LONGLONG unsigned long long
 18  
 19  #define ENVELOPE_PERIOD(Fine,Coarse)  (((unsigned long)Coarse)<<8) + (unsigned long)Fine
 20  #define NOISE_PERIOD(Freq)            ((((unsigned long)Freq)&0x1f)<<11)
 21  #define TONE_PERIOD(Fine,Coarse)      ((((unsigned long)Coarse)&0x0f)<<8) + (unsigned long)Fine
 22  #define MIXTABLE_SIZE    (256*8)        /* Large table, so don't overflow */
 23  #define TONEFREQ_SHIFT   28             /* 4.28 fixed point */
 24  #define NOISEFREQ_SHIFT  28             /* 4.28 fixed point */
 25  #define ENVFREQ_SHIFT    16             /* 16.16 fixed */
 26  
 27  #define SAMPLES_BUFFER_SIZE  1024
 28  /* Number of generated samples per frame (eg. 44Khz=882) : */
 29  #define SAMPLES_PER_FRAME  ((SOUND_FREQ+35)/nScreenRefreshRate)
 30  /* Frequency of generated samples: */
 31  #define SAMPLES_FREQ   (SOUND_FREQ)
 32  #define YM_FREQ        (2000000/SAMPLES_FREQ)      /* YM Frequency 2Mhz */
 33  
 34  /* Original wave samples */
 35  #include "tab_EnvelopeShapeValues.h"
 36  //static int EnvelopeShapeValues[16*1024];                        /* Shape x Length(repeat 3rd/4th entries) */
 37  /* Frequency and time period samples */
 38  static unsigned long ChannelFreq[3], EnvelopeFreq, NoiseFreq;   /* Current frequency of each channel A,B,C,Envelope and Noise */
 39  static int ChannelAmpDecayTime[3];                              /* Store counter to show if amplitude is changed to generate 'samples' */
 40  static int Envelope[SAMPLES_BUFFER_SIZE],Noise[SAMPLES_BUFFER_SIZE];   /* Current sample for this time period */
 41  /* Output channel data */
 42  static int Channel_A_Buffer[SAMPLES_BUFFER_SIZE],Channel_B_Buffer[SAMPLES_BUFFER_SIZE],Channel_C_Buffer[SAMPLES_BUFFER_SIZE];
 43  /* Use table to convert from (A+B+C) to clipped 'unsigned char' for sound buffer */
 44  #include "tab_MixTable.h"
 45  //static char MixTable[MIXTABLE_SIZE];                            /* -ve and +ve range */
 46  static char *pMixTable = &MixTable[MIXTABLE_SIZE/2];            /* Signed index into above */
 47  static int ActiveSndBufIdx;                                     /* Current working index into above mix buffer */
 48  static int nSamplesToGenerate;                                  /* How many samples are needed for this time-frame */
 49  
 50  /* global values */
 51  bool bWriteEnvelopeFreq;                                        /* Did write to register '13' - causes frequency reset */
 52  bool bWriteChannelAAmp, bWriteChannelBAmp, bWriteChannelCAmp;   /* Did write to amplitude registers? */
 53  bool bEnvelopeFreqFlag;                                         /* As above, but cleared each frame for YM saving */
 54  /* Buffer to store circular samples */
 55  char MixBuffer[MIXBUFFER_SIZE];
 56  int nGeneratedSamples;                                          /* Generated samples since audio buffer update */
 57  int SoundCycles;
 58  
 59  static int nScreenRefreshRate=60;
 60  
 61  /*-----------------------------------------------------------------------*/
 62  /* Envelope shape table */
 63  typedef struct
 64  {
 65    int WaveStart[4], WaveDelta[4];
 66  } ENVSHAPE;
 67  
 68  /* Envelope shapes */
 69  static ENVSHAPE EnvShapes[16] =
 70  {
 71   { {127,-128,-128,-128},    {-1, 0, 0, 0} },  /*  \_____  00xx  */
 72   { {127,-128,-128,-128},    {-1, 0, 0, 0} },  /*  \_____  00xx  */
 73   { {127,-128,-128,-128},    {-1, 0, 0, 0} },  /*  \_____  00xx  */
 74   { {127,-128,-128,-128},    {-1, 0, 0, 0} },  /*  \_____  00xx  */
 75   { {-128,-128,-128,-128},   {1, 0, 0, 0} },   /*  /_____  01xx  */
 76   { {-128,-128,-128,-128},   {1, 0, 0, 0} },   /*  /_____  01xx  */
 77   { {-128,-128,-128,-128},   {1, 0, 0, 0} },   /*  /_____  01xx  */
 78   { {-128,-128,-128,-128},   {1, 0, 0, 0} },   /*  /_____  01xx  */
 79   { {127,127,127,127},       {-1,-1,-1,-1} },  /*  \\\\\\  1000  */
 80   { {127,-128,-128,-128},    {-1, 0, 0, 0} },  /*  \_____  1001  */
 81   { {127,-128,127,-128},     {-1, 1,-1, 1} },  /*  \/\/\/  1010  */
 82   { {127,127,127,127},       {-1, 0, 0, 0} },  /*  \~~~~~  1011  */
 83   { {-128,-128,-128,-128},   {1, 1, 1, 1} },   /*  //////  1100  */
 84   { {-128,127,127,127},      {1, 0, 0, 0} },   /*  /~~~~~  1101  */
 85   { {-128,127,-128,127},     {1,-1, 1,-1} },   /*  /\/\/\  1110  */
 86   { {-128,-128,-128,-128},   {1, 0, 0, 0} }    /*  /_____  1111  */
 87  };
 88  
 89  /* Square wave look up table */
 90  static int SquareWave[16] = { 127,127,127,127,127,127,127,127, -128,-128,-128,-128,-128,-128,-128,-128 };
 91  /* LogTable */
 92  #include "tab_LogTable.h"
 93  //static int LogTable[256];
 94  #include "tab_LogTable16.h"
 95  //static int LogTable16[16];
 96  static int *pEnvelopeLogTable = &LogTable[128];
 97  
 98  
 99  /*-----------------------------------------------------------------------*/
100  /*
101    Create Log tables
102  */
103  //static void Sound_CreateLogTables(void)
104  //{
105  //  float a;
106  //  int i;
107  //
108  //  /* Generate 'log' table for envelope output. It isn't quite a 'log' but it mimicks the ST */
109  //  /* output very well */
110  //  a = 1.0f;
111  //  for(i=0; i<256; i++)
112  //  {
113  //    LogTable[255-i] = (int)(255*a);
114  //    a /= 1.02f;
115  //  }
116  //  LogTable[0] = 0;
117  //
118  //  /* And a 16 entry version(thanks to Nick for the '/= 1.5' bit) */
119  //  /* This is VERY important for clear sample playback */
120  //  a = 1.0f;
121  //  for(i=0; i<15; i++)
122  //  {
123  //    LogTable16[15-i] = (int)(255*a);
124  //    a /= 1.5f;
125  //  }
126  //  LogTable16[0] = 0;
127  //}
128  
129  static long RandomNum;
130  
131  static __inline__ long Misc_NextLongRand(long Seed)
132  {
133    unsigned long Lo, Hi;
134  
135    Lo = 16807 * (long)(Seed & 0xffff);
136    Hi = 16807 * (long)((unsigned long)Seed >> 16);
137    Lo += (Hi & 0x7fff) << 16;
138    if (Lo > 2147483647L) {
139      Lo &= 2147483647L;
140      ++Lo;
141    }
142    Lo += Hi >> 15;
143    if (Lo > 2147483647L) {
144      Lo &= 2147483647L;
145      ++Lo;
146    }
147    return((long)Lo);
148  }
149  
150  static __inline__ long Misc_GetRandom(void)
151  {
152    RandomNum = Misc_NextLongRand(RandomNum);
153    if (!RandomNum)
154    {
155      RandomNum++;
156      return 0;
157    }
158    return(RandomNum);
159  }
160  
161  
162  /*-----------------------------------------------------------------------*/
163  /*
164    Create envelope shape, store to table
165    ( Wave is stored as 4 cycles, where cycles 1,2 are start and 3,4 are looped )
166  */
167  static void Sound_CreateEnvelopeShape(ENVSHAPE *pEnvShape,int *pEnvelopeValues)
168  {
169    int i,j,Value;
170  
171    /* Create shape */
172    for(i=0; i<4; i++)
173    {
174      Value = pEnvShape->WaveStart[i];        /* Set starting value for gradient */
175      for(j=0; j<256; j++,Value+=pEnvShape->WaveDelta[i])
176        *pEnvelopeValues++ = Misc_LimitInt(Value,-128,127);
177    }
178  }
179  
180  
181  /*-----------------------------------------------------------------------*/
182  /*
183    Create YM2149 envelope shapes(x16)
184  */
185  //static void Sound_CreateEnvelopeShapes(void)
186  //{
187  //  int i;
188  //
189  //  /* Create 'envelopes' for YM table */
190  //  for(i=0; i<16; i++)
191  //    Sound_CreateEnvelopeShape(&EnvShapes[i],&EnvelopeShapeValues[i*1024]);
192  //}
193  
194  
195  /*-----------------------------------------------------------------------*/
196  /*
197    Create table to clip samples top 8-bit range
198    This keeps then 'signed', although many sound cards want 'unsigned' values,
199    but we keep them signed so we can vary the volume easily.
200  */
201  
202  //static void Sound_CreateSoundMixClipTable(void)
203  //{
204  //  int i,v;
205  //
206  //  /* Create table to 'clip' values to -128...127 */
207  //  for(i=0; i<MIXTABLE_SIZE; i++)
208  //  {
209  //    v = (int)(((float)(i-(MIXTABLE_SIZE/2))) * 0.3f);    /* Scale, to prevent clipping */
210  //    if (v<-128)  v = -128;                      /* Limit -128..128 */
211  //    if (v>127)  v = 127;
212  //    MixTable[i] = v;
213  //  }
214  //}
215  
216  static void Sound_InitNoise(void)
217  {
218    int i;
219    srand(6643680);
220    RandomNum=rand();
221    if (!RandomNum)
222      RandomNum++;
223    for(i=0;i<SAMPLES_BUFFER_SIZE;i++)
224      Noise[i]=(unsigned int)Misc_GetRandom()%96;
225  }
226  
227  
228  /*-----------------------------------------------------------------------*/
229  /*
230    Init sound tables and envelopes
231  */
232  void Sound_Init(void)
233  {
234    //Sound_CreateLogTables();
235    //Sound_CreateEnvelopeShapes();
236    //Sound_CreateSoundMixClipTable();
237    Sound_InitNoise();
238    Sound_Reset();
239  }
240  
241  
242  /*-----------------------------------------------------------------------*/
243  /*
244    Reset the sound emulation
245  */
246  void Sound_Reset(void)
247  {
248    int i;
249  
250    Sound_ClearMixBuffer();       /* Clear buffer */
251  
252    /* Clear cycle counts, buffer index and register '13' flags */
253    SoundCycles = 0;
254    bEnvelopeFreqFlag = FALSE;
255    bWriteEnvelopeFreq = FALSE;
256    bWriteChannelAAmp = bWriteChannelBAmp = bWriteChannelCAmp = FALSE;
257  
258    /* Lock audio system before accessing variables that are also use by the callback function! */
259    Audio_Lock();
260    CompleteSndBufIdx = 0;
261    ActiveSndBufIdx =  (SOUND_BUFFER_SIZE + SAMPLES_PER_FRAME) % MIXBUFFER_SIZE;
262    nGeneratedSamples = 0;
263    Audio_Unlock();
264  
265    /* Clear frequency counter */
266    for(i=0; i<3; i++)
267    {
268      ChannelFreq[i] =
269      ChannelAmpDecayTime[i] = 0;
270    }
271    EnvelopeFreq = NoiseFreq = 0;
272  }
273  
274  
275  /*-----------------------------------------------------------------------*/
276  /*
277    Clear mixer buffer, where samples are stored ready to pass to sound player
278  */
279  void Sound_ClearMixBuffer(void)
280  {
281    Audio_Lock();
282  
283    Memory_Clear(MixBuffer, MIXBUFFER_SIZE);      /* Clear buffer */
284  
285    Audio_Unlock();
286  }
287  
288  
289  /*-----------------------------------------------------------------------*/
290  /*
291    Find how many samples to generate and store in 'nSamplesToGenerate'
292    Also update 'SoundCycles' to store how many we actually did so generates set amount each frame
293  */
294  static void Sound_SetSamplesPassed(void)
295  {
296    int nSampleCycles;
297    int nSamplesPerFrame;
298    int Dec=1;
299  
300    /* Check how many cycles have passed, as we use this to help find out if we are playing sample data */
301  
302    /* First, add decay to channel amplitude variables */
303    if (SoundCycles>(CYCLES_PER_FRAME/4))
304      Dec = 16;                            /* Been long time between sound writes, must be normal tone sound */
305  
306    if (!bWriteChannelAAmp)                /* Not written to amplitude, decay value */
307    {
308      ChannelAmpDecayTime[0]-=Dec;
309      if (ChannelAmpDecayTime[0]<0)  ChannelAmpDecayTime[0] = 0;
310    }
311    if (!bWriteChannelBAmp)
312    {
313      ChannelAmpDecayTime[1]-=Dec;
314      if (ChannelAmpDecayTime[1]<0)  ChannelAmpDecayTime[1] = 0;
315    }
316    if (!bWriteChannelCAmp)
317    {
318      ChannelAmpDecayTime[2]-=Dec;
319      if (ChannelAmpDecayTime[2]<0)  ChannelAmpDecayTime[2] = 0;
320    }
321  
322    /* 160256 cycles per VBL, 44Khz = 882 samples per VBL */
323    /* 882/160256 samples per clock cycle */
324    nSamplesPerFrame = SAMPLES_PER_FRAME;
325  #if 0  /* Use floats for calculation */
326    nSamplesToGenerate = (int)( (float)SoundCycles * ((float)nSamplesPerFrame/(float)CYCLES_PER_FRAME) );
327    if (nSamplesToGenerate > nSamplesPerFrame)
328      nSamplesToGenerate = nSamplesPerFrame;
329  
330    nSampleCycles = (int)( (float)nSamplesToGenerate / ((float)nSamplesPerFrame/(float)CYCLES_PER_FRAME) );
331    SoundCycles -= nSampleCycles;
332  #else  /* Use integers for calculation - both of these calculations should fit into 32-bit int */
333    nSamplesToGenerate = SoundCycles * nSamplesPerFrame / CYCLES_PER_FRAME;
334  //printf("nSamplesToGenerate=%i , SoundCycles=%i\n",nSamplesToGenerate,SoundCycles);
335    if (nSamplesToGenerate > nSamplesPerFrame)
336      nSamplesToGenerate = nSamplesPerFrame;
337  
338    nSampleCycles = nSamplesToGenerate * CYCLES_PER_FRAME / nSamplesPerFrame;
339    SoundCycles -= nSampleCycles;
340  #endif
341  }
342  
343  
344  /*-----------------------------------------------------------------------*/
345  /*
346    Generate envelope wave for this time-frame
347  */
348  static void Sound_GenerateEnvelope(unsigned char EnvShape, unsigned char Fine, unsigned char Coarse)
349  {
350    int *pEnvelopeValues;
351    unsigned long EnvelopePeriod,EnvelopeFreqDelta;
352    int i;
353  
354    /* Find envelope details */
355    if (bWriteEnvelopeFreq)
356      EnvelopeFreq = 0;
357    pEnvelopeValues = &EnvelopeShapeValues[ (EnvShape&0x0f)*1024 ];          /* Envelope shape values */
358    EnvelopePeriod = ENVELOPE_PERIOD((unsigned long)Fine,(unsigned long)Coarse);
359  
360    if (EnvelopePeriod==0)                                                   /* Handle div by zero */
361      EnvelopeFreqDelta = 0;
362    else
363      EnvelopeFreqDelta = ((LONGLONG)YM_FREQ<<ENVFREQ_SHIFT) / (EnvelopePeriod);  /* 16.16 fixed point */
364  
365    /* Create envelope from current shape and frequency */
366    for(i=0; i<nSamplesToGenerate; i++)
367    {
368      Envelope[i] = pEnvelopeValues[EnvelopeFreq>>ENVFREQ_SHIFT];           /* Store envelope wave, already applied 'log' function */
369      EnvelopeFreq += EnvelopeFreqDelta;
370      if (EnvelopeFreq&0xfe000000)
371        EnvelopeFreq = 0x02000000 | (EnvelopeFreq&0x01ffffff);              /* Keep in range 512-1024 once past 511! */
372    }
373  }
374  
375  
376  /*-----------------------------------------------------------------------*/
377  /*
378    Generate nosie for this time-frame
379  */
380  static void Sound_GenerateNoise(unsigned char MixerControl, unsigned char NoiseGen)
381  {
382    int NoiseValue;
383    unsigned long NoisePeriod,NoiseFreqDelta;
384    int i;
385  
386    NoisePeriod = NOISE_PERIOD((unsigned long)NoiseGen);
387  
388    if (NoisePeriod==0)                                            /* Handle div by zero */
389      NoiseFreqDelta = 0;
390    else
391      NoiseFreqDelta = (((LONGLONG)YM_FREQ)<<NOISEFREQ_SHIFT) / NoisePeriod;  /* 4.28 fixed point */
392  
393    /* Generate noise samples */
394    for(i=0; i<nSamplesToGenerate; i++)
395    {
396      NoiseValue = (unsigned int)Misc_GetRandom()%96;              /* Get random value */
397      if (SquareWave[NoiseFreq>>NOISEFREQ_SHIFT]<=0)               /* Add to square wave at given frequency */
398        NoiseValue = -NoiseValue;
399  
400      Noise[i] = NoiseValue;
401      NoiseFreq += NoiseFreqDelta;
402    }
403  }
404  
405  
406  /*-----------------------------------------------------------------------*/
407  /*
408    Generate channel of samples for this time-frame
409  */
410  static void Sound_GenerateChannel(int *pBuffer, unsigned char ToneFine, unsigned char ToneCoarse,unsigned char Amplitude,unsigned char MixerControl,unsigned long *pChannelFreq,int MixMask)
411  {   
412    int *pNoise = Noise, *pEnvelope = Envelope;
413    unsigned long ToneFreq=*pChannelFreq;
414    unsigned long TonePeriod;
415    unsigned long ToneFreqDelta;
416    int i,Amp,Mix;
417    int ToneOutput,NoiseOutput,MixerOutput,EnvelopeOutput,AmplitudeOutput;
418  
419    TonePeriod = TONE_PERIOD((unsigned long)ToneFine,(unsigned long)ToneCoarse);
420    /* Find frequency of channel */
421    if (TonePeriod==0)
422      ToneFreqDelta = 0;                                  /* Handle div by zero */
423    else
424      ToneFreqDelta = (((LONGLONG)YM_FREQ)<<TONEFREQ_SHIFT) / TonePeriod;    /* 4.28 fixed point */
425    Amp = LogTable16[(Amplitude&0x0f)];
426    Mix = (MixerControl>>MixMask)&9;                      /* Read I/O Mixer */
427  
428    /* Check if we are trying to play a 'sample' - we need to up the volume on these as they tend to be rather quiet */
429    if ((Amplitude&0x10)==0)                /* Fixed level amplitude? */
430    {
431      ChannelAmpDecayTime[MixMask]++;       /* Increment counter to find out if we are playing samples... */
432      if (ChannelAmpDecayTime[MixMask]>16)
433        ChannelAmpDecayTime[MixMask] = 16;  /* And limit */
434    }
435  
436    for(i=0; i<nSamplesToGenerate; i++)
437    {
438      /* Output from Tone Generator(0-255) */
439      ToneOutput = SquareWave[ToneFreq>>TONEFREQ_SHIFT];
440  
441      /* Output from Noise Generator(0-255) */
442      NoiseOutput = *pNoise++; 
443      /* Output from Mixer(combines Tone+Noise) */
444      switch (Mix) {
445        case 0:    /* Has Noise and Tone */
446          MixerOutput = NoiseOutput+ToneOutput;
447          break;
448        case 1:    /* Has Noise */
449          MixerOutput = NoiseOutput;
450          break;
451        case 8:    /* Has Tone */
452          MixerOutput = ToneOutput;
453          break;
454  
455        default:  /* This is used to emulate samples - should give no output, but ST gives set tone!!?? */
456          /* MixerControl gets set to give a continuous tone and then then Amplitude */
457          /* of channels A,B and C get changed with all other registers in the PSG */
458          /* staying as zero's. This produces the sounds from Quartet, Speech, NoiseTracker etc...! */
459          MixerOutput = 127;
460      }
461  
462      EnvelopeOutput = pEnvelopeLogTable[*pEnvelope++];
463  
464      if ((Amplitude&0x10)==0)
465      {
466        AmplitudeOutput = Amp;          /* Fixed level amplitude */
467  
468        /* As with most emulators, sample playback is always 'quiet'. We check to see if */
469        /* the amplitude of a channel is repeatedly changing and when this is detected we */
470        /* scale the volume accordingly */
471        if (ChannelAmpDecayTime[MixMask]>8)
472          AmplitudeOutput <<= 1;        /* Scale up by a factor of 2 */
473      }
474      else
475        AmplitudeOutput = EnvelopeOutput;
476  
477      *pBuffer++ = (MixerOutput*AmplitudeOutput)>>8;
478  
479      ToneFreq+=ToneFreqDelta;
480    }
481  
482    /* Store back incremented frequency, for next call */
483    *pChannelFreq = ToneFreq;
484  }
485  
486  
487  /*-----------------------------------------------------------------------*/
488  /*
489    Generate samples for all channels during this time-frame
490  */
491  static void Sound_GenerateSamples(void)
492  {
493    int *pChannelA=Channel_A_Buffer, *pChannelB=Channel_B_Buffer, *pChannelC=Channel_C_Buffer;
494    int i;
495  
496    /* Anything to do? */
497    if (nSamplesToGenerate>0)
498    {
499      /* Generate envelope/noise samples for this time */
500      Sound_GenerateEnvelope(psg[PSG_REG_ENV_SHAPE],psg[PSG_REG_ENV_FINE],psg[PSG_REG_ENV_COARSE]);
501      Sound_GenerateNoise(psg[PSG_REG_MIXER_CONTROL],psg[PSG_REG_NOISE_GENERATOR]);
502  
503      /* Generate 3 channels, store to separate buffer so can mix/clip */
504      Sound_GenerateChannel(pChannelA,psg[PSG_REG_CHANNEL_A_FINE],psg[PSG_REG_CHANNEL_A_COARSE],psg[PSG_REG_CHANNEL_A_AMP],psg[PSG_REG_MIXER_CONTROL],&ChannelFreq[0],0); 
505      Sound_GenerateChannel(pChannelB,psg[PSG_REG_CHANNEL_B_FINE],psg[PSG_REG_CHANNEL_B_COARSE],psg[PSG_REG_CHANNEL_B_AMP],psg[PSG_REG_MIXER_CONTROL],&ChannelFreq[1],1);
506      Sound_GenerateChannel(pChannelC,psg[PSG_REG_CHANNEL_C_FINE],psg[PSG_REG_CHANNEL_C_COARSE],psg[PSG_REG_CHANNEL_C_AMP],psg[PSG_REG_MIXER_CONTROL],&ChannelFreq[2],2);
507  
508      /* Mix channels together, using table to clip and also convert to 'unsigned char' */
509      for(i=0; i<nSamplesToGenerate; i++)
510        MixBuffer[(i+ActiveSndBufIdx)%MIXBUFFER_SIZE] = pMixTable[(*pChannelA++) + (*pChannelB++) + (*pChannelC++)];
511  
512      ActiveSndBufIdx = (ActiveSndBufIdx + nSamplesToGenerate) % MIXBUFFER_SIZE;
513      nGeneratedSamples += nSamplesToGenerate;
514  
515      /* Reset the write to register '13' flag */
516      bWriteEnvelopeFreq = FALSE;
517      /* And amplitude write flags */
518      bWriteChannelAAmp = bWriteChannelBAmp = bWriteChannelCAmp = FALSE;
519    }
520  }
521  
522  
523  /*-----------------------------------------------------------------------*/
524  /*
525    This is called to built samples up until this clock cycle
526  */
527  void Sound_Update(void)
528  {
529    int OldSndBufIdx = ActiveSndBufIdx;
530  
531    /* Make sure that we don't interfere with the audio callback function */
532  #ifndef DREAMCAST
533    Audio_Lock();
534  #endif
535  
536    /* Find how many to generate */
537    Sound_SetSamplesPassed();
538    /* And generate */
539    Sound_GenerateSamples();
540  
541    /* Allow audio callback function to occur again */
542  #ifndef DREAMCAST
543    Audio_Unlock();
544  #endif
545  }
546  
547  
548  /*-----------------------------------------------------------------------*/
549  /*
550    On each VBL (50fps) complete samples.
551  */
552  void Sound_Update_VBL(void)
553  {
554    Sound_Update();
555  
556    /* Clear write to register '13', used for YM file saving */
557    bEnvelopeFreqFlag = FALSE;
558  }
559  
560  
561  /*-----------------------------------------------------------------------*/
562  /*
563    This is called from the audio callback function to create enough samples
564    to fill the current sound buffer.
565  */
566  void Sound_UpdateFromAudioCallBack(void)
567  {
568    /* If there are already enough samples or if we are recording, we should
569     * not generate more samples here! */
570    if(nGeneratedSamples >= SOUND_BUFFER_SIZE)
571      return;
572  
573    nSamplesToGenerate = SOUND_BUFFER_SIZE - nGeneratedSamples;
574  
575    Sound_GenerateSamples();
576  }
577  
578  
579  
580  /*-----------------------------------------------------------------------*/
581  
582  static void Audio_CallBack(void *userdata, uint8 *stream, int len)
583  {
584    int i;
585  
586    uint16 *pBuffer;
587  
588  
589    /* If there are only some samples missing to have a complete buffer,
590     * we generate them here (sounds much better then!). However, if a lot of
591     * samples are missing, then the system is probably too slow, so we don't
592     * generate more samples to not make things worse... */
593  
594    if(nGeneratedSamples < len)
595      Sound_UpdateFromAudioCallBack();
596  
597    /* Pass completed buffer to audio system: Write samples into sound buffer
598     * and convert them from 'signed' to 'unsigned' */
599  
600    pBuffer = (uint16 *)stream;
601  
602    for(i = 0; i < len; i++)
603    {
604      *pBuffer++ = ((int)((char)MixBuffer[(CompleteSndBufIdx + i) % MIXBUFFER_SIZE]))*256;
605    }
606  
607    /* We should now have generated a complete frame of samples.
608     * However, for slow systems we have to check how many generated samples
609     * we may advance... */
610    if(nGeneratedSamples >= len)
611    {
612      CompleteSndBufIdx += len;
613      nGeneratedSamples -= len;
614    }
615    else
616    {
617      CompleteSndBufIdx += nGeneratedSamples;
618      nGeneratedSamples = 0;
619    }
620    CompleteSndBufIdx = CompleteSndBufIdx % MIXBUFFER_SIZE;
621  }
622  
623  void Sound_UpdateFromCallBack16(short *pBuffer, int len)
624  {
625    Audio_CallBack(nullptr, (uint8 *)pBuffer, len);
626  }
627  
628  
629  
630  #else
631  #warning NO_SOUND
632  #warning NO_SOUND
633  #warning NO_SOUND
634  #warning NO_SOUND
635  #warning NO_SOUND
636  #warning NO_SOUND
637  #endif