2
* Hedgewars, a free turn based strategy game
3
* Copyright (c) 2005, 2007, 2009 Andrey Korotaev <unC0Rr@gmail.com>
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
7
* the Free Software Foundation; version 2 of the License
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
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
16
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19
{$INCLUDE "options.inc"}
25
type PVoicepack = ^TVoicepack;
28
chunks: array [TSound] of PMixChunk;
31
var MusicFN: shortstring;
37
procedure ReleaseSound;
39
procedure PlaySound(snd: TSound);
40
procedure PlaySound(snd: TSound; keepPlaying: boolean);
41
procedure PlaySound(snd: TSound; voicepack: PVoicepack);
42
procedure PlaySound(snd: TSound; voicepack: PVoicepack; keepPlaying: boolean);
43
function LoopSound(snd: TSound): LongInt;
44
function LoopSound(snd: TSound; voicepack: PVoicepack): LongInt;
47
procedure ResumeMusic;
48
procedure StopSound(snd: TSound);
49
procedure StopSound(chn: LongInt);
50
function ChangeVolume(voldelta: LongInt): LongInt;
51
function AskForVoicepack(name: shortstring): Pointer;
59
lastChan: array [TSound] of LongInt;
60
voicepacks: array[0..cMaxTeams] of TVoicepack;
61
defVoicepack: PVoicepack;
64
function AskForVoicepack(name: shortstring): Pointer;
68
while (voicepacks[i].name <> name) and (voicepacks[i].name <> '') do
71
TryDo(i <= cMaxTeams, 'Engine bug: AskForVoicepack i > cMaxTeams', true)
74
voicepacks[i].name:= name;
75
AskForVoicepack:= @voicepacks[i]
82
if not isSoundEnabled then exit;
83
WriteToConsole('Init sound...');
84
isSoundEnabled:= SDL_InitSubSystem(SDL_INIT_AUDIO) >= 0;
92
if isSoundEnabled then
93
isSoundEnabled:= Mix_OpenAudio(44100, $8010, channels, 1024) = 0;
95
{$IFDEF SDL_MIXER_NEWER}
96
WriteToConsole('Init SDL_mixer... ');
97
SDLTry(Mix_Init(MIX_INIT_OGG) <> 0, true);
98
WriteLnToConsole(msgOK);
101
if isSoundEnabled then
102
WriteLnToConsole(msgOK)
104
WriteLnToConsole(msgFailed);
106
Mix_AllocateChannels(Succ(chanTPU));
107
if isMusicEnabled then
109
for i:= Low(TSound) to High(TSound) do
113
ChangeVolume(cInitVolume)
116
procedure ReleaseSound;
120
for t:= 0 to cMaxTeams do
121
if voicepacks[t].name <> '' then
122
for i:= Low(TSound) to High(TSound) do
123
if voicepacks[t].chunks[i] <> nil then
124
Mix_FreeChunk(voicepacks[t].chunks[i]);
129
{$IFDEF SDL_MIXER_NEWER}
130
// make sure all instances of sdl_mixer are unloaded before continuing
131
while Mix_Init(0) <> 0 do
143
if not isSoundEnabled then exit;
145
defVoicepack:= AskForVoicepack('Default');
147
for t:= 0 to cMaxTeams do
148
if voicepacks[t].name <> '' then
149
for i:= Low(TSound) to High(TSound) do
150
voicepacks[t].chunks[i]:= nil;
152
for i:= Low(TSound) to High(TSound) do
154
defVoicepack^.chunks[i]:= nil;
155
// preload all the big sound files (>32k) that would otherwise lockup the game
156
if (i in [sndBeeWater, sndBee, sndCake, sndHellishImpact1, sndHellish, sndHomerun, sndMolotov, sndMortar, sndRideOfTheValkyries, sndYoohoo])
157
and (Soundz[i].Path <> ptVoices) and (Soundz[i].FileName <> '') then
159
s:= Pathz[Soundz[i].Path] + '/' + Soundz[i].FileName;
160
WriteToConsole(msgLoading + s + ' ');
161
defVoicepack^.chunks[i]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1);
162
TryDo(defVoicepack^.chunks[i] <> nil, msgFailed, true);
163
WriteLnToConsole(msgOK);
169
procedure PlaySound(snd: TSound);
171
PlaySound(snd, nil, false);
174
procedure PlaySound(snd: TSound; keepPlaying: boolean);
176
PlaySound(snd, nil, keepPlaying);
179
procedure PlaySound(snd: TSound; voicepack: PVoicepack);
181
PlaySound(snd, voicepack, false);
184
procedure PlaySound(snd: TSound; voicepack: PVoicepack; keepPlaying: boolean);
187
if (not isSoundEnabled) or fastUntilLag then
190
if keepPlaying and (lastChan[snd] <> -1) and (Mix_Playing(lastChan[snd]) <> 0) then
193
if (voicepack <> nil) then
195
if (voicepack^.chunks[snd] = nil) and (Soundz[snd].Path = ptVoices) and (Soundz[snd].FileName <> '') then
197
s:= Pathz[Soundz[snd].Path] + '/' + voicepack^.name + '/' + Soundz[snd].FileName;
198
WriteToConsole(msgLoading + s + ' ');
199
voicepack^.chunks[snd]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1);
200
if voicepack^.chunks[snd] = nil then
201
WriteLnToConsole(msgFailed)
203
WriteLnToConsole(msgOK)
205
lastChan[snd]:= Mix_PlayChannelTimed(-1, voicepack^.chunks[snd], 0, -1)
209
if (defVoicepack^.chunks[snd] = nil) and (Soundz[snd].Path <> ptVoices) and (Soundz[snd].FileName <> '') then
211
s:= Pathz[Soundz[snd].Path] + '/' + Soundz[snd].FileName;
212
WriteToConsole(msgLoading + s + ' ');
213
defVoicepack^.chunks[snd]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1);
214
TryDo(defVoicepack^.chunks[snd] <> nil, msgFailed, true);
215
WriteLnToConsole(msgOK);
217
lastChan[snd]:= Mix_PlayChannelTimed(-1, defVoicepack^.chunks[snd], 0, -1)
221
function LoopSound(snd: TSound): LongInt;
223
LoopSound:= LoopSound(snd, nil)
226
function LoopSound(snd: TSound; voicepack: PVoicepack): LongInt;
229
if (not isSoundEnabled) or fastUntilLag then
235
if (voicepack <> nil) then
237
if (voicepack^.chunks[snd] = nil) and (Soundz[snd].Path = ptVoices) and (Soundz[snd].FileName <> '') then
239
s:= Pathz[Soundz[snd].Path] + '/' + voicepack^.name + '/' + Soundz[snd].FileName;
240
WriteToConsole(msgLoading + s + ' ');
241
voicepack^.chunks[snd]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1);
242
if voicepack^.chunks[snd] = nil then
243
WriteLnToConsole(msgFailed)
245
WriteLnToConsole(msgOK)
247
LoopSound:= Mix_PlayChannelTimed(-1, voicepack^.chunks[snd], -1, -1)
251
if (defVoicepack^.chunks[snd] = nil) and (Soundz[snd].Path <> ptVoices) and (Soundz[snd].FileName <> '') then
253
s:= Pathz[Soundz[snd].Path] + '/' + Soundz[snd].FileName;
254
WriteToConsole(msgLoading + s + ' ');
255
defVoicepack^.chunks[snd]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1);
256
TryDo(defVoicepack^.chunks[snd] <> nil, msgFailed, true);
257
WriteLnToConsole(msgOK);
259
LoopSound:= Mix_PlayChannelTimed(-1, defVoicepack^.chunks[snd], -1, -1);
263
procedure StopSound(snd: TSound);
265
if not isSoundEnabled then exit;
266
if (lastChan[snd] <> -1) and (Mix_Playing(lastChan[snd]) <> 0) then
268
Mix_HaltChannel(lastChan[snd]);
273
procedure StopSound(chn: LongInt);
275
if not isSoundEnabled then exit;
277
if (chn <> -1) and (Mix_Playing(chn) <> 0) then
278
Mix_HaltChannel(chn);
284
if (not isSoundEnabled) or (MusicFN = '') or (not isMusicEnabled) then
287
s:= PathPrefix + '/Music/' + MusicFN;
288
WriteToConsole(msgLoading + s + ' ');
290
Mus:= Mix_LoadMUS(Str2PChar(s));
291
TryDo(Mus <> nil, msgFailed, false);
292
WriteLnToConsole(msgOK);
294
SDLTry(Mix_FadeInMusic(Mus, -1, 3000) <> -1, false)
297
function ChangeVolume(voldelta: LongInt): LongInt;
299
if not isSoundEnabled then
302
inc(Volume, voldelta);
303
if Volume < 0 then Volume:= 0;
304
Mix_Volume(-1, Volume);
305
Volume:= Mix_Volume(-1, -1);
306
if isMusicEnabled then Mix_VolumeMusic(Volume * 4 div 8);
307
ChangeVolume:= Volume * 100 div MIX_MAX_VOLUME
310
procedure PauseMusic;
312
if (MusicFN = '') or (not isMusicEnabled) then
318
procedure ResumeMusic;
320
if (MusicFN = '') or (not isMusicEnabled) then
323
Mix_ResumeMusic(Mus);
326
procedure initModule;
331
procedure freeModule;
333
if isSoundEnabled then