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; |