5 // (C) 2014 Underground Software
7 // JLH = James Hammons <jlhamm@acm.org>
10 // --- ---------- -----------------------------------------------------------
11 // JLH 04/18/2014 Created this file
21 #define SAMPLE_RATE 48000
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
32 bool chan1_go = false, chan2_go = false;//, chan3_go = false;
33 bool /*chan4_go = false, chan5_go = false,*/ chan6_go = false;
34 uint8_t * sndp1, * sndp2, /* sndp3, * sndp4, * sndp5,*/ * sndp6;
35 uint32_t rom_pos, end_pos;
36 uint32_t spos1, end_pos1;
37 uint32_t spos2, end_pos2;
38 //uint32_t spos3, end_pos3;
39 //uint32_t spos4, end_pos4;
40 //uint32_t spos5, end_pos5;
41 uint32_t spos6, end_pos6;
49 uint8_t * snd_array[3] = { sunknown, scya, scamera }; // From RESOURCE.H
50 uint32_t snd_lens[3] = { sunknownlen, scyalen, scameralen };
55 // params 1, 4 & 5 are useless
56 // if (YMInit(1, 3579580, 22050, 16, 512))//, (SAMPLE **)sbp))
57 if (YMInit(1, 3579580, SAMPLE_RATE, 16, 512))
59 printf("SOUND: Could not init YM2151 emulator!\n");
65 SDL_AudioSpec desired, obtained;
66 desired.freq = SAMPLE_RATE;
67 desired.format = AUDIO_S16;
69 desired.samples = 1024;
70 desired.callback = SoundFunc;
71 desired.userdata = NULL;
73 // Also, should check to see if it got the hardware it needed, correct sample size, etc.
74 if (SDL_OpenAudio(&desired, &obtained) < 0)
76 soundInitialized = false;
77 printf("SOUND: Couldn't open audio: %s\n", SDL_GetError());
81 // Get that audio going!
83 soundInitialized = true;
87 void SpawnSound(int type, int snd, int channel/* = 0*/)
89 // extern uint32_t psg_lens[16];
90 // extern uint8_t * psg_adrs[16];
91 // extern uint32_t voc_lens[32];
92 // extern uint8_t * voc_adrs[32];
93 // extern uint32_t fm_lens[14];
94 // extern uint8_t * fm_adrs[14];
96 if (!soundInitialized)
100 // SpawnMsg(MSHOWNUMS);
102 // Voice type sounds...
103 if (type == GAMESOUND)
105 // Will that do it??? Yes!!!
110 // 00 nn ss (nn # of repeats of sample ss)
119 spos1 = (voice_rom[st + (snd << 1)] << 8) | voice_rom[st + (snd << 1) + 1];
120 spos1 += st; // Need to add start somewhere...
135 spos2 = (voice_rom[st + (snd << 1)] << 8) | voice_rom[st + (snd << 1) + 1];
136 spos2 += st; // Need to add start somewhere...
143 else if (type == PSGSOUND)
145 if (snd_num & 0x10) // Second channel?
148 end_pos3 = psg_lens[snd_num & 0x0F];
149 sndp3 = psg_adrs[snd_num & 0x0F];
152 if (spos3 == end_pos3)
153 chan3_go = false; // No sound loaded, so don't do it!
155 else // First channel
158 end_pos4 = psg_lens[snd_num & 0x0F];
159 sndp4 = psg_adrs[snd_num & 0x0F];
162 if (spos4 == end_pos4)
163 chan4_go = false; // No sound loaded, so don't do it!
168 else if (type == FMSOUND)
171 end_pos5 = fm_lens[snd_num];
172 sndp5 = fm_adrs[snd_num];
175 if (spos5 == end_pos5)
176 chan5_go = false; // No sound loaded, so don't do it!
179 else if (type == USERSOUND)
182 end_pos6 = snd_lens[snd_num]; // User sound
183 sndp6 = snd_array[snd_num]; // Load pointer
189 void SoundFunc(void * userdata, Uint8 * buffer, int num)
191 static bool psg1go = false, psg2go = false;
192 // Length / 2 is because it's set up for 16-bit samples
193 // YM2151UpdateOne(buffer, length / 2);
194 // Have to go into ym2151.cpp and change this manually back to 8 bit
195 YM2151UpdateOne(buffer, num / 2);
197 UpdatePSG(buffer, num / 2);
199 // 0-22 different sounds...
200 uint16_t cnt = 0;//, sample;
201 uint8_t start_samp1, end_samp1, start_samp2, end_samp2;
202 int16_t samp1 = 0, samp2 = 0, samp6 = 0; // Zero samples...
204 if (!(chan1_go || chan2_go /*|| chan3_go || chan4_go || chan5_go*/ || chan6_go))
207 while (cnt != (num / 2))
213 uint8_t voiceSample = voice_rom[spos1++];
214 samp1 = ((int16_t)voiceSample - 128) * 160;
216 // Kill channel 1 if done...
217 if (voiceSample == 0xFF)
222 // RLE compression...
223 else if (voiceSample == 0x00)
226 sample1 += (float)voice_rom[spos1++] * sampleBase;
227 // Get last good sample
231 // Keep fractional part intact
232 sample1 += sampleBase;
235 prevSamp1 = samp1; // Save last sample value
236 sample1 -= 1.0; // Decrement repeat counter
239 // Stretching 5KHz samples to 22KHz:
241 // 6KHz -> 22KHz: 22/6 repeats...
246 uint8_t voiceSample = voice_rom[spos2++];
247 samp2 = ((int16_t)voiceSample - 128) * 160;
248 // samp2 = voice_rom[spos2++];
250 if (voiceSample == 0xFF)
253 samp2 = 128; // Kill channel 2 if done...
255 else if (voiceSample == 0x00) // RLE compression...
257 sample2 += (float)voice_rom[spos2++] * sampleBase; // # of repeats
261 sample2 += sampleBase;
264 // Delta-X values were making the samples sound like crap...
265 // start_samp2 += delta_x2;
273 samp3 = ((psg1go ? sndp3[spos3++] : sndp3[spos3]) - 128) * 160;
276 if (spos3 == end_pos3)
279 samp3 = 0; // Kill channel 3 if done...
285 samp4 = ((psg2go ? sndp4[spos4++] : sndp4[spos4]) - 128) * 160;
288 if (spos4 == end_pos4)
291 samp4 = 0; // Kill channel 4 if done...
297 samp5 = sndp5[spos5++];
299 if (spos5 == end_pos5)
302 samp5 = 128; // Kill channel 5 if done...
308 samp6 = sndp6[spos6++];
310 if (spos6 == end_pos6)
313 samp6 = 0; // Kill channel 6...
318 // sample = samp1 + samp2 + samp3 + samp4 + samp5 + samp6 - 640;
319 int32_t sample = samp1 + samp2 + samp6;
320 sample += ((int16_t *)buffer)[cnt];
322 // If it overflowed, clip it
323 // if (sample & 0xFFFF0000)
324 // sample = (sample & 0x8000 ? 0x00 : 0xFF);
325 // sample = (sample & 0x80000000 ? 0x0000 : 0xFFFF);
328 else if (sample < -32767)
331 ((int16_t *)buffer)[cnt++] = (int16_t)sample;