5 // (C) 2014 Underground Software
7 // JLH = James Hammons <jlhamm@acm.org>
10 // --- ---------- -----------------------------------------------------------
11 // JLH 04/18/2014 Created this file
20 #define SAMPLE_RATE 48000
21 #define BUFFER_SIZE 512
23 // Function prototypes
24 void SoundFunc(void *, Uint8 *, int);
27 extern uint8_t voice_rom[]; // PCM data pointer
29 static bool soundInitialized = false;
30 const float sampleBase = (float)SAMPLE_RATE / 6000.0; // Voice is between 5512.5 and 6000 Hz
31 bool chan1_go = false, chan2_go = false;
32 bool chan6_go = false;
33 uint8_t * sndp1, * sndp2, * sndp6;
34 uint32_t spos1, end_pos1;
35 uint32_t spos2, end_pos2;
36 uint32_t spos6, end_pos6;
37 float sample1, sample2;
38 int16_t prevSamp1, prevSamp2;
41 uint8_t * snd_array[3] = { sunknown, scya, scamera };
42 uint32_t snd_lens[3] = { sunknownlen, scyalen, scameralen };
46 // params 1, 4 & 5 are useless
47 // if (YMInit(1, 3579580, SAMPLE_RATE, 16, 512))
48 if (YMInit(3579580, SAMPLE_RATE))
50 printf("SOUND: Could not init YM2151 emulator!\n");
56 SDL_AudioSpec desired, obtained;
57 desired.freq = SAMPLE_RATE;
58 desired.format = AUDIO_S16;
60 desired.samples = BUFFER_SIZE * 2; // Size is in BYTES, so x2
61 desired.callback = SoundFunc;
62 desired.userdata = NULL;
64 // Also, should check to see if it got the hardware it needed, correct sample size, etc. (actually, SDL guarantees we get what we asked for--I think)
65 if (SDL_OpenAudio(&desired, &obtained) < 0)
67 soundInitialized = false;
68 printf("SOUND: Couldn't open audio: %s\n", SDL_GetError());
72 // Get that audio going!
74 soundInitialized = true;
77 void SpawnSound(int type, int snd, int channel/* = 0*/)
79 if (!soundInitialized)
84 // Voice type sounds...
85 if (type == GAMESOUND)
87 // Will that do it??? Yes!!!
92 // 00 nn ss (nn # of repeats of sample ss)
101 spos1 = (voice_rom[st + (snd << 1)] << 8) | voice_rom[st + (snd << 1) + 1];
102 spos1 += st; // Need to add start somewhere...
117 spos2 = (voice_rom[st + (snd << 1)] << 8) | voice_rom[st + (snd << 1) + 1];
118 spos2 += st; // Need to add start somewhere...
124 else if (type == USERSOUND)
127 end_pos6 = snd_lens[snd_num]; // User sound
128 sndp6 = snd_array[snd_num]; // Load pointer
133 void SoundFunc(void * userdata, Uint8 * buffer, int num)
135 // We do num / 2 because num is in BYTES, and the buffer uses signed WORDs.
136 YM2151UpdateOne(buffer, num / 2);
137 UpdatePSG(buffer, num / 2);
139 // 0-22 different sounds...
141 uint8_t start_samp1, end_samp1, start_samp2, end_samp2;
142 int16_t samp1 = 0, samp2 = 0, samp6 = 0; // Zero samples...
144 if (!(chan1_go || chan2_go || chan6_go))
147 while (cnt != (num / 2))
153 uint8_t voiceSample = voice_rom[spos1++];
154 samp1 = ((int16_t)voiceSample - 128) * 160;
156 // Kill channel 1 if done...
157 if (voiceSample == 0xFF)
162 // RLE compression...
163 else if (voiceSample == 0x00)
166 sample1 += (float)voice_rom[spos1++] * sampleBase;
167 // Get last good sample
171 // Keep fractional part intact
172 sample1 += sampleBase;
175 prevSamp1 = samp1; // Save last sample value
176 sample1 -= 1.0; // Decrement repeat counter
179 // Stretching 5KHz samples to 22KHz:
181 // 6KHz -> 22KHz: 22/6 repeats...
186 uint8_t voiceSample = voice_rom[spos2++];
187 samp2 = ((int16_t)voiceSample - 128) * 160;
189 if (voiceSample == 0xFF)
192 samp2 = 128; // Kill channel 2 if done...
194 else if (voiceSample == 0x00) // RLE compression...
196 sample2 += (float)voice_rom[spos2++] * sampleBase; // # of repeats
200 sample2 += sampleBase;
203 // Delta-X values were making the samples sound like crap...
204 // start_samp2 += delta_x2;
211 samp6 = sndp6[spos6++];
213 if (spos6 == end_pos6)
216 samp6 = 0; // Kill channel 6...
221 int32_t sample = samp1 + samp2 + samp6;
222 sample += ((int16_t *)buffer)[cnt];
224 // If it overflowed, clip it
227 else if (sample < -32767)
230 ((int16_t *)buffer)[cnt++] = (int16_t)sample;