5 // (C) 2014 Underground Software
7 // JLH = James Hammons <jlhamm@acm.org>
10 // --- ---------- -----------------------------------------------------------
11 // JLH 04/18/2014 Created this file
18 // Function prototypes
19 void SoundFunc(void *, Uint8 *, int);
22 extern uint8_t voice_rom[]; // PCM data pointer
24 static bool soundInitialized = false;
25 const float sampleBase = 22050.0/6000.0; // Btwn 5512.5 and 6000
27 bool chan1_go = false, chan2_go = false, chan3_go = false;
28 bool chan4_go = false, chan5_go = false, chan6_go = false;
29 uint8_t * sndp1, * sndp2, * sndp3, * sndp4, * sndp5, * sndp6;
30 uint32_t rom_pos, end_pos;
31 uint32_t spos1, end_pos1;
32 uint32_t spos2, end_pos2;
33 uint32_t spos3, end_pos3;
34 uint32_t spos4, end_pos4;
35 uint32_t spos5, end_pos5;
36 uint32_t spos6, end_pos6;
44 uint8_t * snd_array[3] = { sunknown, scya, scamera }; // From RESOURCE.H
45 uint32_t snd_lens[3] = { sunknownlen, scyalen, scameralen };
50 SDL_AudioSpec desired, obtained;
52 desired.format = AUDIO_U8;
54 desired.samples = 1024;
55 desired.callback = SoundFunc;
56 desired.userdata = NULL;
57 // Also, should check to see if it got the hardware it needed, correct sample size, etc.
58 if (SDL_OpenAudio(&desired, &obtained) < 0)
60 soundInitialized = false;
61 printf("Couldn't open audio: %s\n", SDL_GetError());
65 // Get that audio going!
67 soundInitialized = true;
71 void SpawnSound(int type, int snd, int channel/* = 0*/)
73 extern uint32_t psg_lens[16];
74 extern uint8_t * psg_adrs[16];
75 extern uint32_t voc_lens[32];
76 extern uint8_t * voc_adrs[32];
77 extern uint32_t fm_lens[14];
78 extern uint8_t * fm_adrs[14];
80 if (!soundInitialized)
84 // SpawnMsg(MSHOWNUMS);
86 if (type == GAMESOUND)
88 // Will that do it??? Yes!!!
93 // 00 nn ss (nn # of repeats of sample ss)
102 spos1 = (voice_rom[st + (snd << 1)] << 8) | voice_rom[st + (snd << 1) + 1];
103 spos1 += st; // Need to add start somewhere...
118 spos2 = (voice_rom[st + (snd << 1)] << 8) | voice_rom[st + (snd << 1) + 1];
119 spos2 += st; // Need to add start somewhere...
125 else if (type == PSGSOUND)
127 if (snd_num & 0x10) // Second channel?
130 end_pos3 = psg_lens[snd_num & 0x0F];
131 sndp3 = psg_adrs[snd_num & 0x0F];
134 if (spos3 == end_pos3)
135 chan3_go = false; // No sound loaded, so don't do it!
137 else // First channel
140 end_pos4 = psg_lens[snd_num & 0x0F];
141 sndp4 = psg_adrs[snd_num & 0x0F];
144 if (spos4 == end_pos4)
145 chan4_go = false; // No sound loaded, so don't do it!
148 else if (type == FMSOUND)
151 end_pos5 = fm_lens[snd_num];
152 sndp5 = fm_adrs[snd_num];
155 if (spos5 == end_pos5)
156 chan5_go = false; // No sound loaded, so don't do it!
158 else if (type == USERSOUND)
161 end_pos6 = snd_lens[snd_num]; // User sound
162 sndp6 = snd_array[snd_num]; // Load pointer
168 void SoundFunc(void * userdata, Uint8 * buff, int num)
170 // 0-22 different sounds...
171 uint16_t cnt = 0, sample;
172 uint8_t start_samp1, end_samp1, start_samp2, end_samp2;
173 uint8_t samp1 = 128, samp2 = 128, samp3 = 128,
174 samp4 = 128, samp5 = 128, samp6 = 128; // Zero samples...
177 memset(buff, 128, num);
179 if (chan1_go || chan2_go || chan3_go || chan4_go || chan5_go || chan6_go)
187 samp1 = voice_rom[spos1++];
189 // Kill channel 1 if done...
195 // RLE compression...
196 else if (samp1 == 0x00)
199 sample1 += (float)voice_rom[spos1++] * sampleBase;
200 // Get last good sample
204 // Keep fractional part intact
205 sample1 += sampleBase;
208 prevSamp1 = samp1; // Save last sample value
209 sample1 -= 1.0; // Decrement repeat counter
212 // Stretching 5KHz samples to 22KHz:
214 // 6KHz -> 22KHz: 22/6 repeats...
219 samp2 = voice_rom[spos2++];
224 samp2 = 128; // Kill channel 2 if done...
226 else if (samp2 == 0x00) // RLE compression...
228 sample2 += (float)voice_rom[spos2++] * sampleBase; // # of repeats
232 sample2 += sampleBase;
235 // Delta-X values were making the samples sound like crap...
236 // start_samp2 += delta_x2;
243 samp3 = sndp3[spos3++];
245 if (spos3 == end_pos3)
248 samp3 = 128; // Kill channel 3 if done...
254 samp4 = sndp4[spos4++];
256 if (spos4 == end_pos4)
259 samp4 = 128; // Kill channel 4 if done...
265 samp5 = sndp5[spos5++];
267 if (spos5 == end_pos5)
270 samp5 = 128; // Kill channel 5 if done...
276 samp6 = sndp6[spos6++];
278 if (spos6 == end_pos6)
281 samp6 = 128; // Kill channel 6...
286 sample = samp1 + samp2 + samp3 + samp4 + samp5 + samp6 - 640;
288 // If it overflowed, clip it
290 sample = (sample & 0x8000 ? 0x00 : 0xFF);
292 buff[cnt++] = sample;