]> Shamusworld >> Repos - stargem2/blobdiff - src/sound.cpp
More cleanup, chasing down problems with the demo mode
[stargem2] / src / sound.cpp
index 6cc1860d29ccea31ef5eb6c0c9842be42bb4fdac..2f7522047072082c2b3c32fba6a6e04be0f340d4 100755 (executable)
@@ -10,6 +10,8 @@
 // ---  ----------  ------------------------------------------------------------
 // JLH  06/15/2006  Added changelog ;-)
 // JLH  06/15/2006  Scrubbed all BYTE, WORD & DWORD references from the code
+// JLH  02/10/2009  Fixed sound IRQ callback so that CPU samples are taken at
+//                  cycle exact boundaries
 //
 // Notes:
 //   The sound CPU (6808) runs at 894,750 (3,579,000 / 4) Hz.
 #include "types.h"
 #include "log.h"
 #include "v6808.h"
+#include "timing.h"
 
 //using namespace std;
 
+#define AUDIO_SAMPLE_RATE      44100
+
 // Local variables
 
 SDL_AudioSpec desired;
@@ -43,7 +48,7 @@ void SoundInit(void)
 {
 //     memory_malloc_secure((void **)&DACBuffer, BUFFER_SIZE * sizeof(uint16), "DAC buffer");
 
-       desired.freq = 44100;                                                   // SDL will do conversion on the fly, if it can't get the exact rate. Nice!
+       desired.freq = AUDIO_SAMPLE_RATE;                               // SDL will do conversion on the fly, if it can't get the exact rate. Nice!
        desired.format = AUDIO_U8;                                              // This uses the native endian (for portability)...
        desired.channels = 1;
 //     desired.samples = 4096;                                                 // Let's try a 4K buffer (can always go lower)
@@ -75,22 +80,72 @@ void SoundDone(void)
        }
 }
 
+/*
+The way to determine the # of cycles for each sample is to take the CPU clock frequency
+and divide by the sample rate.
+
+Like so:
+double cycles = M6808_CLOCK_SPEED_IN_HZ / AUDIO_SAMPLE_RATE;
+Then we need to separate out the fractional part from the integer part.
+*/
+
 //
 // Sound card callback handler
 //
 void SDLSoundCallback(void * userdata, Uint8 * buffer, int length)
 {
        extern V6808REGS soundCPU;
-       extern uint8 * sram;
+       extern uint8 sram[];
        int cnt = 0;
 
+#define CYCLE_EXACT_SOUND
+#ifdef CYCLE_EXACT_SOUND
+       static float overflow = 0.0;
+       static uint32 time = 20;
+#endif
+
        while (cnt != length)
        {
                // This is close, but not cycle exact (exact would be 20.289115646...)
 
-//Need to figure out how to get that fraction to execute... !!! FIX !!!                
+//Need to figure out how to get that fraction to execute... !!! FIX !!! [DONE]
+/*
+One way would be to use a fractional accumulator, then subtract 1 every
+time it overflows. Like so:
+
+double overflow = 0;
+uint32 time = 20;
+while (!done)
+{
+       Execute6808(&soundCPU, time);
+       overflow += 0.289115646;
+       if (overflow > 1.0)
+       {
+               overflow -= 1.0;
+               time = 21;
+       }
+       else
+               time = 20;
+}
+*/
+#ifdef CYCLE_EXACT_SOUND
+               Execute6808(&soundCPU, time);
+               soundCPU.clock -= time;
+#else
                Execute6808(&soundCPU, 20);
                soundCPU.clock -= 20;
+#endif
                buffer[cnt++] = sram[0x0400];                           // Fill the buffer with the PIA output value
+#ifdef CYCLE_EXACT_SOUND
+               overflow += 0.289115646;                                        // Fractional part of CPU cycles...
+
+               if (overflow > 1.0)
+               {
+                       overflow -= 1.0;
+                       time = 21;
+               }
+               else
+                       time = 20;
+#endif
        }
 }