]> Shamusworld >> Repos - stargem2/blob - src/sound.cpp
Finally fixed problems with demo mode.
[stargem2] / src / sound.cpp
1 //
2 // Sound Interface v2.0
3 //
4 // by James Hammons
5 // (c) 2006 Underground Software
6 //
7 // JLH = James Hammons <jlhamm@acm.org>
8 //
9 // WHO  WHEN        WHAT
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
15 // JLH  07/21/2009  Moved numeric constants into macros for sanity's sake
16 //
17 // Notes:
18 //   The sound CPU (6808) runs at 894,750 (3,579,000 / 4) Hz.
19 //   At 44.1 KHz, this works out to 894750 / 44100 = 20.289115646... cycles per
20 //   sample.
21 //
22
23 // Still need to add volume control...
24
25 #include "sound.h"
26
27 #include <SDL2/SDL.h>
28 #include <stdint.h>
29 #include "log.h"
30 #include "v6808.h"
31 #include "timing.h"
32
33 //using namespace std;
34
35 #define AUDIO_SAMPLE_RATE                               48000.0
36 #define CYCLES_TO_EXECUTE                               (M6808_CLOCK_SPEED_IN_HZ / AUDIO_SAMPLE_RATE)
37
38 // Local variables
39
40 static SDL_AudioSpec desired;
41 static bool soundInitialized = false;
42 static uint32_t cyclesToExecuteWholePart;
43 static double cyclesToExecuteFractionalPart;
44
45 // Private function prototypes
46
47 void SDLSoundCallback(void * userdata, Uint8 * buffer, int length);
48
49 //
50 // Initialize the SDL sound system
51 //
52 void SoundInit(void)
53 {
54         desired.freq = AUDIO_SAMPLE_RATE;               // SDL will do conversion on the fly, if it can't get the exact rate. Nice!
55         desired.format = AUDIO_U8;                              // This uses the native endian (for portability)...
56         desired.channels = 1;
57         desired.samples = 2048;                                 // Let's try a 2K buffer (can always go lower)
58         desired.callback = SDLSoundCallback;
59
60         if (SDL_OpenAudio(&desired, NULL) < 0)  // NULL means SDL guarantees what we want
61         {
62                 WriteLog("Sound: Failed to initialize SDL sound.\n");
63                 return;
64         }
65
66         // Setup clock cycles & etc.
67         cyclesToExecuteWholePart = (uint32_t)CYCLES_TO_EXECUTE;
68         cyclesToExecuteFractionalPart = CYCLES_TO_EXECUTE - (double)cyclesToExecuteWholePart;
69
70         SDL_PauseAudio(false);                                                  // Start playback!
71         soundInitialized = true;
72         WriteLog("Sound: Successfully initialized.\n");
73 }
74
75 //
76 // Close down the SDL sound subsystem
77 //
78 void SoundDone(void)
79 {
80         if (soundInitialized)
81         {
82                 SDL_PauseAudio(true);
83                 SDL_CloseAudio();
84                 WriteLog("Sound: Done.\n");
85         }
86 }
87
88 //
89 // Sound card callback handler
90 //
91 void SDLSoundCallback(void * userdata, Uint8 * buffer, int length)
92 {
93         extern V6808REGS soundCPU;
94         extern uint8_t sram[];
95         int cnt = 0;
96
97         static float overflow = 0.0;
98         static uint32_t time = cyclesToExecuteWholePart;
99
100         while (cnt != length)
101         {
102                 Execute6808(&soundCPU, time);
103                 soundCPU.clock -= time;
104 //              buffer[cnt++] = sram[0x0400];                           // Fill the buffer with the PIA output value
105                 // Do some simple volume control...
106                 buffer[cnt++] = sram[0x0400] / 4;                       // Fill the buffer with the PIA output value
107                 time = cyclesToExecuteWholePart;
108                 overflow += cyclesToExecuteFractionalPart;
109
110                 if (overflow > 1.0)
111                 {
112                         overflow -= 1.0;
113                         time++;
114                 }
115         }
116 }