1 (* Copyright (C) Doom 2D: Forever Developers
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 {$INCLUDE ../shared/a_modes.inc}
29 TPlayableSound
= class(TBasicSound
)
35 destructor Destroy(); override;
36 function Play(Force
: Boolean = False): Boolean;
37 function PlayAt(X
, Y
: Integer): Boolean;
38 function PlayPanVolume(Pan
, Volume
: Single; Force
: Boolean = False): Boolean;
39 function PlayVolumeAt(X
, Y
: Integer; Volume
: Single): Boolean;
40 function SetByName(SN
: String): Boolean;
41 function SetCoords(X
, Y
: Integer; Volume
: Single): Boolean;
43 property Loop
: Boolean read FMusic write FMusic
;
44 property Name
: String read FName
;
47 TMusic
= class(TBasicSound
)
50 FSpecPause
: Boolean; // Ñïåö-ïàóçà. "Ñèëüíåå" îáû÷íîé
53 procedure SetSpecPause(Enable
: Boolean);
57 destructor Destroy(); override;
58 function Play(Force
: Boolean = False): Boolean;
59 function SetByName(SN
: String): Boolean;
60 function IsPaused(): Boolean;
61 procedure Pause(Enable
: Boolean);
63 property Name
: String read FName
;
64 property SpecPause
: Boolean read FSpecPause write SetSpecPause
;
65 property NoMusic
: Boolean read FNoMusic
;
68 function g_Sound_PlayEx(SoundName
: ShortString): Boolean;
69 function g_Sound_PlayExPanVolume(SoundName
: ShortString; Pan
: Single; Volume
: Single): Boolean;
70 function g_Sound_PlayAt(ID
: DWORD
; X
, Y
: Integer): Boolean;
71 function g_Sound_PlayExAt(SoundName
: ShortString; X
, Y
: Integer): Boolean;
73 function g_Sound_CreateWAD(var ID
: DWORD
; Resource
: string; isMusic
: Boolean = False): Boolean;
74 function g_Sound_CreateWADEx(SoundName
: ShortString; Resource
: string; isMusic
: Boolean = False): Boolean;
75 function g_Sound_CreateFile(var ID
: DWORD
; FileName
: string; isMusic
: Boolean = False): Boolean;
76 function g_Sound_CreateFileEx(SoundName
: ShortString; FileName
: string; isMusic
: Boolean = False): Boolean;
78 procedure g_Sound_Delete(SoundName
: ShortString);
79 function g_Sound_Exists(SoundName
: string): Boolean;
80 function g_Sound_Get(var ID
: DWORD
; SoundName
: ShortString): Boolean;
82 procedure g_Sound_SetupAllVolumes(SoundVol
, MusicVol
: Byte);
87 e_log
, SysUtils
, g_console
, g_options
, wadreader
,
88 g_game
, g_basic
, g_items
, g_map
, Math
,
99 SoundArray
: Array of TGameSound
;
100 //SoundsMuted: Boolean = False;
103 function FindSound(): DWORD
;
107 if SoundArray
<> nil then
108 for i
:= 0 to High(SoundArray
) do
109 if SoundArray
[i
].Name
= '' then
115 if SoundArray
= nil then
117 SetLength(SoundArray
, 8);
122 Result
:= High(SoundArray
) + 1;
123 SetLength(SoundArray
, Length(SoundArray
) + 8);
127 function g_Sound_PlayEx(SoundName
: ShortString): Boolean;
132 if SoundArray
= nil then
135 for a
:= 0 to High(SoundArray
) do
136 if SoundArray
[a
].Name
= SoundName
then
138 Result
:= (e_PlaySoundVolume(SoundArray
[a
].ID
, gSoundLevel
/255.0) >= 0);
142 e_WriteLog(Format(_lc
[I_GAME_ERROR_SOUND
], [SoundName
]), TMsgType
.Warning
);
145 function g_Sound_PlayExPanVolume(SoundName
: ShortString; Pan
: Single; Volume
: Single): Boolean;
150 if SoundArray
= nil then
153 for a
:= 0 to High(SoundArray
) do
154 if SoundArray
[a
].Name
= SoundName
then
156 Result
:= (e_PlaySoundPanVolume(SoundArray
[a
].ID
, Pan
, Volume
* (gSoundLevel
/255.0)) >= 0);
160 e_WriteLog(Format(_lc
[I_GAME_ERROR_SOUND
], [SoundName
]), TMsgType
.Warning
);
163 function PlaySoundAt(X
, Y
: Integer; var Pan
: Single; var Volume
: Single; InVolume
: Single = 1.0): Boolean;
165 l1
, l2
, lx
, rx
: Integer;
166 d1
, d2
, sMaxDist
: Single;
171 sMaxDist
:= SOUND_MAXDIST
* InVolume
;
175 c
:= SOUND_MINDIST
>= sMaxDist
;
177 if X
> gMapInfo
.Width
then
183 if Y
> gMapInfo
.Height
then
189 if gHearPoint1
.Active
then
191 l1
:= Round(Hypot(X
- gHearPoint1
.Coords
.X
, Y
- gHearPoint1
.Coords
.Y
));
193 lx
:= gHearPoint1
.Coords
.X
- SOUND_MINDIST
;
194 rx
:= gHearPoint1
.Coords
.X
+ SOUND_MINDIST
;
197 else if (X
>= lx
) and (X
<= rx
) then
200 d1
:= (X
-lx
)/sMaxDist
202 d1
:= (X
-rx
)/sMaxDist
;
207 if gHearPoint2
.Active
then
209 l2
:= Round(Hypot(X
- gHearPoint2
.Coords
.X
, Y
- gHearPoint2
.Coords
.Y
));
211 lx
:= gHearPoint2
.Coords
.X
- SOUND_MINDIST
;
212 rx
:= gHearPoint2
.Coords
.X
+ SOUND_MINDIST
;
215 else if (X
>= lx
) and (X
<= rx
) then
218 d2
:= (X
-lx
)/sMaxDist
220 d2
:= (X
-rx
)/sMaxDist
;
229 if l1
>= sMaxDist
then
238 Volume
:= 1.0 - l1
/sMaxDist
;
243 function g_Sound_PlayAt(ID
: DWORD
; X
, Y
: Integer): Boolean;
247 if PlaySoundAt(X
, Y
, Pan
, Vol
) then
248 Result
:= (e_PlaySoundPanVolume(ID
, Pan
, Vol
* (gSoundLevel
/255.0)) >= 0)
253 function g_Sound_PlayExAt(SoundName
: ShortString; X
, Y
: Integer): Boolean;
260 if SoundArray
= nil then
263 for a
:= 0 to High(SoundArray
) do
264 if SoundArray
[a
].Name
= SoundName
then
266 if PlaySoundAt(X
, Y
, Pan
, Vol
) then
267 Result
:= (e_PlaySoundPanVolume(SoundArray
[a
].ID
, Pan
, Vol
* (gSoundLevel
/255.0)) >= 0);
271 e_WriteLog(Format(_lc
[I_GAME_ERROR_SOUND
], [SoundName
]), TMsgType
.Warning
);
274 function g_Sound_CreateFile(var ID
: DWORD
; FileName
: string; isMusic
: Boolean = False): Boolean;
276 Result
:= e_LoadSound(FileName
, ID
, isMusic
);
279 function g_Sound_CreateFileEx(SoundName
: ShortString; FileName
: string; isMusic
: Boolean = False): Boolean;
285 find_id
:= FindSound();
287 if not e_LoadSound(FileName
, SoundArray
[find_id
].ID
, isMusic
) then
290 SoundArray
[find_id
].Name
:= SoundName
;
291 SoundArray
[find_id
].IsMusic
:= isMusic
;
296 function g_Sound_CreateWAD(var ID
: DWORD
; Resource
: string; isMusic
: Boolean = False): Boolean;
307 // e_WriteLog('Loading sound: ' + Resource, MSG_NOTIFY);
308 FileName
:= g_ExtractWadName(Resource
);
310 WAD
:= TWADFile
.Create();
311 WAD
.ReadFile(FileName
);
313 if WAD
.GetResource(g_ExtractFilePathName(Resource
), SoundData
, ResLength
) then
315 if e_LoadSoundMem(SoundData
, ResLength
, ID
, isMusic
) then
322 //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
330 e_WriteLog(Format('Error loading music %s', [Resource
]), TMsgType
.Warning
)
332 e_WriteLog(Format('Error loading sound %s', [Resource
]), TMsgType
.Warning
);
339 function g_Sound_CreateWADEx(SoundName
: ShortString; Resource
: string; isMusic
: Boolean = False): Boolean;
351 // e_WriteLog('Loading sound: ' + Resource, MSG_NOTIFY);
352 FileName
:= g_ExtractWadName(Resource
);
354 find_id
:= FindSound();
356 WAD
:= TWADFile
.Create();
357 WAD
.ReadFile(FileName
);
359 if WAD
.GetResource(g_ExtractFilePathName(Resource
), SoundData
, ResLength
) then
361 if e_LoadSoundMem(SoundData
, ResLength
, SoundArray
[find_id
].ID
, isMusic
) then
363 SoundArray
[find_id
].Name
:= SoundName
;
364 SoundArray
[find_id
].IsMusic
:= isMusic
;
372 //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
380 e_WriteLog(Format('Error loading music %s', [Resource
]), TMsgType
.Warning
)
382 e_WriteLog(Format('Error loading sound %s', [Resource
]), TMsgType
.Warning
);
389 procedure g_Sound_Delete(SoundName
: ShortString);
393 if (SoundArray
= nil) or (SoundName
= '') then
396 for a
:= 0 to High(SoundArray
) do
397 if SoundArray
[a
].Name
= SoundName
then
399 e_DeleteSound(SoundArray
[a
].ID
);
400 SoundArray
[a
].Name
:= '';
401 SoundArray
[a
].ID
:= 0;
402 SoundArray
[a
].IsMusic
:= False;
406 function g_Sound_Exists(SoundName
: string): Boolean;
412 if SoundName
= '' then
415 if SoundArray
<> nil then
416 for a
:= 0 to High(SoundArray
) do
417 if SoundArray
[a
].Name
= SoundName
then
424 function g_Sound_Get(var ID
: DWORD
; SoundName
: ShortString): Boolean;
430 if SoundName
= '' then
433 if SoundArray
<> nil then
434 for a
:= 0 to High(SoundArray
) do
435 if SoundArray
[a
].Name
= SoundName
then
437 ID
:= SoundArray
[a
].ID
;
443 procedure g_Sound_SetupAllVolumes(SoundVol
, MusicVol
: Byte);
448 Mvol
:= 0; // shut up, compiler
449 if (gSoundLevel
= SoundVol
) and (gMusicLevel
= MusicVol
) then
452 if gSoundLevel
> 0 then
454 Svol
:= SoundVol
/ gSoundLevel
;
459 Svol
:= SoundVol
/ 255.0;
463 if gMusic
<> nil then
464 if gMusicLevel
> 0 then
465 Mvol
:= gMusic
.GetVolume() * MusicVol
/ gMusicLevel
467 Mvol
:= MusicVol
/ 255.0;
469 e_ModifyChannelsVolumes(Svol
, sm
);
471 if gMusic
<> nil then
472 gMusic
.SetVolume(Mvol
);
474 gSoundLevel
:= SoundVol
;
475 gMusicLevel
:= MusicVol
;
480 constructor TPlayableSound
.Create();
486 destructor TPlayableSound
.Destroy();
491 function TPlayableSound
.Play(Force
: Boolean = False): Boolean;
493 if Force
or not IsPlaying() then
496 Result
:= RawPlay(0.0, gSoundLevel
/255.0, FPosition
);
502 function TPlayableSound
.PlayAt(X
, Y
: Integer): Boolean;
506 if PlaySoundAt(X
, Y
, Pan
, Vol
) then
509 Result
:= RawPlay(Pan
, Vol
* (gSoundLevel
/255.0), FPosition
);
515 function TPlayableSound
.PlayPanVolume(Pan
, Volume
: Single; Force
: Boolean = False): Boolean;
517 if Force
or not IsPlaying() then
520 Result
:= RawPlay(Pan
, Volume
* (gSoundLevel
/255.0), FPosition
);
526 function TPlayableSound
.PlayVolumeAt(X
, Y
: Integer; Volume
: Single): Boolean;
530 if PlaySoundAt(X
, Y
, Pan
, Vol
, Volume
) then
533 Result
:= RawPlay(Pan
, Volume
* Vol
* (gSoundLevel
/255.0), FPosition
);
539 function TPlayableSound
.SetCoords(X
, Y
: Integer; Volume
: Single): Boolean;
543 if PlaySoundAt(X
, Y
, Pan
, Vol
, Volume
) then
545 SetVolume(Volume
* Vol
* (gSoundLevel
/255.0));
557 function TPlayableSound
.SetByName(SN
: String): Boolean;
561 if g_Sound_Get(id
, SN
) then
573 constructor TMusic
.Create();
581 destructor TMusic
.Destroy();
586 function TMusic
.Play(Force
: Boolean = False): Boolean;
594 if Force
or not IsPlaying() then
597 Result
:= RawPlay(0.0, gMusicLevel
/255.0, FPosition
);
600 if Result
and FSpecPause
then
607 function TMusic
.SetByName(SN
: String): Boolean;
618 if g_Sound_Get(id
, SN
) then
630 function TMusic
.IsPaused(): Boolean;
632 Result
:= inherited IsPaused();
633 Result
:= Result
or FSpecPause
;
636 procedure TMusic
.Pause(Enable
: Boolean);
638 // Îòêëþ÷àåì ïàóçó, òîëüêî åñëè íå áûëî ñïåö-ïàóçû:
639 if Enable
or (not FSpecPause
) then
640 inherited Pause(Enable
);
643 procedure TMusic
.SetSpecPause(Enable
: Boolean);
645 FSpecPause
:= Enable
;