Main: Fix directives to hide compiler notices
[d2df-sdl.git] / src / engine / e_sound_fmod.inc
blobd0db4fed1fa09f7332b8b70cd4dd798127d8bbff
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, either version 3 of the License, or
6  * (at your option) any later version.
7  *
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.
12  *
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/>.
15  *)
16 interface
18 uses
19   fmod,
20   fmodtypes,
21   fmoderrors,
22   {$IFDEF USE_MEMPOOL}mempool,{$ENDIF}
23   e_log,
24   SysUtils;
26 type
27   TSoundRec = record
28     Data: Pointer;
29     Sound: FMOD_SOUND;
30     isMusic: Boolean;
31     nRefs: Integer;
32   end;
34   TBasicSound = class{$IFDEF USE_MEMPOOL}(TPoolObject){$ENDIF}
35   private
36     FChannel: FMOD_CHANNEL;
38   protected
39     FID: DWORD;
40     FMusic: Boolean;
41     FPosition: DWORD;
42     FPriority: Integer;
44     function RawPlay(Pan: Single; Volume: Single; aPos: DWORD): Boolean;
46   public
47     constructor Create();
48     destructor Destroy(); override;
49     procedure SetID(ID: DWORD);
50     procedure FreeSound();
51     function IsPlaying(): Boolean;
52     procedure Stop();
53     function IsPaused(): Boolean;
54     procedure Pause(Enable: Boolean);
55     function GetVolume(): Single;
56     procedure SetVolume(Volume: Single);
57     function GetPan(): Single;
58     procedure SetPan(Pan: Single);
59     function IsMuted(): Boolean;
60     procedure Mute(Enable: Boolean);
61     function GetPosition(): DWORD;
62     procedure SetPosition(aPos: DWORD);
63     procedure SetPriority(priority: Integer);
64   end;
66 const
67   NO_SOUND_ID = DWORD(-1);
69 function e_InitSoundSystem(NoOutput: Boolean = False): Boolean;
71 function e_LoadSound(FileName: string; var ID: DWORD; bLoop: Boolean): Boolean;
72 function e_LoadSoundMem(pData: Pointer; Length: Integer; var ID: DWORD; bLoop: Boolean): Boolean;
74 function e_PlaySound(ID: DWORD): Integer;
75 function e_PlaySoundPan(ID: DWORD; Pan: Single): Integer;
76 function e_PlaySoundVolume(ID: DWORD; Volume: Single): Integer;
77 function e_PlaySoundPanVolume(ID: DWORD; Pan, Volume: Single): Integer;
79 procedure e_ModifyChannelsVolumes(SoundMod: Single; setMode: Boolean);
80 procedure e_MuteChannels(Enable: Boolean);
81 procedure e_StopChannels();
83 procedure e_DeleteSound(ID: DWORD);
84 procedure e_RemoveAllSounds();
85 procedure e_ReleaseSoundSystem();
86 procedure e_SoundUpdate();
88 var
89   e_SoundsArray: array of TSoundRec = nil;
91 implementation
93 uses
94   g_window, g_options, utils;
96 const
97   N_CHANNELS = 512;
99 var
100   F_System: FMOD_SYSTEM = nil;
101   SoundMuted: Boolean = False;
104 function Channel_Callback(channel: FMOD_CHANNEL; callbacktype: FMOD_CHANNEL_CALLBACKTYPE;
105                           commanddata1: Pointer; commanddata2: Pointer): FMOD_RESULT; {$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF}
107   res: FMOD_RESULT;
108   sound: FMOD_SOUND;
109   ud: Pointer;
110   id: DWORD;
112 begin
113   res := FMOD_OK;
115   if callbacktype = FMOD_CHANNEL_CALLBACKTYPE_END then
116   begin
117     res := FMOD_Channel_GetCurrentSound(channel, sound);
118     if res = FMOD_OK then
119     begin
120       res := FMOD_Sound_GetUserData(sound, ud);
121       if res = FMOD_OK then
122       begin
123         id := DWORD(ud^);
124         if id < DWORD(Length(e_SoundsArray)) then
125           if e_SoundsArray[id].nRefs > 0 then
126             Dec(e_SoundsArray[id].nRefs);
127       end;
128     end;
129   end;
131   Result := res;
132 end;
134 function TryInitWithOutput(Output: FMOD_OUTPUTTYPE; OutputName: String): FMOD_RESULT;
135 begin
136   e_WriteLog('Trying with ' + OutputName + '...', TMsgType.Warning);
137   Result := FMOD_System_SetOutput(F_System, Output);
138   if Result <> FMOD_OK then
139   begin
140     e_WriteLog('Error setting FMOD output to ' + OutputName + '!', TMsgType.Warning);
141     e_WriteLog(FMOD_ErrorString(Result), TMsgType.Warning);
142     Exit;
143   end;
144   Result := FMOD_System_Init(F_System, N_CHANNELS, FMOD_INIT_NORMAL, nil);
145   if Result <> FMOD_OK then
146   begin
147     e_WriteLog('Error initializing FMOD system!', TMsgType.Warning);
148     e_WriteLog(FMOD_ErrorString(Result), TMsgType.Warning);
149     Exit;
150   end;
151 end;
153 function e_TrySS (Freq: Integer; forceNoSound: Integer): Boolean;
155   res: FMOD_RESULT;
156   ver: Cardinal;
157   output: FMOD_OUTPUTTYPE;
158   drv: Integer;
160 begin
161   Result := False;
162   e_WriteLog(Format('Trying to initialize FMOD with %d', [Freq]), TMsgType.Notify);
164   res := FMOD_System_Create(F_System);
165   if res <> FMOD_OK then
166   begin
167     e_WriteLog('Error creating FMOD system:', TMsgType.Fatal);
168     e_WriteLog(FMOD_ErrorString(res), TMsgType.Fatal);
169     Exit;
170   end;
172   res := FMOD_System_GetVersion(F_System, ver);
173   if res <> FMOD_OK then
174   begin
175     e_WriteLog('Error getting FMOD version:', TMsgType.Fatal);
176     e_WriteLog(FMOD_ErrorString(res), TMsgType.Fatal);
177     Exit;
178   end;
180   if ver < FMOD_VERSION then
181   begin
182     e_WriteLog('FMOD library version is too old! Need '+IntToStr(FMOD_VERSION), TMsgType.Fatal);
183     Exit;
184   end;
186   res := FMOD_System_SetSoftwareFormat(F_System, Freq, FMOD_SOUND_FORMAT_PCM16, 0, 0, FMOD_DSP_RESAMPLER_LINEAR);
187   if res <> FMOD_OK then
188   begin
189     e_WriteLog('Error setting FMOD software format!', TMsgType.Fatal);
190     e_WriteLog(FMOD_ErrorString(res), TMsgType.Fatal);
191     Exit;
192   end;
194   if forceNoSound = 2 then
195   begin
196     res := TryInitWithOutput(FMOD_OUTPUTTYPE_NOSOUND, 'OUTPUTTYPE_NOSOUND');
197     if res <> FMOD_OK then
198     begin
199       e_WriteLog('FMOD: Giving up, can''t init with NOSOUND.', TMsgType.Fatal);
200       Exit;
201     end;
202   end
203   else
204   begin
205     res := FMOD_System_Init(F_System, N_CHANNELS, FMOD_INIT_NORMAL, nil);
206     if res <> FMOD_OK then
207     begin
208       e_WriteLog('Error initializing FMOD system!', TMsgType.Warning);
209       e_WriteLog(FMOD_ErrorString(res), TMsgType.Warning);
211       {$IFDEF LINUX}
212       res := TryInitWithOutput(FMOD_OUTPUTTYPE_ALSA, 'OUTPUTTYPE_ALSA');
213       if res <> FMOD_OK then
214         res := TryInitWithOutput(FMOD_OUTPUTTYPE_OSS, 'OUTPUTTYPE_OSS');
215       {$ENDIF}
216       if (res <> FMOD_OK) and (forceNoSound <> 1) then Exit;
217       if res <> FMOD_OK then
218         res := TryInitWithOutput(FMOD_OUTPUTTYPE_NOSOUND, 'OUTPUTTYPE_NOSOUND');
219       if res <> FMOD_OK then
220       begin
221         e_WriteLog('FMOD: Giving up, can''t init any output.', TMsgType.Fatal);
222         Exit;
223       end;
224     end;
225   end;
227   res := FMOD_System_GetOutput(F_System, output);
228   if res <> FMOD_OK then
229     e_WriteLog('Error getting FMOD output!', TMsgType.Warning)
230   else
231     case output of
232       FMOD_OUTPUTTYPE_NOSOUND: e_WriteLog('FMOD Output Method: NOSOUND', TMsgType.Notify);
233       FMOD_OUTPUTTYPE_NOSOUND_NRT: e_WriteLog('FMOD Output Method: NOSOUND_NRT', TMsgType.Notify);
234       FMOD_OUTPUTTYPE_DSOUND: e_WriteLog('FMOD Output Method: DSOUND', TMsgType.Notify);
235       FMOD_OUTPUTTYPE_WINMM: e_WriteLog('FMOD Output Method: WINMM', TMsgType.Notify);
236       FMOD_OUTPUTTYPE_OPENAL: e_WriteLog('FMOD Output Method: OPENAL', TMsgType.Notify);
237       FMOD_OUTPUTTYPE_WASAPI: e_WriteLog('FMOD Output Method: WASAPI', TMsgType.Notify);
238       FMOD_OUTPUTTYPE_ASIO: e_WriteLog('FMOD Output Method: ASIO', TMsgType.Notify);
239       FMOD_OUTPUTTYPE_OSS:  e_WriteLog('FMOD Output Method: OSS', TMsgType.Notify);
240       FMOD_OUTPUTTYPE_ALSA: e_Writelog('FMOD Output Method: ALSA', TMsgType.Notify);
241       else e_WriteLog('FMOD Output Method: Unknown', TMsgType.Notify);
242     end;
244   res := FMOD_System_GetDriver(F_System, drv);
245   if res <> FMOD_OK then
246     e_WriteLog('Error getting FMOD driver!', TMsgType.Warning)
247   else
248     e_WriteLog('FMOD driver id: '+IntToStr(drv), TMsgType.Notify);
250   Result := True;
251 end;
253 function e_InitSoundSystem(NoOutput: Boolean = False): Boolean;
254 begin
255   if NoOutput then
256   begin
257     Result := e_TrySS(48000, 2);
258     Exit;
259   end;
260   Result := e_TrySS(48000, 0);
261   if not Result then Result := e_TrySS(44100, 1);
262 end;
264 function FindESound(): DWORD;
266   i: Integer;
268 begin
269   if e_SoundsArray <> nil then
270     for i := 0 to High(e_SoundsArray) do
271       if e_SoundsArray[i].Sound = nil then
272       begin
273         Result := i;
274         Exit;
275       end;
277   if e_SoundsArray = nil then
278     begin
279       SetLength(e_SoundsArray, 16);
280       Result := 0;
281     end
282   else
283     begin
284       Result := High(e_SoundsArray) + 1;
285       SetLength(e_SoundsArray, Length(e_SoundsArray) + 16);
286     end;
287 end;
289 function e_LoadSound(FileName: String; var ID: DWORD; bLoop: Boolean): Boolean;
291   find_id: DWORD;
292   res: FMOD_RESULT;
293   bt: Cardinal;
294   ud: Pointer;
296 begin
297   Result := False;
299   e_WriteLog('Loading sound '+FileName+'...', TMsgType.Notify);
301   find_id := FindESound();
303   if bLoop then
304     bt := FMOD_LOOP_NORMAL
305   else
306     bt := FMOD_LOOP_OFF;
308   if not bLoop then
309     res := FMOD_System_CreateSound(F_System, PAnsiChar(FileName),
310              bt + FMOD_2D + FMOD_HARDWARE,
311              nil, e_SoundsArray[find_id].Sound)
312   else
313     res := FMOD_System_CreateStream(F_System, PAnsiChar(FileName),
314              bt + FMOD_2D + FMOD_HARDWARE,
315              nil, e_SoundsArray[find_id].Sound);
316   if res <> FMOD_OK then
317   begin
318     e_SoundsArray[find_id].Sound := nil;
319     Exit;
320   end;
322   GetMem(ud, SizeOf(DWORD));
323   DWORD(ud^) := find_id;
324   res := FMOD_Sound_SetUserData(e_SoundsArray[find_id].Sound, ud);
325   if res <> FMOD_OK then
326   begin
327     e_SoundsArray[find_id].Sound := nil;
328     Exit;
329   end;
331   e_SoundsArray[find_id].Data := nil;
332   e_SoundsArray[find_id].isMusic := bLoop;
333   e_SoundsArray[find_id].nRefs := 0;
335   ID := find_id;
337   Result := True;
338 end;
340 function e_LoadSoundMem(pData: Pointer; Length: Integer; var ID: DWORD; bLoop: Boolean): Boolean;
342   find_id: DWORD;
343   res: FMOD_RESULT;
344   sz: Integer;
345   bt: Cardinal;
346   soundExInfo: FMOD_CREATESOUNDEXINFO;
347   ud: Pointer;
349 begin
350   Result := False;
352   find_id := FindESound();
354   sz := SizeOf(FMOD_CREATESOUNDEXINFO);
355   FillMemory(@soundExInfo, sz, 0);
356   soundExInfo.cbsize := sz;
357   soundExInfo.length := Length;
359   if bLoop then
360     bt := FMOD_LOOP_NORMAL
361   else
362     bt := FMOD_LOOP_OFF;
364   if not bLoop then
365     res := FMOD_System_CreateSound(F_System, pData,
366              bt + FMOD_2D + FMOD_HARDWARE + FMOD_OPENMEMORY,
367              @soundExInfo, e_SoundsArray[find_id].Sound)
368   else
369     res := FMOD_System_CreateStream(F_System, pData,
370              bt + FMOD_2D + FMOD_HARDWARE + FMOD_OPENMEMORY,
371              @soundExInfo, e_SoundsArray[find_id].Sound);
372   if res <> FMOD_OK then
373   begin
374     e_SoundsArray[find_id].Sound := nil;
375     Exit;
376   end;
378   GetMem(ud, SizeOf(DWORD));
379   DWORD(ud^) := find_id;
380   res := FMOD_Sound_SetUserData(e_SoundsArray[find_id].Sound, ud);
381   if res <> FMOD_OK then
382   begin
383     e_SoundsArray[find_id].Sound := nil;
384     Exit;
385   end;
387   e_SoundsArray[find_id].Data := pData;
388   e_SoundsArray[find_id].isMusic := bLoop;
389   e_SoundsArray[find_id].nRefs := 0;
391   ID := find_id;
393   Result := True;
394 end;
396 function e_PlaySound(ID: DWORD): Integer;
398   res: FMOD_RESULT;
399   Chan: FMOD_CHANNEL;
401 begin
402   if e_SoundsArray[ID].nRefs >= gMaxSimSounds then
403   begin
404     Result := 0;
405     Exit;
406   end;
408   Result := -1;
410   res := FMOD_System_PlaySound(F_System, FMOD_CHANNEL_FREE,
411            e_SoundsArray[ID].Sound, False, Chan);
412   if res <> FMOD_OK then
413   begin
414     Exit;
415   end;
417   res := FMOD_Channel_SetCallback(Chan, Channel_Callback);
418   if res <> FMOD_OK then
419   begin
420   end;
422   if SoundMuted then
423   begin
424     res := FMOD_Channel_SetMute(Chan, True);
425     if res <> FMOD_OK then
426     begin
427     end;
428   end;
430   Inc(e_SoundsArray[ID].nRefs);
431   Result := 0;
432 end;
434 function e_PlaySoundPan(ID: DWORD; Pan: Single): Integer;
436   res: FMOD_RESULT;
437   Chan: FMOD_CHANNEL;
439 begin
440   if e_SoundsArray[ID].nRefs >= gMaxSimSounds then
441   begin
442     Result := 0;
443     Exit;
444   end;
446   Result := -1;
448   res := FMOD_System_PlaySound(F_System, FMOD_CHANNEL_FREE,
449            e_SoundsArray[ID].Sound, False, Chan);
450   if res <> FMOD_OK then
451   begin
452     Exit;
453   end;
455   res := FMOD_Channel_SetPan(Chan, Pan);
456   if res <> FMOD_OK then
457   begin
458   end;
460   res := FMOD_Channel_SetCallback(Chan, Channel_Callback);
461   if res <> FMOD_OK then
462   begin
463   end;
465   if SoundMuted then
466   begin
467     res := FMOD_Channel_SetMute(Chan, True);
468     if res <> FMOD_OK then
469     begin
470     end;
471   end;
473   Inc(e_SoundsArray[ID].nRefs);
474   Result := 0;
475 end;
477 function e_PlaySoundVolume(ID: DWORD; Volume: Single): Integer;
479   res: FMOD_RESULT;
480   Chan: FMOD_CHANNEL;
482 begin
483   if e_SoundsArray[ID].nRefs >= gMaxSimSounds then
484   begin
485     Result := 0;
486     Exit;
487   end;
489   Result := -1;
491   res := FMOD_System_PlaySound(F_System, FMOD_CHANNEL_FREE,
492            e_SoundsArray[ID].Sound, False, Chan);
493   if res <> FMOD_OK then
494   begin
495     Exit;
496   end;
498   res := FMOD_Channel_SetVolume(Chan, Volume);
499   if res <> FMOD_OK then
500   begin
501   end;
503   res := FMOD_Channel_SetCallback(Chan, Channel_Callback);
504   if res <> FMOD_OK then
505   begin
506   end;
508   if SoundMuted then
509   begin
510     res := FMOD_Channel_SetMute(Chan, True);
511     if res <> FMOD_OK then
512     begin
513     end;
514   end;
516   Inc(e_SoundsArray[ID].nRefs);
517   Result := 0;
518 end;
520 function e_PlaySoundPanVolume(ID: DWORD; Pan, Volume: Single): Integer;
522   res: FMOD_RESULT;
523   Chan: FMOD_CHANNEL;
525 begin
526   if e_SoundsArray[ID].nRefs >= gMaxSimSounds then
527   begin
528     Result := 0;
529     Exit;
530   end;
532   Result := -1;
534   res := FMOD_System_PlaySound(F_System, FMOD_CHANNEL_FREE,
535            e_SoundsArray[ID].Sound, False, Chan);
536   if res <> FMOD_OK then
537   begin
538     Exit;
539   end;
541   res := FMOD_Channel_SetPan(Chan, Pan);
542   if res <> FMOD_OK then
543   begin
544   end;
546   res := FMOD_Channel_SetVolume(Chan, Volume);
547   if res <> FMOD_OK then
548   begin
549   end;
551   res := FMOD_Channel_SetCallback(Chan, Channel_Callback);
552   if res <> FMOD_OK then
553   begin
554   end;
556   if SoundMuted then
557   begin
558     res := FMOD_Channel_SetMute(Chan, True);
559     if res <> FMOD_OK then
560     begin
561     end;
562   end;
564   Inc(e_SoundsArray[ID].nRefs);
565   Result := 0;
566 end;
568 procedure e_DeleteSound(ID: DWORD);
570   res: FMOD_RESULT;
571   ud: Pointer;
573 begin
574   if e_SoundsArray[ID].Sound = nil then
575     Exit;
577   if e_SoundsArray[ID].Data <> nil then
578     FreeMem(e_SoundsArray[ID].Data);
580   res := FMOD_Sound_GetUserData(e_SoundsArray[ID].Sound, ud);
581   if res = FMOD_OK then
582   begin
583     FreeMem(ud);
584   end;
586   res := FMOD_Sound_Release(e_SoundsArray[ID].Sound);
587   if res <> FMOD_OK then
588   begin
589     e_WriteLog('Error releasing sound:', TMsgType.Warning);
590     e_WriteLog(FMOD_ErrorString(res), TMsgType.Warning);
591   end;
593   e_SoundsArray[ID].Sound := nil;
594   e_SoundsArray[ID].Data := nil;
595 end;
597 procedure e_ModifyChannelsVolumes(SoundMod: Single; setMode: Boolean);
599   res: FMOD_RESULT;
600   i: Integer;
601   Chan: FMOD_CHANNEL;
602   vol: Single;
604 begin
605   for i := 0 to N_CHANNELS-1 do
606   begin
607     Chan := nil;
608     res := FMOD_System_GetChannel(F_System, i, Chan);
610     if (res = FMOD_OK) and (Chan <> nil) then
611     begin
612       res := FMOD_Channel_GetVolume(Chan, vol);
614       if res = FMOD_OK then
615       begin
616         if setMode then
617           vol := SoundMod
618         else
619           vol := vol * SoundMod;
621         res := FMOD_Channel_SetVolume(Chan, vol);
623         if res <> FMOD_OK then
624         begin
625         end;
626       end;
627     end;
628   end;
629 end;
631 procedure e_MuteChannels(Enable: Boolean);
633   res: FMOD_RESULT;
634   i: Integer;
635   Chan: FMOD_CHANNEL;
637 begin
638   if Enable = SoundMuted then
639     Exit;
641   SoundMuted := Enable;
643   for i := 0 to N_CHANNELS-1 do
644   begin
645     Chan := nil;
646     res := FMOD_System_GetChannel(F_System, i, Chan);
648     if (res = FMOD_OK) and (Chan <> nil) then
649     begin
650       res := FMOD_Channel_SetMute(Chan, Enable);
652       if res <> FMOD_OK then
653       begin
654       end;
655     end;
656   end;
657 end;
659 procedure e_StopChannels();
661   res: FMOD_RESULT;
662   i: Integer;
663   Chan: FMOD_CHANNEL;
665 begin
666   for i := 0 to N_CHANNELS-1 do
667   begin
668     Chan := nil;
669     res := FMOD_System_GetChannel(F_System, i, Chan);
671     if (res = FMOD_OK) and (Chan <> nil) then
672     begin
673       res := FMOD_Channel_Stop(Chan);
675       if res <> FMOD_OK then
676       begin
677       end;
678     end;
679   end;
680 end;
682 procedure e_RemoveAllSounds();
684   i: Integer;
686 begin
687   for i := 0 to High(e_SoundsArray) do
688     if e_SoundsArray[i].Sound <> nil then
689       e_DeleteSound(i);
691   SetLength(e_SoundsArray, 0);
692   e_SoundsArray := nil;
693 end;
695 procedure e_ReleaseSoundSystem();
697   res: FMOD_RESULT;
699 begin
700   e_RemoveAllSounds();
702   res := FMOD_System_Close(F_System);
703   if res <> FMOD_OK then
704   begin
705     e_WriteLog('Error closing FMOD system!', TMsgType.Fatal);
706     e_WriteLog(FMOD_ErrorString(res), TMsgType.Fatal);
707     Exit;
708   end;
710   res := FMOD_System_Release(F_System);
711   if res <> FMOD_OK then
712   begin
713     e_WriteLog('Error releasing FMOD system!', TMsgType.Fatal);
714     e_WriteLog(FMOD_ErrorString(res), TMsgType.Fatal);
715   end;
716 end;
718 procedure e_SoundUpdate();
719 begin
720   FMOD_System_Update(F_System);
721 end;
723 { TBasicSound: }
725 constructor TBasicSound.Create();
726 begin
727   FID := NO_SOUND_ID;
728   FMusic := False;
729   FChannel := nil;
730   FPosition := 0;
731   FPriority := 128;
732 end;
734 destructor TBasicSound.Destroy();
735 begin
736   FreeSound();
737   inherited;
738 end;
740 procedure TBasicSound.FreeSound();
741 begin
742   if FID = NO_SOUND_ID then
743     Exit;
745   Stop();
746   FID := NO_SOUND_ID;
747   FMusic := False;
748   FPosition := 0;
749 end;
751 function TBasicSound.RawPlay(Pan: Single; Volume: Single; aPos: DWORD): Boolean;
753   res: FMOD_RESULT;
755 begin
756   Result := False;
757   if FID = NO_SOUND_ID then Exit;
759   if e_SoundsArray[FID].nRefs >= gMaxSimSounds then
760   begin
761     Result := True;
762     Exit;
763   end;
765   res := FMOD_System_PlaySound(F_System, FMOD_CHANNEL_FREE,
766            e_SoundsArray[FID].Sound, False, FChannel);
767   if res <> FMOD_OK then
768   begin
769     FChannel := nil;
770     Exit;
771   end;
773   res := FMOD_Channel_SetPosition(FChannel, aPos, FMOD_TIMEUNIT_MS);
774   if res <> FMOD_OK then
775     begin
776       FPosition := 0;
777     end
778   else
779     FPosition := aPos;
781   res := FMOD_Channel_SetPan(FChannel, Pan);
782   if res <> FMOD_OK then
783   begin
784   end;
786   res := FMOD_Channel_SetVolume(FChannel, Volume);
787   if res <> FMOD_OK then
788   begin
789   end;
791   res := FMOD_Channel_SetCallback(FChannel, Channel_Callback);
792   if res <> FMOD_OK then
793   begin
794   end;
796   if SoundMuted then
797   begin
798     res := FMOD_Channel_SetMute(FChannel, True);
799     if res <> FMOD_OK then
800     begin
801     end;
802   end;
804   Inc(e_SoundsArray[FID].nRefs);
805   Result := True;
806 end;
808 procedure TBasicSound.SetID(ID: DWORD);
809 begin
810   FreeSound();
811   FID := ID;
812   FMusic := e_SoundsArray[ID].isMusic;
813 end;
815 function TBasicSound.IsPlaying(): Boolean;
817   res: FMOD_RESULT;
818   b: LongBool;
820 begin
821   Result := False;
823   if FChannel = nil then
824     Exit;
826   res := FMOD_Channel_IsPlaying(FChannel, b);
827   if res <> FMOD_OK then
828   begin
829     Exit;
830   end;
832   Result := b;
833 end;
835 procedure TBasicSound.Stop();
837   res: FMOD_RESULT;
839 begin
840   if FChannel = nil then
841     Exit;
843   GetPosition();
845   res := FMOD_Channel_Stop(FChannel);
846   if res <> FMOD_OK then
847   begin
848   end;
850   FChannel := nil;
851 end;
853 function TBasicSound.IsPaused(): Boolean;
855   res: FMOD_RESULT;
856   b: LongBool;
858 begin
859   Result := False;
861   if FChannel = nil then
862     Exit;
864   res := FMOD_Channel_GetPaused(FChannel, b);
865   if res <> FMOD_OK then
866   begin
867     Exit;
868   end;
870   Result := b;
871 end;
873 procedure TBasicSound.Pause(Enable: Boolean);
875   res: FMOD_RESULT;
877 begin
878   if FChannel = nil then
879     Exit;
881   res := FMOD_Channel_SetPaused(FChannel, Enable);
882   if res <> FMOD_OK then
883   begin
884   end;
886   if Enable then
887   begin
888     res := FMOD_Channel_GetPosition(FChannel, FPosition, FMOD_TIMEUNIT_MS);
889     if res <> FMOD_OK then
890     begin
891     end;
892   end;
893 end;
895 function TBasicSound.GetVolume(): Single;
897   res: FMOD_RESULT;
898   vol: Single;
900 begin
901   Result := 0.0;
903   if FChannel = nil then
904     Exit;
906   res := FMOD_Channel_GetVolume(FChannel, vol);
907   if res <> FMOD_OK then
908   begin
909     Exit;
910   end;
912   Result := vol;
913 end;
915 procedure TBasicSound.SetVolume(Volume: Single);
917   res: FMOD_RESULT;
919 begin
920   if FChannel = nil then
921     Exit;
923   res := FMOD_Channel_SetVolume(FChannel, Volume);
924   if res <> FMOD_OK then
925   begin
926   end;
927 end;
929 function TBasicSound.GetPan(): Single;
931   res: FMOD_RESULT;
932   pan: Single;
934 begin
935   Result := 0.0;
937   if FChannel = nil then
938     Exit;
940   res := FMOD_Channel_GetPan(FChannel, pan);
941   if res <> FMOD_OK then
942   begin
943     Exit;
944   end;
946   Result := pan;
947 end;
949 procedure TBasicSound.SetPan(Pan: Single);
951   res: FMOD_RESULT;
953 begin
954   if FChannel = nil then
955     Exit;
957   res := FMOD_Channel_SetPan(FChannel, Pan);
958   if res <> FMOD_OK then
959   begin
960   end;
961 end;
963 function TBasicSound.IsMuted(): Boolean;
965   res: FMOD_RESULT;
966   b: LongBool;
968 begin
969   Result := False;
971   if FChannel = nil then
972     Exit;
974   res := FMOD_Channel_GetMute(FChannel, b);
975   if res <> FMOD_OK then
976   begin
977     Exit;
978   end;
980   Result := b;
981 end;
983 procedure TBasicSound.Mute(Enable: Boolean);
985   res: FMOD_RESULT;
987 begin
988   if FChannel = nil then
989     Exit;
991   res := FMOD_Channel_SetMute(FChannel, Enable);
992   if res <> FMOD_OK then
993   begin
994   end;
995 end;
997 function TBasicSound.GetPosition(): DWORD;
999   res: FMOD_RESULT;
1001 begin
1002   Result := 0;
1004   if FChannel = nil then
1005     Exit;
1007   res := FMOD_Channel_GetPosition(FChannel, FPosition, FMOD_TIMEUNIT_MS);
1008   if res <> FMOD_OK then
1009   begin
1010     Exit;
1011   end;
1013   Result := FPosition;
1014 end;
1016 procedure TBasicSound.SetPosition(aPos: DWORD);
1018   res: FMOD_RESULT;
1020 begin
1021   FPosition := aPos;
1023   if FChannel = nil then
1024     Exit;
1026   res := FMOD_Channel_SetPosition(FChannel, FPosition, FMOD_TIMEUNIT_MS);
1027   if res <> FMOD_OK then
1028   begin
1029   end;
1030 end;
1032 procedure TBasicSound.SetPriority(priority: Integer);
1034   res: FMOD_RESULT;
1036 begin
1037   if (FChannel <> nil) and (FPriority <> priority) and
1038      (priority >= 0) and (priority <= 256) then
1039   begin
1040     FPriority := priority;
1041     res := FMOD_Channel_SetPriority(FChannel, priority);
1042     if res <> FMOD_OK then
1043     begin
1044     end;
1045   end;
1046 end;
1048 end.