]> Shamusworld >> Repos - thunder/blob - src/sound.cpp
Added MCU to execution loop and it works.
[thunder] / src / sound.cpp
1 //
2 // Sound Handler
3 //
4 // by James Hammons
5 // (C) 2014 Underground Software
6 //
7 // JLH = James Hammons <jlhamm@acm.org>
8 //
9 // Who  When        What
10 // ---  ----------  -----------------------------------------------------------
11 // JLH  04/18/2014  Created this file
12 //
13
14 #include "sound.h"
15 #include <SDL2/SDL.h>
16 #include "resource.h"
17
18 // Function prototypes
19 void SoundFunc(void *, Uint8 *, int);
20
21 // Vars
22 extern uint8_t voice_rom[];                     // PCM data pointer
23
24 static bool soundInitialized = false;
25 const float sampleBase = 22050.0/6000.0;  // Btwn 5512.5 and 6000
26 bool snd_go = false;
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;
37 float sample1;
38 uint8_t prevSamp1;
39 int8_t delta_x1;
40 float sample2;
41 uint8_t prevSamp2;
42 int8_t delta_x2;
43 uint16_t snd_num;
44 uint8_t * snd_array[3] = { sunknown, scya, scamera }; // From RESOURCE.H
45 uint32_t snd_lens[3]   = { sunknownlen, scyalen, scameralen };
46
47
48 void InitSound(void)
49 {
50         SDL_AudioSpec desired, obtained;
51         desired.freq = 22050;
52         desired.format = AUDIO_U8;
53         desired.channels = 1;
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)
59         {
60                 soundInitialized = false;
61                 printf("Couldn't open audio: %s\n", SDL_GetError());
62                 return;
63         }
64
65         // Get that audio going!
66         SDL_PauseAudio(0);
67         soundInitialized = true;
68 }
69
70
71 void SpawnSound(int type, int snd, int channel/* = 0*/)
72 {
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];
79
80         if (!soundInitialized)
81                 return;
82
83         snd_num = snd;
84 //      SpawnMsg(MSHOWNUMS);
85
86         if (type == GAMESOUND)
87         {
88                 // Will that do it???  Yes!!!
89                 snd--;
90
91                 if (channel == 0)
92                 {
93                         // 00 nn ss (nn # of repeats of sample ss)
94                         uint32_t st = 0;
95
96                         if (snd & 0x40)
97                         {
98                                 st = 0x10000;
99                                 snd &= 0x0F;
100                         }
101
102                         spos1 = (voice_rom[st + (snd << 1)] << 8) | voice_rom[st + (snd << 1) + 1];
103                         spos1 += st;                                                            // Need to add start somewhere...
104                         prevSamp1 = 128;
105                         sample1 = 0;
106                         chan1_go = true;
107                 }
108                 else
109                 {
110                         uint32_t st = 0;
111
112                         if (snd & 0x40)
113                         {
114                                 st = 0x10000;
115                                 snd &= 0x0F;
116                         }
117
118                         spos2 = (voice_rom[st + (snd << 1)] << 8) | voice_rom[st + (snd << 1) + 1];
119                         spos2 += st;                                                            // Need to add start somewhere...
120                         prevSamp2 = 128;
121                         sample2 = 0;
122                         chan2_go = true;
123                 }
124         }
125         else if (type == PSGSOUND)
126         {
127                 if (snd_num & 0x10)                                                             // Second channel?
128                 {
129                         spos3 = 0;
130                         end_pos3 = psg_lens[snd_num & 0x0F];
131                         sndp3 = psg_adrs[snd_num & 0x0F];
132                         chan3_go = true;
133
134                         if (spos3 == end_pos3)
135                                 chan3_go = false;                                               // No sound loaded, so don't do it!
136                 }
137                 else                                                                                    // First channel
138                 {
139                         spos4 = 0;
140                         end_pos4 = psg_lens[snd_num & 0x0F];
141                         sndp4 = psg_adrs[snd_num & 0x0F];
142                         chan4_go = true;
143
144                         if (spos4 == end_pos4)
145                                 chan4_go = false;                                               // No sound loaded, so don't do it!
146                 }
147         }
148         else if (type == FMSOUND)
149         {
150                 spos5 = 0;
151                 end_pos5 = fm_lens[snd_num];
152                 sndp5 = fm_adrs[snd_num];
153                 chan5_go = true;
154
155                 if (spos5 == end_pos5)
156                         chan5_go = false;                                                       // No sound loaded, so don't do it!
157         }
158         else if (type == USERSOUND)
159         {
160                 spos6 = 0;
161                 end_pos6 = snd_lens[snd_num];                                   // User sound
162                 sndp6 = snd_array[snd_num];                                             // Load pointer
163                 chan6_go = true;
164         }
165 }
166
167
168 void SoundFunc(void * userdata, Uint8 * buff, int num)
169 {
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...
175
176         // Kill sound...
177         memset(buff, 128, num);
178
179         if (chan1_go || chan2_go || chan3_go || chan4_go || chan5_go || chan6_go)
180         {
181                 while (cnt != num)
182                 {
183                         if (chan1_go)
184                         {
185                                 if (sample1 < 1)
186                                 {
187                                         samp1 = voice_rom[spos1++];
188
189                                         // Kill channel 1 if done...
190                                         if (samp1 == 0xFF)
191                                         {
192                                                 chan1_go = false;
193                                                 samp1 = 128;
194                                         }
195                                         // RLE compression...
196                                         else if (samp1 == 0x00)
197                                         {
198                                                 // # of repeats
199                                                 sample1 += (float)voice_rom[spos1++] * sampleBase;
200                                                 // Get last good sample
201                                                 samp1   = prevSamp1;
202                                         }
203                                         else
204                                                 // Keep fractional part intact
205                                                 sample1 += sampleBase;
206                                 }
207
208                                 prevSamp1 = samp1;              // Save last sample value
209                                 sample1 -= 1.0;                 // Decrement repeat counter
210                         }
211
212 // Stretching 5KHz samples to 22KHz:
213 //   numRepeats = 4;
214 //            6KHz -> 22KHz:  22/6 repeats...
215                         if (chan2_go)
216                         {
217                                 if (sample2 < 1)
218                                 {
219                                         samp2 = voice_rom[spos2++];
220
221                                         if (samp2 == 0xFF)
222                                         {
223                                                 chan2_go = false;
224                                                 samp2 = 128;                                    // Kill channel 2 if done...
225                                         }
226                                         else if (samp2 == 0x00)                         // RLE compression...
227                                         {
228                                                 sample2 += (float)voice_rom[spos2++] * sampleBase;      // # of repeats
229                                                 samp2   = prevSamp2;
230                                         }
231                                         else
232                                                 sample2 += sampleBase;
233                                 }
234
235 // Delta-X values were making the samples sound like crap...
236 //                              start_samp2 += delta_x2;
237                                 prevSamp2 = samp2;
238                                 sample2 -= 1.0;
239                         }
240
241                         if (chan3_go)
242                         {
243                                 samp3 = sndp3[spos3++];
244
245                                 if (spos3 == end_pos3)
246                                 {
247                                         chan3_go = false;
248                                         samp3 = 128; // Kill channel 3 if done...
249                                 }
250                         }
251
252                         if (chan4_go)
253                         {
254                                 samp4 = sndp4[spos4++];
255
256                                 if (spos4 == end_pos4)
257                                 {
258                                         chan4_go = false;
259                                         samp4 = 128; // Kill channel 4 if done...
260                                 }
261                         }
262
263                         if (chan5_go)
264                         {
265                                 samp5 = sndp5[spos5++];
266
267                                 if (spos5 == end_pos5)
268                                 {
269                                         chan5_go = false;
270                                         samp5 = 128; // Kill channel 5 if done...
271                                 }
272                         }
273
274                         if (chan6_go)
275                         {
276                                 samp6 = sndp6[spos6++];
277
278                                 if (spos6 == end_pos6)
279                                 {
280                                         chan6_go = false;
281                                         samp6 = 128;            // Kill channel 6...
282                                 }
283                         }
284
285                         // Mix 'em...
286                         sample = samp1 + samp2 + samp3 + samp4 + samp5 + samp6 - 640;
287
288                         // If it overflowed, clip it
289                         if (sample & 0xFF00)
290                                 sample = (sample & 0x8000 ? 0x00 : 0xFF);
291
292                         buff[cnt++] = sample;
293                 }
294         }
295 }
296