ca0203e58079d87673078bcbefad4744ae49a6cf
19 TBasicSound
= class (TObject
)
21 FChannel
: Integer; // <0: no channel allocated
29 function RawPlay(Pan
: Single; Volume
: Single; aPos
: DWORD
): Boolean;
33 destructor Destroy(); override;
34 procedure SetID(ID
: DWORD
);
35 procedure FreeSound();
36 function IsPlaying(): Boolean;
38 function IsPaused(): Boolean;
39 procedure Pause(Enable
: Boolean);
40 function GetVolume(): Single;
41 procedure SetVolume(Volume
: Single);
42 function GetPan(): Single;
43 procedure SetPan(Pan
: Single);
44 function IsMuted(): Boolean;
45 procedure Mute(Enable
: Boolean);
46 function GetPosition(): DWORD
;
47 procedure SetPosition(aPos
: DWORD
);
48 procedure SetPriority(priority
: Integer);
52 NO_SOUND_ID
= DWORD(-1);
54 function e_InitSoundSystem(): Boolean;
56 function e_LoadSound(FileName
: string; var ID
: DWORD
; isMusic
: Boolean): Boolean;
57 function e_LoadSoundMem(pData
: Pointer; Length
: Integer; var ID
: DWORD
; isMusic
: Boolean): Boolean;
59 // returns channel number or -1
60 function e_PlaySound(ID
: DWORD
): Integer;
61 function e_PlaySoundPan(ID
: DWORD
; Pan
: Single): Integer;
62 function e_PlaySoundVolume(ID
: DWORD
; Volume
: Single): Integer;
63 function e_PlaySoundPanVolume(ID
: DWORD
; Pan
, Volume
: Single): Integer;
65 procedure e_ModifyChannelsVolumes(SoundMod
: Single; setMode
: Boolean);
66 procedure e_MuteChannels(Enable
: Boolean);
67 procedure e_StopChannels();
69 procedure e_DeleteSound(ID
: DWORD
);
70 procedure e_RemoveAllSounds();
71 procedure e_ReleaseSoundSystem();
72 procedure e_SoundUpdate();
75 e_SoundsArray
: array of TSoundRec
= nil;
80 g_window
, g_options
, BinEditor
;
84 N_MUSCHAN
= N_CHANNELS
+42;
87 SoundMuted
: Boolean = False;
88 SoundInitialized
: Boolean = False;
91 function e_InitSoundSystem(): Boolean;
95 if SoundInitialized
then begin Result
:= true; Exit
end;
98 SoundInitialized
:= False;
100 { // wow, this is actually MIDI player!
101 // we need module player
102 if (Mix_Init(MIX_INIT_MOD) and MIX_INIT_MOD) <> MIX_INIT_MOD then
104 e_WriteLog('Error initializing SDL module player:', MSG_FATALERROR);
105 e_WriteLog(Mix_GetError(), MSG_FATALERROR);
110 res
:= Mix_OpenAudio(44100, AUDIO_S16LSB
, 2, 512);
113 e_WriteLog('Error initializing SDL mixer:', MSG_FATALERROR
);
114 e_WriteLog(Mix_GetError(), MSG_FATALERROR
);
118 Mix_AllocateChannels(N_CHANNELS
);
120 SoundInitialized
:= True;
124 function e_isMusic (id
: DWORD
): Boolean;
127 if (e_SoundsArray
<> nil) and (id
<= High(e_SoundsArray
)) then
129 Result
:= (e_SoundsArray
[id
].Music
<> nil);
133 function e_isSound (id
: DWORD
): Boolean;
136 if (e_SoundsArray
<> nil) and (id
<= High(e_SoundsArray
)) then
138 Result
:= (e_SoundsArray
[id
].Sound
<> nil);
142 function FindESound(): DWORD
;
146 if e_SoundsArray
<> nil then
147 for i
:= 0 to High(e_SoundsArray
) do
148 if (e_SoundsArray
[i
].Sound
= nil) and (e_SoundsArray
[i
].Music
= nil) then
154 if e_SoundsArray
= nil then
156 SetLength(e_SoundsArray
, 16);
161 Result
:= High(e_SoundsArray
) + 1;
162 SetLength(e_SoundsArray
, Length(e_SoundsArray
) + 16);
166 function e_LoadSound(FileName
: String; var ID
: DWORD
; isMusic
: Boolean): Boolean;
171 if not SoundInitialized
then Exit
;
173 if isMusic
then e_WriteLog('Loading music '+FileName
+'...', MSG_NOTIFY
)
174 else e_WriteLog('Loading sound '+FileName
+'...', MSG_NOTIFY
);
176 find_id
:= FindESound();
178 e_SoundsArray
[find_id
].Data
:= nil;
179 e_SoundsArray
[find_id
].isMusic
:= isMusic
;
183 e_SoundsArray
[find_id
].Music
:= Mix_LoadMUS(PAnsiChar(FileName
));
184 if e_SoundsArray
[find_id
].Music
= nil then Exit
;
188 e_SoundsArray
[find_id
].Sound
:= Mix_LoadWAV(PAnsiChar(FileName
));
189 if e_SoundsArray
[find_id
].Sound
= nil then Exit
;
197 function e_LoadSoundMem(pData
: Pointer; Length
: Integer; var ID
: DWORD
; isMusic
: Boolean): Boolean;
203 if not SoundInitialized
then Exit
;
205 rw
:= SDL_RWFromConstMem(pData
, Length
);
206 if rw
= nil then Exit
;
208 find_id
:= FindESound();
210 e_SoundsArray
[find_id
].Data
:= pData
;
211 e_SoundsArray
[find_id
].isMusic
:= isMusic
;
215 e_SoundsArray
[find_id
].Music
:= Mix_LoadMUS_RW(rw
, 0);
219 e_SoundsArray
[find_id
].Sound
:= Mix_LoadWAV_RW(rw
, 0);
222 if (e_SoundsArray
[find_id
].Sound
= nil) and (e_SoundsArray
[find_id
].Music
= nil) then Exit
;
229 function e_PlaySound (ID
: DWORD
): Integer;
234 if not SoundInitialized
then Exit
;
236 if {(e_SoundsArray[ID].nRefs >= gMaxSimSounds) or} (e_SoundsArray
[ID
].Sound
= nil) and (e_SoundsArray
[ID
].Music
= nil) then Exit
;
238 if e_SoundsArray
[ID
].Music
<> nil then
240 res
:= Mix_PlayMusic(e_SoundsArray
[ID
].Music
, -1);
241 if res
>= 0 then res
:= N_MUSCHAN
;
246 if e_SoundsArray
[ID
].Sound
<> nil then
247 res
:= Mix_PlayChannel(-1, e_SoundsArray
[ID
].Sound
, 0);
249 if e_SoundsArray[ID].isMusic then
250 res := Mix_PlayChannel(-1, e_SoundsArray[ID].Sound, -1)
252 res := Mix_PlayChannel(-1, e_SoundsArray[ID].Sound, 0);
255 if SoundMuted
and (res
>= 0) then Mix_Volume(res
, 0);
260 function e_PlaySoundPan(ID
: DWORD
; Pan
: Single): Integer;
266 chan
:= e_PlaySound(ID
);
267 if (chan
>= 0) and (chan
<> N_MUSCHAN
) then
269 if Pan
< -1.0 then Pan
:= -1.0 else if Pan
> 1.0 then Pan
:= 1.0;
270 Pan
:= Pan
+1.0; // 0..2
271 l
:= trunc(127.0*(2.0-Pan
));
272 r
:= trunc(127.0*Pan
);
273 Mix_SetPanning(chan
, l
, r
);
278 function e_PlaySoundVolume(ID
: DWORD
; Volume
: Single): Integer;
283 chan
:= e_PlaySound(ID
);
284 if (chan
>= 0) and (chan
<> N_MUSCHAN
) then
286 if Volume
< 0 then Volume
:= 0 else if Volume
> 1 then Volume
:= 1;
287 if not SoundMuted
then Mix_Volume(chan
, trunc(Volume
*MIX_MAX_VOLUME
));
292 function e_PlaySoundPanVolume(ID
: DWORD
; Pan
, Volume
: Single): Integer;
298 chan
:= e_PlaySound(ID
);
299 if (chan
>= 0) and (chan
<> N_MUSCHAN
) then
301 if Pan
< -1.0 then Pan
:= -1.0 else if Pan
> 1.0 then Pan
:= 1.0;
302 Pan
:= Pan
+1.0; // 0..2
303 l
:= trunc(127.0*(2.0-Pan
));
304 r
:= trunc(127.0*Pan
);
305 Mix_SetPanning(chan
, l
, r
);
306 if Volume
< 0 then Volume
:= 0 else if Volume
> 1 then Volume
:= 1;
307 if not SoundMuted
then Mix_Volume(chan
, trunc(Volume
*MIX_MAX_VOLUME
));
312 procedure e_DeleteSound(ID
: DWORD
);
314 if (e_SoundsArray
[ID
].Sound
= nil) and (e_SoundsArray
[ID
].Music
= nil) then Exit
;
315 if e_SoundsArray
[ID
].Data
<> nil then FreeMem(e_SoundsArray
[ID
].Data
);
317 if e_SoundsArray
[ID
].Sound
<> nil then Mix_FreeChunk(e_SoundsArray
[ID
].Sound
);
318 if e_SoundsArray
[ID
].Music
<> nil then Mix_FreeMusic(e_SoundsArray
[ID
].Music
);
320 e_SoundsArray
[ID
].Sound
:= nil;
321 e_SoundsArray
[ID
].Music
:= nil;
322 e_SoundsArray
[ID
].Data
:= nil;
326 procedure e_ModifyChannelsVolumes(SoundMod
: Single; setMode
: Boolean);
334 // Mix_Volume(-1, volm);
336 for i := 0 to N_CHANNELS-1 do
339 res := FMOD_System_GetChannel(F_System, i, Chan);
341 if (res = FMOD_OK) and (Chan <> nil) then
343 res := FMOD_Channel_GetVolume(Chan, vol);
345 if res = FMOD_OK then
350 vol := vol * SoundMod;
352 res := FMOD_Channel_SetVolume(Chan, vol);
354 if res <> FMOD_OK then
364 procedure e_MuteChannels(Enable
: Boolean);
373 if Enable = SoundMuted then
376 SoundMuted := Enable;
378 for i := 0 to N_CHANNELS-1 do
381 res := FMOD_System_GetChannel(F_System, i, Chan);
383 if (res = FMOD_OK) and (Chan <> nil) then
385 res := FMOD_Channel_SetMute(Chan, Enable);
387 if res <> FMOD_OK then
395 procedure e_StopChannels();
401 procedure e_RemoveAllSounds();
405 if SoundInitialized
then e_StopChannels();
407 for i
:= 0 to High(e_SoundsArray
) do
408 if e_SoundsArray
[i
].Sound
<> nil then
411 SetLength(e_SoundsArray
, 0);
412 e_SoundsArray
:= nil;
415 procedure e_ReleaseSoundSystem();
419 if SoundInitialized
then
422 SoundInitialized
:= False;
426 procedure e_SoundUpdate();
428 //FMOD_System_Update(F_System);
433 constructor TBasicSound
.Create();
442 destructor TBasicSound
.Destroy();
448 procedure TBasicSound
.FreeSound();
450 if FID
= NO_SOUND_ID
then Exit
;
458 function TBasicSound
.RawPlay(Pan
: Single; Volume
: Single; aPos
: DWORD
): Boolean;
461 if (FID
= NO_SOUND_ID
) or not SoundInitialized
then Exit
;
462 Result
:= (e_PlaySoundPanVolume(FID
, Pan
, Volume
) >= 0);
466 procedure TBasicSound
.SetID(ID
: DWORD
);
470 FMusic
:= e_SoundsArray
[ID
].isMusic
;
473 function TBasicSound
.IsPlaying(): Boolean;
476 if FChannel
< 0 then Exit
;
477 if e_isSound(FID
) then Result
:= (Mix_Playing(FChannel
) > 0)
478 else Result
:= (Mix_PlayingMusic() > 0);
481 procedure TBasicSound
.Stop();
484 if FChannel
< 0 then Exit
;
486 if e_isSound(FID
) then Mix_HaltChannel(FChannel
) else Mix_HaltMusic();
490 function TBasicSound
.IsPaused(): Boolean;
493 if FChannel
< 0 then Exit
;
494 if e_isSound(FID
) then Result
:= (Mix_Paused(FChannel
) > 0) else Result
:= (Mix_PausedMusic() > 0);
497 procedure TBasicSound
.Pause(Enable
: Boolean);
499 if FChannel
< 0 then Exit
;
504 if e_isSound(FID
) then Mix_Resume(FChannel
) else Mix_ResumeMusic();
511 if e_isSound(FID
) then Mix_Pause(FChannel
) else Mix_PauseMusic();
517 res := FMOD_Channel_GetPosition(FChannel, FPosition, FMOD_TIMEUNIT_MS);
518 if res <> FMOD_OK then
526 function TBasicSound
.GetVolume(): Single;
529 if FChannel
< 0 then Exit
;
531 res := FMOD_Channel_GetVolume(FChannel, vol);
532 if res <> FMOD_OK then
540 procedure TBasicSound
.SetVolume(Volume
: Single);
542 if FChannel
< 0 then Exit
;
543 if Volume
< 0 then Volume
:= 0 else if Volume
> 1 then Volume
:= 1;
544 if e_isSound(FID
) then Mix_Volume(FChannel
, trunc(Volume
*MIX_MAX_VOLUME
))
545 else Mix_VolumeMusic(trunc(Volume
*MIX_MAX_VOLUME
))
549 function TBasicSound
.GetPan(): Single;
552 if FChannel
< 0 then Exit
;
554 res := FMOD_Channel_GetPan(FChannel, pan);
555 if res <> FMOD_OK then
563 procedure TBasicSound
.SetPan(Pan
: Single);
567 if FChannel
< 0 then Exit
;
568 if not e_isSound(FID
) then Exit
;
569 if Pan
< -1.0 then Pan
:= -1.0 else if Pan
> 1.0 then Pan
:= 1.0;
570 Pan
:= Pan
+1.0; // 0..2
571 l
:= trunc(127.0*(2.0-Pan
));
572 r
:= trunc(127.0*Pan
);
573 Mix_SetPanning(FChannel
, l
, r
);
577 function TBasicSound
.IsMuted(): Boolean;
580 if FChannel
< 0 then Exit
;
582 res := FMOD_Channel_GetMute(FChannel, b);
583 if res <> FMOD_OK then
592 procedure TBasicSound
.Mute(Enable
: Boolean);
594 if FChannel
< 0 then Exit
;
596 res := FMOD_Channel_SetMute(FChannel, Enable);
597 if res <> FMOD_OK then
604 function TBasicSound
.GetPosition(): DWORD
;
607 if FChannel
< 0 then Exit
;
609 res := FMOD_Channel_GetPosition(FChannel, FPosition, FMOD_TIMEUNIT_MS);
610 if res <> FMOD_OK then
619 procedure TBasicSound
.SetPosition(aPos
: DWORD
);
622 if FChannel
< 0 then Exit
;
624 res := FMOD_Channel_SetPosition(FChannel, FPosition, FMOD_TIMEUNIT_MS);
625 if res <> FMOD_OK then
632 procedure TBasicSound
.SetPriority(priority
: Integer);
635 if (FChannel <> nil) and (FPriority <> priority) and
636 (priority >= 0) and (priority <= 256) then
638 FPriority := priority;
639 res := FMOD_Channel_SetPriority(FChannel, priority);
640 if res <> FMOD_OK then