Net: Don't send large unreliable packets by reliable fragments
[d2df-sdl.git] / src / engine / e_sound_fmod.inc
blobe4fe7ad49ad5320dd18e62d328659babcbfe94a4
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   TSoundID = PtrInt;
28   TSoundRec = record
29     Data: Pointer;
30     Sound: FMOD_SOUND;
31     isMusic: Boolean;
32     nRefs: Integer;
33   end;
35   TBasicSound = class{$IFDEF USE_MEMPOOL}(TPoolObject){$ENDIF}
36   private
37     FChannel: FMOD_CHANNEL;
39   protected
40     FID: TSoundID;
41     FMusic: Boolean;
42     FPosition: DWORD;
43     FPriority: Integer;
45     function RawPlay(Pan: Single; Volume: Single; aPos: DWORD): Boolean;
47   public
48     constructor Create();
49     destructor Destroy(); override;
50     procedure SetID(ID: TSoundID);
51     procedure FreeSound();
52     function IsPlaying(): Boolean;
53     procedure Stop();
54     function IsPaused(): Boolean;
55     procedure Pause(Enable: Boolean);
56     function GetVolume(): Single;
57     procedure SetVolume(Volume: Single);
58     function GetPan(): Single;
59     procedure SetPan(Pan: Single);
60     function IsMuted(): Boolean;
61     procedure Mute(Enable: Boolean);
62     function GetPosition(): DWORD;
63     procedure SetPosition(aPos: DWORD);
64     procedure SetPriority(priority: Cardinal);
65   end;
67 const
68   NO_SOUND_ID = TSoundID(-1);
70 function e_InitSoundSystem(NoOutput: Boolean = False): Boolean;
72 function e_LoadSound(FileName: String; var ID: TSoundID; isMusic: Boolean;
73   ForceNoLoop: Boolean = False): Boolean;
74 function e_LoadSoundMem(pData: Pointer; Length: Integer; var ID: TSoundID; isMusic: Boolean;
75   ForceNoLoop: Boolean = False): Boolean;
77 function e_PlaySound(ID: TSoundID): Integer;
78 function e_PlaySoundPan(ID: TSoundID; Pan: Single): Integer;
79 function e_PlaySoundVolume(ID: TSoundID; Volume: Single): Integer;
80 function e_PlaySoundPanVolume(ID: TSoundID; Pan, Volume: Single): Integer;
82 procedure e_ModifyChannelsVolumes(SoundMod: Single; setMode: Boolean);
83 procedure e_MuteChannels(Enable: Boolean);
84 procedure e_StopChannels();
86 procedure e_DeleteSound(ID: TSoundID);
87 procedure e_RemoveAllSounds();
88 procedure e_ReleaseSoundSystem();
89 procedure e_SoundUpdate();
91 var
92   e_SoundsArray: array of TSoundRec;
94 implementation
96 uses
97   g_window, g_options, utils;
99 const
100   N_CHANNELS = 512;
103   F_System: FMOD_SYSTEM;
104   SoundMuted: Boolean;
107 function Channel_Callback(channel: FMOD_CHANNEL; callbacktype: FMOD_CHANNEL_CALLBACKTYPE;
108   commanddata1: Pointer; commanddata2: Pointer): FMOD_RESULT; winapi;
110   sound: FMOD_SOUND;
111   id: TSoundID;
113 begin
114   Result := FMOD_OK;
116   if callbacktype = FMOD_CHANNEL_CALLBACKTYPE_END then
117   begin
118     Result := FMOD_Channel_GetCurrentSound(channel, sound);
119     if Result = FMOD_OK then
120     begin
121       Result := FMOD_Sound_GetUserData(sound, Pointer(id));
122       if Result = FMOD_OK then
123       begin
124         if id < Length(e_SoundsArray) then
125           if e_SoundsArray[id].nRefs > 0 then
126             e_SoundsArray[ID].nRefs -= 1;
127       end;
128     end;
129   end;
130 end;
132 function TryInitWithOutput(Output: FMOD_OUTPUTTYPE; OutputName: String): FMOD_RESULT;
133 begin
134   e_WriteLog('Trying with ' + OutputName + '...', TMsgType.Warning);
135   Result := FMOD_System_SetOutput(F_System, Output);
136   if Result <> FMOD_OK then
137   begin
138     e_WriteLog('Error setting FMOD output to ' + OutputName + '!', TMsgType.Warning);
139     e_WriteLog(FMOD_ErrorString(Result), TMsgType.Warning);
140     Exit;
141   end;
142   Result := FMOD_System_Init(F_System, N_CHANNELS, FMOD_INIT_NORMAL, nil);
143   if Result <> FMOD_OK then
144   begin
145     e_WriteLog('Error initializing FMOD system!', TMsgType.Warning);
146     e_WriteLog(FMOD_ErrorString(Result), TMsgType.Warning);
147     Exit;
148   end;
149 end;
151 function e_TrySS (Freq: Integer; forceNoSound: Integer): Boolean;
153   res: FMOD_RESULT;
154   ver: Cardinal;
155   output: FMOD_OUTPUTTYPE;
156   drv: Integer;
158 begin
159   Result := False;
160   e_WriteLog(Format('Trying to initialize FMOD with %d', [Freq]), TMsgType.Notify);
162   res := FMOD_System_Create(F_System);
163   if res <> FMOD_OK then
164   begin
165     e_WriteLog('Error creating FMOD system:', TMsgType.Fatal);
166     e_WriteLog(FMOD_ErrorString(res), TMsgType.Fatal);
167     Exit;
168   end;
170   res := FMOD_System_GetVersion(F_System, ver);
171   if res <> FMOD_OK then
172   begin
173     e_WriteLog('Error getting FMOD version:', TMsgType.Fatal);
174     e_WriteLog(FMOD_ErrorString(res), TMsgType.Fatal);
175     Exit;
176   end;
178   if ver < FMOD_VERSION then
179   begin
180     e_WriteLog('FMOD library version is too old! Need '+IntToStr(FMOD_VERSION), TMsgType.Fatal);
181     Exit;
182   end;
184   res := FMOD_System_SetSoftwareFormat(F_System, Freq, FMOD_SOUND_FORMAT_PCM16, 0, 0, FMOD_DSP_RESAMPLER_LINEAR);
185   if res <> FMOD_OK then
186   begin
187     e_WriteLog('Error setting FMOD software format!', TMsgType.Fatal);
188     e_WriteLog(FMOD_ErrorString(res), TMsgType.Fatal);
189     Exit;
190   end;
192   if forceNoSound = 2 then
193   begin
194     res := TryInitWithOutput(FMOD_OUTPUTTYPE_NOSOUND, 'OUTPUTTYPE_NOSOUND');
195     if res <> FMOD_OK then
196     begin
197       e_WriteLog('FMOD: Giving up, can''t init with NOSOUND.', TMsgType.Fatal);
198       Exit;
199     end;
200   end
201   else
202   begin
203     res := FMOD_System_Init(F_System, N_CHANNELS, FMOD_INIT_NORMAL, nil);
204     if res <> FMOD_OK then
205     begin
206       e_WriteLog('Error initializing FMOD system!', TMsgType.Warning);
207       e_WriteLog(FMOD_ErrorString(res), TMsgType.Warning);
209       {$IFDEF LINUX}
210       res := TryInitWithOutput(FMOD_OUTPUTTYPE_ALSA, 'OUTPUTTYPE_ALSA');
211       if res <> FMOD_OK then
212         res := TryInitWithOutput(FMOD_OUTPUTTYPE_OSS, 'OUTPUTTYPE_OSS');
213       {$ENDIF}
214       {$IFDEF DARWIN}
215         res := TryInitWithOutput(FMOD_OUTPUTTYPE_COREAUDIO, 'OUTPUTTYPE_COREAUDIO');
216         if res <> FMOD_OK then
217           res := TryInitWithOutput(FMOD_OUTPUTTYPE_SOUNDMANAGER, 'OUTPUTTYPE_SOUNDMANAGER');
218       {$ENDIF}
219       if (res <> FMOD_OK) and (forceNoSound <> 1) then Exit;
220       if res <> FMOD_OK then
221         res := TryInitWithOutput(FMOD_OUTPUTTYPE_NOSOUND, 'OUTPUTTYPE_NOSOUND');
222       if res <> FMOD_OK then
223       begin
224         e_WriteLog('FMOD: Giving up, can''t init any output.', TMsgType.Fatal);
225         Exit;
226       end;
227     end;
228   end;
230   res := FMOD_System_GetOutput(F_System, output);
231   if res <> FMOD_OK then
232     e_WriteLog('Error getting FMOD output!', TMsgType.Warning)
233   else
234     case output of
235       FMOD_OUTPUTTYPE_NOSOUND: e_WriteLog('FMOD Output Method: NOSOUND', TMsgType.Notify);
236       FMOD_OUTPUTTYPE_NOSOUND_NRT: e_WriteLog('FMOD Output Method: NOSOUND_NRT', TMsgType.Notify);
237       FMOD_OUTPUTTYPE_DSOUND: e_WriteLog('FMOD Output Method: DSOUND', TMsgType.Notify);
238       FMOD_OUTPUTTYPE_WINMM: e_WriteLog('FMOD Output Method: WINMM', TMsgType.Notify);
239       FMOD_OUTPUTTYPE_OPENAL: e_WriteLog('FMOD Output Method: OPENAL', TMsgType.Notify);
240       FMOD_OUTPUTTYPE_WASAPI: e_WriteLog('FMOD Output Method: WASAPI', TMsgType.Notify);
241       FMOD_OUTPUTTYPE_ASIO: e_WriteLog('FMOD Output Method: ASIO', TMsgType.Notify);
242       FMOD_OUTPUTTYPE_OSS:  e_WriteLog('FMOD Output Method: OSS', TMsgType.Notify);
243       FMOD_OUTPUTTYPE_ALSA: e_Writelog('FMOD Output Method: ALSA', TMsgType.Notify);
244       FMOD_OUTPUTTYPE_SOUNDMANAGER: e_Writelog('FMOD Output Method: SOUNDMANAGER', TMsgType.Notify);
245       FMOD_OUTPUTTYPE_COREAUDIO: e_Writelog('FMOD Output Method: COREAUDIO', TMsgType.Notify);
246       else e_WriteLog('FMOD Output Method: Unknown', TMsgType.Notify);
247     end;
249   res := FMOD_System_GetDriver(F_System, drv);
250   if res <> FMOD_OK
251     then e_WriteLog('Error getting FMOD driver!', TMsgType.Warning)
252     else e_WriteLog('FMOD driver id: '+IntToStr(drv), TMsgType.Notify);
254   Result := True;
255 end;
257 function e_InitSoundSystem(NoOutput: Boolean = False): Boolean;
258 begin
259   if NoOutput then
260   begin
261     Result := e_TrySS(48000, 2);
262     Exit;
263   end;
264   Result := e_TrySS(48000, 0);
265   if not Result then Result := e_TrySS(44100, 1);
266 end;
268 function FindESound(): TSoundID;
270   i: TSoundID;
272 begin
273   if e_SoundsArray <> nil then
274     for i := 0 to High(e_SoundsArray) do
275       if e_SoundsArray[i].Sound = nil then
276       begin
277         Result := i;
278         Exit;
279       end;
281   if e_SoundsArray = nil then
282   begin
283     SetLength(e_SoundsArray, 16);
284     Result := 0;
285   end
286   else
287   begin
288     Result := High(e_SoundsArray) + 1;
289     SetLength(e_SoundsArray, Length(e_SoundsArray) + 16);
290   end;
291 end;
293 function e_LoadSound(FileName: String; var ID: TSoundID; isMusic: Boolean;
294   ForceNoLoop: Boolean): Boolean;
296   find_id: TSoundID;
297   res: FMOD_RESULT;
298   bt: Cardinal;
300 begin
301   Result := False;
302   e_WriteLog('Loading sound '+FileName+'...', TMsgType.Notify);
303   find_id := FindESound();
305   if isMusic and not ForceNoLoop
306     then bt := FMOD_LOOP_NORMAL
307     else bt := FMOD_LOOP_OFF;
309   if not isMusic then
310     res := FMOD_System_CreateSound(F_System, PAnsiChar(FileName), bt or FMOD_2D or FMOD_HARDWARE,
311       nil, e_SoundsArray[find_id].Sound)
312   else
313     res := FMOD_System_CreateStream(F_System, PAnsiChar(FileName), bt or FMOD_2D or FMOD_HARDWARE,
314       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   res := FMOD_Sound_SetUserData(e_SoundsArray[find_id].Sound, Pointer(find_id));
323   if res <> FMOD_OK then
324   begin
325     e_SoundsArray[find_id].Sound := nil;
326     Exit;
327   end;
329   e_SoundsArray[find_id].Data := nil;
330   e_SoundsArray[find_id].isMusic := isMusic;
331   e_SoundsArray[find_id].nRefs := 0;
333   ID := find_id;
334   Result := True;
335 end;
337 function e_LoadSoundMem(pData: Pointer; Length: Integer; var ID: TSoundID; isMusic: Boolean;
338   ForceNoLoop: Boolean): Boolean;
340   find_id: TSoundID;
341   res: FMOD_RESULT;
342   sz: Integer;
343   bt: Cardinal;
344   soundExInfo: FMOD_CREATESOUNDEXINFO;
346 begin
347   Result := False;
348   find_id := FindESound();
350   sz := SizeOf(FMOD_CREATESOUNDEXINFO);
351   FillMemory(@soundExInfo, sz, 0);
352   soundExInfo.cbsize := sz;
353   soundExInfo.length := Length;
355   if isMusic and not ForceNoLoop
356     then bt := FMOD_LOOP_NORMAL
357     else bt := FMOD_LOOP_OFF;
359   if not isMusic then
360     res := FMOD_System_CreateSound(F_System, pData, bt or FMOD_2D or FMOD_HARDWARE
361       or FMOD_OPENMEMORY, @soundExInfo, e_SoundsArray[find_id].Sound)
362   else
363     res := FMOD_System_CreateStream(F_System, pData, bt or FMOD_2D or FMOD_HARDWARE
364       or FMOD_OPENMEMORY, @soundExInfo, e_SoundsArray[find_id].Sound);
366   if res <> FMOD_OK then
367   begin
368     e_SoundsArray[find_id].Sound := nil;
369     Exit;
370   end;
372   res := FMOD_Sound_SetUserData(e_SoundsArray[find_id].Sound, Pointer(find_id));
373   if res <> FMOD_OK then
374   begin
375     e_SoundsArray[find_id].Sound := nil;
376     Exit;
377   end;
379   e_SoundsArray[find_id].Data := pData;
380   e_SoundsArray[find_id].isMusic := isMusic;
381   e_SoundsArray[find_id].nRefs := 0;
383   ID := find_id;
384   Result := True;
385 end;
387 function e_PlaySound(ID: TSoundID): Integer;
389   res: FMOD_RESULT;
390   Chan: FMOD_CHANNEL;
392 begin
393   if e_SoundsArray[ID].nRefs >= gMaxSimSounds then
394   begin
395     Result := 0;
396     Exit;
397   end;
399   Result := -1;
401   res := FMOD_System_PlaySound(F_System, FMOD_CHANNEL_FREE, e_SoundsArray[ID].Sound, False, Chan);
402   if res <> FMOD_OK then
403     Exit;
405   res := FMOD_Channel_SetCallback(Chan, Channel_Callback);
406   if res <> FMOD_OK then
407   begin
408   end;
410   if SoundMuted then
411   begin
412     res := FMOD_Channel_SetMute(Chan, True);
413     if res <> FMOD_OK then
414     begin
415     end;
416   end;
418   e_SoundsArray[ID].nRefs += 1;
419   Result := 0;
420 end;
422 function e_PlaySoundPan(ID: TSoundID; Pan: Single): Integer;
424   res: FMOD_RESULT;
425   Chan: FMOD_CHANNEL;
427 begin
428   if e_SoundsArray[ID].nRefs >= gMaxSimSounds then
429   begin
430     Result := 0;
431     Exit;
432   end;
434   Result := -1;
436   res := FMOD_System_PlaySound(F_System, FMOD_CHANNEL_FREE, e_SoundsArray[ID].Sound, False, Chan);
437   if res <> FMOD_OK then
438     Exit;
440   res := FMOD_Channel_SetPan(Chan, Pan);
441   if res <> FMOD_OK then
442   begin
443   end;
445   res := FMOD_Channel_SetCallback(Chan, Channel_Callback);
446   if res <> FMOD_OK then
447   begin
448   end;
450   if SoundMuted then
451   begin
452     res := FMOD_Channel_SetMute(Chan, True);
453     if res <> FMOD_OK then
454     begin
455     end;
456   end;
458   e_SoundsArray[ID].nRefs += 1;
459   Result := 0;
460 end;
462 function e_PlaySoundVolume(ID: TSoundID; Volume: Single): Integer;
464   res: FMOD_RESULT;
465   Chan: FMOD_CHANNEL;
467 begin
468   if e_SoundsArray[ID].nRefs >= gMaxSimSounds then
469   begin
470     Result := 0;
471     Exit;
472   end;
474   Result := -1;
476   res := FMOD_System_PlaySound(F_System, FMOD_CHANNEL_FREE, e_SoundsArray[ID].Sound, False, Chan);
477   if res <> FMOD_OK then
478     Exit;
480   res := FMOD_Channel_SetVolume(Chan, Volume);
481   if res <> FMOD_OK then
482   begin
483   end;
485   res := FMOD_Channel_SetCallback(Chan, Channel_Callback);
486   if res <> FMOD_OK then
487   begin
488   end;
490   if SoundMuted then
491   begin
492     res := FMOD_Channel_SetMute(Chan, True);
493     if res <> FMOD_OK then
494     begin
495     end;
496   end;
498   e_SoundsArray[ID].nRefs += 1;
499   Result := 0;
500 end;
502 function e_PlaySoundPanVolume(ID: TSoundID; Pan, Volume: Single): Integer;
504   res: FMOD_RESULT;
505   Chan: FMOD_CHANNEL;
507 begin
508   if e_SoundsArray[ID].nRefs >= gMaxSimSounds then
509   begin
510     Result := 0;
511     Exit;
512   end;
514   Result := -1;
516   res := FMOD_System_PlaySound(F_System, FMOD_CHANNEL_FREE, e_SoundsArray[ID].Sound, False, Chan);
517   if res <> FMOD_OK then
518     Exit;
520   res := FMOD_Channel_SetPan(Chan, Pan);
521   if res <> FMOD_OK then
522   begin
523   end;
525   res := FMOD_Channel_SetVolume(Chan, Volume);
526   if res <> FMOD_OK then
527   begin
528   end;
530   res := FMOD_Channel_SetCallback(Chan, Channel_Callback);
531   if res <> FMOD_OK then
532   begin
533   end;
535   if SoundMuted then
536   begin
537     res := FMOD_Channel_SetMute(Chan, True);
538     if res <> FMOD_OK then
539     begin
540     end;
541   end;
543   e_SoundsArray[ID].nRefs += 1;
544   Result := 0;
545 end;
547 procedure e_DeleteSound(ID: TSoundID);
549   res: FMOD_RESULT;
551 begin
552   if e_SoundsArray[ID].Sound = nil then
553     Exit;
555   FreeMem(e_SoundsArray[ID].Data);
557   res := FMOD_Sound_Release(e_SoundsArray[ID].Sound);
558   if res <> FMOD_OK then
559   begin
560     e_WriteLog('Error releasing sound:', TMsgType.Warning);
561     e_WriteLog(FMOD_ErrorString(res), TMsgType.Warning);
562   end;
564   e_SoundsArray[ID].Sound := nil;
565   e_SoundsArray[ID].Data := nil;
566 end;
568 procedure e_ModifyChannelsVolumes(SoundMod: Single; setMode: Boolean);
570   res: FMOD_RESULT;
571   i: Integer;
572   Chan: FMOD_CHANNEL;
573   vol: Single;
575 begin
576   for i := 0 to N_CHANNELS-1 do
577   begin
578     Chan := nil;
579     res := FMOD_System_GetChannel(F_System, i, Chan);
581     if (res = FMOD_OK) and (Chan <> nil) then
582     begin
583       res := FMOD_Channel_GetVolume(Chan, vol);
585       if res = FMOD_OK then
586       begin
587         if setMode
588           then vol := SoundMod
589           else vol *= SoundMod;
591         res := FMOD_Channel_SetVolume(Chan, vol);
593         if res <> FMOD_OK then
594         begin
595         end;
596       end;
597     end;
598   end;
599 end;
601 procedure e_MuteChannels(Enable: Boolean);
603   res: FMOD_RESULT;
604   i: Integer;
605   Chan: FMOD_CHANNEL;
607 begin
608   if Enable = SoundMuted then
609     Exit;
611   SoundMuted := Enable;
613   for i := 0 to N_CHANNELS-1 do
614   begin
615     Chan := nil;
616     res := FMOD_System_GetChannel(F_System, i, Chan);
618     if (res = FMOD_OK) and (Chan <> nil) then
619     begin
620       res := FMOD_Channel_SetMute(Chan, Enable);
622       if res <> FMOD_OK then
623       begin
624       end;
625     end;
626   end;
627 end;
629 procedure e_StopChannels();
631   res: FMOD_RESULT;
632   i: Integer;
633   Chan: FMOD_CHANNEL;
635 begin
636   for i := 0 to N_CHANNELS-1 do
637   begin
638     Chan := nil;
639     res := FMOD_System_GetChannel(F_System, i, Chan);
641     if (res = FMOD_OK) and (Chan <> nil) then
642     begin
643       res := FMOD_Channel_Stop(Chan);
645       if res <> FMOD_OK then
646       begin
647       end;
648     end;
649   end;
650 end;
652 procedure e_RemoveAllSounds();
654   i: Integer;
656 begin
657   for i := 0 to High(e_SoundsArray) do
658     if e_SoundsArray[i].Sound <> nil then
659       e_DeleteSound(i);
661   SetLength(e_SoundsArray, 0);
662 end;
664 procedure e_ReleaseSoundSystem();
666   res: FMOD_RESULT;
668 begin
669   e_RemoveAllSounds();
671   res := FMOD_System_Close(F_System);
672   if res <> FMOD_OK then
673   begin
674     e_WriteLog('Error closing FMOD system!', TMsgType.Fatal);
675     e_WriteLog(FMOD_ErrorString(res), TMsgType.Fatal);
676     Exit;
677   end;
679   res := FMOD_System_Release(F_System);
680   if res <> FMOD_OK then
681   begin
682     e_WriteLog('Error releasing FMOD system!', TMsgType.Fatal);
683     e_WriteLog(FMOD_ErrorString(res), TMsgType.Fatal);
684   end;
685 end;
687 procedure e_SoundUpdate();
688 begin
689   FMOD_System_Update(F_System);
690 end;
692 { TBasicSound: }
694 constructor TBasicSound.Create();
695 begin
696   FID := NO_SOUND_ID;
697   FMusic := False;
698   FChannel := nil;
699   FPosition := 0;
700   FPriority := 128;
701 end;
703 destructor TBasicSound.Destroy();
704 begin
705   FreeSound();
706   inherited;
707 end;
709 procedure TBasicSound.FreeSound();
710 begin
711   if FID = NO_SOUND_ID then
712     Exit;
714   Stop();
715   FID := NO_SOUND_ID;
716   FMusic := False;
717   FPosition := 0;
718 end;
720 function TBasicSound.RawPlay(Pan: Single; Volume: Single; aPos: DWORD): Boolean;
722   res: FMOD_RESULT;
724 begin
725   Result := False;
726   if FID = NO_SOUND_ID then Exit;
728   if e_SoundsArray[FID].nRefs >= gMaxSimSounds then
729   begin
730     Result := True;
731     Exit;
732   end;
734   res := FMOD_System_PlaySound(F_System, FMOD_CHANNEL_FREE, e_SoundsArray[FID].Sound, False,
735     FChannel);
736   if res <> FMOD_OK then
737   begin
738     FChannel := nil;
739     Exit;
740   end;
742   res := FMOD_Channel_SetPosition(FChannel, aPos, FMOD_TIMEUNIT_MS);
743   if res <> FMOD_OK
744     then FPosition := 0
745     else FPosition := aPos;
747   res := FMOD_Channel_SetPan(FChannel, Pan);
748   if res <> FMOD_OK then
749   begin
750   end;
752   res := FMOD_Channel_SetVolume(FChannel, Volume);
753   if res <> FMOD_OK then
754   begin
755   end;
757   res := FMOD_Channel_SetCallback(FChannel, Channel_Callback);
758   if res <> FMOD_OK then
759   begin
760   end;
762   if SoundMuted then
763   begin
764     res := FMOD_Channel_SetMute(FChannel, True);
765     if res <> FMOD_OK then
766     begin
767     end;
768   end;
770   e_SoundsArray[FID].nRefs += 1;
771   Result := True;
772 end;
774 procedure TBasicSound.SetID(ID: TSoundID);
775 begin
776   FreeSound();
777   FID := ID;
778   FMusic := e_SoundsArray[ID].isMusic;
779 end;
781 function TBasicSound.IsPlaying(): Boolean;
783   res: FMOD_RESULT;
784   b: LongBool;
786 begin
787   Result := False;
789   if FChannel = nil then
790     Exit;
792   res := FMOD_Channel_IsPlaying(FChannel, b);
793   if res <> FMOD_OK then
794     Exit;
796   Result := b;
797 end;
799 procedure TBasicSound.Stop();
801   res: FMOD_RESULT;
803 begin
804   if FChannel = nil then
805     Exit;
807   GetPosition();
809   res := FMOD_Channel_Stop(FChannel);
810   if res <> FMOD_OK then
811   begin
812   end;
814   FChannel := nil;
815 end;
817 function TBasicSound.IsPaused(): Boolean;
819   res: FMOD_RESULT;
820   b: LongBool;
822 begin
823   Result := False;
825   if FChannel = nil then
826     Exit;
828   res := FMOD_Channel_GetPaused(FChannel, b);
829   if res <> FMOD_OK then
830     Exit;
832   Result := b;
833 end;
835 procedure TBasicSound.Pause(Enable: Boolean);
837   res: FMOD_RESULT;
839 begin
840   if FChannel = nil then
841     Exit;
843   res := FMOD_Channel_SetPaused(FChannel, Enable);
844   if res <> FMOD_OK then
845   begin
846   end;
848   if Enable then
849   begin
850     res := FMOD_Channel_GetPosition(FChannel, FPosition, FMOD_TIMEUNIT_MS);
851     if res <> FMOD_OK then
852     begin
853     end;
854   end;
855 end;
857 function TBasicSound.GetVolume(): Single;
859   res: FMOD_RESULT;
860   vol: Single;
862 begin
863   Result := 0.0;
865   if FChannel = nil then
866     Exit;
868   res := FMOD_Channel_GetVolume(FChannel, vol);
869   if res <> FMOD_OK then
870     Exit;
872   Result := vol;
873 end;
875 procedure TBasicSound.SetVolume(Volume: Single);
877   res: FMOD_RESULT;
879 begin
880   if FChannel = nil then
881     Exit;
883   res := FMOD_Channel_SetVolume(FChannel, Volume);
884   if res <> FMOD_OK then
885   begin
886   end;
887 end;
889 function TBasicSound.GetPan(): Single;
891   res: FMOD_RESULT;
892   pan: Single;
894 begin
895   Result := 0.0;
897   if FChannel = nil then
898     Exit;
900   res := FMOD_Channel_GetPan(FChannel, pan);
901   if res <> FMOD_OK then
902     Exit;
904   Result := pan;
905 end;
907 procedure TBasicSound.SetPan(Pan: Single);
909   res: FMOD_RESULT;
911 begin
912   if FChannel = nil then
913     Exit;
915   res := FMOD_Channel_SetPan(FChannel, Pan);
916   if res <> FMOD_OK then
917   begin
918   end;
919 end;
921 function TBasicSound.IsMuted(): Boolean;
923   res: FMOD_RESULT;
924   b: LongBool;
926 begin
927   Result := False;
929   if FChannel = nil then
930     Exit;
932   res := FMOD_Channel_GetMute(FChannel, b);
933   if res <> FMOD_OK then
934     Exit;
936   Result := b;
937 end;
939 procedure TBasicSound.Mute(Enable: Boolean);
941   res: FMOD_RESULT;
943 begin
944   if FChannel = nil then
945     Exit;
947   res := FMOD_Channel_SetMute(FChannel, Enable);
948   if res <> FMOD_OK then
949   begin
950   end;
951 end;
953 function TBasicSound.GetPosition(): DWORD;
955   res: FMOD_RESULT;
957 begin
958   Result := 0;
960   if FChannel = nil then
961     Exit;
963   res := FMOD_Channel_GetPosition(FChannel, FPosition, FMOD_TIMEUNIT_MS);
964   if res <> FMOD_OK then
965     Exit;
967   Result := FPosition;
968 end;
970 procedure TBasicSound.SetPosition(aPos: DWORD);
972   res: FMOD_RESULT;
974 begin
975   FPosition := aPos;
977   if FChannel = nil then
978     Exit;
980   res := FMOD_Channel_SetPosition(FChannel, FPosition, FMOD_TIMEUNIT_MS);
981   if res <> FMOD_OK then
982   begin
983   end;
984 end;
986 procedure TBasicSound.SetPriority(priority: Cardinal);
988   res: FMOD_RESULT;
990 begin
991   if (FChannel <> nil) and (FPriority <> priority) and (priority <= 256) then
992   begin
993     FPriority := priority;
994     res := FMOD_Channel_SetPriority(FChannel, priority);
995     if res <> FMOD_OK then
996     begin
997     end;
998   end;
999 end;
1001 end.