DEADSOFTWARE

osx: fix build with fmodex
[d2df-sdl.git] / src / engine / e_sound_fmod.inc
1 (* Copyright (C) Doom 2D: Forever Developers
2 *
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, version 3 of the License ONLY.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *)
15 interface
17 uses
18 fmod,
19 fmodtypes,
20 fmoderrors,
21 {$IFDEF USE_MEMPOOL}mempool,{$ENDIF}
22 e_log,
23 SysUtils;
25 type
26 TSoundRec = record
27 Data: Pointer;
28 Sound: FMOD_SOUND;
29 isMusic: Boolean;
30 nRefs: Integer;
31 end;
33 TBasicSound = class{$IFDEF USE_MEMPOOL}(TPoolObject){$ENDIF}
34 private
35 FChannel: FMOD_CHANNEL;
37 protected
38 FID: DWORD;
39 FMusic: Boolean;
40 FPosition: DWORD;
41 FPriority: Integer;
43 function RawPlay(Pan: Single; Volume: Single; aPos: DWORD): Boolean;
45 public
46 constructor Create();
47 destructor Destroy(); override;
48 procedure SetID(ID: DWORD);
49 procedure FreeSound();
50 function IsPlaying(): Boolean;
51 procedure Stop();
52 function IsPaused(): Boolean;
53 procedure Pause(Enable: Boolean);
54 function GetVolume(): Single;
55 procedure SetVolume(Volume: Single);
56 function GetPan(): Single;
57 procedure SetPan(Pan: Single);
58 function IsMuted(): Boolean;
59 procedure Mute(Enable: Boolean);
60 function GetPosition(): DWORD;
61 procedure SetPosition(aPos: DWORD);
62 procedure SetPriority(priority: Integer);
63 end;
65 const
66 NO_SOUND_ID = DWORD(-1);
68 function e_InitSoundSystem(NoOutput: Boolean = False): Boolean;
70 function e_LoadSound(FileName: string; var ID: DWORD; isMusic: Boolean; ForceNoLoop: Boolean = False): Boolean;
71 function e_LoadSoundMem(pData: Pointer; Length: Integer; var ID: DWORD; isMusic: Boolean; ForceNoLoop: Boolean = False): Boolean;
73 function e_PlaySound(ID: DWORD): Integer;
74 function e_PlaySoundPan(ID: DWORD; Pan: Single): Integer;
75 function e_PlaySoundVolume(ID: DWORD; Volume: Single): Integer;
76 function e_PlaySoundPanVolume(ID: DWORD; Pan, Volume: Single): Integer;
78 procedure e_ModifyChannelsVolumes(SoundMod: Single; setMode: Boolean);
79 procedure e_MuteChannels(Enable: Boolean);
80 procedure e_StopChannels();
82 procedure e_DeleteSound(ID: DWORD);
83 procedure e_RemoveAllSounds();
84 procedure e_ReleaseSoundSystem();
85 procedure e_SoundUpdate();
87 var
88 e_SoundsArray: array of TSoundRec = nil;
90 implementation
92 uses
93 g_window, g_options, utils;
95 const
96 N_CHANNELS = 512;
98 var
99 F_System: FMOD_SYSTEM = nil;
100 SoundMuted: Boolean = False;
103 function Channel_Callback(channel: FMOD_CHANNEL; callbacktype: FMOD_CHANNEL_CALLBACKTYPE;
104 commanddata1: Pointer; commanddata2: Pointer): FMOD_RESULT; {$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF}
105 var
106 res: FMOD_RESULT;
107 sound: FMOD_SOUND;
108 ud: Pointer;
109 id: DWORD;
111 begin
112 res := FMOD_OK;
114 if callbacktype = FMOD_CHANNEL_CALLBACKTYPE_END then
115 begin
116 res := FMOD_Channel_GetCurrentSound(channel, sound);
117 if res = FMOD_OK then
118 begin
119 res := FMOD_Sound_GetUserData(sound, ud);
120 if res = FMOD_OK then
121 begin
122 id := DWORD(ud^);
123 if id < DWORD(Length(e_SoundsArray)) then
124 if e_SoundsArray[id].nRefs > 0 then
125 Dec(e_SoundsArray[id].nRefs);
126 end;
127 end;
128 end;
130 Result := res;
131 end;
133 function TryInitWithOutput(Output: FMOD_OUTPUTTYPE; OutputName: String): FMOD_RESULT;
134 begin
135 e_WriteLog('Trying with ' + OutputName + '...', TMsgType.Warning);
136 Result := FMOD_System_SetOutput(F_System, Output);
137 if Result <> FMOD_OK then
138 begin
139 e_WriteLog('Error setting FMOD output to ' + OutputName + '!', TMsgType.Warning);
140 e_WriteLog(FMOD_ErrorString(Result), TMsgType.Warning);
141 Exit;
142 end;
143 Result := FMOD_System_Init(F_System, N_CHANNELS, FMOD_INIT_NORMAL, nil);
144 if Result <> FMOD_OK then
145 begin
146 e_WriteLog('Error initializing FMOD system!', TMsgType.Warning);
147 e_WriteLog(FMOD_ErrorString(Result), TMsgType.Warning);
148 Exit;
149 end;
150 end;
152 function e_TrySS (Freq: Integer; forceNoSound: Integer): Boolean;
153 var
154 res: FMOD_RESULT;
155 ver: Cardinal;
156 output: FMOD_OUTPUTTYPE;
157 drv: Integer;
159 begin
160 Result := False;
161 e_WriteLog(Format('Trying to initialize FMOD with %d', [Freq]), TMsgType.Notify);
163 res := FMOD_System_Create(F_System);
164 if res <> FMOD_OK then
165 begin
166 e_WriteLog('Error creating FMOD system:', TMsgType.Fatal);
167 e_WriteLog(FMOD_ErrorString(res), TMsgType.Fatal);
168 Exit;
169 end;
171 res := FMOD_System_GetVersion(F_System, ver);
172 if res <> FMOD_OK then
173 begin
174 e_WriteLog('Error getting FMOD version:', TMsgType.Fatal);
175 e_WriteLog(FMOD_ErrorString(res), TMsgType.Fatal);
176 Exit;
177 end;
179 if ver < FMOD_VERSION then
180 begin
181 e_WriteLog('FMOD library version is too old! Need '+IntToStr(FMOD_VERSION), TMsgType.Fatal);
182 Exit;
183 end;
185 res := FMOD_System_SetSoftwareFormat(F_System, Freq, FMOD_SOUND_FORMAT_PCM16, 0, 0, FMOD_DSP_RESAMPLER_LINEAR);
186 if res <> FMOD_OK then
187 begin
188 e_WriteLog('Error setting FMOD software format!', TMsgType.Fatal);
189 e_WriteLog(FMOD_ErrorString(res), TMsgType.Fatal);
190 Exit;
191 end;
193 if forceNoSound = 2 then
194 begin
195 res := TryInitWithOutput(FMOD_OUTPUTTYPE_NOSOUND, 'OUTPUTTYPE_NOSOUND');
196 if res <> FMOD_OK then
197 begin
198 e_WriteLog('FMOD: Giving up, can''t init with NOSOUND.', TMsgType.Fatal);
199 Exit;
200 end;
201 end
202 else
203 begin
204 res := FMOD_System_Init(F_System, N_CHANNELS, FMOD_INIT_NORMAL, nil);
205 if res <> FMOD_OK then
206 begin
207 e_WriteLog('Error initializing FMOD system!', TMsgType.Warning);
208 e_WriteLog(FMOD_ErrorString(res), TMsgType.Warning);
210 {$IFDEF LINUX}
211 res := TryInitWithOutput(FMOD_OUTPUTTYPE_ALSA, 'OUTPUTTYPE_ALSA');
212 if res <> FMOD_OK then
213 res := TryInitWithOutput(FMOD_OUTPUTTYPE_OSS, 'OUTPUTTYPE_OSS');
214 {$ENDIF}
215 {$IFDEF DARWIN}
216 res := TryInitWithOutput(FMOD_OUTPUTTYPE_COREAUDIO, 'OUTPUTTYPE_COREAUDIO');
217 if res <> FMOD_OK then
218 res := TryInitWithOutput(FMOD_OUTPUTTYPE_SOUNDMANAGER, 'OUTPUTTYPE_SOUNDMANAGER');
219 {$ENDIF}
220 if (res <> FMOD_OK) and (forceNoSound <> 1) then Exit;
221 if res <> FMOD_OK then
222 res := TryInitWithOutput(FMOD_OUTPUTTYPE_NOSOUND, 'OUTPUTTYPE_NOSOUND');
223 if res <> FMOD_OK then
224 begin
225 e_WriteLog('FMOD: Giving up, can''t init any output.', TMsgType.Fatal);
226 Exit;
227 end;
228 end;
229 end;
231 res := FMOD_System_GetOutput(F_System, output);
232 if res <> FMOD_OK then
233 e_WriteLog('Error getting FMOD output!', TMsgType.Warning)
234 else
235 case output of
236 FMOD_OUTPUTTYPE_NOSOUND: e_WriteLog('FMOD Output Method: NOSOUND', TMsgType.Notify);
237 FMOD_OUTPUTTYPE_NOSOUND_NRT: e_WriteLog('FMOD Output Method: NOSOUND_NRT', TMsgType.Notify);
238 FMOD_OUTPUTTYPE_DSOUND: e_WriteLog('FMOD Output Method: DSOUND', TMsgType.Notify);
239 FMOD_OUTPUTTYPE_WINMM: e_WriteLog('FMOD Output Method: WINMM', TMsgType.Notify);
240 FMOD_OUTPUTTYPE_OPENAL: e_WriteLog('FMOD Output Method: OPENAL', TMsgType.Notify);
241 FMOD_OUTPUTTYPE_WASAPI: e_WriteLog('FMOD Output Method: WASAPI', TMsgType.Notify);
242 FMOD_OUTPUTTYPE_ASIO: e_WriteLog('FMOD Output Method: ASIO', TMsgType.Notify);
243 FMOD_OUTPUTTYPE_OSS: e_WriteLog('FMOD Output Method: OSS', TMsgType.Notify);
244 FMOD_OUTPUTTYPE_ALSA: e_Writelog('FMOD Output Method: ALSA', TMsgType.Notify);
245 FMOD_OUTPUTTYPE_SOUNDMANAGER: e_Writelog('FMOD Output Method: SOUNDMANAGER', TMsgType.Notify);
246 FMOD_OUTPUTTYPE_COREAUDIO: e_Writelog('FMOD Output Method: COREAUDIO', TMsgType.Notify);
247 else e_WriteLog('FMOD Output Method: Unknown', TMsgType.Notify);
248 end;
250 res := FMOD_System_GetDriver(F_System, drv);
251 if res <> FMOD_OK then
252 e_WriteLog('Error getting FMOD driver!', TMsgType.Warning)
253 else
254 e_WriteLog('FMOD driver id: '+IntToStr(drv), TMsgType.Notify);
256 Result := True;
257 end;
259 function e_InitSoundSystem(NoOutput: Boolean = False): Boolean;
260 begin
261 if NoOutput then
262 begin
263 Result := e_TrySS(48000, 2);
264 Exit;
265 end;
266 Result := e_TrySS(48000, 0);
267 if not Result then Result := e_TrySS(44100, 1);
268 end;
270 function FindESound(): DWORD;
271 var
272 i: Integer;
274 begin
275 if e_SoundsArray <> nil then
276 for i := 0 to High(e_SoundsArray) do
277 if e_SoundsArray[i].Sound = nil then
278 begin
279 Result := i;
280 Exit;
281 end;
283 if e_SoundsArray = nil then
284 begin
285 SetLength(e_SoundsArray, 16);
286 Result := 0;
287 end
288 else
289 begin
290 Result := High(e_SoundsArray) + 1;
291 SetLength(e_SoundsArray, Length(e_SoundsArray) + 16);
292 end;
293 end;
295 function e_LoadSound(FileName: String; var ID: DWORD; isMusic: Boolean; ForceNoLoop: Boolean = False): Boolean;
296 var
297 find_id: DWORD;
298 res: FMOD_RESULT;
299 bt: Cardinal;
300 ud: Pointer;
302 begin
303 Result := False;
305 e_WriteLog('Loading sound '+FileName+'...', TMsgType.Notify);
307 find_id := FindESound();
309 if isMusic and not ForceNoLoop then
310 bt := FMOD_LOOP_NORMAL
311 else
312 bt := FMOD_LOOP_OFF;
314 if not isMusic then
315 res := FMOD_System_CreateSound(F_System, PAnsiChar(FileName),
316 bt + FMOD_2D + FMOD_HARDWARE,
317 nil, e_SoundsArray[find_id].Sound)
318 else
319 res := FMOD_System_CreateStream(F_System, PAnsiChar(FileName),
320 bt + FMOD_2D + FMOD_HARDWARE,
321 nil, e_SoundsArray[find_id].Sound);
322 if res <> FMOD_OK then
323 begin
324 e_SoundsArray[find_id].Sound := nil;
325 Exit;
326 end;
328 GetMem(ud, SizeOf(DWORD));
329 DWORD(ud^) := find_id;
330 res := FMOD_Sound_SetUserData(e_SoundsArray[find_id].Sound, ud);
331 if res <> FMOD_OK then
332 begin
333 e_SoundsArray[find_id].Sound := nil;
334 Exit;
335 end;
337 e_SoundsArray[find_id].Data := nil;
338 e_SoundsArray[find_id].isMusic := isMusic;
339 e_SoundsArray[find_id].nRefs := 0;
341 ID := find_id;
343 Result := True;
344 end;
346 function e_LoadSoundMem(pData: Pointer; Length: Integer; var ID: DWORD; isMusic: Boolean; ForceNoLoop: Boolean = False): Boolean;
347 var
348 find_id: DWORD;
349 res: FMOD_RESULT;
350 sz: Integer;
351 bt: Cardinal;
352 soundExInfo: FMOD_CREATESOUNDEXINFO;
353 ud: Pointer;
355 begin
356 Result := False;
358 find_id := FindESound();
360 sz := SizeOf(FMOD_CREATESOUNDEXINFO);
361 FillMemory(@soundExInfo, sz, 0);
362 soundExInfo.cbsize := sz;
363 soundExInfo.length := Length;
365 if isMusic and not ForceNoLoop then
366 bt := FMOD_LOOP_NORMAL
367 else
368 bt := FMOD_LOOP_OFF;
370 if not isMusic then
371 res := FMOD_System_CreateSound(F_System, pData,
372 bt + FMOD_2D + FMOD_HARDWARE + FMOD_OPENMEMORY,
373 @soundExInfo, e_SoundsArray[find_id].Sound)
374 else
375 res := FMOD_System_CreateStream(F_System, pData,
376 bt + FMOD_2D + FMOD_HARDWARE + FMOD_OPENMEMORY,
377 @soundExInfo, e_SoundsArray[find_id].Sound);
378 if res <> FMOD_OK then
379 begin
380 e_SoundsArray[find_id].Sound := nil;
381 Exit;
382 end;
384 GetMem(ud, SizeOf(DWORD));
385 DWORD(ud^) := find_id;
386 res := FMOD_Sound_SetUserData(e_SoundsArray[find_id].Sound, ud);
387 if res <> FMOD_OK then
388 begin
389 e_SoundsArray[find_id].Sound := nil;
390 Exit;
391 end;
393 e_SoundsArray[find_id].Data := pData;
394 e_SoundsArray[find_id].isMusic := isMusic;
395 e_SoundsArray[find_id].nRefs := 0;
397 ID := find_id;
399 Result := True;
400 end;
402 function e_PlaySound(ID: DWORD): Integer;
403 var
404 res: FMOD_RESULT;
405 Chan: FMOD_CHANNEL;
407 begin
408 if e_SoundsArray[ID].nRefs >= gMaxSimSounds then
409 begin
410 Result := 0;
411 Exit;
412 end;
414 Result := -1;
416 res := FMOD_System_PlaySound(F_System, FMOD_CHANNEL_FREE,
417 e_SoundsArray[ID].Sound, False, Chan);
418 if res <> FMOD_OK then
419 begin
420 Exit;
421 end;
423 res := FMOD_Channel_SetCallback(Chan, Channel_Callback);
424 if res <> FMOD_OK then
425 begin
426 end;
428 if SoundMuted then
429 begin
430 res := FMOD_Channel_SetMute(Chan, True);
431 if res <> FMOD_OK then
432 begin
433 end;
434 end;
436 Inc(e_SoundsArray[ID].nRefs);
437 Result := 0;
438 end;
440 function e_PlaySoundPan(ID: DWORD; Pan: Single): Integer;
441 var
442 res: FMOD_RESULT;
443 Chan: FMOD_CHANNEL;
445 begin
446 if e_SoundsArray[ID].nRefs >= gMaxSimSounds then
447 begin
448 Result := 0;
449 Exit;
450 end;
452 Result := -1;
454 res := FMOD_System_PlaySound(F_System, FMOD_CHANNEL_FREE,
455 e_SoundsArray[ID].Sound, False, Chan);
456 if res <> FMOD_OK then
457 begin
458 Exit;
459 end;
461 res := FMOD_Channel_SetPan(Chan, Pan);
462 if res <> FMOD_OK then
463 begin
464 end;
466 res := FMOD_Channel_SetCallback(Chan, Channel_Callback);
467 if res <> FMOD_OK then
468 begin
469 end;
471 if SoundMuted then
472 begin
473 res := FMOD_Channel_SetMute(Chan, True);
474 if res <> FMOD_OK then
475 begin
476 end;
477 end;
479 Inc(e_SoundsArray[ID].nRefs);
480 Result := 0;
481 end;
483 function e_PlaySoundVolume(ID: DWORD; Volume: Single): Integer;
484 var
485 res: FMOD_RESULT;
486 Chan: FMOD_CHANNEL;
488 begin
489 if e_SoundsArray[ID].nRefs >= gMaxSimSounds then
490 begin
491 Result := 0;
492 Exit;
493 end;
495 Result := -1;
497 res := FMOD_System_PlaySound(F_System, FMOD_CHANNEL_FREE,
498 e_SoundsArray[ID].Sound, False, Chan);
499 if res <> FMOD_OK then
500 begin
501 Exit;
502 end;
504 res := FMOD_Channel_SetVolume(Chan, Volume);
505 if res <> FMOD_OK then
506 begin
507 end;
509 res := FMOD_Channel_SetCallback(Chan, Channel_Callback);
510 if res <> FMOD_OK then
511 begin
512 end;
514 if SoundMuted then
515 begin
516 res := FMOD_Channel_SetMute(Chan, True);
517 if res <> FMOD_OK then
518 begin
519 end;
520 end;
522 Inc(e_SoundsArray[ID].nRefs);
523 Result := 0;
524 end;
526 function e_PlaySoundPanVolume(ID: DWORD; Pan, Volume: Single): Integer;
527 var
528 res: FMOD_RESULT;
529 Chan: FMOD_CHANNEL;
531 begin
532 if e_SoundsArray[ID].nRefs >= gMaxSimSounds then
533 begin
534 Result := 0;
535 Exit;
536 end;
538 Result := -1;
540 res := FMOD_System_PlaySound(F_System, FMOD_CHANNEL_FREE,
541 e_SoundsArray[ID].Sound, False, Chan);
542 if res <> FMOD_OK then
543 begin
544 Exit;
545 end;
547 res := FMOD_Channel_SetPan(Chan, Pan);
548 if res <> FMOD_OK then
549 begin
550 end;
552 res := FMOD_Channel_SetVolume(Chan, Volume);
553 if res <> FMOD_OK then
554 begin
555 end;
557 res := FMOD_Channel_SetCallback(Chan, Channel_Callback);
558 if res <> FMOD_OK then
559 begin
560 end;
562 if SoundMuted then
563 begin
564 res := FMOD_Channel_SetMute(Chan, True);
565 if res <> FMOD_OK then
566 begin
567 end;
568 end;
570 Inc(e_SoundsArray[ID].nRefs);
571 Result := 0;
572 end;
574 procedure e_DeleteSound(ID: DWORD);
575 var
576 res: FMOD_RESULT;
577 ud: Pointer;
579 begin
580 if e_SoundsArray[ID].Sound = nil then
581 Exit;
583 if e_SoundsArray[ID].Data <> nil then
584 FreeMem(e_SoundsArray[ID].Data);
586 res := FMOD_Sound_GetUserData(e_SoundsArray[ID].Sound, ud);
587 if res = FMOD_OK then
588 begin
589 FreeMem(ud);
590 end;
592 res := FMOD_Sound_Release(e_SoundsArray[ID].Sound);
593 if res <> FMOD_OK then
594 begin
595 e_WriteLog('Error releasing sound:', TMsgType.Warning);
596 e_WriteLog(FMOD_ErrorString(res), TMsgType.Warning);
597 end;
599 e_SoundsArray[ID].Sound := nil;
600 e_SoundsArray[ID].Data := nil;
601 end;
603 procedure e_ModifyChannelsVolumes(SoundMod: Single; setMode: Boolean);
604 var
605 res: FMOD_RESULT;
606 i: Integer;
607 Chan: FMOD_CHANNEL;
608 vol: Single;
610 begin
611 for i := 0 to N_CHANNELS-1 do
612 begin
613 Chan := nil;
614 res := FMOD_System_GetChannel(F_System, i, Chan);
616 if (res = FMOD_OK) and (Chan <> nil) then
617 begin
618 res := FMOD_Channel_GetVolume(Chan, vol);
620 if res = FMOD_OK then
621 begin
622 if setMode then
623 vol := SoundMod
624 else
625 vol := vol * SoundMod;
627 res := FMOD_Channel_SetVolume(Chan, vol);
629 if res <> FMOD_OK then
630 begin
631 end;
632 end;
633 end;
634 end;
635 end;
637 procedure e_MuteChannels(Enable: Boolean);
638 var
639 res: FMOD_RESULT;
640 i: Integer;
641 Chan: FMOD_CHANNEL;
643 begin
644 if Enable = SoundMuted then
645 Exit;
647 SoundMuted := Enable;
649 for i := 0 to N_CHANNELS-1 do
650 begin
651 Chan := nil;
652 res := FMOD_System_GetChannel(F_System, i, Chan);
654 if (res = FMOD_OK) and (Chan <> nil) then
655 begin
656 res := FMOD_Channel_SetMute(Chan, Enable);
658 if res <> FMOD_OK then
659 begin
660 end;
661 end;
662 end;
663 end;
665 procedure e_StopChannels();
666 var
667 res: FMOD_RESULT;
668 i: Integer;
669 Chan: FMOD_CHANNEL;
671 begin
672 for i := 0 to N_CHANNELS-1 do
673 begin
674 Chan := nil;
675 res := FMOD_System_GetChannel(F_System, i, Chan);
677 if (res = FMOD_OK) and (Chan <> nil) then
678 begin
679 res := FMOD_Channel_Stop(Chan);
681 if res <> FMOD_OK then
682 begin
683 end;
684 end;
685 end;
686 end;
688 procedure e_RemoveAllSounds();
689 var
690 i: Integer;
692 begin
693 for i := 0 to High(e_SoundsArray) do
694 if e_SoundsArray[i].Sound <> nil then
695 e_DeleteSound(i);
697 SetLength(e_SoundsArray, 0);
698 e_SoundsArray := nil;
699 end;
701 procedure e_ReleaseSoundSystem();
702 var
703 res: FMOD_RESULT;
705 begin
706 e_RemoveAllSounds();
708 res := FMOD_System_Close(F_System);
709 if res <> FMOD_OK then
710 begin
711 e_WriteLog('Error closing FMOD system!', TMsgType.Fatal);
712 e_WriteLog(FMOD_ErrorString(res), TMsgType.Fatal);
713 Exit;
714 end;
716 res := FMOD_System_Release(F_System);
717 if res <> FMOD_OK then
718 begin
719 e_WriteLog('Error releasing FMOD system!', TMsgType.Fatal);
720 e_WriteLog(FMOD_ErrorString(res), TMsgType.Fatal);
721 end;
722 end;
724 procedure e_SoundUpdate();
725 begin
726 FMOD_System_Update(F_System);
727 end;
729 { TBasicSound: }
731 constructor TBasicSound.Create();
732 begin
733 FID := NO_SOUND_ID;
734 FMusic := False;
735 FChannel := nil;
736 FPosition := 0;
737 FPriority := 128;
738 end;
740 destructor TBasicSound.Destroy();
741 begin
742 FreeSound();
743 inherited;
744 end;
746 procedure TBasicSound.FreeSound();
747 begin
748 if FID = NO_SOUND_ID then
749 Exit;
751 Stop();
752 FID := NO_SOUND_ID;
753 FMusic := False;
754 FPosition := 0;
755 end;
757 function TBasicSound.RawPlay(Pan: Single; Volume: Single; aPos: DWORD): Boolean;
758 var
759 res: FMOD_RESULT;
761 begin
762 Result := False;
763 if FID = NO_SOUND_ID then Exit;
765 if e_SoundsArray[FID].nRefs >= gMaxSimSounds then
766 begin
767 Result := True;
768 Exit;
769 end;
771 res := FMOD_System_PlaySound(F_System, FMOD_CHANNEL_FREE,
772 e_SoundsArray[FID].Sound, False, FChannel);
773 if res <> FMOD_OK then
774 begin
775 FChannel := nil;
776 Exit;
777 end;
779 res := FMOD_Channel_SetPosition(FChannel, aPos, FMOD_TIMEUNIT_MS);
780 if res <> FMOD_OK then
781 begin
782 FPosition := 0;
783 end
784 else
785 FPosition := aPos;
787 res := FMOD_Channel_SetPan(FChannel, Pan);
788 if res <> FMOD_OK then
789 begin
790 end;
792 res := FMOD_Channel_SetVolume(FChannel, Volume);
793 if res <> FMOD_OK then
794 begin
795 end;
797 res := FMOD_Channel_SetCallback(FChannel, Channel_Callback);
798 if res <> FMOD_OK then
799 begin
800 end;
802 if SoundMuted then
803 begin
804 res := FMOD_Channel_SetMute(FChannel, True);
805 if res <> FMOD_OK then
806 begin
807 end;
808 end;
810 Inc(e_SoundsArray[FID].nRefs);
811 Result := True;
812 end;
814 procedure TBasicSound.SetID(ID: DWORD);
815 begin
816 FreeSound();
817 FID := ID;
818 FMusic := e_SoundsArray[ID].isMusic;
819 end;
821 function TBasicSound.IsPlaying(): Boolean;
822 var
823 res: FMOD_RESULT;
824 b: LongBool;
826 begin
827 Result := False;
829 if FChannel = nil then
830 Exit;
832 res := FMOD_Channel_IsPlaying(FChannel, b);
833 if res <> FMOD_OK then
834 begin
835 Exit;
836 end;
838 Result := b;
839 end;
841 procedure TBasicSound.Stop();
842 var
843 res: FMOD_RESULT;
845 begin
846 if FChannel = nil then
847 Exit;
849 GetPosition();
851 res := FMOD_Channel_Stop(FChannel);
852 if res <> FMOD_OK then
853 begin
854 end;
856 FChannel := nil;
857 end;
859 function TBasicSound.IsPaused(): Boolean;
860 var
861 res: FMOD_RESULT;
862 b: LongBool;
864 begin
865 Result := False;
867 if FChannel = nil then
868 Exit;
870 res := FMOD_Channel_GetPaused(FChannel, b);
871 if res <> FMOD_OK then
872 begin
873 Exit;
874 end;
876 Result := b;
877 end;
879 procedure TBasicSound.Pause(Enable: Boolean);
880 var
881 res: FMOD_RESULT;
883 begin
884 if FChannel = nil then
885 Exit;
887 res := FMOD_Channel_SetPaused(FChannel, Enable);
888 if res <> FMOD_OK then
889 begin
890 end;
892 if Enable then
893 begin
894 res := FMOD_Channel_GetPosition(FChannel, FPosition, FMOD_TIMEUNIT_MS);
895 if res <> FMOD_OK then
896 begin
897 end;
898 end;
899 end;
901 function TBasicSound.GetVolume(): Single;
902 var
903 res: FMOD_RESULT;
904 vol: Single;
906 begin
907 Result := 0.0;
909 if FChannel = nil then
910 Exit;
912 res := FMOD_Channel_GetVolume(FChannel, vol);
913 if res <> FMOD_OK then
914 begin
915 Exit;
916 end;
918 Result := vol;
919 end;
921 procedure TBasicSound.SetVolume(Volume: Single);
922 var
923 res: FMOD_RESULT;
925 begin
926 if FChannel = nil then
927 Exit;
929 res := FMOD_Channel_SetVolume(FChannel, Volume);
930 if res <> FMOD_OK then
931 begin
932 end;
933 end;
935 function TBasicSound.GetPan(): Single;
936 var
937 res: FMOD_RESULT;
938 pan: Single;
940 begin
941 Result := 0.0;
943 if FChannel = nil then
944 Exit;
946 res := FMOD_Channel_GetPan(FChannel, pan);
947 if res <> FMOD_OK then
948 begin
949 Exit;
950 end;
952 Result := pan;
953 end;
955 procedure TBasicSound.SetPan(Pan: Single);
956 var
957 res: FMOD_RESULT;
959 begin
960 if FChannel = nil then
961 Exit;
963 res := FMOD_Channel_SetPan(FChannel, Pan);
964 if res <> FMOD_OK then
965 begin
966 end;
967 end;
969 function TBasicSound.IsMuted(): Boolean;
970 var
971 res: FMOD_RESULT;
972 b: LongBool;
974 begin
975 Result := False;
977 if FChannel = nil then
978 Exit;
980 res := FMOD_Channel_GetMute(FChannel, b);
981 if res <> FMOD_OK then
982 begin
983 Exit;
984 end;
986 Result := b;
987 end;
989 procedure TBasicSound.Mute(Enable: Boolean);
990 var
991 res: FMOD_RESULT;
993 begin
994 if FChannel = nil then
995 Exit;
997 res := FMOD_Channel_SetMute(FChannel, Enable);
998 if res <> FMOD_OK then
999 begin
1000 end;
1001 end;
1003 function TBasicSound.GetPosition(): DWORD;
1004 var
1005 res: FMOD_RESULT;
1007 begin
1008 Result := 0;
1010 if FChannel = nil then
1011 Exit;
1013 res := FMOD_Channel_GetPosition(FChannel, FPosition, FMOD_TIMEUNIT_MS);
1014 if res <> FMOD_OK then
1015 begin
1016 Exit;
1017 end;
1019 Result := FPosition;
1020 end;
1022 procedure TBasicSound.SetPosition(aPos: DWORD);
1023 var
1024 res: FMOD_RESULT;
1026 begin
1027 FPosition := aPos;
1029 if FChannel = nil then
1030 Exit;
1032 res := FMOD_Channel_SetPosition(FChannel, FPosition, FMOD_TIMEUNIT_MS);
1033 if res <> FMOD_OK then
1034 begin
1035 end;
1036 end;
1038 procedure TBasicSound.SetPriority(priority: Integer);
1039 var
1040 res: FMOD_RESULT;
1042 begin
1043 if (FChannel <> nil) and (FPriority <> priority) and
1044 (priority >= 0) and (priority <= 256) then
1045 begin
1046 FPriority := priority;
1047 res := FMOD_Channel_SetPriority(FChannel, priority);
1048 if res <> FMOD_OK then
1049 begin
1050 end;
1051 end;
1052 end;
1054 end.