hedgewars/uSound.pas
branchsdl2transition
changeset 11362 ed5a6478e710
parent 9682 aa2431ed87b2
parent 11261 ce5f1b547a67
child 11499 9c5d9993b14b
equal deleted inserted replaced
11361:31570b766315 11362:ed5a6478e710
     1 (*
     1 (*
     2  * Hedgewars, a free turn based strategy game
     2  * Hedgewars, a free turn based strategy game
     3  * Copyright (c) 2004-2013 Andrey Korotaev <unC0Rr@gmail.com>
     3  * Copyright (c) 2004-2015 Andrey Korotaev <unC0Rr@gmail.com>
     4  *
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation; version 2 of the License
     7  * the Free Software Foundation; version 2 of the License
     8  *
     8  *
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    12  * GNU General Public License for more details.
    13  *
    13  *
    14  * You should have received a copy of the GNU General Public License
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program; if not, write to the Free Software
    15  * along with this program; if not, write to the Free Software
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
    16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    17  *)
    17  *)
    18 
    18 
    19 {$INCLUDE "options.inc"}
    19 {$INCLUDE "options.inc"}
    20 
    20 
    21 unit uSound;
    21 unit uSound;
    68 
    68 
    69 // Plays sound snd [of voicepack] in a loop, but starts with fadems milliseconds of fade-in.
    69 // Plays sound snd [of voicepack] in a loop, but starts with fadems milliseconds of fade-in.
    70 // Returns sound channel of the looped sound.
    70 // Returns sound channel of the looped sound.
    71 function  LoopSound(snd: TSound): LongInt;
    71 function  LoopSound(snd: TSound): LongInt;
    72 function  LoopSound(snd: TSound; fadems: LongInt): LongInt;
    72 function  LoopSound(snd: TSound; fadems: LongInt): LongInt;
    73 function  LoopSoundV(snd: TSound; voicepack: PVoicepack): LongInt; // WTF?
    73 function  LoopSoundV(snd: TSound; voicepack: PVoicepack): LongInt;
    74 function  LoopSoundV(snd: TSound; voicepack: PVoicepack; fadems: LongInt): LongInt;
    74 function  LoopSoundV(snd: TSound; voicepack: PVoicepack; fadems: LongInt): LongInt;
    75 
    75 
    76 // Stops the normal/looped sound of the given type/in the given channel
    76 // Stops the normal/looped sound of the given type/in the given channel
    77 // [with a fade-out effect for fadems milliseconds].
    77 // [with a fade-out effect for fadems milliseconds].
    78 procedure StopSound(snd: TSound);
    78 procedure StopSound(snd: TSound);
   102 function  ChangeVolume(voldelta: LongInt): LongInt;
   102 function  ChangeVolume(voldelta: LongInt): LongInt;
   103 
   103 
   104 // Returns a pointer to the voicepack with the given name.
   104 // Returns a pointer to the voicepack with the given name.
   105 function  AskForVoicepack(name: shortstring): Pointer;
   105 function  AskForVoicepack(name: shortstring): Pointer;
   106 
   106 
       
   107 var MusicFN: shortstring; // music file name
       
   108     SDMusicFN: shortstring; // SD music file name
   107 
   109 
   108 var Volume: LongInt;
   110 var Volume: LongInt;
   109     SoundTimerTicks: Longword;
   111     SoundTimerTicks: Longword;
   110 implementation
   112 implementation
   111 uses uVariables, uConsole, uCommands, uDebug, uPhysFSLayer;
   113 uses uVariables, uConsole, uCommands, uDebug, uPhysFSLayer;
   115     previousVolume: LongInt; // cached volume value
   117     previousVolume: LongInt; // cached volume value
   116     lastChan: array [TSound] of LongInt;
   118     lastChan: array [TSound] of LongInt;
   117     voicepacks: array[0..cMaxTeams] of TVoicepack;
   119     voicepacks: array[0..cMaxTeams] of TVoicepack;
   118     defVoicepack: PVoicepack;
   120     defVoicepack: PVoicepack;
   119     Mus: PMixMusic; // music pointer
   121     Mus: PMixMusic; // music pointer
   120     MusicFN: shortstring; // music file name
       
   121     isMusicEnabled: boolean;
   122     isMusicEnabled: boolean;
   122     isSoundEnabled: boolean;
   123     isSoundEnabled: boolean;
   123     isSEBackup: boolean;
   124     isSEBackup: boolean;
   124     VoiceList : array[0..7] of TVoice =  (
   125     VoiceList : array[0..7] of TVoice =  (
   125                     ( snd: sndNone; voicepack: nil),
   126                     ( snd: sndNone; voicepack: nil),
   258 
   259 
   259 function  AskForVoicepack(name: shortstring): Pointer;
   260 function  AskForVoicepack(name: shortstring): Pointer;
   260 var i: Longword;
   261 var i: Longword;
   261     locName, path: shortstring;
   262     locName, path: shortstring;
   262 begin
   263 begin
   263 i:= 0;
   264     i:= 0;
   264     // First, attempt to locate a localised version of the voice
   265 
       
   266     // Adjust voicepack name if there's a localised version version of the voice
   265     if cLocale <> 'en' then
   267     if cLocale <> 'en' then
   266         begin
   268         begin
   267         locName:= name+'_'+cLocale;
   269         locName:= name+'_'+cLocale;
   268         path:= cPathz[ptVoices] + '/' + locName;
   270         path:= cPathz[ptVoices] + '/' + locName;
   269         if pfsExists(path) then
   271         if pfsExists(path) then
   276                 if pfsExists(path) then
   278                 if pfsExists(path) then
   277                     name:= locName
   279                     name:= locName
   278                 end
   280                 end
   279         end;
   281         end;
   280 
   282 
   281     // If that fails, use the unmodified one
   283     path:= cPathz[ptVoices] + '/' + name;
       
   284 
       
   285     // Fallback to Default if voicepack can't be found at all
       
   286     if (name <> 'Default') and (not pfsExists(path)) then
       
   287         begin
       
   288         path:= cPathz[ptVoices] + '/Default';
       
   289         if pfsExists(path) then
       
   290             exit(AskForVoicepack('Default'));
       
   291         end;
       
   292 
   282     while (voicepacks[i].name <> name) and (voicepacks[i].name <> '') do
   293     while (voicepacks[i].name <> name) and (voicepacks[i].name <> '') do
   283         begin
   294         begin
   284         inc(i);
   295         inc(i);
   285         TryDo(i <= cMaxTeams, 'Engine bug: AskForVoicepack i > cMaxTeams', true)
   296         TryDo(i <= cMaxTeams, 'Engine bug: AskForVoicepack i > cMaxTeams', true)
   286         end;
   297         end;
   288     voicepacks[i].name:= name;
   299     voicepacks[i].name:= name;
   289     AskForVoicepack:= @voicepacks[i]
   300     AskForVoicepack:= @voicepacks[i]
   290 end;
   301 end;
   291 
   302 
   292 procedure InitSound;
   303 procedure InitSound;
   293 const channels: LongInt = {$IFDEF MOBILE}1{$ELSE}2{$ENDIF};
   304 const channels: LongInt = 2;
   294 var success: boolean;
   305 var success: boolean;
   295 begin
   306 begin
   296     if not (isSoundEnabled or isMusicEnabled) then
   307     if not (isSoundEnabled or isMusicEnabled) then
   297         exit;
   308         exit;
   298     WriteToConsole('Init sound...');
   309     WriteToConsole('Init sound...');
   313     WriteToConsole('Init SDL_mixer... ');
   324     WriteToConsole('Init SDL_mixer... ');
   314     SDLTry(Mix_Init(MIX_INIT_OGG) <> 0, 'Mix_Init', true);
   325     SDLTry(Mix_Init(MIX_INIT_OGG) <> 0, 'Mix_Init', true);
   315     WriteLnToConsole(msgOK);
   326     WriteLnToConsole(msgOK);
   316 
   327 
   317     Mix_AllocateChannels(Succ(chanTPU));
   328     Mix_AllocateChannels(Succ(chanTPU));
   318     ChangeVolume(cInitVolume);	
   329     ChangeVolume(cInitVolume);
   319 end;
   330 end;
   320 
   331 
   321 procedure ResetSound;
   332 procedure ResetSound;
   322 begin
   333 begin
   323     isSoundEnabled:= isSEBackup;
   334     isSoundEnabled:= isSEBackup;
   432             VoiceList[i].snd:= sndNone;
   443             VoiceList[i].snd:= sndNone;
   433         LastVoice.snd:= sndNone;
   444         LastVoice.snd:= sndNone;
   434         end;
   445         end;
   435 
   446 
   436     i:= 0;
   447     i:= 0;
   437     while (i<8) and (VoiceList[i].snd <> sndNone) do
   448     while (i <= High(VoiceList)) and (VoiceList[i].snd <> sndNone) do
   438         inc(i);
   449         inc(i);
   439 
   450 
   440     // skip playing same sound for same hog twice
   451     // skip playing same sound for same hog twice
   441     if (i>0) and (VoiceList[i-1].snd = snd) and (VoiceList[i-1].voicepack = voicepack) then
   452     if (i>0) and (VoiceList[i-1].snd = snd) and (VoiceList[i-1].voicepack = voicepack) then
   442         exit;
   453         exit;
   443     VoiceList[i].snd:= snd;
   454     if(i <= High(VoiceList)) then
   444     VoiceList[i].voicepack:= voicepack;
   455         begin
       
   456         VoiceList[i].snd:= snd;
       
   457         VoiceList[i].voicepack:= voicepack;
       
   458         end
   445 end;
   459 end;
   446 
   460 
   447 procedure PlayNextVoice;
   461 procedure PlayNextVoice;
   448 var i : LongInt;
   462 var i : LongInt;
   449 begin
   463 begin
   450     if (not isSoundEnabled) or fastUntilLag or ((LastVoice.snd <> sndNone) and (lastChan[LastVoice.snd] <> -1) and (Mix_Playing(lastChan[LastVoice.snd]) <> 0)) then
   464     if (not isSoundEnabled) or fastUntilLag or ((LastVoice.snd <> sndNone) and (lastChan[LastVoice.snd] <> -1) and (Mix_Playing(lastChan[LastVoice.snd]) <> 0)) then
   451         exit;
   465         exit;
   452     i:= 0;
   466     i:= 0;
   453     while (i<High(VoiceList)) and (VoiceList[i].snd = sndNone) do
   467     while (i<High(VoiceList)) and (VoiceList[i].snd = sndNone) do
   454         inc(i);
   468         inc(i);
   455     
   469 
   456     if (VoiceList[i].snd <> sndNone) then
   470     if (VoiceList[i].snd <> sndNone) then
   457         begin
   471         begin
   458         LastVoice.snd:= VoiceList[i].snd;
   472         LastVoice.snd:= VoiceList[i].snd;
   459         LastVoice.voicepack:= VoiceList[i].voicepack;
   473         LastVoice.voicepack:= VoiceList[i].voicepack;
   460         VoiceList[i].snd:= sndNone;
   474         VoiceList[i].snd:= sndNone;
   552 procedure PlayMusic;
   566 procedure PlayMusic;
   553 var s: shortstring;
   567 var s: shortstring;
   554 begin
   568 begin
   555     if (MusicFN = '') or (not isMusicEnabled) then
   569     if (MusicFN = '') or (not isMusicEnabled) then
   556         exit;
   570         exit;
   557 
   571     if SuddenDeath and (SDMusicFN <> '') then
   558     s:= '/Music/' + MusicFN;
   572          s:= '/Music/' + SDMusicFN
       
   573     else s:= '/Music/' + MusicFN;
   559     WriteToConsole(msgLoading + s + ' ');
   574     WriteToConsole(msgLoading + s + ' ');
   560 
   575 
   561     Mus:= Mix_LoadMUS_RW(rwopsOpenRead(s));
   576     Mus:= Mix_LoadMUS_RW(rwopsOpenRead(s));
   562     SDLTry(Mus <> nil, 'Mix_LoadMUS_RW', false);
   577     SDLTry(Mus <> nil, 'Mix_LoadMUS_RW', false);
   563     WriteLnToConsole(msgOK);
   578     WriteLnToConsole(msgOK);
   710 begin
   725 begin
   711     RegisterVariable('voicepack', @chVoicepack, false);
   726     RegisterVariable('voicepack', @chVoicepack, false);
   712     RegisterVariable('mute'     , @chMute     , true );
   727     RegisterVariable('mute'     , @chMute     , true );
   713 
   728 
   714     MusicFN:='';
   729     MusicFN:='';
       
   730     SDMusicFN:= 'sdmusic.ogg';
   715     Mus:= nil;
   731     Mus:= nil;
   716     isAudioMuted:= false;
   732     isAudioMuted:= false;
   717     isSEBackup:= isSoundEnabled;
   733     isSEBackup:= isSoundEnabled;
   718     Volume:= 0;
   734     Volume:= 0;
   719     SoundTimerTicks:= 0;
   735     SoundTimerTicks:= 0;