DEADSOFTWARE

initial commit:
[d2df-sdl.git] / src / engine / e_sound.pas
1 unit e_sound;
3 interface
5 uses
6 fmod,
7 fmodtypes,
8 fmoderrors,
9 e_log,
10 SysUtils;
12 type
13 TSoundRec = record
14 Data: Pointer;
15 Sound: FMOD_SOUND;
16 Loop: Boolean;
17 nRefs: Integer;
18 end;
20 TBasicSound = class (TObject)
21 private
22 FChannel: FMOD_CHANNEL;
24 protected
25 FID: DWORD;
26 FLoop: Boolean;
27 FPosition: DWORD;
28 FPriority: Integer;
30 function RawPlay(Pan: Single; Volume: Single; aPos: DWORD): Boolean;
32 public
33 constructor Create();
34 destructor Destroy(); override;
35 procedure SetID(ID: DWORD);
36 procedure FreeSound();
37 function IsPlaying(): Boolean;
38 procedure Stop();
39 function IsPaused(): Boolean;
40 procedure Pause(Enable: Boolean);
41 function GetVolume(): Single;
42 procedure SetVolume(Volume: Single);
43 function GetPan(): Single;
44 procedure SetPan(Pan: Single);
45 function IsMuted(): Boolean;
46 procedure Mute(Enable: Boolean);
47 function GetPosition(): DWORD;
48 procedure SetPosition(aPos: DWORD);
49 procedure SetPriority(priority: Integer);
50 end;
52 const
53 NO_SOUND_ID = DWORD(-1);
55 function e_InitSoundSystem(Freq: Integer; forceNoSound: Boolean): Boolean;
57 function e_LoadSound(FileName: string; var ID: DWORD; bLoop: Boolean): Boolean;
58 function e_LoadSoundMem(pData: Pointer; Length: Integer; var ID: DWORD; bLoop: Boolean): Boolean;
60 function e_PlaySound(ID: DWORD): Boolean;
61 function e_PlaySoundPan(ID: DWORD; Pan: Single): Boolean;
62 function e_PlaySoundVolume(ID: DWORD; Volume: Single): Boolean;
63 function e_PlaySoundPanVolume(ID: DWORD; Pan, Volume: Single): Boolean;
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();
74 var
75 e_SoundsArray: array of TSoundRec = nil;
77 implementation
79 uses
80 g_window, g_options, BinEditor;
82 const
83 N_CHANNELS = 512;
85 var
86 F_System: FMOD_SYSTEM = nil;
87 SoundMuted: Boolean = False;
90 function Channel_Callback(channel: FMOD_CHANNEL; callbacktype: FMOD_CHANNEL_CALLBACKTYPE;
91 commanddata1: Pointer; commanddata2: Pointer): FMOD_RESULT; {$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF}
92 var
93 res: FMOD_RESULT;
94 sound: FMOD_SOUND;
95 ud: Pointer;
96 id: DWORD;
98 begin
99 res := FMOD_OK;
101 if callbacktype = FMOD_CHANNEL_CALLBACKTYPE_END then
102 begin
103 res := FMOD_Channel_GetCurrentSound(channel, sound);
104 if res = FMOD_OK then
105 begin
106 res := FMOD_Sound_GetUserData(sound, ud);
107 if res = FMOD_OK then
108 begin
109 id := DWORD(ud^);
110 if id < DWORD(Length(e_SoundsArray)) then
111 if e_SoundsArray[id].nRefs > 0 then
112 Dec(e_SoundsArray[id].nRefs);
113 end;
114 end;
115 end;
117 Result := res;
118 end;
120 function TryInitWithOutput(Output: FMOD_OUTPUTTYPE; OutputName: String): FMOD_RESULT;
121 begin
122 e_WriteLog('Trying with ' + OutputName + '...', MSG_WARNING);
123 Result := FMOD_System_SetOutput(F_System, Output);
124 if Result <> FMOD_OK then
125 begin
126 e_WriteLog('Error setting FMOD output to ' + OutputName + '!', MSG_WARNING);
127 e_WriteLog(FMOD_ErrorString(Result), MSG_WARNING);
128 Exit;
129 end;
130 Result := FMOD_System_Init(F_System, N_CHANNELS, FMOD_INIT_NORMAL, nil);
131 if Result <> FMOD_OK then
132 begin
133 e_WriteLog('Error initializing FMOD system!', MSG_WARNING);
134 e_WriteLog(FMOD_ErrorString(Result), MSG_WARNING);
135 Exit;
136 end;
137 end;
139 function e_InitSoundSystem(Freq: Integer; forceNoSound: Boolean): Boolean;
140 var
141 res: FMOD_RESULT;
142 ver: Cardinal;
143 output: FMOD_OUTPUTTYPE;
144 drv: Integer;
146 begin
147 Result := False;
149 res := FMOD_System_Create(F_System);
150 if res <> FMOD_OK then
151 begin
152 e_WriteLog('Error creating FMOD system:', MSG_FATALERROR);
153 e_WriteLog(FMOD_ErrorString(res), MSG_FATALERROR);
154 Exit;
155 end;
157 res := FMOD_System_GetVersion(F_System, ver);
158 if res <> FMOD_OK then
159 begin
160 e_WriteLog('Error getting FMOD version:', MSG_FATALERROR);
161 e_WriteLog(FMOD_ErrorString(res), MSG_FATALERROR);
162 Exit;
163 end;
165 if ver < FMOD_VERSION then
166 begin
167 e_WriteLog('FMOD library version is too old! Need '+IntToStr(FMOD_VERSION), MSG_FATALERROR);
168 Exit;
169 end;
171 res := FMOD_System_SetSoftwareFormat(F_System, Freq,
172 FMOD_SOUND_FORMAT_PCM16, 0, 0, FMOD_DSP_RESAMPLER_LINEAR);
173 if res <> FMOD_OK then
174 begin
175 e_WriteLog('Error setting FMOD software format!', MSG_FATALERROR);
176 e_WriteLog(FMOD_ErrorString(res), MSG_FATALERROR);
177 Exit;
178 end;
180 res := FMOD_System_Init(F_System, N_CHANNELS, FMOD_INIT_NORMAL, nil);
181 if res <> FMOD_OK then
182 begin
183 e_WriteLog('Error initializing FMOD system!', MSG_WARNING);
184 e_WriteLog(FMOD_ErrorString(res), MSG_WARNING);
186 {$IFDEF LINUX}
187 res := TryInitWithOutput(FMOD_OUTPUTTYPE_ALSA, 'OUTPUTTYPE_ALSA');
188 if res <> FMOD_OK then
189 res := TryInitWithOutput(FMOD_OUTPUTTYPE_OSS, 'OUTPUTTYPE_OSS');
190 {$ENDIF}
191 if not forceNoSound then Exit;
192 if res <> FMOD_OK then
193 res := TryInitWithOutput(FMOD_OUTPUTTYPE_NOSOUND, 'OUTPUTTYPE_NOSOUND');
194 if res <> FMOD_OK then
195 begin
196 e_WriteLog('FMOD: Giving up, can''t init any output.', MSG_FATALERROR);
197 Exit;
198 end;
199 end;
201 res := FMOD_System_GetOutput(F_System, output);
202 if res <> FMOD_OK then
203 e_WriteLog('Error getting FMOD output!', MSG_WARNING)
204 else
205 case output of
206 FMOD_OUTPUTTYPE_NOSOUND: e_WriteLog('FMOD Output Method: NOSOUND', MSG_NOTIFY);
207 FMOD_OUTPUTTYPE_NOSOUND_NRT: e_WriteLog('FMOD Output Method: NOSOUND_NRT', MSG_NOTIFY);
208 FMOD_OUTPUTTYPE_DSOUND: e_WriteLog('FMOD Output Method: DSOUND', MSG_NOTIFY);
209 FMOD_OUTPUTTYPE_WINMM: e_WriteLog('FMOD Output Method: WINMM', MSG_NOTIFY);
210 FMOD_OUTPUTTYPE_OPENAL: e_WriteLog('FMOD Output Method: OPENAL', MSG_NOTIFY);
211 FMOD_OUTPUTTYPE_WASAPI: e_WriteLog('FMOD Output Method: WASAPI', MSG_NOTIFY);
212 FMOD_OUTPUTTYPE_ASIO: e_WriteLog('FMOD Output Method: ASIO', MSG_NOTIFY);
213 FMOD_OUTPUTTYPE_OSS: e_WriteLog('FMOD Output Method: OSS', MSG_NOTIFY);
214 FMOD_OUTPUTTYPE_ALSA: e_Writelog('FMOD Output Method: ALSA', MSG_NOTIFY);
215 else e_WriteLog('FMOD Output Method: Unknown', MSG_NOTIFY);
216 end;
218 res := FMOD_System_GetDriver(F_System, drv);
219 if res <> FMOD_OK then
220 e_WriteLog('Error getting FMOD driver!', MSG_WARNING)
221 else
222 e_WriteLog('FMOD driver id: '+IntToStr(drv), MSG_NOTIFY);
224 Result := True;
225 end;
227 function FindESound(): DWORD;
228 var
229 i: Integer;
231 begin
232 if e_SoundsArray <> nil then
233 for i := 0 to High(e_SoundsArray) do
234 if e_SoundsArray[i].Sound = nil then
235 begin
236 Result := i;
237 Exit;
238 end;
240 if e_SoundsArray = nil then
241 begin
242 SetLength(e_SoundsArray, 16);
243 Result := 0;
244 end
245 else
246 begin
247 Result := High(e_SoundsArray) + 1;
248 SetLength(e_SoundsArray, Length(e_SoundsArray) + 16);
249 end;
250 end;
252 function e_LoadSound(FileName: String; var ID: DWORD; bLoop: Boolean): Boolean;
253 var
254 find_id: DWORD;
255 res: FMOD_RESULT;
256 bt: Cardinal;
257 ud: Pointer;
259 begin
260 Result := False;
262 e_WriteLog('Loading sound '+FileName+'...', MSG_NOTIFY);
264 find_id := FindESound();
266 if bLoop then
267 bt := FMOD_LOOP_NORMAL
268 else
269 bt := FMOD_LOOP_OFF;
271 if not bLoop then
272 res := FMOD_System_CreateSound(F_System, PAnsiChar(FileName),
273 bt + FMOD_2D + FMOD_HARDWARE,
274 nil, e_SoundsArray[find_id].Sound)
275 else
276 res := FMOD_System_CreateStream(F_System, PAnsiChar(FileName),
277 bt + FMOD_2D + FMOD_HARDWARE,
278 nil, e_SoundsArray[find_id].Sound);
279 if res <> FMOD_OK then
280 begin
281 e_SoundsArray[find_id].Sound := nil;
282 Exit;
283 end;
285 GetMem(ud, SizeOf(DWORD));
286 DWORD(ud^) := find_id;
287 res := FMOD_Sound_SetUserData(e_SoundsArray[find_id].Sound, ud);
288 if res <> FMOD_OK then
289 begin
290 e_SoundsArray[find_id].Sound := nil;
291 Exit;
292 end;
294 e_SoundsArray[find_id].Data := nil;
295 e_SoundsArray[find_id].Loop := bLoop;
296 e_SoundsArray[find_id].nRefs := 0;
298 ID := find_id;
300 Result := True;
301 end;
303 function e_LoadSoundMem(pData: Pointer; Length: Integer; var ID: DWORD; bLoop: Boolean): Boolean;
304 var
305 find_id: DWORD;
306 res: FMOD_RESULT;
307 sz: Integer;
308 bt: Cardinal;
309 soundExInfo: FMOD_CREATESOUNDEXINFO;
310 ud: Pointer;
312 begin
313 Result := False;
315 find_id := FindESound();
317 sz := SizeOf(FMOD_CREATESOUNDEXINFO);
318 FillMemory(@soundExInfo, sz, 0);
319 soundExInfo.cbsize := sz;
320 soundExInfo.length := Length;
322 if bLoop then
323 bt := FMOD_LOOP_NORMAL
324 else
325 bt := FMOD_LOOP_OFF;
327 if not bLoop then
328 res := FMOD_System_CreateSound(F_System, pData,
329 bt + FMOD_2D + FMOD_HARDWARE + FMOD_OPENMEMORY,
330 @soundExInfo, e_SoundsArray[find_id].Sound)
331 else
332 res := FMOD_System_CreateStream(F_System, pData,
333 bt + FMOD_2D + FMOD_HARDWARE + FMOD_OPENMEMORY,
334 @soundExInfo, e_SoundsArray[find_id].Sound);
335 if res <> FMOD_OK then
336 begin
337 e_SoundsArray[find_id].Sound := nil;
338 Exit;
339 end;
341 GetMem(ud, SizeOf(DWORD));
342 DWORD(ud^) := find_id;
343 res := FMOD_Sound_SetUserData(e_SoundsArray[find_id].Sound, ud);
344 if res <> FMOD_OK then
345 begin
346 e_SoundsArray[find_id].Sound := nil;
347 Exit;
348 end;
350 e_SoundsArray[find_id].Data := pData;
351 e_SoundsArray[find_id].Loop := bLoop;
352 e_SoundsArray[find_id].nRefs := 0;
354 ID := find_id;
356 Result := True;
357 end;
359 function e_PlaySound(ID: DWORD): Boolean;
360 var
361 res: FMOD_RESULT;
362 Chan: FMOD_CHANNEL;
364 begin
365 if e_SoundsArray[ID].nRefs >= gMaxSimSounds then
366 begin
367 Result := True;
368 Exit;
369 end;
371 Result := False;
373 res := FMOD_System_PlaySound(F_System, FMOD_CHANNEL_FREE,
374 e_SoundsArray[ID].Sound, False, Chan);
375 if res <> FMOD_OK then
376 begin
377 Exit;
378 end;
380 res := FMOD_Channel_SetCallback(Chan, Channel_Callback);
381 if res <> FMOD_OK then
382 begin
383 end;
385 if SoundMuted then
386 begin
387 res := FMOD_Channel_SetMute(Chan, True);
388 if res <> FMOD_OK then
389 begin
390 end;
391 end;
393 Inc(e_SoundsArray[ID].nRefs);
394 Result := True;
395 end;
397 function e_PlaySoundPan(ID: DWORD; Pan: Single): Boolean;
398 var
399 res: FMOD_RESULT;
400 Chan: FMOD_CHANNEL;
402 begin
403 if e_SoundsArray[ID].nRefs >= gMaxSimSounds then
404 begin
405 Result := True;
406 Exit;
407 end;
409 Result := False;
411 res := FMOD_System_PlaySound(F_System, FMOD_CHANNEL_FREE,
412 e_SoundsArray[ID].Sound, False, Chan);
413 if res <> FMOD_OK then
414 begin
415 Exit;
416 end;
418 res := FMOD_Channel_SetPan(Chan, Pan);
419 if res <> FMOD_OK then
420 begin
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 := True;
438 end;
440 function e_PlaySoundVolume(ID: DWORD; Volume: Single): Boolean;
441 var
442 res: FMOD_RESULT;
443 Chan: FMOD_CHANNEL;
445 begin
446 if e_SoundsArray[ID].nRefs >= gMaxSimSounds then
447 begin
448 Result := True;
449 Exit;
450 end;
452 Result := False;
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_SetVolume(Chan, Volume);
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 := True;
481 end;
483 function e_PlaySoundPanVolume(ID: DWORD; Pan, Volume: Single): Boolean;
484 var
485 res: FMOD_RESULT;
486 Chan: FMOD_CHANNEL;
488 begin
489 if e_SoundsArray[ID].nRefs >= gMaxSimSounds then
490 begin
491 Result := True;
492 Exit;
493 end;
495 Result := False;
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_SetPan(Chan, Pan);
505 if res <> FMOD_OK then
506 begin
507 end;
509 res := FMOD_Channel_SetVolume(Chan, Volume);
510 if res <> FMOD_OK then
511 begin
512 end;
514 res := FMOD_Channel_SetCallback(Chan, Channel_Callback);
515 if res <> FMOD_OK then
516 begin
517 end;
519 if SoundMuted then
520 begin
521 res := FMOD_Channel_SetMute(Chan, True);
522 if res <> FMOD_OK then
523 begin
524 end;
525 end;
527 Inc(e_SoundsArray[ID].nRefs);
528 Result := True;
529 end;
531 procedure e_DeleteSound(ID: DWORD);
532 var
533 res: FMOD_RESULT;
534 ud: Pointer;
536 begin
537 if e_SoundsArray[ID].Sound = nil then
538 Exit;
540 if e_SoundsArray[ID].Data <> nil then
541 FreeMem(e_SoundsArray[ID].Data);
543 res := FMOD_Sound_GetUserData(e_SoundsArray[ID].Sound, ud);
544 if res = FMOD_OK then
545 begin
546 FreeMem(ud);
547 end;
549 res := FMOD_Sound_Release(e_SoundsArray[ID].Sound);
550 if res <> FMOD_OK then
551 begin
552 e_WriteLog('Error releasing sound:', MSG_WARNING);
553 e_WriteLog(FMOD_ErrorString(res), MSG_WARNING);
554 end;
556 e_SoundsArray[ID].Sound := nil;
557 e_SoundsArray[ID].Data := nil;
558 end;
560 procedure e_ModifyChannelsVolumes(SoundMod: Single; setMode: Boolean);
561 var
562 res: FMOD_RESULT;
563 i: Integer;
564 Chan: FMOD_CHANNEL;
565 vol: Single;
567 begin
568 for i := 0 to N_CHANNELS-1 do
569 begin
570 Chan := nil;
571 res := FMOD_System_GetChannel(F_System, i, Chan);
573 if (res = FMOD_OK) and (Chan <> nil) then
574 begin
575 res := FMOD_Channel_GetVolume(Chan, vol);
577 if res = FMOD_OK then
578 begin
579 if setMode then
580 vol := SoundMod
581 else
582 vol := vol * SoundMod;
584 res := FMOD_Channel_SetVolume(Chan, vol);
586 if res <> FMOD_OK then
587 begin
588 end;
589 end;
590 end;
591 end;
592 end;
594 procedure e_MuteChannels(Enable: Boolean);
595 var
596 res: FMOD_RESULT;
597 i: Integer;
598 Chan: FMOD_CHANNEL;
600 begin
601 if Enable = SoundMuted then
602 Exit;
604 SoundMuted := Enable;
606 for i := 0 to N_CHANNELS-1 do
607 begin
608 Chan := nil;
609 res := FMOD_System_GetChannel(F_System, i, Chan);
611 if (res = FMOD_OK) and (Chan <> nil) then
612 begin
613 res := FMOD_Channel_SetMute(Chan, Enable);
615 if res <> FMOD_OK then
616 begin
617 end;
618 end;
619 end;
620 end;
622 procedure e_StopChannels();
623 var
624 res: FMOD_RESULT;
625 i: Integer;
626 Chan: FMOD_CHANNEL;
628 begin
629 for i := 0 to N_CHANNELS-1 do
630 begin
631 Chan := nil;
632 res := FMOD_System_GetChannel(F_System, i, Chan);
634 if (res = FMOD_OK) and (Chan <> nil) then
635 begin
636 res := FMOD_Channel_Stop(Chan);
638 if res <> FMOD_OK then
639 begin
640 end;
641 end;
642 end;
643 end;
645 procedure e_RemoveAllSounds();
646 var
647 i: Integer;
649 begin
650 for i := 0 to High(e_SoundsArray) do
651 if e_SoundsArray[i].Sound <> nil then
652 e_DeleteSound(i);
654 SetLength(e_SoundsArray, 0);
655 e_SoundsArray := nil;
656 end;
658 procedure e_ReleaseSoundSystem();
659 var
660 res: FMOD_RESULT;
662 begin
663 e_RemoveAllSounds();
665 res := FMOD_System_Close(F_System);
666 if res <> FMOD_OK then
667 begin
668 e_WriteLog('Error closing FMOD system!', MSG_FATALERROR);
669 e_WriteLog(FMOD_ErrorString(res), MSG_FATALERROR);
670 Exit;
671 end;
673 res := FMOD_System_Release(F_System);
674 if res <> FMOD_OK then
675 begin
676 e_WriteLog('Error releasing FMOD system!', MSG_FATALERROR);
677 e_WriteLog(FMOD_ErrorString(res), MSG_FATALERROR);
678 end;
679 end;
681 procedure e_SoundUpdate();
682 begin
683 FMOD_System_Update(F_System);
684 end;
686 { TBasicSound: }
688 constructor TBasicSound.Create();
689 begin
690 FID := NO_SOUND_ID;
691 FLoop := False;
692 FChannel := nil;
693 FPosition := 0;
694 FPriority := 128;
695 end;
697 destructor TBasicSound.Destroy();
698 begin
699 FreeSound();
700 inherited;
701 end;
703 procedure TBasicSound.FreeSound();
704 begin
705 if FID = NO_SOUND_ID then
706 Exit;
708 Stop();
709 FID := NO_SOUND_ID;
710 FLoop := False;
711 FPosition := 0;
712 end;
714 function TBasicSound.RawPlay(Pan: Single; Volume: Single; aPos: DWORD): Boolean;
715 var
716 res: FMOD_RESULT;
718 begin
719 if e_SoundsArray[FID].nRefs >= gMaxSimSounds then
720 begin
721 Result := True;
722 Exit;
723 end;
725 Result := False;
727 if FID = NO_SOUND_ID then
728 Exit;
730 res := FMOD_System_PlaySound(F_System, FMOD_CHANNEL_FREE,
731 e_SoundsArray[FID].Sound, False, FChannel);
732 if res <> FMOD_OK then
733 begin
734 FChannel := nil;
735 Exit;
736 end;
738 res := FMOD_Channel_SetPosition(FChannel, aPos, FMOD_TIMEUNIT_MS);
739 if res <> FMOD_OK then
740 begin
741 FPosition := 0;
742 end
743 else
744 FPosition := aPos;
746 res := FMOD_Channel_SetPan(FChannel, Pan);
747 if res <> FMOD_OK then
748 begin
749 end;
751 res := FMOD_Channel_SetVolume(FChannel, Volume);
752 if res <> FMOD_OK then
753 begin
754 end;
756 res := FMOD_Channel_SetCallback(FChannel, Channel_Callback);
757 if res <> FMOD_OK then
758 begin
759 end;
761 if SoundMuted then
762 begin
763 res := FMOD_Channel_SetMute(FChannel, True);
764 if res <> FMOD_OK then
765 begin
766 end;
767 end;
769 Inc(e_SoundsArray[FID].nRefs);
770 Result := True;
771 end;
773 procedure TBasicSound.SetID(ID: DWORD);
774 begin
775 FreeSound();
776 FID := ID;
777 FLoop := e_SoundsArray[ID].Loop;
778 end;
780 function TBasicSound.IsPlaying(): Boolean;
781 var
782 res: FMOD_RESULT;
783 b: LongBool;
785 begin
786 Result := False;
788 if FChannel = nil then
789 Exit;
791 res := FMOD_Channel_IsPlaying(FChannel, b);
792 if res <> FMOD_OK then
793 begin
794 Exit;
795 end;
797 Result := b;
798 end;
800 procedure TBasicSound.Stop();
801 var
802 res: FMOD_RESULT;
804 begin
805 if FChannel = nil then
806 Exit;
808 GetPosition();
810 res := FMOD_Channel_Stop(FChannel);
811 if res <> FMOD_OK then
812 begin
813 end;
815 FChannel := nil;
816 end;
818 function TBasicSound.IsPaused(): Boolean;
819 var
820 res: FMOD_RESULT;
821 b: LongBool;
823 begin
824 Result := False;
826 if FChannel = nil then
827 Exit;
829 res := FMOD_Channel_GetPaused(FChannel, b);
830 if res <> FMOD_OK then
831 begin
832 Exit;
833 end;
835 Result := b;
836 end;
838 procedure TBasicSound.Pause(Enable: Boolean);
839 var
840 res: FMOD_RESULT;
842 begin
843 if FChannel = nil then
844 Exit;
846 res := FMOD_Channel_SetPaused(FChannel, Enable);
847 if res <> FMOD_OK then
848 begin
849 end;
851 if Enable then
852 begin
853 res := FMOD_Channel_GetPosition(FChannel, FPosition, FMOD_TIMEUNIT_MS);
854 if res <> FMOD_OK then
855 begin
856 end;
857 end;
858 end;
860 function TBasicSound.GetVolume(): Single;
861 var
862 res: FMOD_RESULT;
863 vol: Single;
865 begin
866 Result := 0.0;
868 if FChannel = nil then
869 Exit;
871 res := FMOD_Channel_GetVolume(FChannel, vol);
872 if res <> FMOD_OK then
873 begin
874 Exit;
875 end;
877 Result := vol;
878 end;
880 procedure TBasicSound.SetVolume(Volume: Single);
881 var
882 res: FMOD_RESULT;
884 begin
885 if FChannel = nil then
886 Exit;
888 res := FMOD_Channel_SetVolume(FChannel, Volume);
889 if res <> FMOD_OK then
890 begin
891 end;
892 end;
894 function TBasicSound.GetPan(): Single;
895 var
896 res: FMOD_RESULT;
897 pan: Single;
899 begin
900 Result := 0.0;
902 if FChannel = nil then
903 Exit;
905 res := FMOD_Channel_GetPan(FChannel, pan);
906 if res <> FMOD_OK then
907 begin
908 Exit;
909 end;
911 Result := pan;
912 end;
914 procedure TBasicSound.SetPan(Pan: Single);
915 var
916 res: FMOD_RESULT;
918 begin
919 if FChannel = nil then
920 Exit;
922 res := FMOD_Channel_SetPan(FChannel, Pan);
923 if res <> FMOD_OK then
924 begin
925 end;
926 end;
928 function TBasicSound.IsMuted(): Boolean;
929 var
930 res: FMOD_RESULT;
931 b: LongBool;
933 begin
934 Result := False;
936 if FChannel = nil then
937 Exit;
939 res := FMOD_Channel_GetMute(FChannel, b);
940 if res <> FMOD_OK then
941 begin
942 Exit;
943 end;
945 Result := b;
946 end;
948 procedure TBasicSound.Mute(Enable: Boolean);
949 var
950 res: FMOD_RESULT;
952 begin
953 if FChannel = nil then
954 Exit;
956 res := FMOD_Channel_SetMute(FChannel, Enable);
957 if res <> FMOD_OK then
958 begin
959 end;
960 end;
962 function TBasicSound.GetPosition(): DWORD;
963 var
964 res: FMOD_RESULT;
966 begin
967 Result := 0;
969 if FChannel = nil then
970 Exit;
972 res := FMOD_Channel_GetPosition(FChannel, FPosition, FMOD_TIMEUNIT_MS);
973 if res <> FMOD_OK then
974 begin
975 Exit;
976 end;
978 Result := FPosition;
979 end;
981 procedure TBasicSound.SetPosition(aPos: DWORD);
982 var
983 res: FMOD_RESULT;
985 begin
986 FPosition := aPos;
988 if FChannel = nil then
989 Exit;
991 res := FMOD_Channel_SetPosition(FChannel, FPosition, FMOD_TIMEUNIT_MS);
992 if res <> FMOD_OK then
993 begin
994 end;
995 end;
997 procedure TBasicSound.SetPriority(priority: Integer);
998 var
999 res: FMOD_RESULT;
1001 begin
1002 if (FChannel <> nil) and (FPriority <> priority) and
1003 (priority >= 0) and (priority <= 256) then
1004 begin
1005 FPriority := priority;
1006 res := FMOD_Channel_SetPriority(FChannel, priority);
1007 if res <> FMOD_OK then
1008 begin
1009 end;
1010 end;
1011 end;
1013 end.