5 // (C) 2014 Underground Software
7 // JLH = James Hammons <jlhamm@acm.org>
10 // --- ---------- -----------------------------------------------------------
11 // JLH 04/18/2014 Created this file
19 // Function prototypes
20 void SoundFunc(void *, Uint8 *, int);
23 extern uint8_t voice_rom[]; // PCM data pointer
25 static bool soundInitialized = false;
26 const float sampleBase = 44010.0/6000.0; // Btwn 5512.5 and 6000
28 bool chan1_go = false, chan2_go = false, chan3_go = false;
29 bool chan4_go = false, chan5_go = false, chan6_go = false;
30 uint8_t * sndp1, * sndp2, * sndp3, * sndp4, * sndp5, * sndp6;
31 uint32_t rom_pos, end_pos;
32 uint32_t spos1, end_pos1;
33 uint32_t spos2, end_pos2;
34 uint32_t spos3, end_pos3;
35 uint32_t spos4, end_pos4;
36 uint32_t spos5, end_pos5;
37 uint32_t spos6, end_pos6;
45 uint8_t * snd_array[3] = { sunknown, scya, scamera }; // From RESOURCE.H
46 uint32_t snd_lens[3] = { sunknownlen, scyalen, scameralen };
51 // params 1, 4 & 5 are useless
52 // if (YMInit(1, 3579580, 22050, 16, 512))//, (SAMPLE **)sbp))
53 if (YMInit(1, 3579580, 44100, 16, 512))
55 printf("SOUND: Could not init YM2151 emulator!\n");
59 SDL_AudioSpec desired, obtained;
61 desired.format = AUDIO_S16;
63 desired.samples = 1024;
64 desired.callback = SoundFunc;
65 desired.userdata = NULL;
66 // Also, should check to see if it got the hardware it needed, correct sample size, etc.
67 if (SDL_OpenAudio(&desired, &obtained) < 0)
69 soundInitialized = false;
70 printf("SOUND: Couldn't open audio: %s\n", SDL_GetError());
74 // Get that audio going!
76 soundInitialized = true;
80 void SpawnSound(int type, int snd, int channel/* = 0*/)
82 extern uint32_t psg_lens[16];
83 extern uint8_t * psg_adrs[16];
84 extern uint32_t voc_lens[32];
85 extern uint8_t * voc_adrs[32];
86 extern uint32_t fm_lens[14];
87 extern uint8_t * fm_adrs[14];
89 if (!soundInitialized)
93 // SpawnMsg(MSHOWNUMS);
95 if (type == GAMESOUND)
97 // Will that do it??? Yes!!!
102 // 00 nn ss (nn # of repeats of sample ss)
111 spos1 = (voice_rom[st + (snd << 1)] << 8) | voice_rom[st + (snd << 1) + 1];
112 spos1 += st; // Need to add start somewhere...
127 spos2 = (voice_rom[st + (snd << 1)] << 8) | voice_rom[st + (snd << 1) + 1];
128 spos2 += st; // Need to add start somewhere...
134 else if (type == PSGSOUND)
136 if (snd_num & 0x10) // Second channel?
139 end_pos3 = psg_lens[snd_num & 0x0F];
140 sndp3 = psg_adrs[snd_num & 0x0F];
143 if (spos3 == end_pos3)
144 chan3_go = false; // No sound loaded, so don't do it!
146 else // First channel
149 end_pos4 = psg_lens[snd_num & 0x0F];
150 sndp4 = psg_adrs[snd_num & 0x0F];
153 if (spos4 == end_pos4)
154 chan4_go = false; // No sound loaded, so don't do it!
158 else if (type == FMSOUND)
161 end_pos5 = fm_lens[snd_num];
162 sndp5 = fm_adrs[snd_num];
165 if (spos5 == end_pos5)
166 chan5_go = false; // No sound loaded, so don't do it!
169 else if (type == USERSOUND)
172 end_pos6 = snd_lens[snd_num]; // User sound
173 sndp6 = snd_array[snd_num]; // Load pointer
179 void SoundFunc(void * userdata, Uint8 * buff, int num)
181 static bool psg1go = false, psg2go = false;
182 // Length / 2 is because it's set up for 16-bit samples
183 // YM2151UpdateOne(buffer, length / 2);
184 // Have to go into ym2151.cpp and change this manually back to 8 bit
185 YM2151UpdateOne(buff, num / 2);
188 // 0-22 different sounds...
189 uint16_t cnt = 0, sample;
190 uint8_t start_samp1, end_samp1, start_samp2, end_samp2;
191 uint8_t samp1 = 128, samp2 = 128, samp3 = 128,
192 samp4 = 128, samp5 = 128, samp6 = 128; // Zero samples...
195 // memset(buff, 128, num);
197 if (!(chan1_go || chan2_go || chan3_go || chan4_go /*|| chan5_go*/ || chan6_go))
200 while (cnt != (num / 2))
206 samp1 = voice_rom[spos1++];
208 // Kill channel 1 if done...
214 // RLE compression...
215 else if (samp1 == 0x00)
218 sample1 += (float)voice_rom[spos1++] * sampleBase;
219 // Get last good sample
223 // Keep fractional part intact
224 sample1 += sampleBase;
227 prevSamp1 = samp1; // Save last sample value
228 sample1 -= 1.0; // Decrement repeat counter
231 // Stretching 5KHz samples to 22KHz:
233 // 6KHz -> 22KHz: 22/6 repeats...
238 samp2 = voice_rom[spos2++];
243 samp2 = 128; // Kill channel 2 if done...
245 else if (samp2 == 0x00) // RLE compression...
247 sample2 += (float)voice_rom[spos2++] * sampleBase; // # of repeats
251 sample2 += sampleBase;
254 // Delta-X values were making the samples sound like crap...
255 // start_samp2 += delta_x2;
262 samp3 = (psg1go ? sndp3[spos3++] : sndp3[spos3]);
265 if (spos3 == end_pos3)
268 samp3 = 128; // Kill channel 3 if done...
274 samp4 = (psg2go ? sndp4[spos4++] : sndp4[spos4]);
277 if (spos4 == end_pos4)
280 samp4 = 128; // Kill channel 4 if done...
286 samp5 = sndp5[spos5++];
288 if (spos5 == end_pos5)
291 samp5 = 128; // Kill channel 5 if done...
297 samp6 = sndp6[spos6++];
299 if (spos6 == end_pos6)
302 samp6 = 128; // Kill channel 6...
307 // sample = samp1 + samp2 + samp3 + samp4 + samp5 + samp6 - 640;
308 sample = samp1 + samp2 + samp3 + samp4 + samp6 - (5 * 128);
310 // If it overflowed, clip it
312 // sample = (sample & 0x8000 ? 0x00 : 0xFF);
313 sample = (sample & 0x8000 ? 0x0000 : 0xFFFF);
315 ((uint16_t *)buff)[cnt++] += sample << 7;