2 // Sound Interface v2.0
5 // (c) 2006 Underground Software
7 // JLH = James L. Hammons <jlhamm@acm.org>
10 // --- ---------- ------------------------------------------------------------
11 // JLH 06/15/2006 Added changelog ;-)
12 // JLH 06/15/2006 Scrubbed all BYTE, WORD & DWORD references from the code
13 // JLH 02/10/2009 Fixed sound IRQ callback so that CPU samples are taken at
14 // cycle exact boundaries
17 // The sound CPU (6808) runs at 894,750 (3,579,000 / 4) Hz.
18 // At 44.1 KHz, this works out to 894750 / 44100 = 20.289115646... cycles per sample.
21 // Still need to add volume control...
31 //using namespace std;
33 #define AUDIO_SAMPLE_RATE 44100
37 SDL_AudioSpec desired;
38 bool soundInitialized = false;
40 // Private function prototypes
42 void SDLSoundCallback(void * userdata, Uint8 * buffer, int length);
45 // Initialize the SDL sound system
49 // memory_malloc_secure((void **)&DACBuffer, BUFFER_SIZE * sizeof(uint16), "DAC buffer");
51 desired.freq = AUDIO_SAMPLE_RATE; // SDL will do conversion on the fly, if it can't get the exact rate. Nice!
52 desired.format = AUDIO_U8; // This uses the native endian (for portability)...
54 // desired.samples = 4096; // Let's try a 4K buffer (can always go lower)
55 desired.samples = 2048; // Let's try a 2K buffer (can always go lower)
56 desired.callback = SDLSoundCallback;
58 if (SDL_OpenAudio(&desired, NULL) < 0) // NULL means SDL guarantees what we want
60 WriteLog("Sound: Failed to initialize SDL sound.\n");
65 SDL_PauseAudio(false); // Start playback!
66 soundInitialized = true;
67 WriteLog("Sound: Successfully initialized.\n");
71 // Close down the SDL sound subsystem
79 WriteLog("Sound: Done.\n");
84 The way to determine the # of cycles for each sample is to take the CPU clock frequency
85 and divide by the sample rate.
88 double cycles = M6808_CLOCK_SPEED_IN_HZ / AUDIO_SAMPLE_RATE;
89 Then we need to separate out the fractional part from the integer part.
93 // Sound card callback handler
95 void SDLSoundCallback(void * userdata, Uint8 * buffer, int length)
97 extern V6808REGS soundCPU;
101 #define CYCLE_EXACT_SOUND
102 #ifdef CYCLE_EXACT_SOUND
103 static float overflow = 0.0;
104 static uint32 time = 20;
107 while (cnt != length)
109 // This is close, but not cycle exact (exact would be 20.289115646...)
111 //Need to figure out how to get that fraction to execute... !!! FIX !!! [DONE]
113 One way would be to use a fractional accumulator, then subtract 1 every
114 time it overflows. Like so:
120 Execute6808(&soundCPU, time);
121 overflow += 0.289115646;
131 #ifdef CYCLE_EXACT_SOUND
132 Execute6808(&soundCPU, time);
133 soundCPU.clock -= time;
135 Execute6808(&soundCPU, 20);
136 soundCPU.clock -= 20;
138 buffer[cnt++] = sram[0x0400]; // Fill the buffer with the PIA output value
139 #ifdef CYCLE_EXACT_SOUND
140 overflow += 0.289115646; // Fractional part of CPU cycles...