unit FModEngine;
interface
uses Windows, Forms, Classes, SysUtils, ExtCtrls, Dialogs,
fmod, fmodpresets, fmodtypes, fmoderrors, CommonTypes, spectrum;
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;
SLMod : integer;
CDLoopMod : integer;
PlayerState : Integer;
EventTimer : TTimer;
CurFileName : String;
//
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;
//EQ Test
Procedure Init_EQ;
public
procedure NotifyState (Sender : TObject);
function EngineState : Integer;
constructor Create (HWND : THandle); virtual;
destructor Destroy;
function Get_OutputType : integer;
procedure Set_Output(TOutputDriver, TOutputType : Integer);
function Get_SoundDriverList : TStringlist;
function Get_SoundDriverName : string;
//
Procedure Play(FileName : String; LoopMode : integer);
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_SongLengthMs : Integer;
Procedure Set_PlayPosition(Pos, Max : integer);
function Get_PlayPosition(Max : integer) : integer;
procedure Get_VULevel(var L_VU, R_VU : integer);
function Get_CPU : String;
Procedure Set_EQ(ID, Pos : integer);
end;
var FSpectrum : TMiniSpectrum;
implementation
{--------------- NotifyState --------------}
procedure TFModEngine.NotifyState (Sender : TObject);
begin
if Stream <> nil then
if ((Get_Time + 0.1 >= Get_SongLengthMs) and not (PlayerState = ENGINE_STOP)) then
begin
PlayerState := ENGINE_SONG_END;
Exit;
end;
// test
if Not FileExists(CurFileName) then
begin
PlayerState := ENGINE_STOP;
Exit;
end;
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_Output(DeviceIDX, 1);
// 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;
SLMod := 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;
{---------------------------- // --------------------------}
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;
{---------------------- Sound Driver ----------------------}
procedure TFModEngine.Set_Output(TOutputDriver, TOutputType : Integer);
begin
Stop;
FMUSIC_StopAllSongs();
FSOUND_Close;
FSOUND_SetBufferSize(100);
// 0 = Windows Multimedia driver
// 1 = DirectSound driver
// 2 = A3D driver
FSOUND_SetOutput(OutputTypes[TOutputType]);
//
FSOUND_SetMixer(FSOUND_MIXER_QUALITY_AUTODETECT);
// Set sound driver
// 0 will select the DEFAULT sound driver.
FSOUND_SetDriver(TOutputDriver);
// Initializes the FMOD Sound System.
if not FSOUND_Init(WaveFreq, 128, FSOUND_INIT_GLOBALFOCUS or
FSOUND_INIT_ENABLESYSTEMCHANNELFX or
FSOUND_INIT_ACCURATEVULEVELS) then
begin
Application.MessageBox(FMOD_ErrorString(FSOUND_GetError), 'FSOUND_Init', MB_OK or MB_ICONHAND);
Halt;
end;
end;
{----------------- EQ Test ----------------}
Procedure TFmodEngine.Set_EQ(ID, Pos : integer);
begin
// Set_EQ(0, TrackBar1.Position);
// Set_EQ(1, TrackBar2.Position);
FSOUND_FX_SetParamEQ(EQBands[ID], 80, 10, Pos);
FSOUND_FX_SetParamEQ(EQBands[ID], 170, 10, Pos);
FSOUND_FX_SetParamEQ(EQBands[ID], 310, 10, Pos);
FSOUND_FX_SetParamEQ(EQBands[ID], 600, 10, Pos);
FSOUND_FX_SetParamEQ(EQBands[ID], 1000, 10, Pos);
FSOUND_FX_SetParamEQ(EQBands[ID], 3000, 10, Pos);
FSOUND_FX_SetParamEQ(EQBands[ID], 6000, 10, Pos);
FSOUND_FX_SetParamEQ(EQBands[ID], 12000, 10, Pos);
FSOUND_FX_SetParamEQ(EQBands[ID], 14000, 10, Pos);
FSOUND_FX_SetParamEQ(EQBands[9], 16000, 10, Pos);
end;
Procedure TFmodEngine.Init_EQ;
var i : integer;
begin
for i:=0 to 10 do
begin
EQBands[i]:= FSOUND_FX_Enable(FSOUND_SYSTEM_CHANNEL, FSOUND_FX_PARAMEQ);
end;
FSOUND_FX_SetParamEQ(EQBands[0], 80, 10, 0);
FSOUND_FX_SetParamEQ(EQBands[1], 170, 10, 0);
FSOUND_FX_SetParamEQ(EQBands[2], 310, 10, 0);
FSOUND_FX_SetParamEQ(EQBands[3], 600, 10, 0);
FSOUND_FX_SetParamEQ(EQBands[4], 1000, 10, 0);
FSOUND_FX_SetParamEQ(EQBands[5], 3000, 10, 0);
FSOUND_FX_SetParamEQ(EQBands[6], 6000, 10, 0);
FSOUND_FX_SetParamEQ(EQBands[7], 12000, 10, 0);
FSOUND_FX_SetParamEQ(EQBands[8], 14000, 10, 0);
FSOUND_FX_SetParamEQ(EQBands[9], 16000, 10, 0);
end;
{----------------- // ----------------}
Procedure TFmodEngine.Play(FileName : String; LoopMode : integer); // Play
var LMode : integer;
begin
CurFileName := FileName;
LMode:= Stream_LoopMode[LoopMode];
FSOUND_Stream_Stop(stream);
Stream := nil;
Stream := FSOUND_Stream_Open(PChar(Filename), FSOUND_NORMAL or
LMode or
FSOUND_2D, 0, 0);
FSOUND_SetPaused(FSOUND_SYSTEM_CHANNEL, True);
Init_EQ;
Fsound_Setpaused(FSOUND_SYSTEM_CHANNEL, False);
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_FX_Disable(-1000);
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;
{-------------------------------- Set/Get Time --------------------------------}
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)
else
result:= 0;
if (PlayerState = ENGINE_STOP) or
(PlayerState = ENGINE_SONG_END) then
Result := 0
end;
{---------------------------------- Get Lenght --------------------------------}
function TFmodEngine.Get_SongLengthMs : 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;
{----------------------------- Get/Set PlayPositio ----------------------------}
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(Max : integer) : 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((Max / Ms) * time + 0.1);
end
else
result:= 0;
if (time >= Ms)or
(PlayerState = ENGINE_STOP) or
(PlayerState = ENGINE_SONG_END) then
Result := 0
end;
{----------------------------------- VULevel ----------------------------------}
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^)* 150); // 100%
R_VU:= trunc((PLevelR^)* 150); // 100%
end
else
begin
L_VU:= 0;
R_VU:= 0;
end
end;
{------------------------------------- CPU ------------------------------------}
function TFModEngine.Get_CPU : String;
begin
result:= Format('%.1f%%', [FSOUND_GetCPUUsage]);
end;
end.