hedgewars/uSound.pas
branchwebgl
changeset 8330 aaefa587e277
parent 8096 453917e94e55
parent 8231 a41d84553ae8
child 8444 75db7bb8dce8
equal deleted inserted replaced
8116:d24257910f8d 8330:aaefa587e277
    19 {$INCLUDE "options.inc"}
    19 {$INCLUDE "options.inc"}
    20 
    20 
    21 unit uSound;
    21 unit uSound;
    22 (*
    22 (*
    23  * This unit controls the sounds and music of the game.
    23  * This unit controls the sounds and music of the game.
    24  * Doesn't really do anything if isSoundEnabled = false.
    24  * Doesn't really do anything if isSoundEnabled = false and isMusicEnabled = false
    25  *
    25  *
    26  * There are three basic types of sound controls:
    26  * There are three basic types of sound controls:
    27  *    Music        - The background music of the game:
    27  *    Music        - The background music of the game:
    28  *                   * will only be played if isMusicEnabled = true
    28  *                   * will only be played if isMusicEnabled = true
    29  *                   * can be started, changed, paused and resumed
    29  *                   * can be started, changed, paused and resumed
   118     Mus: PMixMusic; // music pointer
   118     Mus: PMixMusic; // music pointer
   119     MusicFN: shortstring; // music file name
   119     MusicFN: shortstring; // music file name
   120     isMusicEnabled: boolean;
   120     isMusicEnabled: boolean;
   121     isSoundEnabled: boolean;
   121     isSoundEnabled: boolean;
   122     isSEBackup: boolean;
   122     isSEBackup: boolean;
       
   123     VoiceList : array[0..7] of TVoice =  (
       
   124                     ( snd: sndNone; voicepack: nil),
       
   125                     ( snd: sndNone; voicepack: nil),
       
   126                     ( snd: sndNone; voicepack: nil),
       
   127                     ( snd: sndNone; voicepack: nil),
       
   128                     ( snd: sndNone; voicepack: nil),
       
   129                     ( snd: sndNone; voicepack: nil),
       
   130                     ( snd: sndNone; voicepack: nil),
       
   131                     ( snd: sndNone; voicepack: nil));
       
   132     Soundz: array[TSound] of record
       
   133             FileName: string[31];
       
   134             Path    : TPathType;
       
   135             end = (
       
   136             (FileName:                         ''; Path: ptNone  ),// sndNone
       
   137             (FileName:        'grenadeimpact.ogg'; Path: ptSounds),// sndGrenadeImpact
       
   138             (FileName:            'explosion.ogg'; Path: ptSounds),// sndExplosion
       
   139             (FileName:         'throwpowerup.ogg'; Path: ptSounds),// sndThrowPowerUp
       
   140             (FileName:         'throwrelease.ogg'; Path: ptSounds),// sndThrowRelease
       
   141             (FileName:               'splash.ogg'; Path: ptSounds),// sndSplash
       
   142             (FileName:        'shotgunreload.ogg'; Path: ptSounds),// sndShotgunReload
       
   143             (FileName:          'shotgunfire.ogg'; Path: ptSounds),// sndShotgunFire
       
   144             (FileName:          'graveimpact.ogg'; Path: ptSounds),// sndGraveImpact
       
   145             (FileName:           'mineimpact.ogg'; Path: ptSounds),// sndMineImpact
       
   146             (FileName:             'minetick.ogg'; Path: ptSounds),// sndMineTicks
       
   147             (FileName:             'Droplet1.ogg'; Path: ptSounds),// sndMudballImpact
       
   148             (FileName:           'pickhammer.ogg'; Path: ptSounds),// sndPickhammer
       
   149             (FileName:                  'gun.ogg'; Path: ptSounds),// sndGun
       
   150             (FileName:                  'bee.ogg'; Path: ptSounds),// sndBee
       
   151             (FileName:                'Jump1.ogg'; Path: ptVoices),// sndJump1
       
   152             (FileName:                'Jump2.ogg'; Path: ptVoices),// sndJump2
       
   153             (FileName:                'Jump3.ogg'; Path: ptVoices),// sndJump3
       
   154             (FileName:               'Yessir.ogg'; Path: ptVoices),// sndYesSir
       
   155             (FileName:                'Laugh.ogg'; Path: ptVoices),// sndLaugh
       
   156             (FileName:            'Illgetyou.ogg'; Path: ptVoices),// sndIllGetYou
       
   157             (FileName:          'JustYouWait.ogg'; Path: ptVoices),// sndJustYouWait
       
   158             (FileName:             'Incoming.ogg'; Path: ptVoices),// sndIncoming
       
   159             (FileName:               'Missed.ogg'; Path: ptVoices),// sndMissed
       
   160             (FileName:               'Stupid.ogg'; Path: ptVoices),// sndStupid
       
   161             (FileName:           'Firstblood.ogg'; Path: ptVoices),// sndFirstBlood
       
   162             (FileName:               'Boring.ogg'; Path: ptVoices),// sndBoring
       
   163             (FileName:               'Byebye.ogg'; Path: ptVoices),// sndByeBye
       
   164             (FileName:             'Sameteam.ogg'; Path: ptVoices),// sndSameTeam
       
   165             (FileName:               'Nutter.ogg'; Path: ptVoices),// sndNutter
       
   166             (FileName:       'Reinforcements.ogg'; Path: ptVoices),// sndReinforce
       
   167             (FileName:              'Traitor.ogg'; Path: ptVoices),// sndTraitor
       
   168             (FileName:      'Youllregretthat.ogg'; Path: ptVoices),// sndRegret
       
   169             (FileName:            'Enemydown.ogg'; Path: ptVoices),// sndEnemyDown
       
   170             (FileName:               'Coward.ogg'; Path: ptVoices),// sndCoward
       
   171             (FileName:                'Hurry.ogg'; Path: ptVoices),// sndHurry
       
   172             (FileName:              'Watchit.ogg'; Path: ptVoices),// sndWatchIt
       
   173             (FileName:             'Kamikaze.ogg'; Path: ptVoices),// sndKamikaze
       
   174             (FileName:                'cake2.ogg'; Path: ptSounds),// sndCake
       
   175             (FileName:                  'Ow1.ogg'; Path: ptVoices),// sndOw1
       
   176             (FileName:                  'Ow2.ogg'; Path: ptVoices),// sndOw2
       
   177             (FileName:                  'Ow3.ogg'; Path: ptVoices),// sndOw3
       
   178             (FileName:                  'Ow4.ogg'; Path: ptVoices),// sndOw4
       
   179             (FileName:           'Firepunch1.ogg'; Path: ptVoices),// sndFirepunch1
       
   180             (FileName:           'Firepunch2.ogg'; Path: ptVoices),// sndFirepunch2
       
   181             (FileName:           'Firepunch3.ogg'; Path: ptVoices),// sndFirepunch3
       
   182             (FileName:           'Firepunch4.ogg'; Path: ptVoices),// sndFirepunch4
       
   183             (FileName:           'Firepunch5.ogg'; Path: ptVoices),// sndFirepunch5
       
   184             (FileName:           'Firepunch6.ogg'; Path: ptVoices),// sndFirepunch6
       
   185             (FileName:                'Melon.ogg'; Path: ptVoices),// sndMelon
       
   186             (FileName:              'Hellish.ogg'; Path: ptSounds),// sndHellish
       
   187             (FileName:               'Yoohoo.ogg'; Path: ptSounds),// sndYoohoo
       
   188             (FileName:              'rcplane.ogg'; Path: ptSounds),// sndRCPlane
       
   189             (FileName:            'whipcrack.ogg'; Path: ptSounds),// sndWhipCrack
       
   190             (FileName:'ride_of_the_valkyries.ogg'; Path: ptSounds),// sndRideOfTheValkyries
       
   191             (FileName:               'denied.ogg'; Path: ptSounds),// sndDenied
       
   192             (FileName:               'placed.ogg'; Path: ptSounds),// sndPlaced
       
   193             (FileName:          'baseballbat.ogg'; Path: ptSounds),// sndBaseballBat
       
   194             (FileName:                'steam.ogg'; Path: ptSounds),// sndVaporize
       
   195             (FileName:                 'warp.ogg'; Path: ptSounds),// sndWarp
       
   196             (FileName:          'suddendeath.ogg'; Path: ptSounds),// sndSuddenDeath
       
   197             (FileName:               'mortar.ogg'; Path: ptSounds),// sndMortar
       
   198             (FileName:         'shutterclick.ogg'; Path: ptSounds),// sndShutter
       
   199             (FileName:              'homerun.ogg'; Path: ptSounds),// sndHomerun
       
   200             (FileName:              'molotov.ogg'; Path: ptSounds),// sndMolotov
       
   201             (FileName:            'Takecover.ogg'; Path: ptVoices),// sndCover
       
   202             (FileName:                'Uh-oh.ogg'; Path: ptVoices),// sndUhOh
       
   203             (FileName:                 'Oops.ogg'; Path: ptVoices),// sndOops
       
   204             (FileName:                 'Nooo.ogg'; Path: ptVoices),// sndNooo
       
   205             (FileName:                'Hello.ogg'; Path: ptVoices),// sndHello
       
   206             (FileName:             'ropeshot.ogg'; Path: ptSounds),// sndRopeShot
       
   207             (FileName:           'ropeattach.ogg'; Path: ptSounds),// sndRopeAttach
       
   208             (FileName:          'roperelease.ogg'; Path: ptSounds),// sndRopeRelease
       
   209             (FileName:            'switchhog.ogg'; Path: ptSounds),// sndSwitchHog
       
   210             (FileName:              'Victory.ogg'; Path: ptVoices),// sndVictory
       
   211             (FileName:             'Flawless.ogg'; Path: ptVoices),// sndFlawless
       
   212             (FileName:         'sniperreload.ogg'; Path: ptSounds),// sndSniperReload
       
   213             (FileName:                'steps.ogg'; Path: ptSounds),// sndSteps
       
   214             (FileName:           'lowgravity.ogg'; Path: ptSounds),// sndLowGravity
       
   215             (FileName:           'hell_growl.ogg'; Path: ptSounds),// sndHellishImpact1
       
   216             (FileName:            'hell_ooff.ogg'; Path: ptSounds),// sndHellishImpact2
       
   217             (FileName:              'hell_ow.ogg'; Path: ptSounds),// sndHellishImpact3
       
   218             (FileName:             'hell_ugh.ogg'; Path: ptSounds),// sndHellishImpact4
       
   219             (FileName:          'melonimpact.ogg'; Path: ptSounds),// sndMelonImpact
       
   220             (FileName:             'Droplet1.ogg'; Path: ptSounds),// sndDroplet1
       
   221             (FileName:             'Droplet2.ogg'; Path: ptSounds),// sndDroplet2
       
   222             (FileName:             'Droplet3.ogg'; Path: ptSounds),// sndDroplet3
       
   223             (FileName:                  'egg.ogg'; Path: ptSounds),// sndEggBreak
       
   224             (FileName:             'drillgun.ogg'; Path: ptSounds),// sndDrillRocket
       
   225             (FileName:          'PoisonCough.ogg'; Path: ptVoices),// sndPoisonCough
       
   226             (FileName:           'PoisonMoan.ogg'; Path: ptVoices),// sndPoisonMoan
       
   227             (FileName:             'BirdyLay.ogg'; Path: ptSounds),// sndBirdyLay
       
   228             (FileName:              'Whistle.ogg'; Path: ptSounds),// sndWhistle
       
   229             (FileName:             'beewater.ogg'; Path: ptSounds),// sndBeeWater
       
   230             (FileName:                   '1C.ogg'; Path: ptSounds),// sndPiano0
       
   231             (FileName:                   '2D.ogg'; Path: ptSounds),// sndPiano1
       
   232             (FileName:                   '3E.ogg'; Path: ptSounds),// sndPiano2
       
   233             (FileName:                   '4F.ogg'; Path: ptSounds),// sndPiano3
       
   234             (FileName:                   '5G.ogg'; Path: ptSounds),// sndPiano4
       
   235             (FileName:                   '6A.ogg'; Path: ptSounds),// sndPiano5
       
   236             (FileName:                   '7B.ogg'; Path: ptSounds),// sndPiano6
       
   237             (FileName:                   '8C.ogg'; Path: ptSounds),// sndPiano7
       
   238             (FileName:                   '9D.ogg'; Path: ptSounds),// sndPiano8
       
   239             (FileName:                 'skip.ogg'; Path: ptSounds),// sndSkip
       
   240             (FileName:              'sinegun.ogg'; Path: ptSounds),// sndSineGun
       
   241             (FileName:                'Ooff1.ogg'; Path: ptVoices),// sndOoff1
       
   242             (FileName:                'Ooff2.ogg'; Path: ptVoices),// sndOoff2
       
   243             (FileName:                'Ooff3.ogg'; Path: ptVoices),// sndOoff3
       
   244             (FileName:               'hammer.ogg'; Path: ptSounds),// sndWhack
       
   245             (FileName:           'Comeonthen.ogg'; Path: ptVoices),// sndComeonthen
       
   246             (FileName:            'parachute.ogg'; Path: ptSounds),// sndParachute
       
   247             (FileName:                 'bump.ogg'; Path: ptSounds),// sndBump
       
   248             (FileName:            'hogchant3.ogg'; Path: ptSounds),// sndResurrector
       
   249             (FileName:                'plane.ogg'; Path: ptSounds),// sndPlane
       
   250             (FileName:               'TARDIS.ogg'; Path: ptSounds) // sndTardis
       
   251             );
       
   252 
   123 
   253 
   124 
   254 
   125 function  AskForVoicepack(name: shortstring): Pointer;
   255 function  AskForVoicepack(name: shortstring): Pointer;
   126 var i: Longword;
   256 var i: Longword;
   127     locName, path: shortstring;
   257     locName, path: shortstring;
   155     AskForVoicepack:= @voicepacks[i]
   285     AskForVoicepack:= @voicepacks[i]
   156 end;
   286 end;
   157 
   287 
   158 procedure InitSound;
   288 procedure InitSound;
   159 const channels: LongInt = {$IFDEF MOBILE}1{$ELSE}2{$ENDIF};
   289 const channels: LongInt = {$IFDEF MOBILE}1{$ELSE}2{$ENDIF};
   160 begin
   290 var success: boolean;
   161     if not isSoundEnabled then
   291 begin
       
   292     if not (isSoundEnabled or isMusicEnabled) then
   162         exit;
   293         exit;
   163     WriteToConsole('Init sound...');
   294     WriteToConsole('Init sound...');
   164     isSoundEnabled:= SDL_InitSubSystem(SDL_INIT_AUDIO) >= 0;
   295     success:= SDL_InitSubSystem(SDL_INIT_AUDIO) >= 0;
   165 
   296 
   166     if isSoundEnabled then
   297     if success then
   167         isSoundEnabled:= Mix_OpenAudio(44100, $8010, channels, 1024) = 0;
   298         success:= Mix_OpenAudio(44100, $8010, channels, 1024) = 0;
   168 
   299 
   169     if isSoundEnabled then
   300     if success then
   170         WriteLnToConsole(msgOK)
   301         WriteLnToConsole(msgOK)
   171     else
   302     else
       
   303     begin
   172         WriteLnToConsole(msgFailed);
   304         WriteLnToConsole(msgFailed);
       
   305         isSoundEnabled:= false;
       
   306         isMusicEnabled:= false;
       
   307     end;
   173 
   308 
   174     WriteToConsole('Init SDL_mixer... ');
   309     WriteToConsole('Init SDL_mixer... ');
   175     SDLTry(Mix_Init(MIX_INIT_OGG) <> 0, true);
   310     SDLTry(Mix_Init(MIX_INIT_OGG) <> 0, true);
   176     WriteLnToConsole(msgOK);
   311     WriteLnToConsole(msgOK);
   177 
   312 
   178     Mix_AllocateChannels(Succ(chanTPU));
   313     Mix_AllocateChannels(Succ(chanTPU));
   179     ChangeVolume(cInitVolume);	
   314     ChangeVolume(cInitVolume);
   180 end;
   315 end;
   181 
   316 
   182 procedure ResetSound;
   317 procedure ResetSound;
   183 begin
   318 begin
   184     isSoundEnabled:= isSEBackup;
   319     isSoundEnabled:= isSEBackup;
   254     if (voicepack <> nil) then
   389     if (voicepack <> nil) then
   255         begin
   390         begin
   256         if (voicepack^.chunks[snd] = nil) and (Soundz[snd].Path = ptVoices) and (Soundz[snd].FileName <> '') then
   391         if (voicepack^.chunks[snd] = nil) and (Soundz[snd].Path = ptVoices) and (Soundz[snd].FileName <> '') then
   257             begin
   392             begin
   258             s:= cPathz[Soundz[snd].Path] + '/' + voicepack^.name + '/' + Soundz[snd].FileName;
   393             s:= cPathz[Soundz[snd].Path] + '/' + voicepack^.name + '/' + Soundz[snd].FileName;
   259             if (not FileExists(s)) and (snd in [sndFirePunch2, sndFirePunch3, sndFirePunch4, sndFirePunch5, sndFirePunch6]) then
   394             if (not pfsExists(s)) and (snd in [sndFirePunch2, sndFirePunch3, sndFirePunch4, sndFirePunch5, sndFirePunch6]) then
   260                 s:= cPathz[Soundz[sndFirePunch1].Path] + '/' + voicepack^.name + '/' + Soundz[snd].FileName;
   395                 s:= cPathz[Soundz[sndFirePunch1].Path] + '/' + voicepack^.name + '/' + Soundz[snd].FileName;
   261             WriteToConsole(msgLoading + s + ' ');
   396             WriteToConsole(msgLoading + s + ' ');
   262             voicepack^.chunks[snd]:= Mix_LoadWAV_RW(rwopsOpenRead(s), 1);
   397             voicepack^.chunks[snd]:= Mix_LoadWAV_RW(rwopsOpenRead(s), 1);
   263             if voicepack^.chunks[snd] = nil then
   398             if voicepack^.chunks[snd] = nil then
   264                 WriteLnToConsole(msgFailed)
   399                 WriteLnToConsole(msgFailed)
   287     if (not isSoundEnabled) or fastUntilLag or ((LastVoice.snd = snd) and  (LastVoice.voicepack = voicepack)) then
   422     if (not isSoundEnabled) or fastUntilLag or ((LastVoice.snd = snd) and  (LastVoice.voicepack = voicepack)) then
   288         exit;
   423         exit;
   289     if (snd = sndVictory) or (snd = sndFlawless) then
   424     if (snd = sndVictory) or (snd = sndFlawless) then
   290         begin
   425         begin
   291         Mix_FadeOutChannel(-1, 800);
   426         Mix_FadeOutChannel(-1, 800);
   292         for i:= 0 to 7 do
   427         for i:= 0 to High(VoiceList) do
   293             VoiceList[i].snd:= sndNone;
   428             VoiceList[i].snd:= sndNone;
   294         LastVoice.snd:= sndNone;
   429         LastVoice.snd:= sndNone;
   295         end;
   430         end;
   296 
   431 
   297     i:= 0;
   432     i:= 0;
   309 var i : LongInt;
   444 var i : LongInt;
   310 begin
   445 begin
   311     if (not isSoundEnabled) or fastUntilLag or ((LastVoice.snd <> sndNone) and (lastChan[LastVoice.snd] <> -1) and (Mix_Playing(lastChan[LastVoice.snd]) <> 0)) then
   446     if (not isSoundEnabled) or fastUntilLag or ((LastVoice.snd <> sndNone) and (lastChan[LastVoice.snd] <> -1) and (Mix_Playing(lastChan[LastVoice.snd]) <> 0)) then
   312         exit;
   447         exit;
   313     i:= 0;
   448     i:= 0;
   314     while (i<8) and (VoiceList[i].snd = sndNone) do
   449     while (i<High(VoiceList)) and (VoiceList[i].snd = sndNone) do
   315         inc(i);
   450         inc(i);
   316     
   451 
   317     if (VoiceList[i].snd <> sndNone) then
   452     if (VoiceList[i].snd <> sndNone) then
   318         begin
   453         begin
   319         LastVoice.snd:= VoiceList[i].snd;
   454         LastVoice.snd:= VoiceList[i].snd;
   320         LastVoice.voicepack:= VoiceList[i].voicepack;
   455         LastVoice.voicepack:= VoiceList[i].voicepack;
   321         VoiceList[i].snd:= sndNone;
   456         VoiceList[i].snd:= sndNone;
   411 end;
   546 end;
   412 
   547 
   413 procedure PlayMusic;
   548 procedure PlayMusic;
   414 var s: shortstring;
   549 var s: shortstring;
   415 begin
   550 begin
   416     if (not isSoundEnabled) or (MusicFN = '') or (not isMusicEnabled) then
   551     if (MusicFN = '') or (not isMusicEnabled) then
   417         exit;
   552         exit;
   418 
   553 
   419     s:= '/Music/' + MusicFN;
   554     s:= '/Music/' + MusicFN;
   420     WriteToConsole(msgLoading + s + ' ');
   555     WriteToConsole(msgLoading + s + ' ');
   421 
   556 
   432 end;
   567 end;
   433 
   568 
   434 function ChangeVolume(voldelta: LongInt): LongInt;
   569 function ChangeVolume(voldelta: LongInt): LongInt;
   435 begin
   570 begin
   436     ChangeVolume:= 0;
   571     ChangeVolume:= 0;
   437     if (not isSoundEnabled) or ((voldelta = 0) and (not (cInitVolume = 0))) then
   572     if not (isSoundEnabled or isMusicEnabled) or ((voldelta = 0) and (not (cInitVolume = 0))) then
   438         exit;
   573         exit;
   439 
   574 
   440     inc(Volume, voldelta);
   575     inc(Volume, voldelta);
   441     if Volume < 0 then
   576     if Volume < 0 then
   442         Volume:= 0;
   577         Volume:= 0;
   472     ChangeVolume(previousVolume - Volume);
   607     ChangeVolume(previousVolume - Volume);
   473 end;
   608 end;
   474 
   609 
   475 procedure MuteAudio;
   610 procedure MuteAudio;
   476 begin
   611 begin
   477     if not isSoundEnabled then
   612     if not (isSoundEnabled or isMusicEnabled) then
   478         exit;
   613         exit;
   479 
   614 
   480     if (isAudioMuted) then
   615     if (isAudioMuted) then
   481     begin
   616     begin
   482         ResumeMusic;
   617         ResumeMusic;
   587         if voicepacks[t].name <> '' then
   722         if voicepacks[t].name <> '' then
   588             for i:= Low(TSound) to High(TSound) do
   723             for i:= Low(TSound) to High(TSound) do
   589                 voicepacks[t].chunks[i]:= nil;
   724                 voicepacks[t].chunks[i]:= nil;
   590 
   725 
   591     (* on MOBILE SDL_mixer has to be compiled against Tremor (USE_OGG_TREMOR)
   726     (* on MOBILE SDL_mixer has to be compiled against Tremor (USE_OGG_TREMOR)
   592        or sound files bigger than 32k will lockup the game *)
   727        or sound files bigger than 32k will lockup the game on slow cpu *)
   593     for i:= Low(TSound) to High(TSound) do
   728     for i:= Low(TSound) to High(TSound) do
   594         defVoicepack^.chunks[i]:= nil;
   729         defVoicepack^.chunks[i]:= nil;
   595 
   730 
   596 end;
   731 end;
   597 
   732 
   598 procedure freeModule;
   733 procedure freeModule;
   599 begin
   734 begin
   600     if isSoundEnabled then
   735     if isSoundEnabled or isMusicEnabled then
   601         ReleaseSound(true);
   736         ReleaseSound(true);
   602 end;
   737 end;
   603 
   738 
   604 end.
   739 end.
   605 
   740