unit FModEngine;
interface
uses Windows, Forms, Classes, SysUtils, ExtCtrls, Dialogs,
fmod, fmodpresets, fmodtypes, fmoderrors, CommonTypes;
Type TFModEngine = Class(TObject)
private
AppHWND : THandle;
// Mode
Sample : PFSoundSample;
Module : PFMusicModule;
Stream : PFSoundStream;
StreamCal : TFSoundStreamCallback;
//
Channel : integer;
DeviceIDX : integer;
WaveFreq : Integer;
Volume : integer;
Def_Pane : integer;
SLoopMod : integer;
CDLoopMod : integer;
PlayerState : Integer;
EventTimer : TTimer;
FValues: array [0..1] of PSingle;
FFadeOut : Boolean;
FFadeIn : Boolean;
FFadeTime : LongInt;
SoundDriverList : TStringList;
// CD Function
CD_DriverList : TStringList;
CD_TrackNumber : Integer;
CD_DefDrive : Integer;
public
procedure NotifyState (Sender : TObject);
function EngineState : Integer;
constructor Create (HWND : THandle); virtual;
destructor Destroy;
function Get_OutputType : integer;
Procedure Set_OutputTypes(TOutputType : integer);
procedure Set_Output(Driver: Integer);
function Get_SoundDriverList : TStringlist;
function Get_SoundDriverName : string;
//
Procedure Play(FileName : String);
Procedure Set_Paused(Paused : ByteBool);
function Get_Paused : boolean;
Procedure Stop;
// Vollume
Procedure Set_Volume(Vol : Integer);
function Get_Volume : Integer;
procedure Set_Panning (Pan : Integer);
function Get_Panning : Integer;
Procedure Set_Mute(Mute : ByteBool);
function Get_Mute : ByteBool;
procedure Set_Pitch(Pitch : Integer);
procedure Set_Time(SongPos : Integer);
function Get_Time : integer;
function Get_SongLen : Integer;
Procedure Set_PlayPosition(Pos, Max : integer);
function Get_PlayPosition : integer;
procedure Get_VULevel(var L_VU, R_VU : integer);
// test
Procedure Set_LoopMode(Mode : integer);
end;
implementation
{--------------- NotifyState --------------}
procedure TFModEngine.NotifyState (Sender : TObject);
begin
if Stream <> nil then
if ((Get_Time + 0.1 >= Get_SongLen) and not (PlayerState = ENGINE_STOP)) then
begin
PlayerState := ENGINE_SONG_END;
Exit;
end;
// test
end;
{--------------- EngineState --------------}
function TFModEngine.EngineState : Integer;
begin
Result := PlayerState;
end;
constructor TFModEngine.Create (HWND : THandle);
var i : integer; SDriverChar, CDChar : PChar;
begin
WaveFreq:= 44100;
DeviceIDX := 0;
PlayerState := ENGINE_STOP;
FMOD_Load(nil);
//
Set_OutputTypes(1);
Set_Output(DeviceIDX);
// Get Sound Driver Name
SoundDriverList:= TStringList.Create;
i:= 0;
While (FSOUND_GetDriverName(i)<> nil) do
begin
SDriverChar:= FSOUND_GetDriverName(i);
inc(i);
SoundDriverList.Add(SDriverChar);
end;
SLoopMod := Stream_LoopMode[0];
CDLoopMod:= CD_PlayMode[1];
Def_Pane := trunc(255 / 2);
Volume := 255;
// NotifyState
EventTimer := TTimer.Create (nil);
EventTimer.Interval := 1;
EventTimer.OnTimer := NotifyState;
EventTimer.Enabled := True;
//
end;
destructor TFModEngine.Destroy;
begin
stop;
FSOUND_Close
end;
{---------------------------- Output Type --------------------------}
function TFModEngine.Get_OutputType : integer;
var OutputType : TFSoundOutputTypes;
begin
OutputType:= FSOUND_GetOutput;
case OutputType of
FSOUND_OUTPUT_WINMM: result:= 0;
FSOUND_OUTPUT_DSOUND: result:= 1;
FSOUND_OUTPUT_A3D: result:= 2;
end
end;
Procedure TFModEngine.Set_OutputTypes(TOutputType : integer);
begin
FSOUND_SetOutput(OutputTypes[TOutputType]);
end;
{-------------- Sound Driver ------------}
procedure TFModEngine.Set_Output(Driver: Integer);
begin
Stop;
FMUSIC_StopAllSongs();
FSOUND_Close;
FSOUND_SetMixer(FSOUND_MIXER_QUALITY_AUTODETECT);
FSOUND_SetBufferSize(100);
FSOUND_SetDriver(Driver); //Set sound driver
if not FSOUND_Init(WaveFreq, 128, FSOUND_INIT_GLOBALFOCUS or
FSOUND_INIT_ENABLESYSTEMCHANNELFX) then
begin
Application.MessageBox(FMOD_ErrorString(FSOUND_GetError), 'FSOUND_Init', MB_OK or MB_ICONHAND);
Halt;
end;
end;
function TFModEngine.Get_SoundDriverList : TStringlist;
begin
result:= SoundDriverList;
end;
function TFModEngine.Get_SoundDriverName : string;
var idx : integer;
begin
idx:= FSOUND_GetDriver;
result:= FSOUND_GetDriverName(idx);
end;
{----------------- EQ ----------------}
Procedure TFmodEngine.Set_LoopMode(Mode : integer);
begin
SLoopMod:= Stream_LoopMode[Mode];
end;
Procedure TFmodEngine.Play(FileName : String); // Play
begin
FSOUND_Stream_Stop(stream);
Stream := nil;
Stream := FSOUND_Stream_Open(PChar(Filename), FSOUND_NORMAL or
SLoopMod or
FSOUND_2D, 0, 0);
if Stream <> nil then
begin
Channel := FSOUND_Stream_Play(FSOUND_FREE, Stream);
PlayerState := ENGINE_PLAY;
end;
Set_Volume(Volume);
Set_Panning(Def_Pane);
end;
Procedure TFmodEngine.Set_Paused(Paused : ByteBool); // Set Pause
begin
if Stream <> nil then
FSOUND_SetPaused(Channel, Paused);
if Paused = True then
PlayerState := ENGINE_PAUSE
else
PlayerState := ENGINE_PLAY;
end;
function TFmodEngine.Get_Paused() : boolean; // Get Pause
begin
if Stream <> nil then
Result:= FSOUND_GetPaused(Channel);
end;
Procedure TFmodEngine.Stop; // Stop
begin
if Stream <> nil then
begin
FSOUND_Stream_Stop(Stream);
end;
PlayerState := ENGINE_STOP;
end;
procedure TFmodEngine.Set_Volume(Vol : Integer); // Set Volume
begin
if Vol > 255 then
Vol := 255;
if Vol < 0 then
Vol := 0;
FSOUND_SetVolume(channel, Vol);
Volume:= Vol;
end;
function TFmodEngine.Get_Volume : Integer; // Get Volume
begin
if Stream <> nil then
result:= FSOUND_GetVolume(channel)
end;
procedure TFmodEngine.Set_Panning(Pan : Integer); // Set Panning
begin
//if Stream <> nil then
if Pan > 255 then
Pan := 255;
if Pan < 0 then
Pan := 0;
FSOUND_SetPan(Channel, Pan);
Def_Pane:= Pan;
end;
function TFmodEngine.Get_Panning : Integer; // Get Panning
begin
if Stream <> nil then
result:= FSOUND_GetPan(Channel);
end;
Procedure TFmodEngine.Set_Mute(Mute : ByteBool); // Set Mute
begin
FSOUND_SetMute(Channel, Mute)
end;
function TFmodEngine.Get_Mute : ByteBool; // Get Mute
begin
result := FSOUND_GetMute(Channel)
end;
procedure TFmodEngine.Set_Pitch(Pitch : Integer); // Set Pich
var freq : Integer;
begin
// Pitch (Min = 0) < 20 > (Max = 40)
freq := Trunc((Pitch / 20) * WaveFreq);
if freq < 0 then
freq := 0 ;
if freq > 705600 then
freq := 705600;
FSOUND_SetFrequency(Channel, freq)
end;
procedure TFmodEngine.Set_Time(SongPos : Integer); // Set Time
begin
if Stream <> nil then
FSOUND_Stream_SetTime(Stream, SongPos);
end;
function TFmodEngine.Get_Time : integer; // Get Time
begin
if Stream <> nil then
result:= FSOUND_Stream_GetTime(Stream);
if (PlayerState = ENGINE_STOP) or
(PlayerState = ENGINE_SONG_END) then
Result := 0
end;
function TFmodEngine.Get_SongLen : Integer; //Get SongLen
var MilliSec : integer;
begin
if Stream <> nil then
begin
MilliSec := FSOUND_Stream_GetLengthMs(stream);
result:= MilliSec;
end;
if (PlayerState = ENGINE_STOP) or
(PlayerState = ENGINE_SONG_END) then
Result := 0
end;
Procedure TFmodEngine.Set_PlayPosition(Pos, Max : integer); //Set Position
var Ms, Time : integer;
begin
// Progressbar (Min = 0, Max = 100)
if Stream <> nil then
begin
Ms:= FSOUND_Stream_GetLengthMs(stream);
FSOUND_Stream_SetTime(Stream, Trunc(Ms * Pos /max)div 1);
end
end;
function TFmodEngine.Get_PlayPosition : integer; //Get Position
var Ms, Time : integer;
begin
// Progressbar (Min = 0, Max = 100)
if (Stream <> nil) then
begin
Ms:= FSOUND_Stream_GetLengthMs(stream) ;
Time:= FSOUND_Stream_GetTime(Stream);
result:= Trunc((100 / Ms) * time + 0.1);
end
else
result:= 0;
if (time >= Ms)or
(PlayerState = ENGINE_STOP) or
(PlayerState = ENGINE_SONG_END) then
Result := 0
end;
procedure TFModEngine.Get_VULevel(var L_VU, R_VU: integer); //Get VU Level
var LevelL, LevelR: Single;
PlevelL, PlevelR : PSingle;
begin
if (Stream <> nil) then
begin
PlevelL := @levelL;
PlevelR:= @levelR;
FSOUND_GetCurrentLevels(Channel, PlevelL, PlevelR);
L_VU:= trunc((PLevelL^)*200);
R_VU:= trunc((PLevelR^)*200);
end
else
begin
L_VU:= 0;
R_VU:= 0;
end
end;
end.