1 /*
2  *
3  *   Copyright (c) 1994, 2002, 2003  Johannes Prix
4  *   Copyright (c) 1994, 2002, 2003  Reinhard Prix
5  *
6  *
7  *  This file is part of Freedroid
8  *
9  *  Freedroid is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  Freedroid is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with Freedroid; see the file COPYING. If not, write to the
21  *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22  *  MA  02111-1307  USA
23  *
24  */
25 
26 /*----------------------------------------------------------------------
27  *
28  * Desc:  all functions dealing with sound are contained in this file.
29  *
30  *----------------------------------------------------------------------*/
31 
32 #ifndef _sound_c
33 #define _sound_c
34 #endif
35 
36 #include "system.h"
37 
38 #include "defs.h"
39 #include "struct.h"
40 #include "global.h"
41 #include "proto.h"
42 
43 // The following is the definition of the sound file names used in freedroid
44 // DO NOT CHANGE THE ORDER OF APPEARENCE IN THIS LIST unless you
45 // also adjust the order of appearance in defs.h!
46 
47 char *SoundSampleFilenames[ALL_SOUNDS] = {
48    "ERRORSOUND_NILL.NOWAV",
49    "Blast_Sound_0.wav",
50    "Collision_Sound_0.wav",
51    "GotIntoBlast_Sound_0.wav",
52    "MoveElevator_Sound_0.wav",
53    "Refresh_Sound_0.wav",
54    "LeaveElevator_Sound_0.wav",
55    "EnterElevator_Sound_0.wav",
56    "ThouArtDefeated_Sound_0.wav",
57    "Got_Hit_Sound_0.wav",
58    "TakeoverSetCapsule_Sound_0.wav",
59    "Menu_Item_Selected_Sound_0.wav",
60    "Move_Menu_Position_Sound_0.wav",
61    "Takeover_Game_Won_Sound_0.wav",
62    "Takeover_Game_Deadlock_Sound_0.wav",
63    "Takeover_Game_Lost_Sound_0.wav",
64    "Fire_Bullet_Pulse_Sound_0.wav",
65    "Fire_Bullet_Single_Pulse_Sound_0.wav",
66    "Fire_Bullet_Military_Sound_0.wav",
67    "Fire_Bullet_Flash_Sound_0.wav",
68    "Fire_Bullet_Exterminator_Sound_0.wav",
69    "Fire_Bullet_Laser_Rifle_Sound.wav",
70    "Cry_Sound_0.wav",
71    "Takeover_Sound_0.wav",
72    "Countdown_Sound.wav",
73    "EndCountdown_Sound.wav",
74    "InfluExplosion.wav",
75    "WhiteNoise.wav",
76    "Alert.wav"
77 };
78 
79 #ifdef HAVE_LIBSDL_MIXER
80 Mix_Chunk *Loaded_WAV_Files[ALL_SOUNDS];
81 #endif
82 
83 char *MusicFiles [NUM_COLORS] = {  // we have a background song per color now
84   "AnarchyMenu1.mod",                 // RED
85   "starpaws.mod",                     // YELLOW
86   "The_Last_V8.mod",                  // GREEN
87   "dreamfish-green_beret.mod",        // GRAY
88   "dreamfish-sanxion.mod",            // BLUE
89   "kollaps-tron.mod",                 // GREENBLUE
90   "dreamfish-uridium2_loader.mod"     // DARK
91 };
92 
93 #ifdef HAVE_LIBSDL_MIXER
94 Mix_Music *MusicSongs[NUM_COLORS];
95 Mix_Music *Tmp_MOD_File;
96 #endif
97 
98 void
Init_Audio(void)99 Init_Audio(void)
100 {
101 #ifndef HAVE_LIBSDL_MIXER
102   return;
103 #else
104   char *fpath;
105   int i;
106   int audio_rate = 22050;
107   Uint16 audio_format = AUDIO_S16;
108   int audio_channels = 2;
109   //  int audio_buffers = 4096;
110   int audio_buffers = 2048;
111 
112   DebugPrintf(1, "\nInitializing SDL Audio Systems....\n");
113 
114   if ( !sound_on ) return;
115 
116 
117   // Now SDL_AUDIO is initialized here:
118 
119   if ( SDL_InitSubSystem ( SDL_INIT_AUDIO ) == -1 )
120     {
121       DebugPrintf (0, "WARNING: SDL Sound subsystem could not be initialized.\n\
122 Continuing with sound disabled\n");
123       sound_on = FALSE;
124       return;
125     }
126   else
127     DebugPrintf(1, "SDL Audio initialisation successful.\n");
128 
129   // Now that we have initialized the audio SubSystem, we must open
130   // an audio channel.  This will be done here (see code from Mixer-Tutorial):
131 
132   if ( Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers) )
133     {
134       DebugPrintf (0, "WARNING: SDL audio channel could not be opened. \n");
135       DebugPrintf (0, "SDL Mixer Error: %s\nContinuing with sound disabled\n", Mix_GetError());
136       sound_on = FALSE;
137       return;
138     }
139   else
140     DebugPrintf (1, "\nSuccessfully opened SDL audio channel." );
141 
142   if (Mix_AllocateChannels(20) != 20)
143     DebugPrintf (0, "\nWARNING: could not get all 20 mixer-channels I asked for...\n");
144 
145   // Now that the audio channel is opend, its time to load all the
146   // WAV files into memory, something we NEVER did while using the yiff,
147   // because the yiff did all the loading, analyzing and playing...
148 
149   Loaded_WAV_Files[0]=NULL;
150   for (i = 1; i < ALL_SOUNDS; i++)
151     {
152       fpath = find_file (SoundSampleFilenames[ i ], SOUND_DIR, NO_THEME, WARNONLY);
153       if (fpath) Loaded_WAV_Files[ i ] = Mix_LoadWAV(fpath);
154       if ( Loaded_WAV_Files[i] == NULL )
155 	{
156 	  DebugPrintf (0, "Error: could not load Sound-sample: %s", SoundSampleFilenames[ i ]);
157 	  DebugPrintf (0, "SDL Mixer Error: %s\n Continuing with sound disabled\n", Mix_GetError());
158 	  sound_on = FALSE;
159 	  return;
160 	} // if ( !Loaded_WAV...
161       else
162 	DebugPrintf (1, "\nSuccessfully loaded file %s.", SoundSampleFilenames[i]);
163     } // for (i=1; ...
164 
165   for (i = 0; i < NUM_COLORS; i++)
166     {
167       fpath = find_file ( MusicFiles [ i ], SOUND_DIR, NO_THEME, WARNONLY);
168       if (fpath) MusicSongs [ i ] = Mix_LoadMUS( fpath );
169       if ( MusicSongs[ i ] == NULL )
170 	{
171 	  DebugPrintf ( 0, "\nError loading sound-file: %s\n", MusicFiles[ i ]);
172 	  DebugPrintf (0, "SDL Mixer Error: %s\n Continuing with sound disabled\n", Mix_GetError());
173 	  sound_on = FALSE;
174 	  return;
175 	} // if ( !Loaded_WAV...
176       else
177 	DebugPrintf ( 1 , "\nSuccessfully loaded file %s.", MusicFiles[ i ]);
178     } // for
179 
180 
181   //--------------------
182   // Now that the music files have been loaded successfully, it's time to set
183   // the music and sound volumes accoridingly, i.e. as specifies by the users
184   // configuration.
185   //
186   Set_Sound_FX_Volume( GameConfig.Current_Sound_FX_Volume );
187 
188   // DebugPrintf (1, "done.");
189   // fflush(stdout);
190 #endif // HAVE_SDL_MIXER
191 } // void InitAudio(void)
192 
193 void
Set_BG_Music_Volume(float NewVolume)194 Set_BG_Music_Volume(float NewVolume)
195 {
196 
197 #ifndef HAVE_LIBSDL_MIXER
198   return;
199 #else
200   if ( !sound_on ) return;
201 
202   Mix_VolumeMusic( (int) rintf( NewVolume * MIX_MAX_VOLUME ) );
203 
204 #endif // HAVE_LIBSDL_MIXER
205 } // void Set_BG_Music_Volume(float NewVolume)
206 
207 void
Set_Sound_FX_Volume(float NewVolume)208 Set_Sound_FX_Volume(float NewVolume)
209 {
210   int i;
211 #ifndef HAVE_LIBSDL_MIXER
212   return;
213 #else
214   if ( !sound_on ) return;
215 
216   // Set the volume IN the loaded files, if SDL is used...
217   // This is done here for the Files 1,2,3 and 4, since these
218   // are background music files.
219   for ( i=5 ; i<ALL_SOUNDS ; i++ )
220     {
221       Mix_VolumeChunk( Loaded_WAV_Files[i], (int) rintf(NewVolume* MIX_MAX_VOLUME) );
222     }
223 
224 #endif // HAVE_LIBSDL_MIXER
225 
226 } // void Set_BG_Music_Volume(float NewVolume)
227 
228 
229 void
CountdownSound(void)230 CountdownSound (void)
231 {
232   Play_Sound (COUNTDOWN_SOUND);
233 }
234 
235 void
EndCountdownSound(void)236 EndCountdownSound (void)
237 {
238   Play_Sound (ENDCOUNTDOWN_SOUND);
239 }
240 
241 /*@Function============================================================
242 @Desc: Starts a Tune.
243 
244 @Ret:
245 @Int:
246 * $Function----------------------------------------------------------*/
247 void
StartSound(int Tune)248 StartSound (int Tune)
249 {
250 
251 } /* void StartSound(int Tune) */
252 
253 /*@Function============================================================
254 @Desc:
255 
256 @Ret:
257 @Int:
258 * $Function----------------------------------------------------------*/
259 void
CrySound(void)260 CrySound (void)
261 {
262   Play_Sound ( CRY_SOUND );
263 }
264 
265 /*@Function============================================================
266 @Desc:
267 
268 @Ret:
269 @Int:
270 * $Function----------------------------------------------------------*/
271 void
TransferSound(void)272 TransferSound (void)
273 {
274   Play_Sound ( TRANSFER_SOUND );
275 }
276 
277 /*@Function============================================================
278 @Desc:
279 
280 This function is intended to provide a convenient way of switching
281 between different backround sounds in freedroid.
282 If no background sound was yet running, the function should start playing
283 the given background music.
284 If some background sound was already playing, the function should shut down
285 the old background music and start playing the new one.
286 
287 Technical details:
288 
289 
290 
291 @Ret:
292 @Int:
293 * $Function----------------------------------------------------------*/
294 void
Switch_Background_Music_To(char * filename_raw)295 Switch_Background_Music_To ( char* filename_raw )
296 {
297   char* fpath;
298   static int prev_color = -1;
299   static bool paused = FALSE;
300 
301 #ifndef HAVE_LIBSDL_MIXER
302   return;
303 #else
304 
305   if ( !sound_on ) return;
306 
307   if ( filename_raw == NULL )
308     {
309       Mix_PauseMusic(); // pause currently played background music
310       paused = TRUE;
311       return;
312     }
313 
314   // rp: lets cheat when using Mingw32
315 #if (!defined __WIN32__  && !defined HAVE_LIBVORBIS)
316   if (strstr (filename_raw, ".ogg"))
317     {
318       DebugPrintf (1, "\n\nWARNING: no ogg vorbis libs were found when configuring,\n\
319  can't play %s!\n", filename_raw);
320       return;
321     }
322 
323 #endif
324 
325   // New feature: choose background music by level-color:
326   // if filename_raw==BYCOLOR then chose bg_music[color]
327   // NOTE: if new level-color is the same as before, just resume paused music!
328   if (!strcmp( filename_raw, BYCOLOR))
329     {
330       if (paused && (prev_color == CurLevel->color) )  // current level-song was just paused
331 	{
332 	  Mix_ResumeMusic ();
333 	  paused = FALSE;
334 	}
335       else
336 	{
337 	  Mix_PlayMusic (MusicSongs[CurLevel->color], -1);
338 	  paused = FALSE;
339 	  prev_color = CurLevel->color;
340 	}
341     }
342   else  // not using BYCOLOR mechanism: just play specified song
343     {
344       if (Tmp_MOD_File) Mix_FreeMusic(Tmp_MOD_File);
345       fpath = find_file (filename_raw, SOUND_DIR, NO_THEME, WARNONLY);
346       if (fpath) Tmp_MOD_File = Mix_LoadMUS (fpath);
347       if ( Tmp_MOD_File == NULL )
348 	{
349 	  DebugPrintf (0, "\nError loading sound-file: %s\n", filename_raw);
350 	  DebugPrintf (0, "SDL Mixer Error: %s\n Continuing with sound disabled\n", Mix_GetError());
351 	  sound_on = FALSE;
352 	  return;
353 	} // if ( !Loaded_WAV...
354       Mix_PlayMusic (Tmp_MOD_File, -1);
355     }
356 
357   Mix_VolumeMusic ( (int) rintf( GameConfig.Current_BG_Music_Volume * MIX_MAX_VOLUME ) );
358 
359 #endif // HAVE_LIBSDL_MIXER
360 
361 }; // void Switch_Background_Music_To(int Tune)
362 
363 
364 /*@Function============================================================
365 @Desc:
366 
367 @Ret:
368 @Int:
369 * $Function----------------------------------------------------------*/
370 void
Play_Sound(int Tune)371 Play_Sound (int Tune)
372 {
373 #ifndef HAVE_LIBSDL_MIXER
374   return;
375 #else
376   int Newest_Sound_Channel=0;
377 
378   if ( !sound_on ) return;
379 
380   Newest_Sound_Channel = Mix_PlayChannel(-1, Loaded_WAV_Files[Tune] , 0);
381   if ( Newest_Sound_Channel == -1 )
382     {
383       DebugPrintf (0, "WARNING: Could not play sound-sample: %s Error: %s\n\
384 This usually just means that too many samples where played at the same time\n",
385 		   SoundSampleFilenames[ Tune ] , Mix_GetError() );
386     } // if ( ... = -1
387   else
388     DebugPrintf( 2 , "\nSuccessfully playing file %s.", SoundSampleFilenames[ Tune ]);
389 
390 #endif // HAVE_LIBSDL_MIXER
391 
392 }  // void Play_Sound(int Tune)
393 
394 /*@Function============================================================
395 @Desc:
396 
397 @Ret:
398 @Int:
399 * $Function----------------------------------------------------------*/
400 void
GotHitSound(void)401 GotHitSound (void)
402 {
403   if (!sound_on) return;
404 
405   Play_Sound (GOT_HIT_SOUND);
406 }				// void GotHitSound(void)
407 
408 
409 /*@Function============================================================
410 @Desc:
411 
412 @Ret:
413 @Int:
414 * $Function----------------------------------------------------------*/
415 void
GotIntoBlastSound(void)416 GotIntoBlastSound (void)
417 {
418   if (!sound_on) return;
419 
420   Play_Sound (GOT_INTO_BLAST_SOUND);
421   return;
422 }				// void GotIntoBlastSound(void)
423 
424 /*@Function============================================================
425 @Desc:
426 
427 @Ret:
428 @Int:
429 * $Function----------------------------------------------------------*/
430 void
RefreshSound(void)431 RefreshSound (void)
432 {
433   if (!sound_on) return;
434 
435   Play_Sound (REFRESH_SOUND);
436   return;
437 }				// void RefreshSound(void)
438 
439 
440 /*@Function============================================================
441 @Desc:
442 
443 @Ret:
444 @Int:
445 * $Function----------------------------------------------------------*/
446 void
MoveLiftSound(void)447 MoveLiftSound (void)
448 {
449   if (!sound_on) return;
450 
451   Play_Sound (MOVE_ELEVATOR_SOUND);
452 }				// void MoveLiftSound(void)
453 
454 /*@Function============================================================
455 @Desc:
456 
457 @Ret:
458 @Int:
459 * $Function----------------------------------------------------------*/
460 void
MenuItemSelectedSound(void)461 MenuItemSelectedSound (void)
462 {
463   if (!sound_on) return;
464 
465   Play_Sound (MENU_ITEM_SELECTED_SOUND);
466 }				// void MoveLiftSound(void)
467 
468 /*@Function============================================================
469 @Desc:
470 
471 @Ret:
472 @Int:
473 * $Function----------------------------------------------------------*/
474 void
MoveMenuPositionSound(void)475 MoveMenuPositionSound (void)
476 {
477   if (!sound_on) return;
478 
479   Play_Sound (MOVE_MENU_POSITION_SOUND);
480 }				// void MoveLiftSound(void)
481 
482 
483 /*@Function============================================================
484 @Desc:
485 
486 @Ret:
487 @Int:
488 * $Function----------------------------------------------------------*/
489 void
ThouArtDefeatedSound(void)490 ThouArtDefeatedSound (void)
491 {
492   if (!sound_on) return;
493   Play_Sound (THOU_ART_DEFEATED_SOUND);
494 }				// void MoveLiftSound(void)
495 
496 
497 /*@Function============================================================
498 @Desc:
499 
500 @Ret:
501 @Int:
502 * $Function----------------------------------------------------------*/
503 void
EnterLiftSound(void)504 EnterLiftSound (void)
505 {
506   if (!sound_on) return;
507 
508   Play_Sound (ENTER_ELEVATOR_SOUND);
509   return;
510 }				// void EnterLiftSound(void)
511 
512 
513 /*@Function============================================================
514 @Desc:
515 
516 @Ret:
517 @Int:
518 * $Function----------------------------------------------------------*/
519 void
LeaveLiftSound(void)520 LeaveLiftSound (void)
521 {
522   if (!sound_on) return;
523 
524   Play_Sound (LEAVE_ELEVATOR_SOUND);
525 
526   return;
527 }				// void LeaveLiftSound(void)
528 
529 
530 /*@Function============================================================
531 @Desc:
532 
533 @Ret:
534 @Int:
535 * $Function----------------------------------------------------------*/
536 void
Fire_Bullet_Sound(int BulletType)537 Fire_Bullet_Sound (int BulletType)
538 {
539   if (!sound_on) return;
540 
541   switch (BulletType)
542     {
543       case PULSE:
544 	Play_Sound ( FIRE_BULLET_PULSE_SOUND );
545 	break;
546 
547       case SINGLE_PULSE:
548 	Play_Sound ( FIRE_BULLET_SINGLE_PULSE_SOUND );
549 	break;
550 
551       case MILITARY:
552 	Play_Sound ( FIRE_BULLET_MILITARY_SOUND );
553 	break;
554 
555       case FLASH:
556 	Play_Sound ( FIRE_BULLET_FLASH_SOUND );
557 	break;
558 
559       case EXTERMINATOR:
560 	Play_Sound ( FIRE_BULLET_EXTERMINATOR_SOUND );
561 	break;
562 
563       case LASER_RIFLE:
564 	Play_Sound ( FIRE_BULLET_LASER_RIFLE_SOUND );
565 	break;
566 
567     }
568 }				// void FireBulletSound(void)
569 
570 
571 /*@Function============================================================
572 @Desc:
573 
574 @Ret:
575 @Int:
576 * $Function----------------------------------------------------------*/
577 void
Takeover_Set_Capsule_Sound(void)578 Takeover_Set_Capsule_Sound (void)
579 {
580   if (!sound_on) return;
581 
582   Play_Sound (TAKEOVER_SET_CAPSULE_SOUND);
583 }				// void FireBulletSound(void)
584 
585 /*@Function============================================================
586 @Desc:
587 
588 @Ret:
589 @Int:
590 * $Function----------------------------------------------------------*/
591 void
Takeover_Game_Won_Sound(void)592 Takeover_Game_Won_Sound (void)
593 {
594   if (!sound_on) return;
595 
596   Play_Sound ( TAKEOVER_GAME_WON_SOUND );
597 }				// void FireBulletSound(void)
598 
599 /*@Function============================================================
600 @Desc:
601 
602 @Ret:
603 @Int:
604 * $Function----------------------------------------------------------*/
605 void
Takeover_Game_Deadlock_Sound(void)606 Takeover_Game_Deadlock_Sound (void)
607 {
608   if (!sound_on) return;
609 
610   Play_Sound ( TAKEOVER_GAME_DEADLOCK_SOUND );
611 }				// void FireBulletSound(void)
612 
613 /*@Function============================================================
614 @Desc:
615 
616 @Ret:
617 @Int:
618 * $Function----------------------------------------------------------*/
619 void
Takeover_Game_Lost_Sound(void)620 Takeover_Game_Lost_Sound (void)
621 {
622   if (!sound_on) return;
623 
624   Play_Sound ( TAKEOVER_GAME_LOST_SOUND );
625 }				// void FireBulletSound(void)
626 
627 
628 /*@Function============================================================
629 @Desc:
630 
631 @Ret:
632 @Int:
633 * $Function----------------------------------------------------------*/
634 void
BounceSound(void)635 BounceSound (void)
636 {
637   if (!sound_on) return;
638 
639   // Play_Sound (COMBAT_BACKGROUND_MUSIC_SOUND );
640   Play_Sound ( COLLISIONSOUND );
641 
642 }				// void BounceSound(void)
643 
644 /*@Function============================================================
645 @Desc:
646 
647 @Ret:
648 @Int:
649 * $Function----------------------------------------------------------*/
650 void
DruidBlastSound(void)651 DruidBlastSound (void)
652 {
653   if (!sound_on) return;
654 
655   Play_Sound (BLASTSOUND);
656 
657 }				// void BounceSound(void)
658 
659 
660 #undef _sound_c
661