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;
72 // Also, should check to see if it got the hardware it needed, correct sample size, etc.
73 if (SDL_OpenAudio(&desired, &obtained) < 0)
75 soundInitialized = false;
76 printf("SOUND: Couldn't open audio: %s\n", SDL_GetError());
80 // Get that audio going!
82 soundInitialized = true;
86 void SpawnSound(int type, int snd, int channel/* = 0*/)
88 extern uint32_t psg_lens[16];
89 extern uint8_t * psg_adrs[16];
90 // extern uint32_t voc_lens[32];
91 // extern uint8_t * voc_adrs[32];
92 // extern uint32_t fm_lens[14];
93 // extern uint8_t * fm_adrs[14];
95 if (!soundInitialized)
99 // SpawnMsg(MSHOWNUMS);
101 // Voice type sounds...
102 if (type == GAMESOUND)
104 // Will that do it??? Yes!!!
109 // 00 nn ss (nn # of repeats of sample ss)
118 spos1 = (voice_rom[st + (snd << 1)] << 8) | voice_rom[st + (snd << 1) + 1];
119 spos1 += st; // Need to add start somewhere...
134 spos2 = (voice_rom[st + (snd << 1)] << 8) | voice_rom[st + (snd << 1) + 1];
135 spos2 += st; // Need to add start somewhere...
142 else if (type == PSGSOUND)
144 if (snd_num & 0x10) // Second channel?
147 end_pos3 = psg_lens[snd_num & 0x0F];
148 sndp3 = psg_adrs[snd_num & 0x0F];
151 if (spos3 == end_pos3)
152 chan3_go = false; // No sound loaded, so don't do it!
154 else // First channel
157 end_pos4 = psg_lens[snd_num & 0x0F];
158 sndp4 = psg_adrs[snd_num & 0x0F];
161 if (spos4 == end_pos4)
162 chan4_go = false; // No sound loaded, so don't do it!
167 else if (type == FMSOUND)
170 end_pos5 = fm_lens[snd_num];
171 sndp5 = fm_adrs[snd_num];
174 if (spos5 == end_pos5)
175 chan5_go = false; // No sound loaded, so don't do it!
178 else if (type == USERSOUND)
181 end_pos6 = snd_lens[snd_num]; // User sound
182 sndp6 = snd_array[snd_num]; // Load pointer
188 void SoundFunc(void * userdata, Uint8 * buffer, int num)
190 static bool psg1go = false, psg2go = false;
191 // Length / 2 is because it's set up for 16-bit samples
192 // YM2151UpdateOne(buffer, length / 2);
193 // Have to go into ym2151.cpp and change this manually back to 8 bit
194 YM2151UpdateOne(buffer, num / 2);
196 UpdatePSG(buffer, num / 2);
198 // 0-22 different sounds...
199 uint16_t cnt = 0;//, sample;
200 uint8_t start_samp1, end_samp1, start_samp2, end_samp2;
201 int16_t samp1 = 0, samp2 = 0, samp6 = 0; // Zero samples...
203 if (!(chan1_go || chan2_go /*|| chan3_go || chan4_go || chan5_go*/ || chan6_go))
206 while (cnt != (num / 2))
212 uint8_t voiceSample = voice_rom[spos1++];
213 samp1 = ((int16_t)voiceSample - 128) * 160;
215 // Kill channel 1 if done...
216 if (voiceSample == 0xFF)
221 // RLE compression...
222 else if (voiceSample == 0x00)
225 sample1 += (float)voice_rom[spos1++] * sampleBase;
226 // Get last good sample
230 // Keep fractional part intact
231 sample1 += sampleBase;
234 prevSamp1 = samp1; // Save last sample value
235 sample1 -= 1.0; // Decrement repeat counter
238 // Stretching 5KHz samples to 22KHz:
240 // 6KHz -> 22KHz: 22/6 repeats...
245 uint8_t voiceSample = voice_rom[spos2++];
246 samp2 = ((int16_t)voiceSample - 128) * 160;
247 // samp2 = voice_rom[spos2++];
249 if (voiceSample == 0xFF)
252 samp2 = 128; // Kill channel 2 if done...
254 else if (voiceSample == 0x00) // RLE compression...
256 sample2 += (float)voice_rom[spos2++] * sampleBase; // # of repeats
260 sample2 += sampleBase;
263 // Delta-X values were making the samples sound like crap...
264 // start_samp2 += delta_x2;
272 samp3 = ((psg1go ? sndp3[spos3++] : sndp3[spos3]) - 128) * 160;
275 if (spos3 == end_pos3)
278 samp3 = 0; // Kill channel 3 if done...
284 samp4 = ((psg2go ? sndp4[spos4++] : sndp4[spos4]) - 128) * 160;
287 if (spos4 == end_pos4)
290 samp4 = 0; // Kill channel 4 if done...
296 samp5 = sndp5[spos5++];
298 if (spos5 == end_pos5)
301 samp5 = 128; // Kill channel 5 if done...
307 samp6 = sndp6[spos6++];
309 if (spos6 == end_pos6)
312 samp6 = 0; // Kill channel 6...
317 // sample = samp1 + samp2 + samp3 + samp4 + samp5 + samp6 - 640;
318 int32_t sample = samp1 + samp2 + samp6;
319 sample += ((int16_t *)buffer)[cnt];
321 // If it overflowed, clip it
322 // if (sample & 0xFFFF0000)
323 // sample = (sample & 0x8000 ? 0x00 : 0xFF);
324 // sample = (sample & 0x80000000 ? 0x0000 : 0xFFFF);
327 else if (sample < -32767)
330 ((int16_t *)buffer)[cnt++] = (int16_t)sample;