diff options
Diffstat (limited to 'apps/plugins/sdl/progs/wolf3d/id_sd.c')
-rw-r--r-- | apps/plugins/sdl/progs/wolf3d/id_sd.c | 1578 |
1 files changed, 1578 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/wolf3d/id_sd.c b/apps/plugins/sdl/progs/wolf3d/id_sd.c new file mode 100644 index 0000000000..a528caa606 --- /dev/null +++ b/apps/plugins/sdl/progs/wolf3d/id_sd.c | |||
@@ -0,0 +1,1578 @@ | |||
1 | // | ||
2 | // ID Engine | ||
3 | // ID_SD.c - Sound Manager for Wolfenstein 3D | ||
4 | // v1.2 | ||
5 | // By Jason Blochowiak | ||
6 | // | ||
7 | |||
8 | // | ||
9 | // This module handles dealing with generating sound on the appropriate | ||
10 | // hardware | ||
11 | // | ||
12 | // Depends on: User Mgr (for parm checking) | ||
13 | // | ||
14 | // Globals: | ||
15 | // For User Mgr: | ||
16 | // SoundBlasterPresent - SoundBlaster card present? | ||
17 | // AdLibPresent - AdLib card present? | ||
18 | // SoundMode - What device is used for sound effects | ||
19 | // (Use SM_SetSoundMode() to set) | ||
20 | // MusicMode - What device is used for music | ||
21 | // (Use SM_SetMusicMode() to set) | ||
22 | // DigiMode - What device is used for digitized sound effects | ||
23 | // (Use SM_SetDigiDevice() to set) | ||
24 | // | ||
25 | // For Cache Mgr: | ||
26 | // NeedsDigitized - load digitized sounds? | ||
27 | // NeedsMusic - load music? | ||
28 | // | ||
29 | |||
30 | #include "wl_def.h" | ||
31 | #include "fmopl.h" | ||
32 | |||
33 | #include "fixedpoint.h" | ||
34 | |||
35 | #pragma hdrstop | ||
36 | |||
37 | #define ORIGSAMPLERATE 7042 | ||
38 | |||
39 | typedef struct | ||
40 | { | ||
41 | char RIFF[4]; | ||
42 | longword filelenminus8; | ||
43 | char WAVE[4]; | ||
44 | char fmt_[4]; | ||
45 | longword formatlen; | ||
46 | word val0x0001; | ||
47 | word channels; | ||
48 | longword samplerate; | ||
49 | longword bytespersec; | ||
50 | word bytespersample; | ||
51 | word bitspersample; | ||
52 | } headchunk; | ||
53 | |||
54 | typedef struct | ||
55 | { | ||
56 | char chunkid[4]; | ||
57 | longword chunklength; | ||
58 | } wavechunk; | ||
59 | |||
60 | typedef struct | ||
61 | { | ||
62 | uint32_t startpage; | ||
63 | uint32_t length; | ||
64 | } digiinfo; | ||
65 | |||
66 | static Mix_Chunk *SoundChunks[ STARTMUSIC - STARTDIGISOUNDS]; | ||
67 | static byte *SoundBuffers[STARTMUSIC - STARTDIGISOUNDS]; | ||
68 | |||
69 | globalsoundpos channelSoundPos[MIX_CHANNELS]; | ||
70 | |||
71 | // Global variables | ||
72 | boolean AdLibPresent, | ||
73 | SoundBlasterPresent,SBProPresent, | ||
74 | SoundPositioned; | ||
75 | SDMode SoundMode; | ||
76 | SMMode MusicMode; | ||
77 | SDSMode DigiMode; | ||
78 | static byte **SoundTable; | ||
79 | int DigiMap[LASTSOUND]; | ||
80 | int DigiChannel[STARTMUSIC - STARTDIGISOUNDS]; | ||
81 | |||
82 | // Internal variables | ||
83 | static boolean SD_Started; | ||
84 | static boolean nextsoundpos; | ||
85 | static soundnames SoundNumber; | ||
86 | static soundnames DigiNumber; | ||
87 | static word SoundPriority; | ||
88 | static word DigiPriority; | ||
89 | static int LeftPosition; | ||
90 | static int RightPosition; | ||
91 | |||
92 | word NumDigi; | ||
93 | static digiinfo *DigiList; | ||
94 | static boolean DigiPlaying; | ||
95 | |||
96 | // PC Sound variables | ||
97 | static volatile byte pcLastSample; | ||
98 | static byte * volatile pcSound; | ||
99 | static longword pcLengthLeft; | ||
100 | |||
101 | // AdLib variables | ||
102 | static byte * volatile alSound; | ||
103 | static byte alBlock; | ||
104 | static longword alLengthLeft; | ||
105 | static longword alTimeCount; | ||
106 | static Instrument alZeroInst; | ||
107 | |||
108 | // Sequencer variables | ||
109 | static volatile boolean sqActive; | ||
110 | static word *sqHack; | ||
111 | static word *sqHackPtr; | ||
112 | static int sqHackLen; | ||
113 | static int sqHackSeqLen; | ||
114 | static longword sqHackTime; | ||
115 | |||
116 | |||
117 | static void SDL_SoundFinished(void) | ||
118 | { | ||
119 | #ifdef SOUND_ENABLE | ||
120 | SoundNumber = (soundnames)0; | ||
121 | SoundPriority = 0; | ||
122 | #endif | ||
123 | } | ||
124 | |||
125 | |||
126 | #ifdef NOTYET | ||
127 | |||
128 | void SDL_turnOnPCSpeaker(word timerval); | ||
129 | #pragma aux SDL_turnOnPCSpeaker = \ | ||
130 | "mov al,0b6h" \ | ||
131 | "out 43h,al" \ | ||
132 | "mov al,bl" \ | ||
133 | "out 42h,al" \ | ||
134 | "mov al,bh" \ | ||
135 | "out 42h,al" \ | ||
136 | "in al,61h" \ | ||
137 | "or al,3" \ | ||
138 | "out 61h,al" \ | ||
139 | parm [bx] \ | ||
140 | modify exact [al] | ||
141 | |||
142 | void SDL_turnOffPCSpeaker(); | ||
143 | #pragma aux SDL_turnOffPCSpeaker = \ | ||
144 | "in al,61h" \ | ||
145 | "and al,0fch" \ | ||
146 | "out 61h,al" \ | ||
147 | modify exact [al] | ||
148 | |||
149 | void SDL_setPCSpeaker(byte val); | ||
150 | #pragma aux SDL_setPCSpeaker = \ | ||
151 | "in al,61h" \ | ||
152 | "and al,0fch" \ | ||
153 | "or al,ah" \ | ||
154 | "out 61h,al" \ | ||
155 | parm [ah] \ | ||
156 | modify exact [al] | ||
157 | |||
158 | void SDL_DoFX() | ||
159 | { | ||
160 | if(pcSound) | ||
161 | { | ||
162 | if(*pcSound!=pcLastSample) | ||
163 | { | ||
164 | pcLastSample=*pcSound; | ||
165 | |||
166 | if(pcLastSample) | ||
167 | SDL_turnOnPCSpeaker(pcLastSample*60); | ||
168 | else | ||
169 | SDL_turnOffPCSpeaker(); | ||
170 | } | ||
171 | pcSound++; | ||
172 | pcLengthLeft--; | ||
173 | if(!pcLengthLeft) | ||
174 | { | ||
175 | pcSound=0; | ||
176 | SoundNumber=(soundnames)0; | ||
177 | SoundPriority=0; | ||
178 | SDL_turnOffPCSpeaker(); | ||
179 | } | ||
180 | } | ||
181 | |||
182 | // [adlib sound stuff removed...] | ||
183 | } | ||
184 | |||
185 | static void SDL_DigitizedDoneInIRQ(void); | ||
186 | |||
187 | void SDL_DoFast() | ||
188 | { | ||
189 | count_fx++; | ||
190 | if(count_fx>=5) | ||
191 | { | ||
192 | count_fx=0; | ||
193 | |||
194 | SDL_DoFX(); | ||
195 | |||
196 | count_time++; | ||
197 | if(count_time>=2) | ||
198 | { | ||
199 | TimeCount++; | ||
200 | count_time=0; | ||
201 | } | ||
202 | } | ||
203 | |||
204 | // [adlib music and soundsource stuff removed...] | ||
205 | |||
206 | TimerCount+=TimerDivisor; | ||
207 | if(*((word *)&TimerCount+1)) | ||
208 | { | ||
209 | *((word *)&TimerCount+1)=0; | ||
210 | t0OldService(); | ||
211 | } | ||
212 | else | ||
213 | { | ||
214 | outp(0x20,0x20); | ||
215 | } | ||
216 | } | ||
217 | |||
218 | // Timer 0 ISR for 7000Hz interrupts | ||
219 | void __interrupt SDL_t0ExtremeAsmService(void) | ||
220 | { | ||
221 | if(pcindicate) | ||
222 | { | ||
223 | if(pcSound) | ||
224 | { | ||
225 | SDL_setPCSpeaker(((*pcSound++)&0x80)>>6); | ||
226 | pcLengthLeft--; | ||
227 | if(!pcLengthLeft) | ||
228 | { | ||
229 | pcSound=0; | ||
230 | SDL_turnOffPCSpeaker(); | ||
231 | SDL_DigitizedDoneInIRQ(); | ||
232 | } | ||
233 | } | ||
234 | } | ||
235 | extreme++; | ||
236 | if(extreme>=10) | ||
237 | { | ||
238 | extreme=0; | ||
239 | SDL_DoFast(); | ||
240 | } | ||
241 | else | ||
242 | outp(0x20,0x20); | ||
243 | } | ||
244 | |||
245 | // Timer 0 ISR for 700Hz interrupts | ||
246 | void __interrupt SDL_t0FastAsmService(void) | ||
247 | { | ||
248 | SDL_DoFast(); | ||
249 | } | ||
250 | |||
251 | // Timer 0 ISR for 140Hz interrupts | ||
252 | void __interrupt SDL_t0SlowAsmService(void) | ||
253 | { | ||
254 | count_time++; | ||
255 | if(count_time>=2) | ||
256 | { | ||
257 | TimeCount++; | ||
258 | count_time=0; | ||
259 | } | ||
260 | |||
261 | SDL_DoFX(); | ||
262 | |||
263 | TimerCount+=TimerDivisor; | ||
264 | if(*((word *)&TimerCount+1)) | ||
265 | { | ||
266 | *((word *)&TimerCount+1)=0; | ||
267 | t0OldService(); | ||
268 | } | ||
269 | else | ||
270 | outp(0x20,0x20); | ||
271 | } | ||
272 | |||
273 | void SDL_IndicatePC(boolean ind) | ||
274 | { | ||
275 | pcindicate=ind; | ||
276 | } | ||
277 | |||
278 | /////////////////////////////////////////////////////////////////////////// | ||
279 | // | ||
280 | // SDL_SetTimer0() - Sets system timer 0 to the specified speed | ||
281 | // | ||
282 | /////////////////////////////////////////////////////////////////////////// | ||
283 | static void | ||
284 | SDL_SetTimer0(word speed) | ||
285 | { | ||
286 | #ifndef TPROF // If using Borland's profiling, don't screw with the timer | ||
287 | // _asm pushfd | ||
288 | _asm cli | ||
289 | |||
290 | outp(0x43,0x36); // Change timer 0 | ||
291 | outp(0x40,(byte)speed); | ||
292 | outp(0x40,speed >> 8); | ||
293 | // Kludge to handle special case for digitized PC sounds | ||
294 | if (TimerDivisor == (1192030 / (TickBase * 100))) | ||
295 | TimerDivisor = (1192030 / (TickBase * 10)); | ||
296 | else | ||
297 | TimerDivisor = speed; | ||
298 | |||
299 | // _asm popfd | ||
300 | _asm sti | ||
301 | #else | ||
302 | TimerDivisor = 0x10000; | ||
303 | #endif | ||
304 | } | ||
305 | |||
306 | /////////////////////////////////////////////////////////////////////////// | ||
307 | // | ||
308 | // SDL_SetIntsPerSec() - Uses SDL_SetTimer0() to set the number of | ||
309 | // interrupts generated by system timer 0 per second | ||
310 | // | ||
311 | /////////////////////////////////////////////////////////////////////////// | ||
312 | static void | ||
313 | SDL_SetIntsPerSec(word ints) | ||
314 | { | ||
315 | TimerRate = ints; | ||
316 | SDL_SetTimer0(1192030 / ints); | ||
317 | } | ||
318 | |||
319 | static void | ||
320 | SDL_SetTimerSpeed(void) | ||
321 | { | ||
322 | word rate; | ||
323 | void (_interrupt *isr)(void); | ||
324 | |||
325 | if ((DigiMode == sds_PC) && DigiPlaying) | ||
326 | { | ||
327 | rate = TickBase * 100; | ||
328 | isr = SDL_t0ExtremeAsmService; | ||
329 | } | ||
330 | else if ((MusicMode == smm_AdLib) || ((DigiMode == sds_SoundSource) && DigiPlaying) ) | ||
331 | { | ||
332 | rate = TickBase * 10; | ||
333 | isr = SDL_t0FastAsmService; | ||
334 | } | ||
335 | else | ||
336 | { | ||
337 | rate = TickBase * 2; | ||
338 | isr = SDL_t0SlowAsmService; | ||
339 | } | ||
340 | |||
341 | if (rate != TimerRate) | ||
342 | { | ||
343 | _dos_setvect(8,isr); | ||
344 | SDL_SetIntsPerSec(rate); | ||
345 | TimerRate = rate; | ||
346 | } | ||
347 | } | ||
348 | |||
349 | // | ||
350 | // PC Sound code | ||
351 | // | ||
352 | |||
353 | /////////////////////////////////////////////////////////////////////////// | ||
354 | // | ||
355 | // SDL_PCPlaySample() - Plays the specified sample on the PC speaker | ||
356 | // | ||
357 | /////////////////////////////////////////////////////////////////////////// | ||
358 | #ifdef _MUSE_ | ||
359 | void | ||
360 | #else | ||
361 | static void | ||
362 | #endif | ||
363 | SDL_PCPlaySample(byte *data,longword len,boolean inIRQ) | ||
364 | { | ||
365 | if(!inIRQ) | ||
366 | { | ||
367 | // _asm pushfd | ||
368 | _asm cli | ||
369 | } | ||
370 | |||
371 | SDL_IndicatePC(true); | ||
372 | |||
373 | pcLengthLeft = len; | ||
374 | pcSound = (volatile byte *)data; | ||
375 | |||
376 | if(!inIRQ) | ||
377 | { | ||
378 | // _asm popfd | ||
379 | _asm sti | ||
380 | } | ||
381 | } | ||
382 | |||
383 | /////////////////////////////////////////////////////////////////////////// | ||
384 | // | ||
385 | // SDL_PCStopSample() - Stops a sample playing on the PC speaker | ||
386 | // | ||
387 | /////////////////////////////////////////////////////////////////////////// | ||
388 | #ifdef _MUSE_ | ||
389 | void | ||
390 | #else | ||
391 | static void | ||
392 | #endif | ||
393 | SDL_PCStopSampleInIRQ(void) | ||
394 | { | ||
395 | pcSound = 0; | ||
396 | |||
397 | SDL_IndicatePC(false); | ||
398 | |||
399 | _asm in al,0x61 // Turn the speaker off | ||
400 | _asm and al,0xfd // ~2 | ||
401 | _asm out 0x61,al | ||
402 | } | ||
403 | |||
404 | /////////////////////////////////////////////////////////////////////////// | ||
405 | // | ||
406 | // SDL_PCPlaySound() - Plays the specified sound on the PC speaker | ||
407 | // | ||
408 | /////////////////////////////////////////////////////////////////////////// | ||
409 | #ifdef _MUSE_ | ||
410 | void | ||
411 | #else | ||
412 | static void | ||
413 | #endif | ||
414 | SDL_PCPlaySound(PCSound *sound) | ||
415 | { | ||
416 | // _asm pushfd | ||
417 | _asm cli | ||
418 | |||
419 | pcLastSample = -1; | ||
420 | pcLengthLeft = sound->common.length; | ||
421 | pcSound = sound->data; | ||
422 | |||
423 | // _asm popfd | ||
424 | _asm sti | ||
425 | } | ||
426 | |||
427 | /////////////////////////////////////////////////////////////////////////// | ||
428 | // | ||
429 | // SDL_PCStopSound() - Stops the current sound playing on the PC Speaker | ||
430 | // | ||
431 | /////////////////////////////////////////////////////////////////////////// | ||
432 | #ifdef _MUSE_ | ||
433 | void | ||
434 | #else | ||
435 | static void | ||
436 | #endif | ||
437 | SDL_PCStopSound(void) | ||
438 | { | ||
439 | // _asm pushfd | ||
440 | _asm cli | ||
441 | |||
442 | pcSound = 0; | ||
443 | |||
444 | _asm in al,0x61 // Turn the speaker off | ||
445 | _asm and al,0xfd // ~2 | ||
446 | _asm out 0x61,al | ||
447 | |||
448 | // _asm popfd | ||
449 | _asm sti | ||
450 | } | ||
451 | |||
452 | /////////////////////////////////////////////////////////////////////////// | ||
453 | // | ||
454 | // SDL_ShutPC() - Turns off the pc speaker | ||
455 | // | ||
456 | /////////////////////////////////////////////////////////////////////////// | ||
457 | static void | ||
458 | SDL_ShutPC(void) | ||
459 | { | ||
460 | // _asm pushfd | ||
461 | _asm cli | ||
462 | |||
463 | pcSound = 0; | ||
464 | |||
465 | _asm in al,0x61 // Turn the speaker & gate off | ||
466 | _asm and al,0xfc // ~3 | ||
467 | _asm out 0x61,al | ||
468 | |||
469 | // _asm popfd | ||
470 | _asm sti | ||
471 | } | ||
472 | |||
473 | #endif | ||
474 | |||
475 | void | ||
476 | SD_StopDigitized(void) | ||
477 | { | ||
478 | #ifdef SOUND_ENABLE | ||
479 | DigiPlaying = false; | ||
480 | DigiNumber = (soundnames) 0; | ||
481 | DigiPriority = 0; | ||
482 | SoundPositioned = false; | ||
483 | if ((DigiMode == sds_PC) && (SoundMode == sdm_PC)) | ||
484 | SDL_SoundFinished(); | ||
485 | |||
486 | switch (DigiMode) | ||
487 | { | ||
488 | case sds_PC: | ||
489 | // SDL_PCStopSampleInIRQ(); | ||
490 | break; | ||
491 | case sds_SoundBlaster: | ||
492 | // SDL_SBStopSampleInIRQ(); | ||
493 | Mix_HaltChannel(-1); | ||
494 | break; | ||
495 | } | ||
496 | #endif | ||
497 | } | ||
498 | |||
499 | int SD_GetChannelForDigi(int which) | ||
500 | { | ||
501 | #ifdef SOUND_ENABLE | ||
502 | if(DigiChannel[which] != -1) return DigiChannel[which]; | ||
503 | |||
504 | int channel = Mix_GroupAvailable(1); | ||
505 | if(channel == -1) channel = Mix_GroupOldest(1); | ||
506 | if(channel == -1) // All sounds stopped in the meantime? | ||
507 | return Mix_GroupAvailable(1); | ||
508 | return channel; | ||
509 | #endif | ||
510 | return 0; | ||
511 | } | ||
512 | |||
513 | void SD_SetPosition(int channel, int leftpos, int rightpos) | ||
514 | { | ||
515 | #ifdef SOUND_ENABLE | ||
516 | if((leftpos < 0) || (leftpos > 15) || (rightpos < 0) || (rightpos > 15) | ||
517 | || ((leftpos == 15) && (rightpos == 15))) | ||
518 | Quit("SD_SetPosition: Illegal position"); | ||
519 | |||
520 | switch (DigiMode) | ||
521 | { | ||
522 | case sds_SoundBlaster: | ||
523 | // SDL_PositionSBP(leftpos,rightpos); | ||
524 | Mix_SetPanning(channel, ((15 - leftpos) << 4) + 15, | ||
525 | ((15 - rightpos) << 4) + 15); | ||
526 | break; | ||
527 | } | ||
528 | #endif | ||
529 | } | ||
530 | |||
531 | #define FP_FLOOR(x, fracbits) (x & (~((1<<(fracbits))-1))) | ||
532 | |||
533 | /* more precise than original samples */ | ||
534 | #define FRACBITS 10 | ||
535 | #define FP_MATH | ||
536 | |||
537 | #ifdef FP_MATH | ||
538 | /* Looks to be some sort of interpolation - FW19 */ | ||
539 | Sint16 GetSample(long csample_fp, byte *samples, int size) | ||
540 | { | ||
541 | //float s0=0, s1=0, s2=0; | ||
542 | long s0_fp = 0, s1_fp = 0, s2_fp = 0; | ||
543 | long cursample_fp = FP_FLOOR(csample_fp, FRACBITS); | ||
544 | long sf_fp = csample_fp - cursample_fp; | ||
545 | const long one = 1 << FRACBITS; | ||
546 | |||
547 | int cursample = cursample_fp >> FRACBITS; | ||
548 | |||
549 | if(cursample-1 >= 0) s0_fp = (samples[cursample-1] - 128) << FRACBITS; | ||
550 | s1_fp = (samples[cursample] - 128) << FRACBITS; | ||
551 | if(cursample+1 < size) s2_fp = (samples[cursample+1] - 128) << FRACBITS; | ||
552 | |||
553 | //float val = s0*sf*(sf-1)/2 - s1*(sf*sf-1) + s2*(sf+1)*sf/2; | ||
554 | |||
555 | long val_fp = fp_mul(s0_fp, fp_mul(sf_fp, sf_fp - one, FRACBITS), FRACBITS) / 2 - | ||
556 | fp_mul(s1_fp, fp_mul(sf_fp, sf_fp, FRACBITS) - one, FRACBITS) + | ||
557 | fp_mul(s2_fp, fp_mul(sf_fp + one, sf_fp, FRACBITS), FRACBITS) / 2; | ||
558 | |||
559 | int32_t intval = (int32_t) (val_fp * 256) >> FRACBITS; | ||
560 | if(intval < -32768) intval = -32768; | ||
561 | else if(intval > 32767) intval = 32767; | ||
562 | return (Sint16) intval; | ||
563 | } | ||
564 | #else | ||
565 | Sint16 GetSample(float csample, byte *samples, int size) | ||
566 | { | ||
567 | float s0=0, s1=0, s2=0; | ||
568 | int cursample = (int) csample; | ||
569 | float sf = csample - (float) cursample; | ||
570 | |||
571 | if(cursample-1 >= 0) s0 = (float) (samples[cursample-1] - 128); | ||
572 | s1 = (float) (samples[cursample] - 128); | ||
573 | if(cursample+1 < size) s2 = (float) (samples[cursample+1] - 128); | ||
574 | |||
575 | float val = s0*sf*(sf-1)/2 - s1*(sf*sf-1) + s2*(sf+1)*sf/2; | ||
576 | int32_t intval = (int32_t) (val * 256); | ||
577 | if(intval < -32768) intval = -32768; | ||
578 | else if(intval > 32767) intval = 32767; | ||
579 | return (Sint16) intval; | ||
580 | } | ||
581 | #endif | ||
582 | |||
583 | void SD_PrepareSound(int which) | ||
584 | { | ||
585 | #ifdef SOUND_ENABLE | ||
586 | #ifdef FP_MATH | ||
587 | if(DigiList == NULL) | ||
588 | Quit("SD_PrepareSound(%i): DigiList not initialized!\n", which); | ||
589 | |||
590 | int page = DigiList[which].startpage; | ||
591 | int size = DigiList[which].length; | ||
592 | |||
593 | byte *origsamples = PM_GetSound(page); | ||
594 | if(origsamples + size >= PM_GetEnd()) | ||
595 | Quit("SD_PrepareSound(%i): Sound reaches out of page file!\n", which); | ||
596 | |||
597 | /* this is fine to keep as floating-point */ | ||
598 | int destsamples = (int) ((float) size * (float) param_samplerate | ||
599 | / (float) ORIGSAMPLERATE); | ||
600 | |||
601 | byte *wavebuffer = (byte *) malloc(sizeof(headchunk) + sizeof(wavechunk) | ||
602 | + destsamples * 2); // dest are 16-bit samples | ||
603 | if(wavebuffer == NULL) | ||
604 | Quit("Unable to allocate wave buffer for sound %i size %d %d %d %d!\n", which, destsamples, size, param_samplerate, ORIGSAMPLERATE); | ||
605 | |||
606 | headchunk head = {{'R','I','F','F'}, 0, {'W','A','V','E'}, | ||
607 | {'f','m','t',' '}, 0x10, 0x0001, 1, param_samplerate, param_samplerate*2, 2, 16}; | ||
608 | wavechunk dhead = {{'d', 'a', 't', 'a'}, destsamples*2}; | ||
609 | head.filelenminus8 = sizeof(head) + destsamples*2; // (sizeof(dhead)-8 = 0) | ||
610 | memcpy(wavebuffer, &head, sizeof(head)); | ||
611 | memcpy(wavebuffer+sizeof(head), &dhead, sizeof(dhead)); | ||
612 | |||
613 | // alignment is correct, as wavebuffer comes from malloc | ||
614 | // and sizeof(headchunk) % 4 == 0 and sizeof(wavechunk) % 4 == 0 | ||
615 | Sint16 *newsamples = (Sint16 *)(void *) (wavebuffer + sizeof(headchunk) | ||
616 | + sizeof(wavechunk)); | ||
617 | |||
618 | long scale_fac_fp = fp_div(size << FRACBITS, destsamples << FRACBITS, FRACBITS); | ||
619 | |||
620 | for(int i=0; i<destsamples; i++) | ||
621 | { | ||
622 | newsamples[i] = GetSample(fp_mul(i << FRACBITS, scale_fac_fp, FRACBITS), | ||
623 | origsamples, size); | ||
624 | } | ||
625 | SoundBuffers[which] = wavebuffer; | ||
626 | |||
627 | SoundChunks[which] = Mix_LoadWAV_RW(SDL_RWFromMem(wavebuffer, | ||
628 | sizeof(headchunk) + sizeof(wavechunk) + destsamples * 2), 1); | ||
629 | #else | ||
630 | if(DigiList == NULL) | ||
631 | Quit("SD_PrepareSound(%i): DigiList not initialized!\n", which); | ||
632 | |||
633 | int page = DigiList[which].startpage; | ||
634 | int size = DigiList[which].length; | ||
635 | |||
636 | byte *origsamples = PM_GetSound(page); | ||
637 | if(origsamples + size >= PM_GetEnd()) | ||
638 | Quit("SD_PrepareSound(%i): Sound reaches out of page file!\n", which); | ||
639 | |||
640 | int destsamples = (int) ((float) size * (float) param_samplerate | ||
641 | / (float) ORIGSAMPLERATE); | ||
642 | |||
643 | byte *wavebuffer = (byte *) malloc(sizeof(headchunk) + sizeof(wavechunk) | ||
644 | + destsamples * 2); // dest are 16-bit samples | ||
645 | if(wavebuffer == NULL) | ||
646 | Quit("Unable to allocate wave buffer for sound %i!\n", which); | ||
647 | |||
648 | headchunk head = {{'R','I','F','F'}, 0, {'W','A','V','E'}, | ||
649 | {'f','m','t',' '}, 0x10, 0x0001, 1, param_samplerate, param_samplerate*2, 2, 16}; | ||
650 | wavechunk dhead = {{'d', 'a', 't', 'a'}, destsamples*2}; | ||
651 | head.filelenminus8 = sizeof(head) + destsamples*2; // (sizeof(dhead)-8 = 0) | ||
652 | memcpy(wavebuffer, &head, sizeof(head)); | ||
653 | memcpy(wavebuffer+sizeof(head), &dhead, sizeof(dhead)); | ||
654 | |||
655 | // alignment is correct, as wavebuffer comes from malloc | ||
656 | // and sizeof(headchunk) % 4 == 0 and sizeof(wavechunk) % 4 == 0 | ||
657 | Sint16 *newsamples = (Sint16 *)(void *) (wavebuffer + sizeof(headchunk) | ||
658 | + sizeof(wavechunk)); | ||
659 | float cursample = 0.F; | ||
660 | float samplestep = (float) ORIGSAMPLERATE / (float) param_samplerate; | ||
661 | for(int i=0; i<destsamples; i++, cursample+=samplestep) | ||
662 | { | ||
663 | newsamples[i] = GetSample((float)size * (float)i / (float)destsamples, | ||
664 | origsamples, size); | ||
665 | } | ||
666 | SoundBuffers[which] = wavebuffer; | ||
667 | |||
668 | SoundChunks[which] = Mix_LoadWAV_RW(SDL_RWFromMem(wavebuffer, | ||
669 | sizeof(headchunk) + sizeof(wavechunk) + destsamples * 2), 1); | ||
670 | #endif | ||
671 | #endif | ||
672 | } | ||
673 | |||
674 | int SD_PlayDigitized(word which,int leftpos,int rightpos) | ||
675 | { | ||
676 | #ifdef SOUND_ENABLE | ||
677 | if (!DigiMode) | ||
678 | return 0; | ||
679 | |||
680 | if (which >= NumDigi) | ||
681 | Quit("SD_PlayDigitized: bad sound number %i", which); | ||
682 | |||
683 | int channel = SD_GetChannelForDigi(which); | ||
684 | SD_SetPosition(channel, leftpos,rightpos); | ||
685 | |||
686 | DigiPlaying = true; | ||
687 | |||
688 | Mix_Chunk *sample = SoundChunks[which]; | ||
689 | if(sample == NULL) | ||
690 | { | ||
691 | printf("SoundChunks[%i] is NULL!\n", which); | ||
692 | return 0; | ||
693 | } | ||
694 | |||
695 | if(Mix_PlayChannel(channel, sample, 0) == -1) | ||
696 | { | ||
697 | printf("Unable to play sound: %s\n", Mix_GetError()); | ||
698 | return 0; | ||
699 | } | ||
700 | |||
701 | return channel; | ||
702 | #endif | ||
703 | return 0; | ||
704 | } | ||
705 | |||
706 | void SD_ChannelFinished(int channel) | ||
707 | { | ||
708 | #ifdef SOUND_ENABLE | ||
709 | channelSoundPos[channel].valid = 0; | ||
710 | #endif | ||
711 | } | ||
712 | |||
713 | void | ||
714 | SD_SetDigiDevice(SDSMode mode) | ||
715 | { | ||
716 | #ifdef SOUND_ENABLE | ||
717 | boolean devicenotpresent; | ||
718 | |||
719 | if (mode == DigiMode) | ||
720 | return; | ||
721 | |||
722 | SD_StopDigitized(); | ||
723 | |||
724 | devicenotpresent = false; | ||
725 | switch (mode) | ||
726 | { | ||
727 | case sds_SoundBlaster: | ||
728 | if (!SoundBlasterPresent) | ||
729 | devicenotpresent = true; | ||
730 | break; | ||
731 | } | ||
732 | |||
733 | if (!devicenotpresent) | ||
734 | { | ||
735 | DigiMode = mode; | ||
736 | |||
737 | #ifdef NOTYET | ||
738 | SDL_SetTimerSpeed(); | ||
739 | #endif | ||
740 | } | ||
741 | #endif | ||
742 | } | ||
743 | |||
744 | void | ||
745 | SDL_SetupDigi(void) | ||
746 | { | ||
747 | #ifdef SOUND_ENABLE | ||
748 | // Correct padding enforced by PM_Startup() | ||
749 | word *soundInfoPage = (word *) (void *) PM_GetPage(ChunksInFile-1); | ||
750 | NumDigi = (word) PM_GetPageSize(ChunksInFile - 1) / 4; | ||
751 | |||
752 | DigiList = (digiinfo *) malloc(NumDigi * sizeof(digiinfo)); | ||
753 | int i; | ||
754 | for(i = 0; i < NumDigi; i++) | ||
755 | { | ||
756 | // Calculate the size of the digi from the sizes of the pages between | ||
757 | // the start page and the start page of the next sound | ||
758 | |||
759 | DigiList[i].startpage = soundInfoPage[i * 2]; | ||
760 | if((int) DigiList[i].startpage >= ChunksInFile - 1) | ||
761 | { | ||
762 | NumDigi = i; | ||
763 | break; | ||
764 | } | ||
765 | |||
766 | int lastPage; | ||
767 | if(i < NumDigi - 1) | ||
768 | { | ||
769 | lastPage = soundInfoPage[i * 2 + 2]; | ||
770 | if(lastPage == 0 || lastPage + PMSoundStart > ChunksInFile - 1) lastPage = ChunksInFile - 1; | ||
771 | else lastPage += PMSoundStart; | ||
772 | } | ||
773 | else lastPage = ChunksInFile - 1; | ||
774 | |||
775 | int size = 0; | ||
776 | for(int page = PMSoundStart + DigiList[i].startpage; page < lastPage; page++) | ||
777 | size += PM_GetPageSize(page); | ||
778 | |||
779 | // Don't include padding of sound info page, if padding was added | ||
780 | if(lastPage == ChunksInFile - 1 && PMSoundInfoPagePadded) size--; | ||
781 | |||
782 | // Patch lower 16-bit of size with size from sound info page. | ||
783 | // The original VSWAP contains padding which is included in the page size, | ||
784 | // but not included in the 16-bit size. So we use the more precise value. | ||
785 | if((size & 0xffff0000) != 0 && (size & 0xffff) < soundInfoPage[i * 2 + 1]) | ||
786 | size -= 0x10000; | ||
787 | size = (size & 0xffff0000) | soundInfoPage[i * 2 + 1]; | ||
788 | |||
789 | DigiList[i].length = size; | ||
790 | } | ||
791 | |||
792 | for(i = 0; i < LASTSOUND; i++) | ||
793 | { | ||
794 | DigiMap[i] = -1; | ||
795 | DigiChannel[i] = -1; | ||
796 | } | ||
797 | #endif | ||
798 | } | ||
799 | |||
800 | // AdLib Code | ||
801 | |||
802 | /////////////////////////////////////////////////////////////////////////// | ||
803 | // | ||
804 | // SDL_ALStopSound() - Turns off any sound effects playing through the | ||
805 | // AdLib card | ||
806 | // | ||
807 | /////////////////////////////////////////////////////////////////////////// | ||
808 | static void | ||
809 | SDL_ALStopSound(void) | ||
810 | { | ||
811 | #ifdef SOUND_ENABLE | ||
812 | alSound = 0; | ||
813 | alOut(alFreqH + 0, 0); | ||
814 | #endif | ||
815 | } | ||
816 | |||
817 | static void | ||
818 | SDL_AlSetFXInst(Instrument *inst) | ||
819 | { | ||
820 | #ifdef SOUND_ENABLE | ||
821 | byte c,m; | ||
822 | |||
823 | m = 0; // modulator cell for channel 0 | ||
824 | c = 3; // carrier cell for channel 0 | ||
825 | alOut(m + alChar,inst->mChar); | ||
826 | alOut(m + alScale,inst->mScale); | ||
827 | alOut(m + alAttack,inst->mAttack); | ||
828 | alOut(m + alSus,inst->mSus); | ||
829 | alOut(m + alWave,inst->mWave); | ||
830 | alOut(c + alChar,inst->cChar); | ||
831 | alOut(c + alScale,inst->cScale); | ||
832 | alOut(c + alAttack,inst->cAttack); | ||
833 | alOut(c + alSus,inst->cSus); | ||
834 | alOut(c + alWave,inst->cWave); | ||
835 | |||
836 | // Note: Switch commenting on these lines for old MUSE compatibility | ||
837 | // alOutInIRQ(alFeedCon,inst->nConn); | ||
838 | alOut(alFeedCon,0); | ||
839 | #endif | ||
840 | } | ||
841 | |||
842 | /////////////////////////////////////////////////////////////////////////// | ||
843 | // | ||
844 | // SDL_ALPlaySound() - Plays the specified sound on the AdLib card | ||
845 | // | ||
846 | /////////////////////////////////////////////////////////////////////////// | ||
847 | static void | ||
848 | SDL_ALPlaySound(AdLibSound *sound) | ||
849 | { | ||
850 | #ifdef SOUND_ENABLE | ||
851 | Instrument *inst; | ||
852 | byte *data; | ||
853 | |||
854 | SDL_ALStopSound(); | ||
855 | |||
856 | alLengthLeft = sound->common.length; | ||
857 | data = sound->data; | ||
858 | alBlock = ((sound->block & 7) << 2) | 0x20; | ||
859 | inst = &sound->inst; | ||
860 | |||
861 | if (!(inst->mSus | inst->cSus)) | ||
862 | { | ||
863 | Quit("SDL_ALPlaySound() - Bad instrument"); | ||
864 | } | ||
865 | |||
866 | SDL_AlSetFXInst(inst); | ||
867 | alSound = (byte *)data; | ||
868 | #endif | ||
869 | } | ||
870 | |||
871 | /////////////////////////////////////////////////////////////////////////// | ||
872 | // | ||
873 | // SDL_ShutAL() - Shuts down the AdLib card for sound effects | ||
874 | // | ||
875 | /////////////////////////////////////////////////////////////////////////// | ||
876 | static void | ||
877 | SDL_ShutAL(void) | ||
878 | { | ||
879 | #ifdef SOUND_ENABLE | ||
880 | alSound = 0; | ||
881 | alOut(alEffects,0); | ||
882 | alOut(alFreqH + 0,0); | ||
883 | SDL_AlSetFXInst(&alZeroInst); | ||
884 | #endif | ||
885 | } | ||
886 | |||
887 | /////////////////////////////////////////////////////////////////////////// | ||
888 | // | ||
889 | // SDL_CleanAL() - Totally shuts down the AdLib card | ||
890 | // | ||
891 | /////////////////////////////////////////////////////////////////////////// | ||
892 | static void | ||
893 | SDL_CleanAL(void) | ||
894 | { | ||
895 | #ifdef SOUND_ENABLE | ||
896 | int i; | ||
897 | |||
898 | alOut(alEffects,0); | ||
899 | for (i = 1; i < 0xf5; i++) | ||
900 | alOut(i, 0); | ||
901 | #endif | ||
902 | } | ||
903 | |||
904 | /////////////////////////////////////////////////////////////////////////// | ||
905 | // | ||
906 | // SDL_StartAL() - Starts up the AdLib card for sound effects | ||
907 | // | ||
908 | /////////////////////////////////////////////////////////////////////////// | ||
909 | static void | ||
910 | SDL_StartAL(void) | ||
911 | { | ||
912 | #ifdef SOUND_ENABLE | ||
913 | alOut(alEffects, 0); | ||
914 | SDL_AlSetFXInst(&alZeroInst); | ||
915 | #endif | ||
916 | } | ||
917 | |||
918 | /////////////////////////////////////////////////////////////////////////// | ||
919 | // | ||
920 | // SDL_DetectAdLib() - Determines if there's an AdLib (or SoundBlaster | ||
921 | // emulating an AdLib) present | ||
922 | // | ||
923 | /////////////////////////////////////////////////////////////////////////// | ||
924 | static boolean | ||
925 | SDL_DetectAdLib(void) | ||
926 | { | ||
927 | #ifdef SOUND_ENABLE | ||
928 | for (int i = 1; i <= 0xf5; i++) // Zero all the registers | ||
929 | alOut(i, 0); | ||
930 | |||
931 | alOut(1, 0x20); // Set WSE=1 | ||
932 | // alOut(8, 0); // Set CSM=0 & SEL=0 | ||
933 | |||
934 | return true; | ||
935 | #endif | ||
936 | } | ||
937 | |||
938 | //////////////////////////////////////////////////////////////////////////// | ||
939 | // | ||
940 | // SDL_ShutDevice() - turns off whatever device was being used for sound fx | ||
941 | // | ||
942 | //////////////////////////////////////////////////////////////////////////// | ||
943 | static void | ||
944 | SDL_ShutDevice(void) | ||
945 | { | ||
946 | #ifdef SOUND_ENABLE | ||
947 | switch (SoundMode) | ||
948 | { | ||
949 | case sdm_PC: | ||
950 | // SDL_ShutPC(); | ||
951 | break; | ||
952 | case sdm_AdLib: | ||
953 | SDL_ShutAL(); | ||
954 | break; | ||
955 | } | ||
956 | SoundMode = sdm_Off; | ||
957 | #endif | ||
958 | } | ||
959 | |||
960 | /////////////////////////////////////////////////////////////////////////// | ||
961 | // | ||
962 | // SDL_CleanDevice() - totally shuts down all sound devices | ||
963 | // | ||
964 | /////////////////////////////////////////////////////////////////////////// | ||
965 | static void | ||
966 | SDL_CleanDevice(void) | ||
967 | { | ||
968 | #ifdef SOUND_ENABLE | ||
969 | if ((SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib)) | ||
970 | SDL_CleanAL(); | ||
971 | #endif | ||
972 | } | ||
973 | |||
974 | /////////////////////////////////////////////////////////////////////////// | ||
975 | // | ||
976 | // SDL_StartDevice() - turns on whatever device is to be used for sound fx | ||
977 | // | ||
978 | /////////////////////////////////////////////////////////////////////////// | ||
979 | static void | ||
980 | SDL_StartDevice(void) | ||
981 | { | ||
982 | #ifdef SOUND_ENABLE | ||
983 | switch (SoundMode) | ||
984 | { | ||
985 | case sdm_AdLib: | ||
986 | SDL_StartAL(); | ||
987 | break; | ||
988 | } | ||
989 | SoundNumber = (soundnames) 0; | ||
990 | SoundPriority = 0; | ||
991 | #endif | ||
992 | } | ||
993 | |||
994 | // Public routines | ||
995 | |||
996 | /////////////////////////////////////////////////////////////////////////// | ||
997 | // | ||
998 | // SD_SetSoundMode() - Sets which sound hardware to use for sound effects | ||
999 | // | ||
1000 | /////////////////////////////////////////////////////////////////////////// | ||
1001 | boolean | ||
1002 | SD_SetSoundMode(SDMode mode) | ||
1003 | { | ||
1004 | #ifdef SOUND_ENABLE | ||
1005 | boolean result = false; | ||
1006 | word tableoffset; | ||
1007 | |||
1008 | SD_StopSound(); | ||
1009 | |||
1010 | if ((mode == sdm_AdLib) && !AdLibPresent) | ||
1011 | mode = sdm_PC; | ||
1012 | |||
1013 | switch (mode) | ||
1014 | { | ||
1015 | case sdm_Off: | ||
1016 | tableoffset = STARTADLIBSOUNDS; | ||
1017 | result = true; | ||
1018 | break; | ||
1019 | case sdm_PC: | ||
1020 | tableoffset = STARTPCSOUNDS; | ||
1021 | result = true; | ||
1022 | break; | ||
1023 | case sdm_AdLib: | ||
1024 | tableoffset = STARTADLIBSOUNDS; | ||
1025 | if (AdLibPresent) | ||
1026 | result = true; | ||
1027 | break; | ||
1028 | default: | ||
1029 | Quit("SD_SetSoundMode: Invalid sound mode %i", mode); | ||
1030 | return false; | ||
1031 | } | ||
1032 | SoundTable = &audiosegs[tableoffset]; | ||
1033 | |||
1034 | if (result && (mode != SoundMode)) | ||
1035 | { | ||
1036 | SDL_ShutDevice(); | ||
1037 | SoundMode = mode; | ||
1038 | SDL_StartDevice(); | ||
1039 | } | ||
1040 | |||
1041 | return(result); | ||
1042 | #endif | ||
1043 | return true; | ||
1044 | } | ||
1045 | |||
1046 | /////////////////////////////////////////////////////////////////////////// | ||
1047 | // | ||
1048 | // SD_SetMusicMode() - sets the device to use for background music | ||
1049 | // | ||
1050 | /////////////////////////////////////////////////////////////////////////// | ||
1051 | boolean | ||
1052 | SD_SetMusicMode(SMMode mode) | ||
1053 | { | ||
1054 | #ifdef SOUND_ENABLE | ||
1055 | boolean result = false; | ||
1056 | |||
1057 | SD_FadeOutMusic(); | ||
1058 | while (SD_MusicPlaying()) | ||
1059 | SDL_Delay(5); | ||
1060 | |||
1061 | switch (mode) | ||
1062 | { | ||
1063 | case smm_Off: | ||
1064 | result = true; | ||
1065 | break; | ||
1066 | case smm_AdLib: | ||
1067 | if (AdLibPresent) | ||
1068 | result = true; | ||
1069 | break; | ||
1070 | } | ||
1071 | |||
1072 | if (result) | ||
1073 | MusicMode = mode; | ||
1074 | |||
1075 | // SDL_SetTimerSpeed(); | ||
1076 | |||
1077 | return(result); | ||
1078 | #endif | ||
1079 | } | ||
1080 | |||
1081 | int numreadysamples = 0; | ||
1082 | byte *curAlSound = 0; | ||
1083 | byte *curAlSoundPtr = 0; | ||
1084 | longword curAlLengthLeft = 0; | ||
1085 | int soundTimeCounter = 5; | ||
1086 | int samplesPerMusicTick; | ||
1087 | |||
1088 | void *OPL_ptr = NULL; | ||
1089 | |||
1090 | void SDL_IMFMusicPlayer(void *udata, Uint8 *stream, int len) | ||
1091 | { | ||
1092 | #ifdef SOUND_ENABLE | ||
1093 | int stereolen = len>>1; | ||
1094 | int sampleslen = stereolen>>1; | ||
1095 | INT16 *stream16 = (INT16 *) (void *) stream; // expect correct alignment | ||
1096 | |||
1097 | while(1) | ||
1098 | { | ||
1099 | if(numreadysamples) | ||
1100 | { | ||
1101 | if(numreadysamples<sampleslen) | ||
1102 | { | ||
1103 | YM3812UpdateOne(OPL_ptr, stream16, numreadysamples); | ||
1104 | stream16 += numreadysamples*2; | ||
1105 | sampleslen -= numreadysamples; | ||
1106 | } | ||
1107 | else | ||
1108 | { | ||
1109 | YM3812UpdateOne(OPL_ptr, stream16, sampleslen); | ||
1110 | numreadysamples -= sampleslen; | ||
1111 | return; | ||
1112 | } | ||
1113 | } | ||
1114 | soundTimeCounter--; | ||
1115 | if(!soundTimeCounter) | ||
1116 | { | ||
1117 | soundTimeCounter = 5; | ||
1118 | if(curAlSound != alSound) | ||
1119 | { | ||
1120 | curAlSound = curAlSoundPtr = alSound; | ||
1121 | curAlLengthLeft = alLengthLeft; | ||
1122 | } | ||
1123 | if(curAlSound) | ||
1124 | { | ||
1125 | if(*curAlSoundPtr) | ||
1126 | { | ||
1127 | alOut(alFreqL, *curAlSoundPtr); | ||
1128 | alOut(alFreqH, alBlock); | ||
1129 | } | ||
1130 | else alOut(alFreqH, 0); | ||
1131 | curAlSoundPtr++; | ||
1132 | curAlLengthLeft--; | ||
1133 | if(!curAlLengthLeft) | ||
1134 | { | ||
1135 | curAlSound = alSound = 0; | ||
1136 | SoundNumber = (soundnames) 0; | ||
1137 | SoundPriority = 0; | ||
1138 | alOut(alFreqH, 0); | ||
1139 | } | ||
1140 | } | ||
1141 | } | ||
1142 | if(sqActive) | ||
1143 | { | ||
1144 | do | ||
1145 | { | ||
1146 | if(sqHackTime > alTimeCount) break; | ||
1147 | sqHackTime = alTimeCount + *(sqHackPtr+1); | ||
1148 | alOut(*(byte *) sqHackPtr, *(((byte *) sqHackPtr)+1)); | ||
1149 | sqHackPtr += 2; | ||
1150 | sqHackLen -= 4; | ||
1151 | } | ||
1152 | while(sqHackLen>0); | ||
1153 | alTimeCount++; | ||
1154 | if(!sqHackLen) | ||
1155 | { | ||
1156 | sqHackPtr = sqHack; | ||
1157 | sqHackLen = sqHackSeqLen; | ||
1158 | sqHackTime = 0; | ||
1159 | alTimeCount = 0; | ||
1160 | } | ||
1161 | } | ||
1162 | numreadysamples = samplesPerMusicTick; | ||
1163 | } | ||
1164 | #endif | ||
1165 | } | ||
1166 | |||
1167 | /////////////////////////////////////////////////////////////////////////// | ||
1168 | // | ||
1169 | // SD_Startup() - starts up the Sound Mgr | ||
1170 | // Detects all additional sound hardware and installs my ISR | ||
1171 | // | ||
1172 | /////////////////////////////////////////////////////////////////////////// | ||
1173 | void | ||
1174 | SD_Startup(void) | ||
1175 | { | ||
1176 | #ifdef SOUND_ENABLE | ||
1177 | int i; | ||
1178 | |||
1179 | if (SD_Started) | ||
1180 | return; | ||
1181 | |||
1182 | if(Mix_OpenAudio(param_samplerate, AUDIO_S16, 2, param_audiobuffer)) | ||
1183 | { | ||
1184 | printf("Unable to open audio: %s\n", Mix_GetError()); | ||
1185 | return; | ||
1186 | } | ||
1187 | |||
1188 | Mix_ReserveChannels(2); // reserve player and boss weapon channels | ||
1189 | Mix_GroupChannels(2, MIX_CHANNELS-1, 1); // group remaining channels | ||
1190 | |||
1191 | // Init music | ||
1192 | |||
1193 | samplesPerMusicTick = param_samplerate / 700; // SDL_t0FastAsmService played at 700Hz | ||
1194 | |||
1195 | if(!(OPL_ptr = YM3812Init((void*)1,3579545,param_samplerate))) | ||
1196 | { | ||
1197 | //printf("Unable to create virtual OPL!!\n"); | ||
1198 | } | ||
1199 | |||
1200 | for(i=1;i<0xf6;i++) | ||
1201 | YM3812Write(OPL_ptr,i,0); | ||
1202 | |||
1203 | YM3812Write(OPL_ptr,1,0x20); // Set WSE=1 | ||
1204 | // YM3812Write(0,8,0); // Set CSM=0 & SEL=0 // already set in for statement | ||
1205 | |||
1206 | Mix_HookMusic(SDL_IMFMusicPlayer, 0); | ||
1207 | Mix_ChannelFinished(SD_ChannelFinished); | ||
1208 | AdLibPresent = true; | ||
1209 | SoundBlasterPresent = true; | ||
1210 | |||
1211 | alTimeCount = 0; | ||
1212 | |||
1213 | SD_SetSoundMode(sdm_Off); | ||
1214 | SD_SetMusicMode(smm_Off); | ||
1215 | |||
1216 | SDL_SetupDigi(); | ||
1217 | |||
1218 | SD_Started = true; | ||
1219 | #endif | ||
1220 | } | ||
1221 | |||
1222 | /////////////////////////////////////////////////////////////////////////// | ||
1223 | // | ||
1224 | // SD_Shutdown() - shuts down the Sound Mgr | ||
1225 | // Removes sound ISR and turns off whatever sound hardware was active | ||
1226 | // | ||
1227 | /////////////////////////////////////////////////////////////////////////// | ||
1228 | void | ||
1229 | SD_Shutdown(void) | ||
1230 | { | ||
1231 | #ifdef SOUND_ENABLE | ||
1232 | if (!SD_Started) | ||
1233 | return; | ||
1234 | |||
1235 | SD_MusicOff(); | ||
1236 | SD_StopSound(); | ||
1237 | |||
1238 | for(int i = 0; i < STARTMUSIC - STARTDIGISOUNDS; i++) | ||
1239 | { | ||
1240 | if(SoundChunks[i]) Mix_FreeChunk(SoundChunks[i]); | ||
1241 | if(SoundBuffers[i]) free(SoundBuffers[i]); | ||
1242 | } | ||
1243 | |||
1244 | free(DigiList); | ||
1245 | |||
1246 | SD_Started = false; | ||
1247 | #endif | ||
1248 | } | ||
1249 | |||
1250 | /////////////////////////////////////////////////////////////////////////// | ||
1251 | // | ||
1252 | // SD_PositionSound() - Sets up a stereo imaging location for the next | ||
1253 | // sound to be played. Each channel ranges from 0 to 15. | ||
1254 | // | ||
1255 | /////////////////////////////////////////////////////////////////////////// | ||
1256 | void | ||
1257 | SD_PositionSound(int leftvol,int rightvol) | ||
1258 | { | ||
1259 | #ifdef SOUND_ENABLE | ||
1260 | LeftPosition = leftvol; | ||
1261 | RightPosition = rightvol; | ||
1262 | nextsoundpos = true; | ||
1263 | #endif | ||
1264 | } | ||
1265 | |||
1266 | /////////////////////////////////////////////////////////////////////////// | ||
1267 | // | ||
1268 | // SD_PlaySound() - plays the specified sound on the appropriate hardware | ||
1269 | // | ||
1270 | /////////////////////////////////////////////////////////////////////////// | ||
1271 | boolean | ||
1272 | SD_PlaySound(soundnames sound) | ||
1273 | { | ||
1274 | #ifdef SOUND_ENABLE | ||
1275 | boolean ispos; | ||
1276 | SoundCommon *s; | ||
1277 | int lp,rp; | ||
1278 | |||
1279 | lp = LeftPosition; | ||
1280 | rp = RightPosition; | ||
1281 | LeftPosition = 0; | ||
1282 | RightPosition = 0; | ||
1283 | |||
1284 | ispos = nextsoundpos; | ||
1285 | nextsoundpos = false; | ||
1286 | |||
1287 | if (sound == -1 || (DigiMode == sds_Off && SoundMode == sdm_Off)) | ||
1288 | return 0; | ||
1289 | |||
1290 | s = (SoundCommon *) SoundTable[sound]; | ||
1291 | |||
1292 | if ((SoundMode != sdm_Off) && !s) | ||
1293 | Quit("SD_PlaySound() - Uncached sound"); | ||
1294 | |||
1295 | if ((DigiMode != sds_Off) && (DigiMap[sound] != -1)) | ||
1296 | { | ||
1297 | if ((DigiMode == sds_PC) && (SoundMode == sdm_PC)) | ||
1298 | { | ||
1299 | #ifdef NOTYET | ||
1300 | if (s->priority < SoundPriority) | ||
1301 | return 0; | ||
1302 | |||
1303 | SDL_PCStopSound(); | ||
1304 | |||
1305 | SD_PlayDigitized(DigiMap[sound],lp,rp); | ||
1306 | SoundPositioned = ispos; | ||
1307 | SoundNumber = sound; | ||
1308 | SoundPriority = s->priority; | ||
1309 | #else | ||
1310 | return 0; | ||
1311 | #endif | ||
1312 | } | ||
1313 | else | ||
1314 | { | ||
1315 | #ifdef NOTYET | ||
1316 | if (s->priority < DigiPriority) | ||
1317 | return(false); | ||
1318 | #endif | ||
1319 | |||
1320 | int channel = SD_PlayDigitized(DigiMap[sound], lp, rp); | ||
1321 | SoundPositioned = ispos; | ||
1322 | DigiNumber = sound; | ||
1323 | DigiPriority = s->priority; | ||
1324 | return channel + 1; | ||
1325 | } | ||
1326 | |||
1327 | return(true); | ||
1328 | } | ||
1329 | |||
1330 | if (SoundMode == sdm_Off) | ||
1331 | return 0; | ||
1332 | |||
1333 | if (!s->length) | ||
1334 | Quit("SD_PlaySound() - Zero length sound"); | ||
1335 | if (s->priority < SoundPriority) | ||
1336 | return 0; | ||
1337 | |||
1338 | switch (SoundMode) | ||
1339 | { | ||
1340 | case sdm_PC: | ||
1341 | // SDL_PCPlaySound((PCSound *)s); | ||
1342 | break; | ||
1343 | case sdm_AdLib: | ||
1344 | SDL_ALPlaySound((AdLibSound *)s); | ||
1345 | break; | ||
1346 | } | ||
1347 | |||
1348 | SoundNumber = sound; | ||
1349 | SoundPriority = s->priority; | ||
1350 | |||
1351 | return 0; | ||
1352 | #endif | ||
1353 | return 0; | ||
1354 | } | ||
1355 | |||
1356 | /////////////////////////////////////////////////////////////////////////// | ||
1357 | // | ||
1358 | // SD_SoundPlaying() - returns the sound number that's playing, or 0 if | ||
1359 | // no sound is playing | ||
1360 | // | ||
1361 | /////////////////////////////////////////////////////////////////////////// | ||
1362 | word | ||
1363 | SD_SoundPlaying(void) | ||
1364 | { | ||
1365 | #ifdef SOUND_ENABLE | ||
1366 | boolean result = false; | ||
1367 | |||
1368 | switch (SoundMode) | ||
1369 | { | ||
1370 | case sdm_PC: | ||
1371 | result = pcSound? true : false; | ||
1372 | break; | ||
1373 | case sdm_AdLib: | ||
1374 | result = alSound? true : false; | ||
1375 | break; | ||
1376 | } | ||
1377 | |||
1378 | if (result) | ||
1379 | return(SoundNumber); | ||
1380 | else | ||
1381 | return(false); | ||
1382 | #endif | ||
1383 | return false; | ||
1384 | } | ||
1385 | |||
1386 | /////////////////////////////////////////////////////////////////////////// | ||
1387 | // | ||
1388 | // SD_StopSound() - if a sound is playing, stops it | ||
1389 | // | ||
1390 | /////////////////////////////////////////////////////////////////////////// | ||
1391 | void | ||
1392 | SD_StopSound(void) | ||
1393 | { | ||
1394 | #ifdef SOUND_ENABLE | ||
1395 | if (DigiPlaying) | ||
1396 | SD_StopDigitized(); | ||
1397 | |||
1398 | switch (SoundMode) | ||
1399 | { | ||
1400 | case sdm_PC: | ||
1401 | // SDL_PCStopSound(); | ||
1402 | break; | ||
1403 | case sdm_AdLib: | ||
1404 | SDL_ALStopSound(); | ||
1405 | break; | ||
1406 | } | ||
1407 | |||
1408 | SoundPositioned = false; | ||
1409 | |||
1410 | SDL_SoundFinished(); | ||
1411 | #endif | ||
1412 | } | ||
1413 | |||
1414 | /////////////////////////////////////////////////////////////////////////// | ||
1415 | // | ||
1416 | // SD_WaitSoundDone() - waits until the current sound is done playing | ||
1417 | // | ||
1418 | /////////////////////////////////////////////////////////////////////////// | ||
1419 | void | ||
1420 | SD_WaitSoundDone(void) | ||
1421 | { | ||
1422 | #ifdef SOUND_ENABLE | ||
1423 | while (SD_SoundPlaying()) | ||
1424 | SDL_Delay(5); | ||
1425 | #endif | ||
1426 | } | ||
1427 | |||
1428 | /////////////////////////////////////////////////////////////////////////// | ||
1429 | // | ||
1430 | // SD_MusicOn() - turns on the sequencer | ||
1431 | // | ||
1432 | /////////////////////////////////////////////////////////////////////////// | ||
1433 | void | ||
1434 | SD_MusicOn(void) | ||
1435 | { | ||
1436 | #ifdef SOUND_ENABLE | ||
1437 | sqActive = true; | ||
1438 | #endif | ||
1439 | } | ||
1440 | |||
1441 | /////////////////////////////////////////////////////////////////////////// | ||
1442 | // | ||
1443 | // SD_MusicOff() - turns off the sequencer and any playing notes | ||
1444 | // returns the last music offset for music continue | ||
1445 | // | ||
1446 | /////////////////////////////////////////////////////////////////////////// | ||
1447 | int | ||
1448 | SD_MusicOff(void) | ||
1449 | { | ||
1450 | #ifdef SOUND_ENABLE | ||
1451 | word i; | ||
1452 | |||
1453 | sqActive = false; | ||
1454 | switch (MusicMode) | ||
1455 | { | ||
1456 | case smm_AdLib: | ||
1457 | alOut(alEffects, 0); | ||
1458 | for (i = 0;i < sqMaxTracks;i++) | ||
1459 | alOut(alFreqH + i + 1, 0); | ||
1460 | break; | ||
1461 | } | ||
1462 | |||
1463 | return (int) (sqHackPtr-sqHack); | ||
1464 | #endif | ||
1465 | } | ||
1466 | |||
1467 | /////////////////////////////////////////////////////////////////////////// | ||
1468 | // | ||
1469 | // SD_StartMusic() - starts playing the music pointed to | ||
1470 | // | ||
1471 | /////////////////////////////////////////////////////////////////////////// | ||
1472 | void | ||
1473 | SD_StartMusic(int chunk) | ||
1474 | { | ||
1475 | #ifdef SOUND_ENABLE | ||
1476 | SD_MusicOff(); | ||
1477 | |||
1478 | if (MusicMode == smm_AdLib) | ||
1479 | { | ||
1480 | int32_t chunkLen = CA_CacheAudioChunk(chunk); | ||
1481 | sqHack = (word *)(void *) audiosegs[chunk]; // alignment is correct | ||
1482 | if(*sqHack == 0) sqHackLen = sqHackSeqLen = chunkLen; | ||
1483 | else sqHackLen = sqHackSeqLen = *sqHack++; | ||
1484 | sqHackPtr = sqHack; | ||
1485 | sqHackTime = 0; | ||
1486 | alTimeCount = 0; | ||
1487 | SD_MusicOn(); | ||
1488 | } | ||
1489 | #endif | ||
1490 | } | ||
1491 | |||
1492 | void | ||
1493 | SD_ContinueMusic(int chunk, int startoffs) | ||
1494 | { | ||
1495 | #ifdef SOUND_ENABLE | ||
1496 | SD_MusicOff(); | ||
1497 | |||
1498 | if (MusicMode == smm_AdLib) | ||
1499 | { | ||
1500 | int32_t chunkLen = CA_CacheAudioChunk(chunk); | ||
1501 | sqHack = (word *)(void *) audiosegs[chunk]; // alignment is correct | ||
1502 | if(*sqHack == 0) sqHackLen = sqHackSeqLen = chunkLen; | ||
1503 | else sqHackLen = sqHackSeqLen = *sqHack++; | ||
1504 | sqHackPtr = sqHack; | ||
1505 | |||
1506 | if(startoffs >= sqHackLen) | ||
1507 | { | ||
1508 | Quit("SD_StartMusic: Illegal startoffs provided!"); | ||
1509 | } | ||
1510 | |||
1511 | // fast forward to correct position | ||
1512 | // (needed to reconstruct the instruments) | ||
1513 | |||
1514 | for(int i = 0; i < startoffs; i += 2) | ||
1515 | { | ||
1516 | byte reg = *(byte *)sqHackPtr; | ||
1517 | byte val = *(((byte *)sqHackPtr) + 1); | ||
1518 | if(reg >= 0xb1 && reg <= 0xb8) val &= 0xdf; // disable play note flag | ||
1519 | else if(reg == 0xbd) val &= 0xe0; // disable drum flags | ||
1520 | |||
1521 | alOut(reg,val); | ||
1522 | sqHackPtr += 2; | ||
1523 | sqHackLen -= 4; | ||
1524 | } | ||
1525 | sqHackTime = 0; | ||
1526 | alTimeCount = 0; | ||
1527 | |||
1528 | SD_MusicOn(); | ||
1529 | } | ||
1530 | #endif | ||
1531 | } | ||
1532 | |||
1533 | /////////////////////////////////////////////////////////////////////////// | ||
1534 | // | ||
1535 | // SD_FadeOutMusic() - starts fading out the music. Call SD_MusicPlaying() | ||
1536 | // to see if the fadeout is complete | ||
1537 | // | ||
1538 | /////////////////////////////////////////////////////////////////////////// | ||
1539 | void | ||
1540 | SD_FadeOutMusic(void) | ||
1541 | { | ||
1542 | #ifdef SOUND_ENABLE | ||
1543 | switch (MusicMode) | ||
1544 | { | ||
1545 | case smm_AdLib: | ||
1546 | // DEBUG - quick hack to turn the music off | ||
1547 | SD_MusicOff(); | ||
1548 | break; | ||
1549 | } | ||
1550 | #endif | ||
1551 | } | ||
1552 | |||
1553 | /////////////////////////////////////////////////////////////////////////// | ||
1554 | // | ||
1555 | // SD_MusicPlaying() - returns true if music is currently playing, false if | ||
1556 | // not | ||
1557 | // | ||
1558 | /////////////////////////////////////////////////////////////////////////// | ||
1559 | boolean | ||
1560 | SD_MusicPlaying(void) | ||
1561 | { | ||
1562 | #ifdef SOUND_ENABLE | ||
1563 | boolean result; | ||
1564 | |||
1565 | switch (MusicMode) | ||
1566 | { | ||
1567 | case smm_AdLib: | ||
1568 | result = sqActive; | ||
1569 | break; | ||
1570 | default: | ||
1571 | result = false; | ||
1572 | break; | ||
1573 | } | ||
1574 | |||
1575 | return(result); | ||
1576 | #endif | ||
1577 | return false; | ||
1578 | } | ||