ab3f4fe1c14a0e5dd00dc909c79e48e91406ac0b
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}
106 var
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;
154 var
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;
265 var
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;
290 var
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;
341 var
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;
397 var
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;
435 var
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;
478 var
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;
521 var
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);
569 var
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);
598 var
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);
632 var
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();
660 var
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();
683 var
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();
696 var
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;
752 var
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;
816 var
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();
836 var
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;
854 var
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);
874 var
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;
896 var
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);
916 var
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;
930 var
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);
950 var
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;
964 var
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);
984 var
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;
998 var
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);
1017 var
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);
1033 var
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.