DEADSOFTWARE

even more useless logs
[d2df-sdl.git] / src / engine / e_sound_sdl.inc
1 interface
3 uses
4 sdl2,
5 SDL2_mixer,
6 e_log,
7 SysUtils;
9 type
10 TSoundRec = record
11 Data: Pointer;
12 Sound: PMix_Chunk;
13 Music: PMix_Music;
14 isMusic: Boolean;
15 nRefs: Integer;
16 end;
18 TBasicSound = class (TObject)
19 private
20 FChanNum: Integer; // <0: no channel allocated
22 protected
23 FID: DWORD;
24 FMusic: Boolean;
25 FPosition: DWORD;
26 FPriority: Integer;
28 function RawPlay(Pan: Single; Volume: Single; aPos: DWORD): Boolean;
29 function GetChan (): Integer;
31 property Channel: Integer read GetChan;
33 public
34 constructor Create();
35 destructor Destroy(); override;
36 procedure SetID(ID: DWORD);
37 procedure FreeSound();
38 function IsPlaying(): Boolean;
39 procedure Stop();
40 function IsPaused(): Boolean;
41 procedure Pause(Enable: Boolean);
42 function GetVolume(): Single;
43 procedure SetVolume(Volume: Single);
44 function GetPan(): Single;
45 procedure SetPan(Pan: Single);
46 function IsMuted(): Boolean;
47 procedure Mute(Enable: Boolean);
48 function GetPosition(): DWORD;
49 procedure SetPosition(aPos: DWORD);
50 procedure SetPriority(priority: Integer);
51 end;
53 const
54 NO_SOUND_ID = DWORD(-1);
56 function e_InitSoundSystem(): Boolean;
58 function e_LoadSound(FileName: string; var ID: DWORD; isMusic: Boolean): Boolean;
59 function e_LoadSoundMem(pData: Pointer; Length: Integer; var ID: DWORD; isMusic: Boolean): Boolean;
61 // returns channel number or -1
62 function e_PlaySound(ID: DWORD): Integer;
63 function e_PlaySoundPan(ID: DWORD; Pan: Single): Integer;
64 function e_PlaySoundVolume(ID: DWORD; Volume: Single): Integer;
65 function e_PlaySoundPanVolume(ID: DWORD; Pan, Volume: Single): Integer;
67 procedure e_ModifyChannelsVolumes(SoundMod: Single; setMode: Boolean);
68 procedure e_MuteChannels(Enable: Boolean);
69 procedure e_StopChannels();
71 procedure e_DeleteSound(ID: DWORD);
72 procedure e_RemoveAllSounds();
73 procedure e_ReleaseSoundSystem();
74 procedure e_SoundUpdate();
76 var
77 e_SoundsArray: array of TSoundRec = nil;
79 implementation
81 uses
82 g_window, g_options, BinEditor;
84 const
85 N_CHANNELS = 512;
86 N_MUSCHAN = N_CHANNELS+42;
88 type
89 TChanInfo = record
90 id: DWORD; // sound id
91 muted: Boolean;
92 oldvol: Integer; // for muted
93 pan: Single;
94 end;
96 var
97 SoundMuted: Boolean = False;
98 SoundInitialized: Boolean = False;
99 ChanSIds: array[0..N_CHANNELS] of TChanInfo;
100 MusVolume: Integer = MIX_MAX_VOLUME;
103 procedure chanFinished (chan: Integer); cdecl;
104 begin
105 //e_WriteLog(Format('chanFinished: %d', [chan]), MSG_NOTIFY);
106 if (chan >= 0) and (chan < N_CHANNELS) then
107 begin
108 if ChanSIds[chan].id <> NO_SOUND_ID then
109 begin
110 if (ChanSIds[chan].id <= High(e_SoundsArray)) and (e_SoundsArray[ChanSIds[chan].id].nRefs > 0) then
111 begin
112 Dec(e_SoundsArray[ChanSIds[chan].id].nRefs);
113 end;
114 ChanSIds[chan].id := NO_SOUND_ID;
115 end;
116 end;
117 end;
120 procedure dumpMusicType (ms: PMix_Music);
121 begin
122 if ms = nil then
123 begin
124 e_WriteLog('MUSIC FORMAT: NONE', MSG_NOTIFY);
125 end
126 else
127 begin
128 case Mix_GetMusicType(ms^) of
129 TMix_MusicType.MUS_NONE:
130 e_WriteLog('MUSIC FORMAT: NONE', MSG_NOTIFY);
131 TMix_MusicType.MUS_CMD:
132 e_WriteLog('MUSIC FORMAT: CMD', MSG_NOTIFY);
133 TMix_MusicType.MUS_WAV:
134 e_WriteLog('MUSIC FORMAT: WAV', MSG_NOTIFY);
135 TMix_MusicType.MUS_MOD:
136 e_WriteLog('MUSIC FORMAT: MOD', MSG_NOTIFY);
137 TMix_MusicType.MUS_MID:
138 e_WriteLog('MUSIC FORMAT: MID', MSG_NOTIFY);
139 TMix_MusicType.MUS_OGG:
140 e_WriteLog('MUSIC FORMAT: OGG', MSG_NOTIFY);
141 TMix_MusicType.MUS_MP3:
142 e_WriteLog('MUSIC FORMAT: MP3', MSG_NOTIFY);
143 TMix_MusicType.MUS_MP3_MAD:
144 e_WriteLog('MUSIC FORMAT: MP3_MAD', MSG_NOTIFY);
145 TMix_MusicType.MUS_FLAC:
146 e_WriteLog('MUSIC FORMAT: FLAC', MSG_NOTIFY);
147 TMix_MusicType.MUS_MODPLUG:
148 e_WriteLog('MUSIC FORMAT: MODPLUG', MSG_NOTIFY);
149 otherwise
150 e_WriteLog('MUSIC FORMAT: UNKNOWN', MSG_NOTIFY);
151 end;
152 end;
153 end;
155 function e_InitSoundSystem(): Boolean;
156 var
157 res, i: Integer;
158 rfreq: Integer;
159 rformat: UInt16;
160 rchans: Integer;
161 begin
162 if SoundInitialized then begin Result := true; Exit end;
164 Result := False;
165 SoundInitialized := False;
167 // wow, this is actually MIDI player!
168 // we need module player
169 res := Mix_Init(MIX_INIT_FLAC or MIX_INIT_MOD or MIX_INIT_MODPLUG or MIX_INIT_MP3 or MIX_INIT_OGG or MIX_INIT_FLUIDSYNTH);
170 e_WriteLog(Format('SDL: res=0x%x', [res]), MSG_NOTIFY);
171 if (res and MIX_INIT_FLAC) <> 0 then e_WriteLog('SDL: FLAC playback is active', MSG_NOTIFY);
172 if (res and MIX_INIT_MOD) <> 0 then e_WriteLog('SDL: MOD playback is active', MSG_NOTIFY);
173 if (res and MIX_INIT_MODPLUG) <> 0 then e_WriteLog('SDL: MODPLUG playback is active', MSG_NOTIFY);
174 if (res and MIX_INIT_MP3) <> 0 then e_WriteLog('SDL: MP3 playback is active', MSG_NOTIFY);
175 if (res and MIX_INIT_OGG) <> 0 then e_WriteLog('SDL: OGG playback is active', MSG_NOTIFY);
176 if (res and MIX_INIT_FLUIDSYNTH) <> 0 then e_WriteLog('SDL: FLUIDSYNTH playback is active', MSG_NOTIFY);
178 res := Mix_OpenAudio(44100, AUDIO_S16LSB, 2, 2048);
179 if res = -1 then
180 begin
181 e_WriteLog('Error initializing SDL mixer:', MSG_FATALERROR);
182 e_WriteLog(Mix_GetError(), MSG_FATALERROR);
183 Exit;
184 end;
186 if Mix_QuerySpec(@rfreq, @rformat, @rchans) > 0 then
187 begin
188 e_WriteLog(Format('SDL: frequency=%d; format=%u; channels=%d', [rfreq, rformat, rchans]), MSG_NOTIFY);
189 end;
191 for i := 0 to Mix_GetNumChunkDecoders()-1 do
192 begin
193 e_WriteLog(Format('SDL: chunk decoder %s is avalable', [Mix_GetChunkDecoder(i)]), MSG_NOTIFY);
194 end;
195 for i := 0 to Mix_GetNumMusicDecoders()-1 do
196 begin
197 e_WriteLog(Format('SDL: music decoder %s is avalable', [Mix_GetMusicDecoder(i)]), MSG_NOTIFY);
198 end;
200 Mix_AllocateChannels(N_CHANNELS);
201 Mix_ChannelFinished(chanFinished);
203 for i := 0 to N_CHANNELS-1 do
204 begin
205 ChanSIds[i].id := NO_SOUND_ID;
206 ChanSIds[i].muted := SoundMuted;
207 ChanSIds[i].oldvol := MIX_MAX_VOLUME;
208 ChanSIds[i].pan := 1.0;
209 end;
210 MusVolume := MIX_MAX_VOLUME;
212 SoundInitialized := True;
213 Result := True;
214 end;
216 function e_isMusic (id: DWORD): Boolean;
217 begin
218 Result := False;
219 if (e_SoundsArray <> nil) and (id <= High(e_SoundsArray)) then
220 begin
221 Result := (e_SoundsArray[id].Music <> nil);
222 end;
223 end;
225 function e_isSound (id: DWORD): Boolean;
226 begin
227 Result := False;
228 if (e_SoundsArray <> nil) and (id <= High(e_SoundsArray)) then
229 begin
230 Result := (e_SoundsArray[id].Sound <> nil);
231 end;
232 end;
234 function FindESound(): DWORD;
235 var
236 i: Integer;
237 begin
238 if e_SoundsArray <> nil then
239 begin
240 for i := 0 to High(e_SoundsArray) do
241 if (e_SoundsArray[i].Sound = nil) and (e_SoundsArray[i].Music = nil) then
242 begin
243 Result := i;
244 Exit;
245 end;
246 end;
247 if e_SoundsArray = nil then
248 begin
249 SetLength(e_SoundsArray, 16);
250 Result := 0;
251 end
252 else
253 begin
254 Result := High(e_SoundsArray) + 1;
255 SetLength(e_SoundsArray, Length(e_SoundsArray) + 16);
256 end;
257 for i := Result to High(e_SoundsArray) do
258 begin
259 e_SoundsArray[i].Sound := nil;
260 e_SoundsArray[i].Music := nil;
261 e_SoundsArray[i].Data := nil;
262 e_SoundsArray[i].isMusic := False;
263 e_SoundsArray[i].nRefs := 0;
264 end;
265 end;
267 function e_LoadSound(FileName: String; var ID: DWORD; isMusic: Boolean): Boolean;
268 var
269 find_id: DWORD;
270 begin
271 ID := NO_SOUND_ID;
272 Result := False;
273 if not SoundInitialized then Exit;
275 if isMusic then e_WriteLog('Loading music '+FileName+'...', MSG_NOTIFY)
276 else e_WriteLog('Loading sound '+FileName+'...', MSG_NOTIFY);
279 if isMusic then
280 begin
281 e_WriteLog('IGNORING MUSIC FROM FILE', MSG_WARNING);
282 Exit;
283 end;
286 find_id := FindESound();
288 e_SoundsArray[find_id].Data := nil;
289 e_SoundsArray[find_id].isMusic := isMusic;
290 e_SoundsArray[find_id].nRefs := 0;
292 if isMusic then
293 begin
294 e_WriteLog(Format(' MUSIC SLOT: %u', [find_id]), MSG_NOTIFY);
295 e_SoundsArray[find_id].Music := Mix_LoadMUS(PAnsiChar(FileName));
296 if e_SoundsArray[find_id].Music = nil then
297 begin
298 e_WriteLog(Format('ERROR LOADING MUSIC:', [find_id]), MSG_WARNING);
299 e_WriteLog(Mix_GetError(), MSG_WARNING);
300 Exit;
301 end;
302 dumpMusicType(e_SoundsArray[find_id].Music);
303 end
304 else
305 begin
306 e_SoundsArray[find_id].Sound := Mix_LoadWAV(PAnsiChar(FileName));
307 if e_SoundsArray[find_id].Sound = nil then Exit;
308 end;
310 ID := find_id;
312 Result := True;
313 end;
315 function e_LoadSoundMem(pData: Pointer; Length: Integer; var ID: DWORD; isMusic: Boolean): Boolean;
316 var
317 find_id: DWORD;
318 rw: PSDL_RWops;
319 //pc: PChar;
320 isid3: Boolean;
321 begin
322 ID := NO_SOUND_ID;
323 Result := False;
324 if not SoundInitialized then Exit;
325 isid3 := False;
328 if isMusic then
329 begin
330 e_WriteLog('IGNORING MUSIC FROM MEMORY', MSG_WARNING);
331 Exit;
332 end;
335 //FIXME: correctly skip ID3
337 pc := PChar(pData);
338 if (Length > $400) and (pc[0] = 'I') and (pc[1] = 'D') and (pc[2] = '3') then
339 begin
340 isid3 := True;
341 Inc(pc, $400);
342 pData := Pointer(pc);
343 Dec(Length, $400);
344 e_WriteLog('MUSIC: MP3 ID3 WORKAROUND APPLIED!', MSG_WARNING);
345 end;
348 rw := SDL_RWFromConstMem(pData, Length);
349 if rw = nil then Exit;
351 find_id := FindESound();
353 e_SoundsArray[find_id].Data := pData;
354 if isid3 then e_SoundsArray[find_id].Data := nil;
355 e_SoundsArray[find_id].isMusic := isMusic;
356 e_SoundsArray[find_id].nRefs := 0;
358 if isMusic then
359 begin
360 e_WriteLog(Format(' MUSIC SLOT: %u', [find_id]), MSG_NOTIFY);
361 e_SoundsArray[find_id].Music := Mix_LoadMUS_RW(rw, 0);
362 if e_SoundsArray[find_id].Music = nil then
363 begin
364 e_WriteLog(Format('ERROR LOADING MUSIC:', [find_id]), MSG_WARNING);
365 e_WriteLog(Mix_GetError(), MSG_WARNING);
366 end
367 else
368 begin
369 dumpMusicType(e_SoundsArray[find_id].Music);
370 end;
371 //SDL_FreeRW(rw);
373 if e_SoundsArray[find_id].Music <> nil then
374 begin
375 Mix_FreeMusic(e_SoundsArray[find_id].Music);
376 end;
377 e_SoundsArray[find_id].Music := nil;
378 Exit;
380 end
381 else
382 begin
383 e_SoundsArray[find_id].Sound := Mix_LoadWAV_RW(rw, 0);
384 end;
385 //SDL_FreeRW(rw); // somehow it segfaults...
386 if (e_SoundsArray[find_id].Sound = nil) and (e_SoundsArray[find_id].Music = nil) then
387 begin
388 e_SoundsArray[find_id].Data := nil;
389 Exit;
390 end;
392 ID := find_id;
394 Result := True;
395 end;
397 function e_PlaySound (ID: DWORD): Integer;
398 var
399 res: Integer = -1;
400 begin
401 Result := -1;
402 if not SoundInitialized then Exit;
404 if e_isSound(ID) then
405 begin
406 if e_SoundsArray[ID].nRefs >= gMaxSimSounds then Exit;
407 Inc(e_SoundsArray[ID].nRefs);
408 res := Mix_PlayChannel(-1, e_SoundsArray[ID].Sound, 0);
409 if res >= 0 then
410 begin
411 ChanSIds[res].id := ID;
412 ChanSIds[res].muted := SoundMuted;
413 if SoundMuted then Mix_Volume(res, 0) else Mix_Volume(res, ChanSIds[res].oldvol);
415 if e_SoundsArray[ID].isMusic then
416 res := Mix_PlayChannel(-1, e_SoundsArray[ID].Sound, -1)
417 else
418 res := Mix_PlayChannel(-1, e_SoundsArray[ID].Sound, 0);
420 end;
421 end
422 else
423 begin
424 if not e_isMusic(ID) then Exit;
425 Mix_HaltMusic();
426 res := Mix_PlayMusic(e_SoundsArray[ID].Music, -1);
427 if res >= 0 then res := N_MUSCHAN;
428 if SoundMuted then Mix_VolumeMusic(0) else Mix_VolumeMusic(MusVolume);
429 Result := res;
430 end;
432 Result := res;
433 end;
435 function e_chanSetPan (chan: Integer; Pan: Single): Boolean;
436 var
437 l, r: UInt8;
438 begin
439 Result := True;
440 if chan = N_MUSCHAN then
441 begin
442 // no panning for music
443 end
444 else if chan >= 0 then
445 begin
446 if Pan < -1.0 then Pan := -1.0 else if Pan > 1.0 then Pan := 1.0;
447 Pan := Pan+1.0; // 0..2
448 l := trunc(127.0*(2.0-Pan));
449 r := trunc(127.0*Pan);
450 Mix_SetPanning(chan, l, r);
451 ChanSIds[chan].pan := Pan;
452 end
453 else
454 begin
455 Result := False;
456 end;
457 end;
459 function e_chanSetVol (chan: Integer; Volume: Single): Boolean;
460 var
461 vol: Integer;
462 begin
463 Result := True;
464 if Volume < 0 then Volume := 0 else if Volume > 1 then Volume := 1;
465 vol := trunc(Volume*MIX_MAX_VOLUME);
466 if chan = N_MUSCHAN then
467 begin
468 MusVolume := vol;
469 if SoundMuted then Mix_VolumeMusic(0) else Mix_VolumeMusic(vol);
470 end
471 else if chan >= 0 then
472 begin
473 ChanSIds[chan].oldvol := vol;
474 if ChanSIds[chan].muted then Mix_Volume(chan, 0) else Mix_Volume(chan, vol);
475 end
476 else
477 begin
478 Result := False;
479 end;
480 end;
482 function e_PlaySoundPan(ID: DWORD; Pan: Single): Integer;
483 var
484 chan: Integer;
485 begin
486 Result := -1;
487 chan := e_PlaySound(ID);
488 e_chanSetPan(chan, Pan);
489 Result := chan;
490 end;
492 function e_PlaySoundVolume(ID: DWORD; Volume: Single): Integer;
493 var
494 chan: Integer;
495 begin
496 Result := -1;
497 chan := e_PlaySound(ID);
498 e_chanSetVol(chan, Volume);
499 Result := chan;
500 end;
502 function e_PlaySoundPanVolume(ID: DWORD; Pan, Volume: Single): Integer;
503 var
504 chan: Integer;
505 begin
506 Result := -1;
507 chan := e_PlaySound(ID);
508 e_chanSetPan(chan, Pan);
509 e_chanSetVol(chan, Volume);
510 Result := chan;
511 end;
513 procedure e_DeleteSound(ID: DWORD);
514 var
515 i: Integer;
516 begin
517 if ID > High(e_SoundsArray) then Exit;
518 if (e_SoundsArray[ID].Sound = nil) and (e_SoundsArray[ID].Music = nil) then Exit;
520 for i := 0 to N_CHANNELS-1 do
521 begin
522 if ChanSIds[i].id = ID then
523 begin
524 ChanSIds[i].id := NO_SOUND_ID;
525 Mix_HaltChannel(i);
526 end;
527 end;
529 if e_SoundsArray[ID].Sound <> nil then Mix_FreeChunk(e_SoundsArray[ID].Sound);
530 if e_SoundsArray[ID].Music <> nil then Mix_FreeMusic(e_SoundsArray[ID].Music);
531 if e_SoundsArray[ID].Data <> nil then FreeMem(e_SoundsArray[ID].Data);
533 e_SoundsArray[ID].Sound := nil;
534 e_SoundsArray[ID].Music := nil;
535 e_SoundsArray[ID].Data := nil;
536 e_SoundsArray[ID].nRefs := 0;
537 end;
539 procedure e_ModifyChannelsVolumes(SoundMod: Single; setMode: Boolean);
540 var
541 i: Integer;
542 vol: Single;
543 ovol: Integer;
544 begin
545 for i := 0 to N_CHANNELS-1 do
546 begin
547 ovol := ChanSIds[i].oldvol;
548 if setMode then
549 begin
550 vol := SoundMod;
551 end
552 else
553 begin
554 vol := (MIX_MAX_VOLUME+0.0)/ovol;
555 vol := vol*SoundMod;
556 end;
557 if vol < 0 then vol := 0 else if vol > 1 then vol := 1;
558 ChanSIds[i].oldvol := trunc(vol*MIX_MAX_VOLUME);
559 //if i = 0 then e_WriteLog(Format('modifying volumes: vol=%f; newvol=%d', [vol, ChanSIds[i].oldvol]), MSG_WARNING);
560 if ChanSIds[i].muted then Mix_Volume(i, 0) else Mix_Volume(i, ChanSIds[i].oldvol);
561 end;
562 ovol := Mix_VolumeMusic(-1);
563 if ovol >= 0 then
564 begin
565 if setMode then
566 begin
567 vol := SoundMod;
568 end
569 else
570 begin
571 vol := (MIX_MAX_VOLUME+0.0)/ovol;
572 vol := vol * SoundMod;
573 end;
574 if vol < 0 then vol := 0 else if vol > 1 then vol := 1;
575 MusVolume := trunc(vol*MIX_MAX_VOLUME);
576 if SoundMuted then Mix_VolumeMusic(0) else Mix_VolumeMusic(MusVolume);
577 end;
578 end;
580 procedure e_MuteChannels(Enable: Boolean);
581 var
582 i: Integer;
583 begin
584 //if Enable = SoundMuted then Exit;
585 SoundMuted := Enable;
586 for i := 0 to N_CHANNELS-1 do
587 begin
588 if ChanSIds[i].muted <> SoundMuted then
589 begin
590 ChanSIds[i].muted := SoundMuted;
591 //e_WriteLog(Format('gmuting sound for channel %d', [i]), MSG_WARNING);
592 if ChanSIds[i].muted then Mix_Volume(i, 0) else Mix_Volume(i, ChanSIds[i].oldvol);
593 end;
594 end;
595 //if SoundMuted then e_WriteLog('muting music', MSG_NOTIFY) else e_WriteLog(Format('unmuting music (%d)', [MusVolume]), MSG_NOTIFY);
596 if SoundMuted then Mix_VolumeMusic(0) else Mix_VolumeMusic(MusVolume);
597 end;
599 procedure e_StopChannels();
600 var
601 i: Integer;
602 begin
603 Mix_HaltChannel(-1);
604 Mix_HaltMusic();
605 for i := 0 to High(e_SoundsArray) do e_SoundsArray[i].nRefs := 0;
606 for i := 0 to N_CHANNELS-1 do ChanSIds[i].id := NO_SOUND_ID;
607 end;
609 procedure e_RemoveAllSounds();
610 var
611 i: Integer;
612 begin
613 if SoundInitialized then e_StopChannels();
614 for i := 0 to High(e_SoundsArray) do e_DeleteSound(i);
615 SetLength(e_SoundsArray, 0);
616 e_SoundsArray := nil;
617 end;
619 procedure e_ReleaseSoundSystem();
620 begin
621 e_RemoveAllSounds();
622 if SoundInitialized then
623 begin
624 Mix_CloseAudio();
625 SoundInitialized := False;
626 end;
627 end;
629 procedure e_SoundUpdate();
630 begin
631 //FMOD_System_Update(F_System);
632 end;
635 { TBasicSound: }
637 constructor TBasicSound.Create();
638 begin
639 FID := NO_SOUND_ID;
640 FMusic := False;
641 FChanNum := -1;
642 FPosition := 0;
643 FPriority := 128;
644 end;
646 destructor TBasicSound.Destroy();
647 begin
648 FreeSound();
649 inherited;
650 end;
652 function TBasicSound.GetChan (): Integer;
653 begin
654 if (FID <> NO_SOUND_ID) and (FChanNum >= 0) and (FChanNum < N_CHANNELS) then
655 begin
656 if ChanSIds[FChanNum].id <> FID then FChanNum := -1;
657 end
658 else if e_isMusic(FID) then
659 begin
660 FChanNum := N_MUSCHAN;
661 end;
662 Result := FChanNum;
663 end;
665 procedure TBasicSound.FreeSound();
666 begin
667 if FID = NO_SOUND_ID then Exit;
668 Stop();
669 FID := NO_SOUND_ID;
670 FMusic := False;
671 FPosition := 0;
672 FChanNum := -1;
673 end;
675 // aPos: msecs
676 function TBasicSound.RawPlay(Pan: Single; Volume: Single; aPos: DWORD): Boolean;
677 begin
678 Result := False;
679 if (FID = NO_SOUND_ID) or not SoundInitialized then Exit;
680 FChanNum := e_PlaySoundPanVolume(FID, Pan, Volume);
681 Result := (FChanNum >= 0);
682 //if e_isMusic(FID) then e_WriteLog(Format('playing music (%u)', [FID]), MSG_NOTIFY);
683 //TODO: aPos
684 end;
686 procedure TBasicSound.SetID(ID: DWORD);
687 begin
688 FreeSound();
689 FID := ID;
690 if ID <> NO_SOUND_ID then
691 begin
692 FMusic := e_SoundsArray[ID].isMusic;
693 end;
694 FChanNum := -1;
695 end;
697 function TBasicSound.IsPlaying(): Boolean;
698 var
699 chan: Integer;
700 begin
701 Result := False;
702 if e_isSound(FID) then
703 begin
704 //e_WriteLog(Format('IsPlaying: FID=%u; FChanNum=%d', [FID, FChanNum]), MSG_WARNING);
705 chan := Channel;
706 if chan < 0 then
707 begin
708 //e_WriteLog(Format('IsPlaying: FID=%u; ONA', [FID]), MSG_WARNING);
709 Exit;
710 end;
711 //Result := (Mix_Playing(chan) > 0)
712 //e_WriteLog(Format('IsPlaying: FID=%u; TAN', [FID]), MSG_WARNING);
713 Result := True;
714 end
715 else if e_isMusic(FID) then
716 begin
717 Result := (Mix_PlayingMusic() > 0);
718 end;
719 end;
721 procedure TBasicSound.Stop();
722 var
723 chan: Integer;
724 begin
725 if e_isSound(FID) then
726 begin
727 chan := Channel;
728 if chan >= 0 then
729 begin
730 //GetPosition();
731 Mix_HaltChannel(chan);
732 end;
733 end
734 else if e_isMusic(FID) then
735 begin
736 Mix_HaltMusic();
737 end;
738 FChanNum := -1;
739 end;
741 function TBasicSound.IsPaused(): Boolean;
742 var
743 chan: Integer;
744 begin
745 Result := False;
746 if e_isSound(FID) then
747 begin
748 chan := Channel;
749 if chan < 0 then Exit;
750 Result := (Mix_Paused(chan) > 0);
751 end
752 else if e_isMusic(FID) then
753 begin
754 Result := (Mix_PausedMusic() > 0);
755 end;
756 end;
758 procedure TBasicSound.Pause(Enable: Boolean);
759 var
760 chan: Integer;
761 pl: Boolean;
762 begin
763 Enable := not Enable; // fuckin' double negation
764 if e_isSound(FID) then
765 begin
766 chan := Channel;
767 if chan < 0 then Exit;
768 pl := not (Mix_Paused(chan) > 0);
769 if pl <> Enable then
770 begin
771 if Enable then Mix_Resume(chan) else Mix_Pause(chan);
772 end;
773 end
774 else if e_isMusic(FID) then
775 begin
776 pl := not (Mix_PausedMusic() > 0);
777 if pl <> Enable then
778 begin
779 if Enable then Mix_ResumeMusic() else Mix_PauseMusic();
780 end;
781 end;
783 if Enable then
784 begin
785 res := FMOD_Channel_GetPosition(FChanNum, FPosition, FMOD_TIMEUNIT_MS);
786 if res <> FMOD_OK then
787 begin
788 end;
789 end;
791 end;
793 function TBasicSound.GetVolume(): Single;
794 var
795 chan: Integer;
796 begin
797 Result := 0.0;
798 if e_isSound(FID) then
799 begin
800 chan := Channel;
801 if chan < 0 then Exit;
802 Result := (ChanSIds[chan].oldvol+0.0)/(MIX_MAX_VOLUME+0.0);
803 end
804 else if e_isMusic(FID) then
805 begin
806 Result := (MusVolume+0.0)/(MIX_MAX_VOLUME+0.0);
807 end;
808 end;
810 procedure TBasicSound.SetVolume(Volume: Single);
811 var
812 chan: Integer;
813 begin
814 if e_isSound(FID) then
815 begin
816 chan := Channel;
817 if chan < 0 then Exit;
818 //e_WriteLog(Format('SetVolume: chan=%d; Volume=%f', [chan, Volume]), MSG_WARNING);
819 e_chanSetVol(chan, Volume);
820 end
821 else if e_isMusic(FID) then
822 begin
823 //e_WriteLog(Format('SetVolume: chan=MUSIC; Volume=%f', [Volume]), MSG_WARNING);
824 e_chanSetVol(N_MUSCHAN, Volume);
825 end;
826 end;
828 function TBasicSound.GetPan(): Single;
829 var
830 chan: Integer;
831 begin
832 Result := 1.0;
833 if e_isSound(FID) then
834 begin
835 chan := Channel;
836 if chan < 0 then Exit;
837 Result := ChanSIds[chan].pan;
838 end;
839 end;
841 procedure TBasicSound.SetPan(Pan: Single);
842 var
843 chan: Integer;
844 begin
845 if e_isSound(FID) then
846 begin
847 chan := Channel;
848 if chan < 0 then Exit;
849 e_chanSetPan(chan, Pan);
850 end;
851 end;
853 function TBasicSound.IsMuted(): Boolean;
854 var
855 chan: Integer;
856 begin
857 Result := False;
858 if e_isSound(FID) then
859 begin
860 chan := Channel;
861 if chan < 0 then Exit;
862 Result := ChanSIds[chan].muted;
863 end
864 else if e_isMusic(FID) then
865 begin
866 Result := SoundMuted;
867 end;
868 end;
870 procedure TBasicSound.Mute(Enable: Boolean);
871 var
872 chan: Integer;
873 begin
874 if e_isSound(FID) then
875 begin
876 chan := Channel;
877 if chan < 0 then Exit;
878 if ChanSIds[chan].muted <> Enable then
879 begin
880 //e_WriteLog(Format('muting sound for channel %d', [cnan]), MSG_WARNING);
881 ChanSIds[chan].muted := Enable;
882 if ChanSIds[chan].muted then Mix_Volume(chan, 0) else Mix_Volume(chan, ChanSIds[chan].oldvol);
883 end;
884 end
885 else if e_isMusic(FID) then
886 begin
887 if Enable then Mix_VolumeMusic(0) else Mix_VolumeMusic(MusVolume);
888 end;
889 end;
891 //TODO
892 function TBasicSound.GetPosition(): DWORD;
893 begin
894 Result := 0;
896 if FChanNum < 0 then Exit;
897 res := FMOD_Channel_GetPosition(FChanNum, FPosition, FMOD_TIMEUNIT_MS);
898 if res <> FMOD_OK then
899 begin
900 Exit;
901 end;
902 Result := FPosition;
904 end;
906 //TODO
907 procedure TBasicSound.SetPosition(aPos: DWORD);
908 begin
909 FPosition := aPos;
911 if FChanNum < 0 then Exit;
912 res := FMOD_Channel_SetPosition(FChanNum, FPosition, FMOD_TIMEUNIT_MS);
913 if res <> FMOD_OK then
914 begin
915 end;
917 end;
919 //TODO
920 procedure TBasicSound.SetPriority(priority: Integer);
921 begin
923 if (FChanNum <> nil) and (FPriority <> priority) and
924 (priority >= 0) and (priority <= 256) then
925 begin
926 FPriority := priority;
927 res := FMOD_Channel_SetPriority(FChanNum, priority);
928 if res <> FMOD_OK then
929 begin
930 end;
931 end;
933 end;
935 end.