1
2 #include "witchaven.h"
3 #include "sound.h"
4 #include "compat.h"
5 #include "baselayer.h"
6 #include "renderlayer.h" // for win_gethwnd()
7 #include "build.h"
8 #include "cache1d.h"
9 #include "music.h"
10 #include "fx_man.h"
11 #include "hmpplay.h"
12 #include "keyboard.h"
13 #include "control.h"
14 #include "config.h"
15 #include "player.h"
16
17 void SND_MIDIFlush(void);
18 char* SND_LoadMIDISong(int nSong);
19 int SND_PrepareMIDISong(int SongIndex);
20 int SND_StartMIDISong(int wSongHandle);
21
22 int lavasnd = -1;
23 int batsnd = -1;
24 int cartsnd = -1;
25
26 int SoundMode, wDIGIVol;
27 int MusicMode, wMIDIVol;
28 int use_rec_driver, voicecom_enabled;
29 int SD_Started;
30 int wMIDIDeviceID;
31 int SongPending;
32
33 #define _MIDI_MPU_401 0xa001
34 #define _MIDI_FM 0xa002
35 #define _MIDI_OPL2 0xa002
36 #define _MIDI_OPL3 0xa009
37 char *BaseSongPtr;
38 char *EmbSongPtr;
39 char *SpiceSongPtr;
40
41 char *m_bnkptr, *d_bnkptr;
42
43 #define MAX_ACTIVE_SONGS 4
44
45 int hSOSSongHandles[MAX_ACTIVE_SONGS];
46 InitSong sSOSInitSongs[MAX_ACTIVE_SONGS];
47 TrackDevice sSOSTrackMap[MAX_ACTIVE_SONGS] = {
48 {
49 0xff, 0xff, 0xff, 0xff,
50 0xff, 0xff, 0xff, 0xff,
51 0xff, 0xff, 0xff, 0xff,
52 0xff, 0xff, 0xff, 0xff
53 },
54 {
55 0xff, 0xff, 0xff, 0xff,
56 0xff, 0xff, 0xff, 0xff,
57 0xff, 0xff, 0xff, 0xff,
58 0xff, 0xff, 0xff, 0xff
59 },
60 {
61 0xff, 0xff, 0xff, 0xff,
62 0xff, 0xff, 0xff, 0xff,
63 0xff, 0xff, 0xff, 0xff,
64 0xff, 0xff, 0xff, 0xff
65 },
66 {
67 0xff, 0xff, 0xff, 0xff,
68 0xff, 0xff, 0xff, 0xff,
69 0xff, 0xff, 0xff, 0xff,
70 0xff, 0xff, 0xff, 0xff
71 },
72 };
73
74 static uint16_t songelements = 3;
75 static uint16_t arrangements = 3;
76 static uint16_t songsperlevel;
77 static uint16_t totallevels = 6; // really there use two to test menusong
78
79 uint32_t DigiList[4096];
80 uint32_t LoopList[4096];
81 uint32_t SongList[4096];
82
83 uint32_t PanArray[] = {
84 // REAR to HARD LEFT (angle = 0->512)
85 0x8000,0x7000,0x6000,0x5000,0x4000,0x3000,0x2000,0x1000,0x0000,
86 // HARD LEFT to CENTER (angle = 513-1024)
87 0x1000,0x20F0,0x2000,0x3000,0x4000,0x5000,0x6000,0x7000,0x8000,
88 // CENTER to HARD RIGHT (angle = 1025-1536)
89 0x70F0,0x8000,0x9000,0xA000,0xB000,0xC000,0xD000,0xE000,0xF000,
90 // HARD RIGHT to REAR (angle = 1537-2047)
91 0xFFFF,0xF000,0xE000,0xD000,0xC000,0xB000,0xA000,0x9000,0x8000
92 };
93
94 struct SampleType
95 {
96 // int playing;
97 int32_t nFXHandle;
98 int32_t number;
99 int32_t priority;
100 int32_t loopcount;
101 int32_t x, y;
102
103 int nSize;
104 char* pData;
105 };
106
107 SampleType SampleRay[MAX_ACTIVE_SAMPLES];
108
109
110 ambsounds ambsoundarray[] =
111 {
112 0,0,
113 S_WINDLOOP1,-1,
114 S_WINDLOOP2,-1,
115 S_WAVELOOP1,-1,
116 S_LAVALOOP1,-1,
117 S_WATERY,-1,
118 S_STONELOOP1,-1,
119 S_BATSLOOP,-1
120 };
121
122 buildvfs_kfd hSoundFile = buildvfs_kfd_invalid;
123 buildvfs_kfd hLoopsFile = buildvfs_kfd_invalid;
124 buildvfs_kfd hSongsFile = buildvfs_kfd_invalid;
125
126
SND_SetupTables()127 void SND_SetupTables()
128 {
129 if (SoundMode)
130 {
131 hSoundFile = kopen4loadfrommod("joesnd", 0);
132 if (hSoundFile == buildvfs_kfd_invalid) {
133 crash("Couldn't open joesnd");
134 }
135
136 int nSize = kfilelength(hSoundFile);
137 if (nSize < 4096) {
138 crash("Invalid size for joesdn");
139 }
140
141 klseek(hSoundFile, nSize - 4096, SEEK_SET);
142
143 if (kread(hSoundFile, DigiList, 4096) != 4096) {
144 crash("Couldn't read from joesnd");
145 }
146 }
147
148 if (MusicMode == _LOOP_MUSIC)
149 {
150 hLoopsFile = kopen4loadfrommod("loops", 0);
151 if (hLoopsFile == buildvfs_kfd_invalid) {
152 crash("Couldn't open loops");
153 }
154
155 int nSize = kfilelength(hLoopsFile);
156 if (nSize < 4096) {
157 crash("Invalid size for loops");
158 }
159
160 klseek(hLoopsFile, nSize - 4096, SEEK_SET);
161
162 if (kread(hLoopsFile, LoopList, 4096) != 4096) {
163 crash("Couldn't read from loops");
164 }
165 }
166 else if (MusicMode)
167 {
168 hSongsFile = kopen4loadfrommod("songs", 0);
169 if (hSongsFile == buildvfs_kfd_invalid) {
170 crash("Couldn't open songs");
171 }
172
173 int nSize = kfilelength(hSongsFile);
174 if (nSize < 4096) {
175 crash("Invalid size for songs");
176 }
177
178 klseek(hSongsFile, nSize - 4096, SEEK_SET);
179
180 if (kread(hSongsFile, SongList, 4096) != 4096) {
181 crash("Couldn't read from songs");
182 }
183 }
184
185 return;
186 }
187
SND_LoadMidiIns(void)188 void SND_LoadMidiIns(void)
189 {
190 static int wLength;
191
192 //JSA_DEMO check port address to verify FM device
193 buildvfs_kfd handle = kopen4loadfrommod("melodic.bnk", 0);
194 if (handle == buildvfs_kfd_invalid)
195 crash("MELODIC BANK FILE FAILED!");
196 m_bnkptr = (char*)malloc(0x152c);
197 kread(handle, m_bnkptr, 0x152c);
198 kclose(handle);
199 if (FMSetBank(m_bnkptr))
200 crash("BAD SetInsData MEL!");
201
202 handle = kopen4loadfrommod("drum.bnk", 0);
203 if (handle == buildvfs_kfd_invalid)
204 crash("PERCUSSIVE BANK FILE FAILED!");
205 d_bnkptr = (char*)malloc(0x152c);
206 kread(handle, d_bnkptr, 0x152c);
207 kclose(handle);
208 if (FMSetBank(d_bnkptr))
209 printf("BAD SetInsData DRUM!");
210 }
211
ASSCallback(intptr_t pSample)212 void ASSCallback(intptr_t pSample)
213 {
214 SampleType *sample = (SampleType*)pSample;
215 sample->loopcount = 0;
216 sample->nSize = 0;
217 sample->nFXHandle = 0;
218 sample->priority = 0;
219 sample->number = -1;
220 }
221
222 extern int MV_MixRate;
223 extern int musiclevel;
224
SND_Startup()225 void SND_Startup()
226 {
227 #ifdef MIXERTYPEWIN
228 void* initdata = (void*)win_gethwnd(); // used for DirectSound
229 #else
230 void* initdata = NULL;
231 #endif
232
233 // if (bNoSound)
234 // return;
235
236 if (FX_Init(NumVoices, NumChannels, MixRate, initdata) != FX_Ok)
237 {
238 // crash("Error initializing sound card!\n");
239 initprintf("Error initializing sound card!\n");
240 // DebugOut("ERROR: %s\n", FX_ErrorString(FX_Error));
241 return;
242 }
243
244 FX_SetCallBack(ASSCallback);
245
246 memset(SampleRay, 0, sizeof(SampleRay));
247 for (int i = 0; i < MAX_ACTIVE_SAMPLES; i++)
248 {
249 SampleRay[i].number = -1;
250 // SampleRay[i].loopcount = -1;
251 }
252
253 // init buffer space
254 for (int i = 0; i < MAX_ACTIVE_SAMPLES; i++) {
255 SampleRay[i].pData = new char[55000]; // just alloc a big block, like the original code
256 }
257
258 // Init music
259 #if 1
260 // if they chose None lets return
261 #if 0
262 if (!MusicToggle)
263 {
264 gs.MusicOn = FALSE;
265 return;
266 }
267 #endif
268
269 wMIDIVol = (musiclevel<<3);
270 wMIDIDeviceID = _MIDI_FM;
271 HMIInit(MV_MixRate);
272
273 SND_LoadMidiIns();
274 for (int i = 0; i < MAX_ACTIVE_SONGS; i++)
275 hSOSSongHandles[i] = 0x7fff;
276
277 songsperlevel = songelements * arrangements;
278
279 HMISetMasterVolume(wMIDIVol);
280 /*
281 auto const fil = kopen4load("swtimbr.tmb", 0);
282
283 if (fil != buildvfs_kfd_invalid)
284 {
285 int l = kfilelength(fil);
286 auto tmb = (uint8_t*)Xmalloc(l);
287 kread(fil, tmb, l);
288 AL_RegisterTimbreBank(tmb);
289 Xfree(tmb);
290 kclose(fil);
291 }
292 */
293 #endif
294
295 // read in offset page lists
296 SND_SetupTables();
297
298 SD_Started = 1;
299 }
300
SND_Shutdown()301 void SND_Shutdown()
302 {
303 FX_Shutdown();
304
305 for (int i = 0; i < MAX_ACTIVE_SAMPLES; i++)
306 {
307 if (SampleRay[i].pData) {
308 delete[] SampleRay[i].pData;
309 }
310 }
311
312
313 SND_MIDIFlush();
314 HMIUnInit();
315 if (m_bnkptr != NULL)
316 free(m_bnkptr);
317 if (d_bnkptr != NULL)
318 free(d_bnkptr);
319
320 if (hSoundFile != buildvfs_kfd_invalid) {
321 kclose(hSoundFile);
322 }
323
324 if (hLoopsFile != buildvfs_kfd_invalid) {
325 kclose(hLoopsFile);
326 }
327
328 if (hSongsFile != buildvfs_kfd_invalid) {
329 kclose(hSongsFile);
330 }
331
332 SD_Started = 0;
333 }
334
SND_Sound(int nSound)335 int SND_Sound(int nSound)
336 {
337 if (!SoundMode)
338 return -1;
339
340 return(SND_PlaySound(nSound, 0, 0, 0, 0));
341 }
342
SND_PlaySound(int nSound,int32_t x,int32_t y,int16_t Pan,int16_t loopcount)343 int SND_PlaySound(int nSound, int32_t x, int32_t y, int16_t Pan, int16_t loopcount)
344 {
345 //return 0; // TODO
346
347 short wVol, flag = 0;
348 int32_t sqrdist;
349 int32_t prioritize;
350 int i;
351
352 if (!SoundMode)
353 return 0;
354
355 prioritize = DigiList[(nSound * 3) + 2];
356
357 if (((x == 0) && (y == 0)) || ((player[pyrn].x == x) && (player[pyrn].y == y)))
358 {
359 wVol = 0x7fff;
360 Pan = 0;
361 }
362 else
363 {
364 sqrdist = labs(player[pyrn].x - x) + labs(player[pyrn].y - y);
365 if (sqrdist < 1500)
366 wVol = 0x7fff;
367 else if (sqrdist > 8500)
368 wVol = 0x1f00;
369 else
370 wVol = 39000 - (sqrdist << 2);
371 }
372
373 if (nSound == S_STONELOOP1)
374 {
375 for (i = 0, flag = 0; i < MAX_ACTIVE_SAMPLES; i++)
376 {
377 if (nSound == SampleRay[i].number)
378 return 0;
379 }
380 }
381
382 for (i = 0, flag = 0; i < MAX_ACTIVE_SAMPLES; i++)
383 {
384 if (SampleRay[i].nFXHandle <= 0)
385 {
386 flag = 1;
387 break;
388 }
389 }
390
391 if (!flag && prioritize < 9) // none available low priority
392 return 0;
393 else if (!flag) // none available but high priority
394 {
395 for (i = 0; i < MAX_ACTIVE_SAMPLES; i++)
396 {
397 if (SampleRay[i].priority < 9 && SampleRay[i].loopcount != -1)//sSOSSampleData[i].wLoopCount != -1)
398 {
399 //if (!sosDIGISampleDone(hSOSDriverHandles[DIGI], SampleRay[i].SOSHandle) && (sSOSSampleData[i].dwSampleSize != 0))
400 if (SampleRay[i].nFXHandle > 0)
401 {
402 FX_StopSound(SampleRay[i].nFXHandle);
403 SampleRay[i].loopcount = 0;
404 SampleRay[i].nSize = 0;
405 SampleRay[i].nFXHandle = 0;
406 // SampleRay[i].playing = 0;
407 SampleRay[i].priority = 0;
408 SampleRay[i].number = -1;
409 break;
410 }
411 }
412 }
413 }
414
415 if (i >= MAX_ACTIVE_SAMPLES)
416 {
417 return 0; // FIXME - this shouldn't trigger?
418 }
419
420 assert(i >= 0 && i < 10);
421
422 if (Pan) {
423 Pan = ((getangle(player[pyrn].x - x, player[pyrn].y - y) + (2047 - player[pyrn].ang)) % kAngleMask) >> 6;
424 }
425
426 int SeekIndex = (DigiList[(nSound * 3) + 0] * 4096);
427
428 if (klseek(hSoundFile, SeekIndex, SEEK_SET) < 0)
429 {
430 assert(1 == 2);
431 }
432
433 SampleRay[i].nSize = (uint16_t)DigiList[(nSound * 3) + 1];
434
435 // assert(hSoundFileSize - SeekIndex >= SampleRay[i].nSize);
436
437
438 int nRead = kread(hSoundFile, SampleRay[i].pData, SampleRay[i].nSize);
439 if (nRead != SampleRay[i].nSize)
440 {
441 assert(1 == 2);
442 }
443
444 SampleRay[i].nFXHandle = FX_PlayRaw(SampleRay[i].pData, SampleRay[i].nSize, 11025, 0, 32, 32, 32, 0, fix16_one, (intptr_t)&SampleRay[i]);
445 assert(SampleRay[i].nFXHandle > 0);
446
447 #if 0 // TODO
448 if (loopcount)
449 sSOSSampleData[i].wLoopCount = loopcount;
450
451 if (Pan)
452 Pan = ((getangle(player[pyrn].x - x, player[pyrn].y - y) + (2047 - player[pyrn].ang)) % 2047) >> 6;
453
454 sSOSSampleData[wIndex].wSamplePanLocation = PanArray[Pan];
455 sSOSSampleData[wIndex].wVolume = wVol;
456 SampleRay[wIndex].SOSHandle = sosDIGIStartSample(hSOSDriverHandles[DIGI], &sSOSSampleData[wIndex]);
457 #endif
458
459 SampleRay[i].x = x;
460 SampleRay[i].y = y;
461 // SampleRay[i].playing = 1;
462 SampleRay[i].number = nSound;
463 SampleRay[i].priority = prioritize;
464 // TODO ActiveSampleBits |= (0x01 << wIndex);
465
466 return SampleRay[i].nFXHandle;
467 }
468
playsound_loc(int nSound,int32_t xplc,int32_t yplc)469 void playsound_loc(int nSound, int32_t xplc, int32_t yplc)
470 {
471 SND_PlaySound(nSound, xplc, yplc, 1, 0);
472 }
473
SND_UpdateSoundLoc(int which,int Volume,int Pan)474 void SND_UpdateSoundLoc(int which, int Volume, int Pan)
475 {
476 #if 0
477 gVol = Volume;
478 gPan = sosDIGISetPanLocation(hSOSDriverHandles[DIGI], SampleRay[which].SOSHandle, PanArray[Pan]);
479 sosDIGISetSampleVolume(hSOSDriverHandles[DIGI], SampleRay[which].SOSHandle, Volume);
480 #endif
481 }
482
updatesound_loc()483 void updatesound_loc()
484 {
485 #if 0
486 unsigned wVol, wPan;
487 long sqrdist;
488
489 if (!SoundMode)
490 return;
491
492 for (int i = 0; i < MAX_ACTIVE_SAMPLES; i++)
493 {
494 if (SampleRay[i].playing && SampleRay[i].x && SampleRay[i].y)
495 {
496 if (sSOSSampleData[wIndex].dwSampleSize != 0)
497 {
498 sqrdist = labs(player[pyrn].x - SampleRay[wIndex].x) +
499 labs(player[pyrn].y - SampleRay[wIndex].y);
500
501 if (sqrdist < 1500)
502 wVol = 0x7fff;
503 else if (sqrdist > 8500)
504 wVol = 0x1f00;
505 else
506 wVol = 39000 - (sqrdist << 2);
507
508 wPan = ((getangle(player[pyrn].x - SampleRay[wIndex].x, player[pyrn].y - SampleRay[wIndex].y) + (2047 - player[pyrn].ang)) % kAngleMask) >> 6;
509 SND_UpdateSoundLoc(wIndex, wVol, wPan);
510 //sprintf(displaybuf,"%dVol %x Pan %x Dist %ld",SampleRay[wIndex].number,wVol,wPan,sqrdist);
511 //displaytime=100;
512 }
513 }
514 }
515 #endif
516 }
517
SND_CheckLoops()518 void SND_CheckLoops()
519 {
520 }
521
SND_StopLoop(int16_t nSound)522 void SND_StopLoop(int16_t nSound)
523 {
524 }
525
SND_LoadSongs(uint16_t which)526 void SND_LoadSongs(uint16_t which)
527 {
528 static int index;
529
530 index = songsperlevel * which; //vanilla
531
532 //if digi_midi used skip to those songs
533 // if (wMIDIDeviceID == _MIDI_AWE32)
534 // index += songelements; //skip past vanilla
535
536 //if soundcanvas skip to those songs
537 if (wMIDIDeviceID == _MIDI_MPU_401/* || wMIDIDeviceID == _MIDI_GUS*/)
538 index += songelements * 2;
539
540 BaseSongPtr = SND_LoadMIDISong(index + BASE_SONG);
541 EmbSongPtr = SND_LoadMIDISong(index + EMB_SONG);
542 SpiceSongPtr = SND_LoadMIDISong(index + SPICE_SONG);
543 }
544
SND_StartMusic(int16_t level)545 void SND_StartMusic(int16_t level)
546 {
547 if ((!MusicMode) || !SD_Started)
548 return;
549
550 if (level > 5)
551 level = rand() % 6;
552
553 SND_SongFlush();
554 SND_LoadSongs(level);
555 SongPending = SND_PrepareMIDISong(BASE_SONG);
556 SND_StartMIDISong(SongPending);
557 SongPending = 0;
558 }
559
SND_Mixer(int16_t wSource,int16_t wVolume)560 void SND_Mixer(int16_t wSource, int16_t wVolume)
561 {
562 if (wSource == MIDI) {
563 wMIDIVol = (wVolume << 3);
564 HMISetMasterVolume(wMIDIVol);
565 }
566 }
567
SND_Sting(int16_t nSound)568 void SND_Sting(int16_t nSound)
569 {
570 }
571
SND_FadeMusic()572 void SND_FadeMusic()
573 {
574 }
575
576 // temp
577 int nMusicSize = 0;
578
SND_LoadMIDISong(int nSong)579 char* SND_LoadMIDISong(int nSong)
580 {
581 uint32_t nLength = SongList[(nSong * 3) + 1];
582 uint32_t SeekIndex = (SongList[(nSong * 3) + 0] * 4096);
583 char* pData = (char*)malloc(nLength);
584
585 klseek(hSongsFile, SeekIndex, SEEK_SET);
586 kread(hSongsFile, pData, nLength);
587
588 nMusicSize = nLength;
589
590 return pData;
591 }
592
SND_MenuMusic(int nSong)593 void SND_MenuMusic(int nSong)
594 {
595 if (!MusicMode || !SD_Started)
596 return;
597
598 if ((nSong == DEATHSONG) && (wMIDIDeviceID == _MIDI_FM))
599 return;
600 SND_SongFlush();
601
602 if (nSong == MENUSONG)
603 {
604 if (wMIDIDeviceID == _MIDI_MPU_401/* || wMIDIDeviceID == _MIDI_AWE32 || wMIDIDeviceID == _MIDI_GUS*/)
605 {
606 BaseSongPtr = SND_LoadMIDISong((totallevels * songsperlevel) + BASE_SONG + 2);
607 }
608 else
609 {
610 BaseSongPtr = SND_LoadMIDISong((totallevels * songsperlevel) + BASE_SONG);
611 }
612 }
613 else if (wMIDIDeviceID == _MIDI_MPU_401/* || wMIDIDeviceID == _MIDI_AWE32 || wMIDIDeviceID == _MIDI_GUS*/)
614 {
615 BaseSongPtr = SND_LoadMIDISong((totallevels * songsperlevel) + 3 + BASE_SONG + 2);
616 }
617
618 SongPending = SND_PrepareMIDISong(BASE_SONG);
619 SND_StartMIDISong(SongPending);
620 SongPending = 0;
621 }
622
sosMIDISongCallback(uint32_t hSong)623 void sosMIDISongCallback(uint32_t hSong)
624 {
625 int i;
626 for (i = 0; i < MAX_ACTIVE_SONGS; i++)
627 if (hSong == hSOSSongHandles[i])
628 break;
629
630 HMIUnInitSong(hSOSSongHandles[i]);
631 hSOSSongHandles[i] = 0x7fff;
632 }
633
SND_PrepareMIDISong(int SongIndex)634 int SND_PrepareMIDISong(int SongIndex)
635 {
636 int status;
637 if (!MusicMode)
638 return(0x7fff);
639
640 if (hSOSSongHandles[SongIndex] != 0x7fff)
641 return(0x7fff);
642
643 if (SongIndex == BASE_SONG)
644 sSOSInitSongs[SongIndex].songptr = (uint8_t*)BaseSongPtr;
645 if (SongIndex == EMB_SONG)
646 sSOSInitSongs[SongIndex].songptr = (uint8_t*)EmbSongPtr;
647 if (SongIndex == SPICE_SONG)
648 sSOSInitSongs[SongIndex].songptr = (uint8_t*)SpiceSongPtr;
649
650 sSOSInitSongs[SongIndex].callback = sosMIDISongCallback;
651 if ((status = HMIInitSong(&sSOSInitSongs[SongIndex], &sSOSTrackMap[SongIndex], (uint32_t*)&hSOSSongHandles[SongIndex])))
652 {
653 crash("Init Song Failed!");
654 }
655
656 return((int)hSOSSongHandles[SongIndex]);
657 }
SND_StartMIDISong(int wSongHandle)658 int SND_StartMIDISong(int wSongHandle)
659 {
660 HMISetMasterVolume(wMIDIVol);
661 return(HMIStartSong(wSongHandle));
662 }
663
SND_StopMIDISong(int wSongHandle)664 void SND_StopMIDISong(int wSongHandle)
665 {
666 int i;
667 for (i = 0; i < MAX_ACTIVE_SONGS; i++)
668 if (hSOSSongHandles[i] == wSongHandle)
669 break;
670
671 if (i >= MAX_ACTIVE_SONGS)
672 return;
673
674 if (!HMISongDone(hSOSSongHandles[i]))
675 {
676 HMIStopSong(hSOSSongHandles[i]);
677 HMIUnInitSong(hSOSSongHandles[i]);
678 hSOSSongHandles[i] = 0x7fff;
679 free(sSOSInitSongs[i].songptr);
680 }
681 }
682
SND_SongFlush()683 void SND_SongFlush()
684 {
685 if (!MusicMode)
686 return;
687
688 if (hSOSSongHandles[BASE_SONG] != 0x7fff)
689 SND_StopMIDISong(hSOSSongHandles[BASE_SONG]);
690 if (hSOSSongHandles[EMB_SONG] != 0x7fff)
691 SND_StopMIDISong(hSOSSongHandles[EMB_SONG]);
692 if (hSOSSongHandles[SPICE_SONG] != 0x7fff)
693 SND_StopMIDISong(hSOSSongHandles[SPICE_SONG]);
694 }
695
SND_MIDIFlush(void)696 void SND_MIDIFlush(void)
697 {
698 int i;
699 for (i = 0; i < MAX_ACTIVE_SONGS; i++) {
700 if (!HMISongDone(hSOSSongHandles[i]))
701 HMIStopSong(hSOSSongHandles[i]);
702 if (hSOSSongHandles[i] != 0x7fff)
703 HMIUnInitSong(hSOSSongHandles[i]);
704 hSOSSongHandles[i] = 0x7fff;
705 }
706
707 free(BaseSongPtr);
708 free(EmbSongPtr);
709 free(SpiceSongPtr);
710 }
711