Стартовый пул
This commit is contained in:
834
acs/Src/classes/acs_audio.pas
Normal file
834
acs/Src/classes/acs_audio.pas
Normal file
@@ -0,0 +1,834 @@
|
||||
(*
|
||||
this file is a part of audio components suite
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
|
||||
$Log: acs_audio.pas,v $
|
||||
Revision 1.12 2006/07/07 15:51:19 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.11 2006/07/04 18:38:32 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.10 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.4 2006/01/02 18:54:46 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.3 2006/01/01 18:46:40 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/12/26 17:31:38 z0m3ie
|
||||
fixed some problems in acs_dsfiles
|
||||
fixed some problems in acs_vorbis
|
||||
reworked all buffers
|
||||
|
||||
Revision 1.1 2005/12/19 18:34:35 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.14 2005/12/18 17:01:54 z0m3ie
|
||||
delphi compatibility
|
||||
|
||||
Revision 1.13 2005/12/04 16:54:33 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.12 2005/11/28 21:57:24 z0m3ie
|
||||
mostly FileOut fixes
|
||||
moved PBuffer to PBuffer8
|
||||
set all to dynamically Buffering
|
||||
|
||||
Revision 1.11 2005/11/27 16:50:33 z0m3ie
|
||||
add ACS VolumeQuerry
|
||||
make ACS_VolumeQuerry localizeable
|
||||
some little errorfixes (buffersize for linuxdrivers was initially 0)
|
||||
make TAudioIn workable
|
||||
|
||||
Revision 1.10 2005/10/02 16:51:46 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.9 2005/09/23 14:04:58 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.8 2005/09/18 19:28:59 z0m3ie
|
||||
more progress on driver handling
|
||||
|
||||
Revision 1.7 2005/09/16 17:34:29 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.6 2005/09/15 20:59:37 z0m3ie
|
||||
start translate the documentation in the source for pasdoc
|
||||
|
||||
Revision 1.5 2005/09/14 21:19:37 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.4 2005/09/13 21:54:11 z0m3ie
|
||||
acs is localizeable now (ACS_Strings)
|
||||
|
||||
Revision 1.3 2005/09/13 20:14:52 z0m3ie
|
||||
driver handling classes (basic audio class)
|
||||
*)
|
||||
|
||||
{
|
||||
@abstract(this unit introduces the base classes for acs)
|
||||
@author(Andrei Borovsky (2003-2005))
|
||||
@author(Christian Ulrich (2005))
|
||||
}
|
||||
|
||||
unit acs_audio;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
ACS_Types, ACS_Classes,Classes,ACS_Strings,SysUtils;
|
||||
|
||||
type
|
||||
{ Audio Formats used in DeviceInfo record
|
||||
format constants mask : af<SampleRate><Mono/Stereo><BitsPerSample>
|
||||
where 1, 2, 4 means sample rate of 11025, 22050, and 44100 Hz respectively
|
||||
M, S means mono or stereo, 08, 16 means 8 or 16 bits per sample.
|
||||
For example, af4S16 corresponds to 44100 Hz stereo 16 bit format.
|
||||
}
|
||||
|
||||
TACSAudioFormat = (af1M08, af1M16, af1S08, af1S16, af2M08, af2M16, af2S08, af2S16,
|
||||
af4M08, af4M16, af4S08, af4S16);
|
||||
TACSAudioFormats = set of TACSAudioFormat;
|
||||
TACSBaseAudioOut = class;
|
||||
TACSBaseAudioIn = class;
|
||||
|
||||
{ This record is used to get an deviceinfo from the Drivers
|
||||
}
|
||||
TACSDeviceInfo = record
|
||||
DeviceName : String;
|
||||
DrvVersion : LongWord;
|
||||
Formats : TACSAudioFormats;
|
||||
Stereo : Boolean;
|
||||
end;
|
||||
|
||||
{ This introduces an base class for the drivers
|
||||
}
|
||||
|
||||
{ TAudioOut }
|
||||
|
||||
{ TACSAudioOut }
|
||||
|
||||
TACSAudioOut = class(TComponent)
|
||||
private
|
||||
FDriver: string;
|
||||
FOutput : TACSBaseAudioOut;
|
||||
FInput : TACSCustomInput;
|
||||
FOnDone: TACSOutputDoneEvent;
|
||||
FOnProgress: TACSOutputProgressEvent;
|
||||
FOnThreadException: TACSThreadExceptionEvent;
|
||||
FLatency : Integer;
|
||||
FBufferSize : Integer;
|
||||
function GetBufferSize: Integer;
|
||||
function GetBusy: Boolean;
|
||||
function GetDelay: Integer;
|
||||
function GetPriority: TTPriority;
|
||||
function GetProgress: real;
|
||||
function GetStatus: TACSOutputStatus;
|
||||
function GetSuspend: Boolean;
|
||||
function GetTE: Integer;
|
||||
procedure SetBufferSize(const AValue: Integer);
|
||||
procedure SetDelay(const AValue: Integer);
|
||||
procedure SetPriority(const AValue: TTPriority);
|
||||
procedure SetSuspend(const AValue: Boolean);
|
||||
|
||||
procedure ThreadException(Sender : TComponent;E : Exception);
|
||||
procedure OutputDone(Sender : TComponent);
|
||||
procedure OutputProgress(Sender : TComponent);
|
||||
protected
|
||||
FBaseChannel: Integer;
|
||||
FVolume: Byte;
|
||||
|
||||
procedure SetInput(Input : TACSCustomInput);
|
||||
|
||||
procedure SetDevice(Ch : Integer);virtual;
|
||||
function GetDeviceInfo : TACSDeviceInfo;virtual;
|
||||
function GetDeviceCount : Integer;virtual;
|
||||
procedure SetDriver(Driver : string);virtual;
|
||||
|
||||
function GetDriverName(idx : Integer) : string;
|
||||
function GetDriversCount : Integer;
|
||||
|
||||
procedure Done;
|
||||
function DoOutput(Abort : Boolean):Boolean;
|
||||
procedure Prepare;
|
||||
public
|
||||
constructor Create(AOwner: TComponent);override;
|
||||
destructor Destroy;override;
|
||||
{ The result returns an deviceinfo record that can be used to enumerate devices
|
||||
just set device property from 0 to DeviceCount-1 and read deviceInfo to
|
||||
enumerate all Devices from current Driver
|
||||
}
|
||||
property DeviceInfo : TACSDeviceInfo read GetDeviceInfo;
|
||||
{ Returns the count of devices supported by actual driver
|
||||
}
|
||||
property DeviceCount : Integer read GetDeviceCount;
|
||||
{ This can be used to enumerate the Drivers
|
||||
just use Driverscount as index it returns the DriverName
|
||||
}
|
||||
property Drivers[idx : Integer] : string read GetDriverName;
|
||||
{ Returns the total count of avalible drivers
|
||||
}
|
||||
property DriversCount : Integer read GetDriversCount;
|
||||
{ pauses the output.
|
||||
}
|
||||
procedure Pause;virtual;
|
||||
{ Resumes previously paused output.
|
||||
}
|
||||
procedure Resume;virtual;
|
||||
{ This is the most important method in the output components.
|
||||
After an input component has been assigned, call Run to start audio-processing chain.
|
||||
}
|
||||
procedure Run;
|
||||
{ Stops the running output process.
|
||||
}
|
||||
procedure Stop;
|
||||
{ Output components perform output in their own threads.
|
||||
Use this property to set the priority for the thread.
|
||||
}
|
||||
property ThreadPriority : TTPriority read GetPriority write SetPriority;
|
||||
{ Read Progress to get the output progress in percents.
|
||||
This value is meaningful only after the input component has been set
|
||||
and only if the input component can tell the size of its stream.
|
||||
}
|
||||
property Progress : real read GetProgress;
|
||||
{ This property indicates the output component's current status. Possible values are:
|
||||
|
||||
tosPlaying: the component is working;
|
||||
|
||||
tosPaused: the component is paused (the Pause method was called);
|
||||
|
||||
tosIdle: the component is idle;
|
||||
}
|
||||
property Status : TACSOutputStatus read GetStatus;
|
||||
property TimeElapsed : Integer read GetTE;
|
||||
property Latency : Integer read FLatency;
|
||||
published
|
||||
{ The output buffer size in bytes default is 4000
|
||||
}
|
||||
property Buffersize : Integer read GetBufferSize write SetBufferSize;
|
||||
{ use this property to set an driver, on create of this component the driver
|
||||
with lowest latency is used for default
|
||||
}
|
||||
property Driver : string read FDriver write SetDriver stored True;
|
||||
{ Use this property to set the output device
|
||||
}
|
||||
property Busy : Boolean read GetBusy;
|
||||
property Device : Integer read FBaseChannel write SetDevice stored True;
|
||||
property Volume : Byte read FVolume write FVolume;
|
||||
property Input : TACSCustomInput read FInput write SetInput;
|
||||
{ Use this property to set the delay (in milliseconds) in output thread.
|
||||
This property allows the user to reduce the stress the output thread puts
|
||||
on the CPU (especially under Windows).
|
||||
Be careful with this property when using TAudioOut component.
|
||||
Assigning too large values to it can cause dropouts in audio playback.
|
||||
}
|
||||
property Delay : Integer read GetDelay write SetDelay;
|
||||
property SuspendWhenIdle : Boolean read GetSuspend write SetSuspend;
|
||||
property OnDone : TACSOutputDoneEvent read FOnDone write FOndone;
|
||||
property OnProgress : TACSOutputProgressEvent read FOnProgress write FOnProgress;
|
||||
property OnThreadException : TACSThreadExceptionEvent read FOnThreadException write FOnThreadException;
|
||||
end;
|
||||
|
||||
{ TAudioIn }
|
||||
|
||||
TACSAudioIn = class(TACSCustomInput)
|
||||
private
|
||||
FInput : TACSBaseAudioIn;
|
||||
FDriver : string;
|
||||
function GetBPS : Integer;override;
|
||||
function GetCh : Integer;override;
|
||||
function GetSR : Integer;override;
|
||||
procedure SetDevice(Ch : Integer);
|
||||
function GetDeviceInfo : TACSDeviceInfo;
|
||||
function GetTotalTime : real;override;
|
||||
function GetDriverName(idx : Integer) : string;
|
||||
function GetDriversCount : Integer;
|
||||
procedure SetDriver(Driver : string);
|
||||
protected
|
||||
FBPS: Integer;
|
||||
FChan: Integer;
|
||||
FFreq: Integer;
|
||||
FRecTime: Integer;
|
||||
FBaseChannel: Integer;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer;override;
|
||||
procedure Init;override;
|
||||
procedure Flush;override;
|
||||
{ The result returns an deviceinfo record that can be used to enumerate devices
|
||||
just set device property from 0 to DeviceCount-1 and read deviceInfo to
|
||||
enumerate all Devices from current Driver
|
||||
}
|
||||
property DeviceInfo : TACSDeviceInfo read GetDeviceInfo;
|
||||
{ This can be used to enumerate the Drivers
|
||||
just use Driverscount as index it returns the DriverName
|
||||
}
|
||||
property Drivers[idx : Integer] : string read GetDriverName;
|
||||
{ Returns the total count of avalible drivers
|
||||
}
|
||||
property DriversCount : Integer read GetDriversCount;
|
||||
published
|
||||
{ use this property to set an driver, on create of this component the driver
|
||||
with lowest latency is used for default
|
||||
}
|
||||
property Driver : string read FDriver write SetDriver stored True;
|
||||
{ Use this property to set the output device
|
||||
}
|
||||
property Device : Integer read FBaseChannel write SetDevice stored True;
|
||||
{ Use this property to set the number of bits per sample for the input audio stream.
|
||||
Possible values are 8 and 16.
|
||||
}
|
||||
property InBitsPerSample : Integer read GetBPS write FBPS stored True;
|
||||
{ Use this property to set the number of channels for the input audio stream.
|
||||
Possible values are 1 (mono) and 2 (stereo).
|
||||
}
|
||||
property InChannels : Integer read GetCh write FChan stored True;
|
||||
{ Use this property to set the sample rate for the input audio stream.
|
||||
Possible values are determined by the soundcard hardware.
|
||||
}
|
||||
property InSampleRate : Integer read GetSR write FFreq stored True;
|
||||
{ This property allow you to set the record duration time in seconds.
|
||||
If you assign -1 to this property TAudioIn will never stop recording by itself.
|
||||
In both cases you can stop recording at any time by calling Stop method of
|
||||
the respective output component.
|
||||
}
|
||||
property RecTime : Integer read FRecTime write FRecTime stored True;
|
||||
end;
|
||||
|
||||
{ This class is an abstract base class for the drivers
|
||||
}
|
||||
|
||||
{ TBaseAudioOut }
|
||||
|
||||
TACSBaseAudioOut = class(TACSCustomOutput)
|
||||
private
|
||||
FDriver: string;
|
||||
FOutput : TACSAudioOut;
|
||||
protected
|
||||
FBaseChannel: Integer;
|
||||
FVolume: Byte;
|
||||
procedure SetDevice(Ch : Integer);virtual;abstract;
|
||||
function GetDeviceInfo : TACSDeviceInfo;virtual;abstract;
|
||||
function GetDeviceCount : Integer;virtual;abstract;
|
||||
public
|
||||
constructor Create(AOwner: TComponent);override;
|
||||
destructor Destroy;override;
|
||||
property DeviceInfo : TACSDeviceInfo read GetDeviceInfo;
|
||||
property DeviceCount : Integer read GetDeviceCount;
|
||||
property Buffersize : Integer read FBufferSize write FBufferSize;
|
||||
published
|
||||
property Device : Integer read FBaseChannel write SetDevice stored True;
|
||||
property Volume : Byte read FVolume write FVolume;
|
||||
end;
|
||||
|
||||
{ This class is an abstract base class for the drivers
|
||||
}
|
||||
|
||||
{ TBaseAudioIn }
|
||||
|
||||
TACSBaseAudioIn = class(TACSCustomInput)
|
||||
private
|
||||
FInput : TACSAudioIn;
|
||||
FDriver : string;
|
||||
protected
|
||||
FBPS: Integer;
|
||||
FChan: Integer;
|
||||
FFreq: Integer;
|
||||
FRecTime: Integer;
|
||||
FBaseChannel: Integer;
|
||||
procedure SetDevice(Ch : Integer);virtual;abstract;
|
||||
function GetDeviceInfo : TACSDeviceInfo;virtual;abstract;
|
||||
function GetDeviceCount : Integer;virtual;abstract;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
property DeviceInfo : TACSDeviceInfo read GetDeviceInfo;
|
||||
published
|
||||
property Device : Integer read FBaseChannel write SetDevice stored True;
|
||||
property InBitsPerSample : Integer read GetBPS write FBPS stored True;
|
||||
property InChannels : Integer read GetCh write FChan stored True;
|
||||
property InSampleRate : Integer read GetSR write FFreq stored True;
|
||||
property RecTime : Integer read FRecTime write FRecTime stored True;
|
||||
end;
|
||||
|
||||
TACSAudioOutClass = class of TACSBaseAudioOut;
|
||||
TACSAudioInClass = class of TACSBaseAudioIn;
|
||||
|
||||
TACSOutDriverinfo = record
|
||||
DriverName : string;
|
||||
Latency : Integer;
|
||||
DrvClass : TACSAudioOutClass;
|
||||
end;
|
||||
|
||||
TACSInDriverinfo = record
|
||||
DriverName : string;
|
||||
Latency : Integer;
|
||||
DrvClass : TACSAudioInClass;
|
||||
end;
|
||||
|
||||
{ This procedure must be used to register drivers to the system
|
||||
just call them at initialization of the driver main unit
|
||||
}
|
||||
procedure RegisterAudioOut(DrvName : string;OutClass : TACSAudioOutClass;Latency : Integer);
|
||||
{ This procedure must be used to register drivers to the system
|
||||
just call them at initialization of the driver main unit
|
||||
}
|
||||
procedure RegisterAudioIn(DrvName : string;InClass : TACSAudioInClass;Latency : Integer);
|
||||
|
||||
var
|
||||
OutDriverInfos : array of TACSOutDriverInfo;
|
||||
InDriverInfos : array of TACSInDriverInfo;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
{ TAudioOut }
|
||||
|
||||
function TACSAudioOut.GetDelay: Integer;
|
||||
begin
|
||||
if Assigned(FOutput) then
|
||||
Result := FOutput.GetDelay
|
||||
else
|
||||
Result := -1;
|
||||
end;
|
||||
|
||||
function TACSAudioOut.GetBufferSize: Integer;
|
||||
begin
|
||||
if Assigned(FOutput) then
|
||||
Result := FOutput.BufferSize
|
||||
else
|
||||
Result := -1;
|
||||
end;
|
||||
|
||||
function TACSAudioOut.GetBusy: Boolean;
|
||||
begin
|
||||
if Assigned(FOutput) then
|
||||
Result := FOutput.Busy;
|
||||
end;
|
||||
|
||||
function TACSAudioOut.GetPriority: TTPriority;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException(strNoDriverselected);
|
||||
Result := FOutput.GetPriority;
|
||||
end;
|
||||
|
||||
function TACSAudioOut.GetProgress: real;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoDriverselected);
|
||||
Result := FOutput.GetProgress;
|
||||
end;
|
||||
|
||||
function TACSAudioOut.GetStatus: TACSOutputStatus;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
Result := tosUndefined
|
||||
else
|
||||
Result := FOutput.Status;
|
||||
end;
|
||||
|
||||
function TACSAudioOut.GetSuspend: Boolean;
|
||||
begin
|
||||
if Assigned(FOutput) then
|
||||
Result := FOutput.GetSuspend;
|
||||
end;
|
||||
|
||||
function TACSAudioOut.GetTE: Integer;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoDriverselected);
|
||||
Result := FOutput.GetTE;
|
||||
end;
|
||||
|
||||
procedure TACSAudioOut.SetBufferSize(const AValue: Integer);
|
||||
begin
|
||||
if Assigned(FOutput) then
|
||||
FOutput.BufferSize := AValue;
|
||||
FBufferSize := AValue;
|
||||
end;
|
||||
|
||||
procedure TACSAudioOut.SetDelay(const AValue: Integer);
|
||||
begin
|
||||
if Assigned(FOutput) then
|
||||
FOutput.SetDelay(AValue);
|
||||
end;
|
||||
|
||||
procedure TACSAudioOut.SetPriority(const AValue: TTPriority);
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoDriverselected);
|
||||
FOutput.SetPriority(AValue);
|
||||
end;
|
||||
|
||||
procedure TACSAudioOut.SetSuspend(const AValue: Boolean);
|
||||
begin
|
||||
if Assigned(FOutput) then
|
||||
FOutput.SetSuspend(AValue);
|
||||
end;
|
||||
|
||||
procedure TACSAudioOut.ThreadException(Sender: TComponent; E: Exception);
|
||||
begin
|
||||
if Assigned(FOnThreadException) then
|
||||
FOnThreadException(Sender,E);
|
||||
end;
|
||||
|
||||
procedure TACSAudioOut.OutputDone(Sender: TComponent);
|
||||
begin
|
||||
if Assigned(FOnDone) then
|
||||
FOnDone(Sender);
|
||||
end;
|
||||
|
||||
procedure TACSAudioOut.OutputProgress(Sender: TComponent);
|
||||
begin
|
||||
if Assigned(FOnProgress) then
|
||||
FOnProgress(Sender);
|
||||
end;
|
||||
|
||||
procedure TACSAudioOut.SetInput(Input: TACSCustomInput);
|
||||
begin
|
||||
FInput := Input;
|
||||
if Assigned(FOutput) then
|
||||
FOutput.Input := Input;
|
||||
end;
|
||||
|
||||
procedure TACSAudioOut.SetDevice(Ch: Integer);
|
||||
begin
|
||||
FBaseChannel := ch;
|
||||
if Assigned(FOutput) then
|
||||
FOutput.SetDevice(ch);
|
||||
end;
|
||||
|
||||
function TACSAudioOut.GetDeviceInfo : TACSDeviceInfo;
|
||||
begin
|
||||
if Assigned(FOutput) then
|
||||
Result := FOutput.DeviceInfo;
|
||||
end;
|
||||
|
||||
function TACSAudioOut.GetDeviceCount : Integer;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoDriverselected);
|
||||
Result := FOutput.GetDeviceCount;
|
||||
end;
|
||||
|
||||
procedure TACSAudioOut.SetDriver(Driver: string);
|
||||
var
|
||||
i : Integer;
|
||||
begin
|
||||
if Driver = '' then
|
||||
exit;
|
||||
if Assigned(Foutput) then
|
||||
FOutput.Free;
|
||||
FOutput := nil;
|
||||
for i := 0 to length(OutDriverInfos)-1 do
|
||||
if OutDriverInfos[i].DriverName = Driver then
|
||||
begin
|
||||
FOutput := OutDriverInfos[i].DrvClass.Create(nil);
|
||||
try
|
||||
FOutput.SetDevice(FBaseChannel);
|
||||
except
|
||||
FOutput.SetDevice(0);
|
||||
end;
|
||||
FDriver := OutDriverInfos[i].DriverName;
|
||||
FLatency := OutDriverInfos[i].Latency;
|
||||
if Assigned(FInput) then
|
||||
FOutput.Input := FInput;
|
||||
FOutput.OnDone := OutputDone;
|
||||
FOutput.OnProgress := OutputProgress;
|
||||
Foutput.OnThreadException := ThreadException;
|
||||
Foutput.Buffersize := FBuffersize;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TACSAudioOut.GetDriverName(idx: Integer): string;
|
||||
begin
|
||||
if (idx < 0) or (idx > length(OutDriverInfos)-1)then
|
||||
exit;
|
||||
Result := OutDriverInfos[idx].DriverName;
|
||||
end;
|
||||
|
||||
function TACSAudioOut.GetDriversCount: Integer;
|
||||
begin
|
||||
Result := length(OutDriverInfos);
|
||||
end;
|
||||
|
||||
procedure TACSAudioOut.Done;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoDriverselected);
|
||||
Foutput.Done;
|
||||
end;
|
||||
|
||||
function TACSAudioOut.DoOutput(Abort: Boolean): Boolean;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoDriverselected);
|
||||
FOutput.DoOutput(Abort);
|
||||
end;
|
||||
|
||||
procedure TACSAudioOut.Prepare;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoDriverselected);
|
||||
FOutput.Prepare;
|
||||
end;
|
||||
|
||||
constructor TACSAudioOut.Create(AOwner: TComponent);
|
||||
var
|
||||
lowestindex,lowest,minlat,i : Integer;
|
||||
tmp : string;
|
||||
exc: Boolean;
|
||||
label retry;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
minlat := 0;
|
||||
retry:
|
||||
lowest := 99999;
|
||||
for i := 0 to length(OutDriverInfos)-1 do
|
||||
if (OutDriverInfos[i].Latency < lowest) and (OutDriverInfos[i].Latency > minlat) then
|
||||
begin
|
||||
lowest := OutDriverInfos[i].Latency;
|
||||
lowestindex := i;
|
||||
end;
|
||||
if lowest < 99999 then
|
||||
begin
|
||||
try
|
||||
SetDriver(OutDriverInfos[lowestindex].DriverName);
|
||||
exc := false;
|
||||
except
|
||||
minlat := lowest+1;
|
||||
exc := true;
|
||||
end;
|
||||
if exc then
|
||||
goto retry;
|
||||
end
|
||||
else
|
||||
FDriver := 'No Driver';
|
||||
end;
|
||||
|
||||
destructor TACSAudioOut.Destroy;
|
||||
begin
|
||||
FOutput.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TACSAudioOut.Pause;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoDriverselected);
|
||||
FOutput.Pause;
|
||||
end;
|
||||
|
||||
procedure TACSAudioOut.Resume;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoDriverselected);
|
||||
FOutput.Resume;
|
||||
end;
|
||||
|
||||
procedure TACSAudioOut.Run;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoDriverselected);
|
||||
FOutput.Run;
|
||||
end;
|
||||
|
||||
procedure TACSAudioOut.Stop;
|
||||
begin
|
||||
if Assigned(FOutput) then
|
||||
FOutput.Stop;
|
||||
end;
|
||||
|
||||
{ TACSAudioIn }
|
||||
|
||||
function TACSAudioIn.GetBPS: Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strNoDriverselected);
|
||||
Result := FInput.GetBPS;
|
||||
end;
|
||||
|
||||
function TACSAudioIn.GetCh: Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strNoDriverselected);
|
||||
Result := FInput.GetCh;
|
||||
end;
|
||||
|
||||
function TACSAudioIn.GetSR: Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strNoDriverselected);
|
||||
Result := FInput.GetSr;
|
||||
end;
|
||||
|
||||
procedure TACSAudioIn.SetDevice(Ch: Integer);
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strNoDriverselected);
|
||||
FInput.SetDevice(Ch);
|
||||
end;
|
||||
|
||||
function TACSAudioIn.GetDeviceInfo : TACSDeviceInfo;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strNoDriverselected);
|
||||
//TODO: Complete
|
||||
end;
|
||||
|
||||
function TACSAudioIn.GetTotalTime : real;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strNoDriverselected);
|
||||
Result := FInput.GetTotalTime;
|
||||
end;
|
||||
|
||||
function TACSAudioIn.GetDriverName(idx: Integer): string;
|
||||
begin
|
||||
if (idx < 0) or (idx > length(InDriverInfos)-1)then
|
||||
exit;
|
||||
Result := InDriverInfos[idx].DriverName;
|
||||
end;
|
||||
|
||||
function TACSAudioIn.GetDriversCount: Integer;
|
||||
begin
|
||||
Result := length(InDriverInfos);
|
||||
end;
|
||||
|
||||
procedure TACSAudioIn.SetDriver(Driver: string);
|
||||
var
|
||||
i : Integer;
|
||||
begin
|
||||
if Assigned(FInput) then
|
||||
FInput.Free;
|
||||
for i := 0 to length(InDriverInfos)-1 do
|
||||
if InDriverInfos[i].DriverName = Driver then
|
||||
begin
|
||||
FDriver := InDriverInfos[i].DriverName;
|
||||
FInput := InDriverInfos[i].DrvClass.Create(nil);
|
||||
FInput.SetDevice(FBaseChannel);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TACSAudioIn.Create(AOwner: TComponent);
|
||||
var
|
||||
lowestindex,lowest,i : Integer;
|
||||
minlat: Integer;
|
||||
exc: Boolean;
|
||||
label retry;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
minlat := 0;
|
||||
retry:
|
||||
lowest := 99999;
|
||||
for i := 0 to length(InDriverInfos)-1 do
|
||||
if (InDriverInfos[i].Latency < lowest) and (InDriverInfos[i].Latency > minlat) then
|
||||
begin
|
||||
lowest := InDriverInfos[i].Latency;
|
||||
lowestindex := i;
|
||||
end;
|
||||
if lowest < 99999 then
|
||||
begin
|
||||
try
|
||||
SetDriver(InDriverInfos[lowestindex].DriverName);
|
||||
exc := false;
|
||||
except
|
||||
minlat := lowest+1;
|
||||
exc := true;
|
||||
end;
|
||||
if exc then
|
||||
goto retry;
|
||||
end
|
||||
else
|
||||
FDriver := 'No Driver';
|
||||
end;
|
||||
|
||||
destructor TACSAudioIn.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TACSAudioIn.GetData(Buffer: Pointer; BufferSize: Integer): Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strNoDriverselected);
|
||||
Result := FInput.GetData(Buffer,BufferSize);
|
||||
end;
|
||||
|
||||
procedure TACSAudioIn.Init;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strNoDriverselected);
|
||||
FInput.Init;
|
||||
end;
|
||||
|
||||
procedure TACSAudioIn.Flush;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strNoDriverselected);
|
||||
FInput.Flush;
|
||||
end;
|
||||
|
||||
procedure RegisterAudioOut(DrvName : string;OutClass : TACSAudioOutClass;Latency : Integer);
|
||||
begin
|
||||
Setlength(OutDriverInfos,length(OutdriverInfos)+1);
|
||||
OutDriverInfos[length(OutDriverInfos)-1].DriverName := DrvName;
|
||||
OutDriverInfos[length(OutDriverInfos)-1].Latency := Latency;
|
||||
OutDriverInfos[length(OutDriverInfos)-1].DrvClass := OutClass;
|
||||
end;
|
||||
|
||||
procedure RegisterAudioIn(DrvName : string;InClass : TACSAudioInClass;Latency : Integer);
|
||||
begin
|
||||
Setlength(InDriverInfos,length(IndriverInfos)+1);
|
||||
InDriverInfos[length(InDriverInfos)-1].DriverName := DrvName;
|
||||
InDriverInfos[length(InDriverInfos)-1].Latency := Latency;
|
||||
InDriverInfos[length(InDriverInfos)-1].DrvClass := InClass;
|
||||
end;
|
||||
|
||||
{ TACSBaseAudioOut }
|
||||
|
||||
constructor TACSBaseAudioOut.Create(AOwner: TComponent);
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
end;
|
||||
|
||||
destructor TACSBaseAudioOut.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
{ TBaseAudioIn }
|
||||
|
||||
constructor TACSBaseAudioIn.Create(AOwner: TComponent);
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
end;
|
||||
|
||||
destructor TACSBaseAudioIn.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
||||
Setlength(OutDriverInfos,0);
|
||||
Setlength(InDriverInfos,0);
|
||||
|
||||
finalization
|
||||
|
||||
Setlength(OutDriverInfos,0);
|
||||
Setlength(InDriverInfos,0);
|
||||
|
||||
end.
|
||||
413
acs/Src/classes/acs_audiomix.pas
Normal file
413
acs/Src/classes/acs_audiomix.pas
Normal file
@@ -0,0 +1,413 @@
|
||||
(*
|
||||
this file is a part of audio components suite.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
|
||||
$Log: acs_audiomix.pas,v $
|
||||
Revision 1.6 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.1 2005/12/19 18:34:35 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.4 2005/12/04 16:54:33 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.3 2005/09/15 20:59:37 z0m3ie
|
||||
start translate the documentation in the source for pasdoc
|
||||
|
||||
Revision 1.2 2005/09/13 21:54:11 z0m3ie
|
||||
acs is localizeable now (ACS_Strings)
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.3 2005/08/23 19:45:51 z0m3ie
|
||||
changed to Version 2.31
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
*)
|
||||
|
||||
{
|
||||
@abstract(this unit introduces the base classes for acs)
|
||||
@author(Andrei Borovsky (2003-2005))
|
||||
@author(Christian Ulrich (2005))
|
||||
}
|
||||
|
||||
{$hints off}
|
||||
unit acs_audiomix;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, ACS_Types, ACS_Classes, ACS_Strings;
|
||||
|
||||
const
|
||||
BUF_SIZE = $100000;
|
||||
|
||||
type
|
||||
TACSAudioMixerMode = (amMix, amConcatenate, amRTMix, amCustomMix);
|
||||
TACSAudioMixer = class(TACSCustomInput)
|
||||
private
|
||||
FInput1, FInput2 : TACSCustomInput;
|
||||
BufStart, BufEnd : Integer;
|
||||
ByteCount : Cardinal; // add by leozhang
|
||||
FVolume1, FVolume2 : Byte;
|
||||
EndOfInput1, EndOfInput2 : Boolean;
|
||||
InBuf1, InBuf2 : array[1..BUF_SIZE] of Byte;
|
||||
Buisy : Boolean;
|
||||
FMode : TACSAudioMixerMode;
|
||||
FInput2Start: Cardinal;
|
||||
FLock : Boolean;
|
||||
FFgPlaying : Boolean;
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
procedure SetInput1(aInput : TACSCustomInput);
|
||||
procedure SetInput2(aInput : TACSCustomInput);
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
property FgPlaying : Boolean read FFgPlaying;
|
||||
published
|
||||
property Input1 : TACSCustomInput read FInput1 write SetInput1;
|
||||
property Input2 : TACSCustomInput read FInput2 write SetInput2;
|
||||
property Mode : TACSAudioMixerMode read FMode write FMode;
|
||||
property Input2Start :Cardinal read FInput2Start write FInput2Start;
|
||||
property Volume1 : Byte read FVolume1 write FVolume1;
|
||||
property Volume2 : Byte read FVolume2 write FVolume2;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure MixChannels16(Buf1, Buf2 : PACSBuffer16; Vol1, Vol2, InSize : Integer);
|
||||
var // optimized by leozhang
|
||||
i, tmp : Integer;
|
||||
V1,V2: Real;
|
||||
begin
|
||||
V1 := Vol1 / 127;
|
||||
V2 := Vol2 / 127;
|
||||
for i := 0 to (Insize shr 1) - 1 do
|
||||
begin
|
||||
if Buf2[i] = 0 then
|
||||
begin
|
||||
Buf2[i] := Round(Buf1[i] * V1);
|
||||
end else
|
||||
if Buf1[i] = 0 then
|
||||
begin
|
||||
Buf2[i] := Round(Buf2[i] * V2);
|
||||
end else
|
||||
Buf2[i] := Round(Buf1[i] * V1) + Round(Buf2[i] * V2);
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TACSAudioMixer.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FVolume1 := 127;
|
||||
FVolume2 := 127;
|
||||
FInput2Start := 0;
|
||||
end;
|
||||
|
||||
destructor TACSAudioMixer.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TACSAudioMixer.GetBPS;
|
||||
begin
|
||||
if not Assigned(FInput1) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
Result := FInput1.BitsPerSample;
|
||||
end;
|
||||
|
||||
function TACSAudioMixer.GetCh;
|
||||
begin
|
||||
if not Assigned(FInput1) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
Result:= FInput1.Channels;
|
||||
end;
|
||||
|
||||
function TACSAudioMixer.GetSR;
|
||||
begin
|
||||
if not Assigned(FInput1) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
Result := FInput1.SampleRate;
|
||||
end;
|
||||
|
||||
procedure TACSAudioMixer.Init;
|
||||
var
|
||||
In2StartByte : Cardinal; // add by zhangl.
|
||||
begin
|
||||
Buisy := True;
|
||||
FPosition := 0;
|
||||
BufStart := 1;
|
||||
BufEnd := 0;
|
||||
EndOfInput1 := False;
|
||||
EndOfInput2 := False;
|
||||
if not Assigned(FInput1) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
if FMode = amRTMix then
|
||||
begin
|
||||
FInput1.Init;
|
||||
FSize := FInput1.Size;
|
||||
if Assigned(FInput2) then
|
||||
begin
|
||||
FInput2.Init;
|
||||
FFgPlaying := True;
|
||||
end else EndOfInput2 := True;
|
||||
FLock := False;
|
||||
end else
|
||||
begin
|
||||
if not Assigned(FInput2) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
FInput1.Init;
|
||||
FInput2.Init;
|
||||
case FMode of
|
||||
amMix :
|
||||
if FInput1.Size > FInput2.Size then FSize := FInput1.Size
|
||||
else FSize := FInput2.Size;
|
||||
amConcatenate :
|
||||
FSize := FInput1.Size + FInput2.Size; //determine the size of the output stream in bytes
|
||||
amCustomMix:
|
||||
// add by leozhang
|
||||
begin
|
||||
In2StartByte := Round(Int((FInput2Start * FInput2.SampleRate) /1000) *
|
||||
(FInput2.Channels) * ((FInput2.BitsPerSample) shr 3));
|
||||
ByteCount := In2StartByte;
|
||||
if Cardinal(FInput1.Size) > In2StartByte + FInput2.Size then
|
||||
FSize := FInput1.Size
|
||||
else
|
||||
FSize := In2StartByte + FInput2.Size;
|
||||
FLock := False;
|
||||
end;
|
||||
// leozhang
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
procedure TACSAudioMixer.Flush;
|
||||
begin
|
||||
FInput1.Flush;
|
||||
if (FMode <> amRTMix) or Assigned(FInput2) then
|
||||
FInput2.Flush;
|
||||
Buisy := False;
|
||||
end;
|
||||
function TACSAudioMixer.GetData;
|
||||
var
|
||||
l1, l2 : Integer;
|
||||
InSize : Integer;
|
||||
begin
|
||||
if not Buisy then raise EACSException.Create(strStreamnotopen);
|
||||
if BufStart > BufEnd then
|
||||
begin
|
||||
if EndOfInput1 and EndOfInput2 then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
if (FMode = amRTMix) and EndOfInput1 then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
BufStart := 1;
|
||||
case Mode of
|
||||
amMix :
|
||||
begin
|
||||
l1 := 0;
|
||||
l2 := 0;
|
||||
FillChar(InBuf1[1], BUF_SIZE, 0);
|
||||
FillChar(InBuf2[1], BUF_SIZE, 0);
|
||||
if not EndOfInput1 then
|
||||
begin
|
||||
l1 := FInput1.GetData(@InBuf1[1], BUF_SIZE);
|
||||
InSize := l1;
|
||||
while (InSize <> 0) and (l1 < BUF_SIZE) do
|
||||
begin
|
||||
InSize := FInput1.GetData(@InBuf1[l1+1], BUF_SIZE - l1);
|
||||
Inc(l1, InSize);
|
||||
end;
|
||||
if InSize = 0 then EndOfInput1 := True;
|
||||
end;
|
||||
if not EndOfInput2 then
|
||||
begin
|
||||
l2 := FInput2.GetData(@InBuf2[1], BUF_SIZE);
|
||||
InSize := l2;
|
||||
while (InSize <> 0) and (l2 < BUF_SIZE) do
|
||||
begin
|
||||
InSize := FInput2.GetData(@InBuf2[l2+1], BUF_SIZE - l2);
|
||||
Inc(l2, InSize);
|
||||
end;
|
||||
if InSize = 0 then EndOfInput2 := True;
|
||||
end;
|
||||
if (l1 = 0) and (l2 = 0) then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
if l1 > l2 then BufEnd := l1 else BufEnd := l2;
|
||||
MixChannels16(@InBuf1[1], @InBuf2[1], FVolume1, FVolume2, BufEnd);
|
||||
end;
|
||||
amConcatenate :
|
||||
begin
|
||||
if not EndOfInput1 then
|
||||
begin
|
||||
l1 := FInput1.GetData(@InBuf2[1], BUF_SIZE);
|
||||
if l1 = 0 then EndOfInput1 := True
|
||||
else BufEnd := l1;
|
||||
end;
|
||||
if EndOfInput1 then
|
||||
begin
|
||||
l2 := FInput2.GetData(@InBuf2[1], BUF_SIZE);
|
||||
if l2 = 0 then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end
|
||||
else BufEnd := l2;
|
||||
end;
|
||||
end;
|
||||
// add by leo.zhang
|
||||
amCustomMix:
|
||||
begin
|
||||
l1 := 0;
|
||||
l2 := 0;
|
||||
FillChar(InBuf1[1], BUF_SIZE, 0);
|
||||
FillChar(InBuf2[1], BUF_SIZE, 0);
|
||||
if not EndOfInput1 then
|
||||
begin
|
||||
l1 := FInput1.GetData(@InBuf1[1], BUF_SIZE);
|
||||
InSize := l1;
|
||||
while (InSize <> 0) and (l1 < BUF_SIZE) do
|
||||
begin
|
||||
InSize := FInput1.GetData(@InBuf1[l1+1], BUF_SIZE - l1);
|
||||
Inc(l1, InSize);
|
||||
end;
|
||||
if InSize = 0 then EndOfInput1 := True;
|
||||
end;
|
||||
if not (FLock or EndOfInput2) then
|
||||
begin
|
||||
FLock := True;
|
||||
if ByteCount > BUF_SIZE then
|
||||
begin
|
||||
ByteCount := ByteCount - BUF_SIZE;
|
||||
l2 := BUF_SIZE; InSize := l2;
|
||||
end else
|
||||
begin
|
||||
l2 := FInput2.GetData(@InBuf2[ByteCount+1],BUF_SIZE - ByteCount);
|
||||
InSize := l2;
|
||||
if ByteCount <> 0 then
|
||||
begin
|
||||
Inc(l2,ByteCount);
|
||||
InSize := l2;
|
||||
ByteCount := 0;
|
||||
end;
|
||||
while (InSize <> 0) and (l2 < BUF_SIZE) do
|
||||
begin
|
||||
InSize := FInput2.GetData(@InBuf2[l2+1], BUF_SIZE - l2);
|
||||
Inc(l2, InSize);
|
||||
end;
|
||||
end;
|
||||
if InSize = 0 then EndOfInput2 := True;
|
||||
FLock := False;
|
||||
end;
|
||||
if (l1 = 0) and (l2 = 0) then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
if l1 > l2 then BufEnd := l1 else BufEnd := l2;
|
||||
MixChannels16(@InBuf1[1], @InBuf2[1], FVolume1, FVolume2, BufEnd);
|
||||
end;
|
||||
// leo.zhang.
|
||||
amRTMix :
|
||||
begin
|
||||
l1 := 0;
|
||||
l2 := 0;
|
||||
FillChar(InBuf1[1], BUF_SIZE, 0);
|
||||
FillChar(InBuf2[1], BUF_SIZE, 0);
|
||||
if not EndOfInput1 then
|
||||
begin
|
||||
l1 := FInput1.GetData(@InBuf1[1], BUF_SIZE);
|
||||
InSize := l1;
|
||||
while (InSize <> 0) and (l1 < BUF_SIZE) do
|
||||
begin
|
||||
InSize := FInput1.GetData(@InBuf1[l1+1], BUF_SIZE - l1);
|
||||
Inc(l1, InSize);
|
||||
end;
|
||||
if InSize = 0 then EndOfInput1 := True;
|
||||
end;
|
||||
if not (FLock or EndOfInput2) then
|
||||
begin
|
||||
FLock := True;
|
||||
l2 := FInput2.GetData(@InBuf2[1], BUF_SIZE);
|
||||
InSize := l2;
|
||||
while (InSize <> 0) and (l2 < BUF_SIZE) do
|
||||
begin
|
||||
InSize := FInput2.GetData(@InBuf2[l2+1], BUF_SIZE - l2);
|
||||
Inc(l2, InSize);
|
||||
end;
|
||||
if InSize = 0 then
|
||||
begin
|
||||
EndOfInput2 := True;
|
||||
FFGPlaying := False;
|
||||
FInput2.Flush;
|
||||
FInput2 := nil;
|
||||
end;
|
||||
FLock := False;
|
||||
end;
|
||||
if (l1 = 0) and (l2 = 0) then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
if l1 > l2 then BufEnd := l1 else BufEnd := l2;
|
||||
MixChannels16(@InBuf1[1], @InBuf2[1], FVolume1, FVolume2, BufEnd);
|
||||
end;
|
||||
end; // case end.
|
||||
end; // endif.
|
||||
if BufferSize < (BufEnd - BufStart + 1)
|
||||
then Result := BufferSize
|
||||
else Result := BufEnd - BufStart + 1;
|
||||
Move(InBuf2[BufStart], Buffer^, Result);
|
||||
Inc(BufStart, Result);
|
||||
Inc(FPosition, Result);
|
||||
end; // procedure end.
|
||||
procedure TACSAudioMixer.SetInput1;
|
||||
begin
|
||||
if Buisy then
|
||||
raise EACSException.Create(strBusy);
|
||||
FInput1 := aInput;
|
||||
end;
|
||||
procedure TACSAudioMixer.SetInput2;
|
||||
begin
|
||||
if not Buisy then FInput2 := aInput
|
||||
else
|
||||
if FMode = amRTMix then
|
||||
begin
|
||||
if FFgPlaying then
|
||||
begin
|
||||
while Flock do;
|
||||
FLock := True;
|
||||
Input2.Flush;
|
||||
end;
|
||||
FInput2 := aInput;
|
||||
Finput2.Init;
|
||||
Flock := False;
|
||||
FFgPlaying := True;
|
||||
EndOfInput2 := False;
|
||||
end else
|
||||
raise EACSException.Create(strNotinFBMode);
|
||||
end;
|
||||
|
||||
end.
|
||||
321
acs/Src/classes/acs_cdrom.pas
Normal file
321
acs/Src/classes/acs_cdrom.pas
Normal file
@@ -0,0 +1,321 @@
|
||||
(*
|
||||
this file is a part of audio components suite
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
|
||||
Special thanks to Thomas Grelle <grelle@online.de> for improving this unit.
|
||||
|
||||
$Log: acs_cdrom.pas,v $
|
||||
Revision 1.11 2006/08/31 20:10:54 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.10 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.2 2005/12/26 17:31:38 z0m3ie
|
||||
fixed some problems in acs_dsfiles
|
||||
fixed some problems in acs_vorbis
|
||||
reworked all buffers
|
||||
|
||||
Revision 1.1 2005/12/19 18:34:35 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.7 2005/12/18 17:01:54 z0m3ie
|
||||
delphi compatibility
|
||||
|
||||
Revision 1.6 2005/12/04 16:54:33 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.5 2005/11/28 21:57:24 z0m3ie
|
||||
mostly FileOut fixes
|
||||
moved PBuffer to PBuffer8
|
||||
set all to dynamically Buffering
|
||||
|
||||
Revision 1.4 2005/10/02 16:51:46 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.3 2005/09/15 20:59:38 z0m3ie
|
||||
start translate the documentation in the source for pasdoc
|
||||
|
||||
Revision 1.2 2005/09/13 21:54:11 z0m3ie
|
||||
acs is localizeable now (ACS_Strings)
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.6 2005/09/09 21:33:42 z0m3ie
|
||||
linux corrections
|
||||
|
||||
Revision 1.5 2005/09/08 22:18:59 z0m3ie
|
||||
completed akrip based CDIn
|
||||
|
||||
Revision 1.4 2005/09/07 20:53:22 z0m3ie
|
||||
begon to add MPEG and WMA support using DirectX
|
||||
|
||||
Revision 1.3 2005/09/04 17:59:37 z0m3ie
|
||||
moving CDIn support to AKRip mostly
|
||||
begon to add mpegin support for Win with mpg123
|
||||
|
||||
Revision 1.2 2005/08/28 20:31:17 z0m3ie
|
||||
linux restructuring for 2.4
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
Revision 1.5 2005/08/22 20:17:02 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
*)
|
||||
|
||||
{
|
||||
@abstract(this unit introduces the base classes for acs)
|
||||
@author(Andrei Borovsky (2003-2005))
|
||||
@author(Christian Ulrich (2005))
|
||||
}
|
||||
|
||||
|
||||
unit acs_cdrom;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, ACS_Classes,ACS_Strings,ACS_Types
|
||||
{$IFDEF MSWINDOWS}
|
||||
,Windows, MMSystem, akrip32
|
||||
{$ELSE}
|
||||
,baseunix,cd_rom
|
||||
{$ENDIF}
|
||||
;
|
||||
|
||||
type
|
||||
{$IFDEF MSWINDOWS}
|
||||
{$IFDEF FPC}
|
||||
TAuxCaps = AUXCAPS;
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
TACSCDStatus = (cdsNotReady, cdsReady, cdsPlaying, cdsPaused);
|
||||
TACSTrackType = (ttAudio, ttData);
|
||||
TACSCDInfo = (cdiNoDisc, cdiDiscAudio, cdiDiscData, cdiDiscMixed, cdiUnknown);
|
||||
TACSMCN = array[0..13] of Char;
|
||||
|
||||
TACSCDMSF = record
|
||||
Minute : Byte;
|
||||
Second : Byte;
|
||||
Frame : Byte;
|
||||
end;
|
||||
PACSCDMSF = ^TACSCDMSF;
|
||||
|
||||
TACSCDTrackInfo = record
|
||||
TrackStart: TACSCDMSF;
|
||||
TrackLength : TACSCDMSF;
|
||||
TrackType : TACSTrackType;
|
||||
end;
|
||||
|
||||
TACSCDPosition = record
|
||||
Track : Integer;
|
||||
MSF : TACSCDMSF;
|
||||
end;
|
||||
|
||||
const
|
||||
|
||||
EndOfDisc : TACSCDPosition = (Track : 100; MSF : (Minute : 0; Second : 0; Frame : 0));
|
||||
CD_FRAMESIZE_RAW = 2352;
|
||||
BUF_SIZE = 50; // 75 frames - 1 sec
|
||||
|
||||
var
|
||||
AppPath : String;
|
||||
WinPath : String;
|
||||
|
||||
type
|
||||
|
||||
{ This is the cdreader component of acs it reads in windows with aspi
|
||||
and linux direct from device
|
||||
}
|
||||
|
||||
TACSCDIn = class(TACSCustomInput)
|
||||
private
|
||||
FBuffer : array of byte;
|
||||
FCurrentDrive : Integer;
|
||||
FStartTrack, FEndTrack : Integer;
|
||||
FStartPos, FEndPos: TACSCDPosition;
|
||||
FRipEnd : Integer;
|
||||
FCDDBId: Longint;
|
||||
{$IFDEF LINUX}
|
||||
FOpened : Integer;
|
||||
FCurPos,FEndMSF : TACSCDMSF;
|
||||
FDrivesCount : Integer;
|
||||
_cd_fd : Integer;
|
||||
BufSize : Integer;
|
||||
{$ELSE}
|
||||
FToc: TOC;
|
||||
FCDList: CDLIST;
|
||||
FCDHandle : HCDROM;
|
||||
FPlaying : Boolean;
|
||||
FRipStart : LongInt;
|
||||
FiBuffer : PTRACKBUF;
|
||||
{$ENDIF}
|
||||
procedure OpenCD;
|
||||
procedure CloseCD;
|
||||
function GetStatus : TACSCDStatus;
|
||||
function GetNumTracks : Integer;
|
||||
function GetTrackInfo(const vIndex : Integer) : TACSCDTrackInfo;
|
||||
procedure SetST(Track : Integer);
|
||||
procedure SetET(Track : Integer);
|
||||
procedure SetSP(Pos : TACSCDPosition);
|
||||
procedure SetEP(Pos : TACSCDPosition);
|
||||
function GetSize : Integer;
|
||||
function GetInfo : TACSCDInfo;
|
||||
function GetDrivesCount : Integer;
|
||||
procedure SetCurrentDrive(Value : Integer);
|
||||
function GetDriveName : String;
|
||||
function GetCDDBID : LongInt;
|
||||
function GetTotalTime : real; override;
|
||||
protected
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
procedure Eject;
|
||||
procedure CloseTray;
|
||||
property DiscInfo: TACSCDInfo read GetInfo;
|
||||
property Status: TACSCDStatus read GetStatus;
|
||||
property Tracks[const vIndex : Integer] : TACSCDTrackInfo read GetTrackInfo;
|
||||
property TracksCount : Integer read GetNumTracks;
|
||||
property DriveName : String read GetDriveName;
|
||||
property DrivesCount : Integer read GetDrivesCount;
|
||||
property StartPos : TACSCDPosition read FStartPos write SetSP;
|
||||
property EndPos : TACSCDPosition read FEndPos write SetEP;
|
||||
property CDDBId : LongInt read GetCDDBID;
|
||||
published
|
||||
property CurrentDrive : Integer read FCurrentDrive write SetCurrentDrive;
|
||||
property StartTrack: Integer read FStartTrack write SetSt;
|
||||
property EndTrack: Integer read FEndTrack write SetET;
|
||||
end;
|
||||
|
||||
function MSFToStr(const MSF : TACSCDMSF) : String;
|
||||
procedure Frames2MSF(Frames : Integer; var MSF : TACSCDMSF);
|
||||
function MSF2Frames(const MSF : TACSCDMSF) : Integer;
|
||||
|
||||
{$IFDEF LINUX}
|
||||
var
|
||||
DrivesCount : Integer;
|
||||
DrivesPaths : array of string;
|
||||
|
||||
procedure CountDrives;
|
||||
{$ENDIF}
|
||||
|
||||
implementation
|
||||
|
||||
{$I ACS_CDROM.inc}
|
||||
|
||||
function MSFToStr(const MSF : TACSCDMSF) : String;
|
||||
var
|
||||
sep : String;
|
||||
sec, min : Integer;
|
||||
begin
|
||||
min := MSF.Minute;
|
||||
if MSF.Frame > 37 then
|
||||
begin
|
||||
sec := MSF.Second + 1;
|
||||
if sec = 60 then
|
||||
begin
|
||||
Inc(min);
|
||||
sec := 0;
|
||||
end;
|
||||
end
|
||||
else sec := MSF.Second;
|
||||
if sec<10 then sep := ':0'
|
||||
else sep := ':';
|
||||
Result := IntToStr(min) + sep + IntToStr(sec);
|
||||
end;
|
||||
|
||||
procedure Frames2MSF(Frames : Integer; var MSF : TACSCDMSF);
|
||||
var
|
||||
Temp : Integer;
|
||||
begin
|
||||
Temp := Frames div 75;
|
||||
MSF.Minute := Temp div 60;
|
||||
MSF.Second := Temp mod 60;
|
||||
MSF.Frame := Frames mod 75;
|
||||
end;
|
||||
|
||||
function MSF2Frames(const MSF : TACSCDMSF) : Integer;
|
||||
begin
|
||||
Result := ((MSF.Minute * 60) + MSF.Second) * 75 + MSF.Frame;
|
||||
end;
|
||||
|
||||
function TACSCDIn.GetBPS : Integer;
|
||||
begin
|
||||
Result := 16;
|
||||
end;
|
||||
|
||||
function TACSCDIn.GetCh : Integer;
|
||||
begin
|
||||
Result := 2;
|
||||
end;
|
||||
|
||||
function TACSCDIn.GetSR : Integer;
|
||||
begin
|
||||
Result := 44100;
|
||||
end;
|
||||
|
||||
function TACSCDIn.GetTotalTime : real;
|
||||
begin
|
||||
if (SampleRate = 0) or (Channels = 0) or (BitsPerSample = 0) then
|
||||
Exit;
|
||||
Result := Size/(SampleRate*Channels*(BitsPerSample shr 3));
|
||||
end;
|
||||
|
||||
function TACSCDIn.GetCDDBID: LongInt;
|
||||
FUNCTION prg_sum(n: integer): integer;
|
||||
VAR
|
||||
buf: STRING;
|
||||
ib: Integer;
|
||||
BEGIN
|
||||
buf := IntToStr(n);
|
||||
Result := 0;
|
||||
FOR ib := 1 TO Length(buf) DO
|
||||
Result := Result + (StrToInt(Copy(Buf, ib, 1)));
|
||||
END;
|
||||
VAR
|
||||
i, N, L: Longint;
|
||||
CDM: TACSCDMSF;
|
||||
BEGIN
|
||||
N := 0;
|
||||
L := 0;
|
||||
FOR i := 0 TO GetNumTracks-1 DO
|
||||
BEGIN
|
||||
WITH Tracks[i].TrackStart DO
|
||||
BEGIN
|
||||
N := N + prg_sum((minute * 60) + second + 2);
|
||||
L := L + MSF2Frames(Tracks[i].TrackLength);
|
||||
// adjust the length of last audio track if a data track is following
|
||||
IF (i > 0) AND (i = TracksCount - 2) AND (Tracks[i + 1].TrackType = ttData) THEN
|
||||
inc(L, 152 * 75);
|
||||
END;
|
||||
END;
|
||||
Frames2MSF(L, CDM);
|
||||
L := CDM.Minute * 60 + CDM.Second;
|
||||
Result := ((N MOD $0FF) SHL 24) XOR (L SHL 8) XOR TracksCount;
|
||||
FCDDBId := Result;
|
||||
end;
|
||||
|
||||
{$IFDEF LINUX}
|
||||
initialization
|
||||
CountDrives;
|
||||
{$ENDIF}
|
||||
|
||||
end.
|
||||
1376
acs/Src/classes/acs_classes.pas
Normal file
1376
acs/Src/classes/acs_classes.pas
Normal file
File diff suppressed because it is too large
Load Diff
910
acs/Src/classes/acs_converters.pas
Normal file
910
acs/Src/classes/acs_converters.pas
Normal file
@@ -0,0 +1,910 @@
|
||||
(*
|
||||
this file is a part of audio components suite.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
|
||||
$Log: acs_converters.pas,v $
|
||||
Revision 1.6 2006/08/31 20:10:54 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.5 2006/07/04 18:38:32 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.4 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.2 2006/01/01 18:46:40 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/12/19 18:34:35 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.4 2005/12/04 16:54:33 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.3 2005/09/15 20:59:38 z0m3ie
|
||||
start translate the documentation in the source for pasdoc
|
||||
|
||||
Revision 1.2 2005/09/13 21:54:11 z0m3ie
|
||||
acs is localizeable now (ACS_Strings)
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.4 2005/09/01 19:55:48 z0m3ie
|
||||
again Delphi corrections
|
||||
|
||||
Revision 1.3 2005/08/31 20:30:39 z0m3ie
|
||||
Mixer Channelname work now
|
||||
minior corrections for Converters
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
*)
|
||||
|
||||
{
|
||||
@abstract(this unit introduces the base classes for acs)
|
||||
@author(Andrei Borovsky (2003-2005))
|
||||
@author(Christian Ulrich (2005))
|
||||
}
|
||||
|
||||
unit acs_converters;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, ACS_Types, ACS_Procs, ACS_Classes, ACS_Strings, Math;
|
||||
|
||||
const
|
||||
BUF_SIZE = $8000;
|
||||
|
||||
KERNEL_WIDTH = 64;
|
||||
|
||||
SD_BUF_SIZE = 2048;
|
||||
|
||||
type
|
||||
|
||||
TACSMSConverterMode = (msmMonoToBoth, msmMonoToLeft, msmMonoToRight);
|
||||
|
||||
TDA = array[0..63] of Double;
|
||||
PDA = ^TDA;
|
||||
|
||||
|
||||
TACSRateConverter = class(TACSCustomConverter)
|
||||
private
|
||||
FOutSampleRate : Integer;
|
||||
WantedSize : Integer;
|
||||
EndOfInput : Boolean;
|
||||
remainder : Integer;
|
||||
InBufM, OutBufM : PACSBuffer16;
|
||||
InBufS, OutBufS : PACSStereoBuffer16;
|
||||
DAM : array of Double;
|
||||
DAS : array of TACSStereoSampleD;
|
||||
Kernel : array of Double;
|
||||
FKernelWidth : Integer;
|
||||
FFilterWindow : TACSFilterWindowType;
|
||||
Tail : Pointer;
|
||||
LBS : TACSStereoSample16;
|
||||
function ConvertFreqs16Mono(InSize : Integer): Integer;
|
||||
function ConvertFreqs16Stereo(InSize : Integer): Integer;
|
||||
procedure SetOutSampleRate(aSR : Integer);
|
||||
procedure SetKernelWidth(aKW : Integer);
|
||||
protected
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
published
|
||||
property FilterWindow : TACSFilterWindowType read FFilterWindow write FFilterWindow;
|
||||
property KernelWidth : Integer read FKernelWidth write SetKernelWidth;
|
||||
property OutSampleRate : Integer read FOutSampleRate write SetOutSampleRate;
|
||||
end;
|
||||
|
||||
TACSMSConverter = class(TACSCustomConverter)
|
||||
private
|
||||
WantedSize : Integer;
|
||||
EndOfInput : Boolean;
|
||||
InOutBuf : array[1..BUF_SIZE] of Byte;
|
||||
FMode : TACSMSConverterMode;
|
||||
protected
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
published
|
||||
property Mode : TACSMSConverterMode read FMode write FMode;
|
||||
end;
|
||||
|
||||
TACSSampleConverter = class(TACSCustomConverter)
|
||||
private
|
||||
WantedSize : Integer;
|
||||
EndOfInput : Boolean;
|
||||
InOutBuf : array[1..BUF_SIZE] of Byte;
|
||||
protected
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
end;
|
||||
|
||||
TACSStereoBalance = class(TACSCustomConverter)
|
||||
private
|
||||
FBalance : Single;
|
||||
procedure SetBalance(a : Single);
|
||||
protected
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
published
|
||||
property Balance : Single read FBalance write SetBalance;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
function TACSRateConverter.ConvertFreqs16Mono(InSize : Integer): Integer;
|
||||
var
|
||||
i, step, j, k, s, m : Integer;
|
||||
D : Double;
|
||||
TailMono : PACSBuffer16;
|
||||
TailMonoD : PACSDoubleArray;
|
||||
begin
|
||||
TailMono := Tail;
|
||||
s := InSize shr 1;
|
||||
if FInput.SampleRate > FOutSampleRate then
|
||||
begin
|
||||
step := FInput.SampleRate - FOutSampleRate;
|
||||
j := 0;
|
||||
if remainder < 0 then remainder := FOutSampleRate;
|
||||
for i := 0 to s - 1 do
|
||||
begin
|
||||
if remainder > FOutSampleRate then Dec(remainder, FOutSampleRate)
|
||||
else begin
|
||||
D := 0;
|
||||
for k := 0 to FKernelWidth - 1 do
|
||||
if i-k >= 0 then
|
||||
D := D + InBufM[i-k]*Kernel[FKernelWidth - 1 - k]
|
||||
else
|
||||
D := D + TailMono[FKernelWidth-1+i-k]*Kernel[FKernelWidth - 1 - k];
|
||||
OutBufM[j] := Round(D);
|
||||
Inc(j);
|
||||
Inc(remainder, step);
|
||||
end;
|
||||
end;
|
||||
for i := 0 to FKernelWidth-2 do TailMono[i] := InBufM[i+s-FKernelWidth+1]
|
||||
end else
|
||||
begin
|
||||
TailMonoD := Tail;
|
||||
FillChar(DAM[0], Length(DAM)*8, 0);
|
||||
for i := 0 to FKernelWidth-2 do
|
||||
begin
|
||||
DAM[i] := TailMonoD[i];
|
||||
TailMonoD[i] := 0;
|
||||
end;
|
||||
Step := Finput.SampleRate;
|
||||
j := 0;
|
||||
if remainder < 0 then remainder := 0;
|
||||
while remainder < FOutSampleRate do
|
||||
begin
|
||||
m := Round(((FOutSampleRate - remainder)*LBS.Left + remainder*InBufM[0])/FOutSampleRate);
|
||||
for k := 0 to FKernelWidth-1 do
|
||||
DAM[j+k] := DAM[j+k] + m*Kernel[k];
|
||||
Inc(j);
|
||||
Inc(remainder, step);
|
||||
end;
|
||||
Dec(remainder, FOutSampleRate);
|
||||
for i := 0 to s - 2 do
|
||||
begin
|
||||
while remainder < FOutSampleRate do
|
||||
begin
|
||||
m := Round(((FOutSampleRate - remainder)*InBufM[i] + remainder*InBufM[i+1])/FOutSampleRate);
|
||||
for k := 0 to FKernelWidth-1 do
|
||||
DAM[j+k] := DAM[j+k] + m*Kernel[k];
|
||||
Inc(j);
|
||||
Inc(remainder, step);
|
||||
end;
|
||||
Dec(remainder, FOutSampleRate);
|
||||
end;
|
||||
LBS.Left := InBufM[s-1];
|
||||
for i := 0 to j-1 do
|
||||
OutBufM[i] := Round(DAM[i]);
|
||||
for i := 0 to FKernelWidth-2 do TailMonoD[i] := DAM[i+j];
|
||||
end;
|
||||
Result := j shl 1;
|
||||
end;
|
||||
|
||||
function TACSRateConverter.ConvertFreqs16Stereo(InSize : Integer): Integer;
|
||||
var
|
||||
i, step, j, k, s, m1, m2 : Integer;
|
||||
D1, D2 : Double;
|
||||
TailStereo : PACSStereoBuffer16;
|
||||
TailStereoD : PACSStereoBufferD;
|
||||
begin
|
||||
TailStereo := Tail;
|
||||
s := InSize shr 2;
|
||||
if FInput.SampleRate > FOutSampleRate then
|
||||
begin
|
||||
step := FInput.SampleRate - FOutSampleRate;
|
||||
j := 0;
|
||||
if remainder < 0 then remainder := FOutSampleRate;
|
||||
for i := 0 to s - 1 do
|
||||
begin
|
||||
try
|
||||
if remainder > FOutSampleRate then Dec(remainder, FOutSampleRate)
|
||||
else begin
|
||||
D1 := 0;
|
||||
D2 := 0;
|
||||
for k := 0 to FKernelWidth - 1 do
|
||||
if i-k >= 0 then
|
||||
begin
|
||||
D1 := D1 + InBufS[i-k].Left*Kernel[FKernelWidth - 1 - k];
|
||||
D2 := D2 + InBufS[i-k].Right*Kernel[FKernelWidth - 1 - k];
|
||||
end else
|
||||
begin
|
||||
D1 := D1 + TailStereo[FKernelWidth-1+i-k].Left*Kernel[FKernelWidth - 1 - k];
|
||||
D2 := D2 + TailStereo[FKernelWidth-1+i-k].Right*Kernel[FKernelWidth - 1 - k];
|
||||
end;
|
||||
OutBufS[j].Left := Round(D1);
|
||||
OutBufS[j].Right := Round(D2);
|
||||
Inc(j);
|
||||
Inc(remainder, step);
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
for i := 0 to FKernelWidth-2 do TailStereo[i] := InBufS[i+s-FKernelWidth+1]
|
||||
//Move(InBufS[s-FKernelWidth+1], TailStereo[0], FKernelWidth-1);
|
||||
end else
|
||||
begin
|
||||
TailStereoD := Tail;
|
||||
FillChar(DAS[0], Length(DAS)*16, 0);
|
||||
for i := 0 to FKernelWidth-2 do
|
||||
begin
|
||||
DAS[i] := TailStereoD[i];
|
||||
TailStereoD[i].Left := 0;
|
||||
TailStereoD[i].Right := 0;
|
||||
end;
|
||||
Step := Finput.SampleRate;
|
||||
j := 0;
|
||||
if remainder < 0 then remainder := 0;
|
||||
while remainder < FOutSampleRate do
|
||||
begin
|
||||
m1 := Round(((FOutSampleRate - remainder)*LBS.Left + remainder*InBufS[0].Left)/FOutSampleRate);
|
||||
m2 := Round(((FOutSampleRate - remainder)*LBS.Right + remainder*InBufS[0].Right)/FOutSampleRate);
|
||||
for k := 0 to FKernelWidth-1 do
|
||||
begin
|
||||
DAS[j+k].Left := DAS[j+k].Left + m1*Kernel[k]; //InBufS[i].Left*Kernel[k];
|
||||
DAS[j+k].Right := DAS[j+k].Right + m2*Kernel[k]; //InBufS[i].Right*Kernel[k];
|
||||
end;
|
||||
Inc(j);
|
||||
Inc(remainder, step);
|
||||
end;
|
||||
Dec(remainder, FOutSampleRate);
|
||||
for i := 0 to s - 2 do
|
||||
begin
|
||||
while remainder < FOutSampleRate do
|
||||
begin
|
||||
m1 := Round(((FOutSampleRate - remainder)*InBufS[i].Left + remainder*InBufS[i+1].Left)/FOutSampleRate);
|
||||
m2 := Round(((FOutSampleRate - remainder)*InBufS[i].Right + remainder*InBufS[i+1].Right)/FOutSampleRate);
|
||||
for k := 0 to FKernelWidth-1 do
|
||||
begin
|
||||
DAS[j+k].Left := DAS[j+k].Left + m1*Kernel[k]; //InBufS[i].Left*Kernel[k];
|
||||
DAS[j+k].Right := DAS[j+k].Right + m2*Kernel[k]; //InBufS[i].Right*Kernel[k];
|
||||
end;
|
||||
Inc(j);
|
||||
Inc(remainder, step);
|
||||
end;
|
||||
Dec(remainder, FOutSampleRate);
|
||||
end;
|
||||
LBS := InBufS[s-1];
|
||||
for i := 0 to j-1 do
|
||||
begin
|
||||
OutBufS[i].Left := Round(DAS[i].Left);
|
||||
OutBufS[i].Right := Round(DAS[i].Right);
|
||||
end;
|
||||
for i := 0 to FKernelWidth-2 do TailStereoD[i] := DAS[i+j];
|
||||
end;
|
||||
Result := j shl 2;
|
||||
end;
|
||||
|
||||
procedure Convert16To8(InOutBuf : PACSBuffer8; InSize : Integer);
|
||||
var
|
||||
i : Integer;
|
||||
P : PACSBuffer16;
|
||||
begin
|
||||
P := @InOutBuf[0];
|
||||
for i := 0 to (Insize shr 1) -1 do
|
||||
InOutBuf[i] := Hi(P[i]+$8000);
|
||||
end;
|
||||
|
||||
procedure Convert8To16(InOutBuf : PACSBuffer8; InSize : Integer);
|
||||
var
|
||||
i : Integer;
|
||||
P : PACSBuffer16;
|
||||
begin
|
||||
P := @InOutBuf[0];
|
||||
for i := Insize - 1 downto 0 do P[i] := (InOutBuf[i] shl 8) - $8000;
|
||||
end;
|
||||
|
||||
procedure ConvertStereoToMono16(InOutBuf : PACSBuffer16; InSize : Integer);
|
||||
var
|
||||
i : Integer;
|
||||
begin
|
||||
for i := 0 to (Insize shr 2) - 1 do
|
||||
begin
|
||||
InOutBuf[i] := (InOutBuf[i shl 1] + InOutBuf[(i shl 1)+1]) div 2;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure ConvertMonoToStereo16(InOutBuf : PACSBuffer16; InSize : Integer; Mode : TACSMSConverterMode);
|
||||
var
|
||||
i : Integer;
|
||||
begin
|
||||
case Mode of
|
||||
msmMonoToBoth :
|
||||
for i := (Insize shr 1) - 1 downto 0 do
|
||||
begin
|
||||
InOutBuf[i shl 1] := InOutBuf[i];
|
||||
InOutBuf[(i shl 1)+1] := InOutBuf[i];
|
||||
end;
|
||||
msmMonoToLeft :
|
||||
for i := (Insize shr 1) - 1 downto 0 do
|
||||
begin
|
||||
InOutBuf[i shl 1] := 0;
|
||||
InOutBuf[(i shl 1)+1] := InOutBuf[i];
|
||||
end;
|
||||
msmMonoToRight :
|
||||
for i := (Insize shr 1) - 1 downto 0 do
|
||||
begin
|
||||
InOutBuf[i shl 1] := InOutBuf[i];
|
||||
InOutBuf[(i shl 1)+1] := 0;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function GCD(a, b : Integer) : Integer;
|
||||
var
|
||||
p, q, r : Integer;
|
||||
begin
|
||||
p := a;
|
||||
q := b;
|
||||
r := p mod q;
|
||||
while r <> 0 do
|
||||
begin
|
||||
p := q;
|
||||
q := r;
|
||||
r := p mod q;
|
||||
end;
|
||||
Result := q;
|
||||
end;
|
||||
|
||||
constructor TACSRateConverter.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FOutSampleRate := 22050;
|
||||
FKernelWidth := 30;
|
||||
FFilterWindow := fwBlackman;
|
||||
end;
|
||||
|
||||
destructor TACSRateConverter.Destroy;
|
||||
begin
|
||||
Kernel := nil;
|
||||
DAS := nil;
|
||||
DAM := nil;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TACSRateConverter.GetBPS : Integer;
|
||||
begin
|
||||
Result := 16;
|
||||
end;
|
||||
|
||||
function TACSRateConverter.GetCh : Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
Result := FInput.Channels;
|
||||
end;
|
||||
|
||||
function TACSRateConverter.GetSR : Integer;
|
||||
begin
|
||||
Result := FOutSampleRate;
|
||||
end;
|
||||
|
||||
procedure TACSRateConverter.Init;
|
||||
var
|
||||
Ratio : Single;
|
||||
TailSize : Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
FInput.Init;
|
||||
InputLock := False;
|
||||
FBusy := True;
|
||||
FPosition := 0;
|
||||
BufStart := 1;
|
||||
BufEnd := 0;
|
||||
EndOfInput := False;
|
||||
Ratio := FOutSampleRate/Finput.SampleRate;
|
||||
if Ratio > 1. then
|
||||
WantedSize := (Trunc(BUF_SIZE/Ratio) shr 2) * 4
|
||||
else WantedSize := BUF_SIZE;
|
||||
if Finput.Channels = 1 then
|
||||
begin
|
||||
GetMem(InBufM, WantedSize);
|
||||
GetMem(OutBufM, BUF_SIZE);
|
||||
if Ratio < 1. then
|
||||
TailSize := (KernelWidth-1)*2
|
||||
else
|
||||
begin
|
||||
SetLength(DAM, (BUF_SIZE div 2)+KernelWidth);
|
||||
TailSize := (KernelWidth-1)*8;
|
||||
end;
|
||||
FillChar(DAM[0], Length(DAM)*Sizeof(DAM[0]), 0);
|
||||
end else
|
||||
begin
|
||||
GetMem(InBufS, WantedSize);
|
||||
GetMem(OutBufS, BUF_SIZE);
|
||||
if Ratio < 1. then
|
||||
TailSize := (KernelWidth-1)*4
|
||||
else
|
||||
begin
|
||||
SetLength(DAS, (BUF_SIZE div 4)+KernelWidth);
|
||||
TailSize := (KernelWidth-1)*16;
|
||||
end;
|
||||
end;
|
||||
GetMem(Tail, TailSize);
|
||||
FillChar(Tail^, TailSize, 0);
|
||||
FSize := Round(FInput.Size*Ratio);
|
||||
remainder := -1;
|
||||
if Ratio > 1. then Ratio := 1/Ratio;
|
||||
Ratio := Ratio*0.4;
|
||||
SetLength(Kernel, FKernelWidth);
|
||||
CalculateSincKernel(@Kernel[0], Ratio, FKernelWidth, FFilterWindow);
|
||||
end;
|
||||
|
||||
procedure TACSRateConverter.Flush;
|
||||
begin
|
||||
FreeMem(Tail);
|
||||
FInput.Flush;
|
||||
if Finput.Channels = 1 then
|
||||
begin
|
||||
FreeMem(InBufM);
|
||||
FreeMem(OutBufM);
|
||||
end else
|
||||
begin
|
||||
FreeMem(InBufS);
|
||||
FreeMem(OutBufS);
|
||||
end;
|
||||
FBusy := False;
|
||||
end;
|
||||
|
||||
function TACSRateConverter.GetData(Buffer : Pointer; BufferSize : Integer): Integer;
|
||||
var
|
||||
l : Integer;
|
||||
InSize : Integer;
|
||||
P : PACSBuffer8;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create(strStreamnotopen);
|
||||
if BufStart > BufEnd then
|
||||
begin
|
||||
if EndOfInput then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
BufStart := 1;
|
||||
if FInput.Channels = 1 then P := Pointer(InBufM)
|
||||
else P := Pointer(InBufS);
|
||||
while InputLock do;
|
||||
InputLock := True;
|
||||
l := Finput.GetData(@P[0], WantedSize);
|
||||
InputLock := False;
|
||||
if l = 0 then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
InSize := l;
|
||||
while (l<>0) and (InSize < WantedSize) do
|
||||
begin
|
||||
while InputLock do;
|
||||
InputLock := True;
|
||||
l := Finput.GetData(@P[InSize], WantedSize - InSize);
|
||||
InputLock := False;
|
||||
Inc(InSize, l);
|
||||
end;
|
||||
if l = 0 then
|
||||
begin
|
||||
EndOfInput := True;
|
||||
if InSize < FKernelWidth*2 then
|
||||
begin // stop buffer corruption?
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
if Self.Channels = 1 then
|
||||
begin
|
||||
BufEnd := ConvertFreqs16Mono(InSize);
|
||||
end else
|
||||
begin
|
||||
BufEnd := ConvertFreqs16Stereo(InSize);
|
||||
end;
|
||||
end;
|
||||
if BufferSize < (BufEnd - BufStart + 1)
|
||||
then Result := BufferSize
|
||||
else Result := BufEnd - BufStart + 1;
|
||||
if FInput.Channels = 1 then P := Pointer(OutBufM)
|
||||
else P := Pointer(OutBufS);
|
||||
Move(P[BufStart-1], Buffer^, Result);
|
||||
Inc(BufStart, Result);
|
||||
// FPosition := Round(FInput.Position*(FSize/FInput.Size));
|
||||
Inc(FPosition, Result);
|
||||
end;
|
||||
|
||||
constructor TACSMSConverter.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
end;
|
||||
|
||||
destructor TACSMSConverter.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TACSMSConverter.GetBPS : Integer;
|
||||
begin
|
||||
Result := 16;
|
||||
end;
|
||||
|
||||
function TACSMSConverter.GetCh : Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
if FInput.Channels = 1 then Result := 2
|
||||
else Result := 1;
|
||||
end;
|
||||
|
||||
function TACSMSConverter.GetSR : Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
Result := FInput.SampleRate;
|
||||
end;
|
||||
|
||||
procedure TACSMSConverter.Init;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
FInput.Init;
|
||||
FBusy := True;
|
||||
FPosition := 0;
|
||||
BufStart := 1;
|
||||
BufEnd := 0;
|
||||
InputLock := False;
|
||||
EndOfInput := False;
|
||||
if FInput.Channels = 2 then WantedSize := BUF_SIZE else
|
||||
WantedSize := BUF_SIZE shr 1;
|
||||
if FInput.Channels = 2 then
|
||||
FSize := FInput.Size shr 1
|
||||
else FSize := FInput.Size shl 1;
|
||||
end;
|
||||
|
||||
procedure TACSMSConverter.Flush;
|
||||
begin
|
||||
FInput.Flush;
|
||||
FBusy := False;
|
||||
end;
|
||||
|
||||
function TACSMSConverter.GetData(Buffer : Pointer; BufferSize : Integer): Integer;
|
||||
var
|
||||
l : Integer;
|
||||
InSize : Integer;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create(strStreamnotopen);
|
||||
if BufStart > BufEnd then
|
||||
begin
|
||||
if EndOfInput then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
BufStart := 1;
|
||||
while InputLock do;
|
||||
InputLock := True;
|
||||
l := Finput.GetData(@InOutBuf[1], WantedSize);
|
||||
InputLock := False;
|
||||
if l = 0 then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
InSize := l;
|
||||
while (l<>0) and (InSize < WantedSize) do
|
||||
begin
|
||||
while InputLock do;
|
||||
InputLock := True;
|
||||
l := Finput.GetData(@InOutBuf[InSize+1], WantedSize - InSize);
|
||||
InputLock := False;
|
||||
Inc(InSize, l);
|
||||
end;
|
||||
if l = 0 then EndOfInput := True;
|
||||
if FInput.Channels = 2 then
|
||||
begin
|
||||
ConvertStereoToMono16(@InOutBuf[1], InSize);
|
||||
BufEnd := InSize shr 1;
|
||||
end else
|
||||
begin
|
||||
ConvertMonoToStereo16(@InOutBuf[1], InSize, FMode);
|
||||
BufEnd := InSize shl 1;
|
||||
end;
|
||||
end;
|
||||
if BufferSize < (BufEnd - BufStart + 1)
|
||||
then Result := BufferSize
|
||||
else Result := BufEnd - BufStart + 1;
|
||||
Move(InOutBuf[BufStart], Buffer^, Result);
|
||||
Inc(BufStart, Result);
|
||||
// FPosition := Round(FInput.Position*(FSize/FInput.Size));
|
||||
Inc(FPosition, Result);
|
||||
end;
|
||||
|
||||
constructor TACSSampleConverter.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
end;
|
||||
|
||||
destructor TACSSampleConverter.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TACSSampleConverter.GetBPS : Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
if FInput.BitsPerSample = 16 then Result := 8
|
||||
else Result := 16;
|
||||
end;
|
||||
|
||||
function TACSSampleConverter.GetCh : Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
Result:= FInput.Channels;
|
||||
end;
|
||||
|
||||
function TACSSampleConverter.GetSR : Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
Result := FInput.SampleRate;
|
||||
end;
|
||||
|
||||
procedure TACSSampleConverter.Init;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
FInput.Init;
|
||||
FBusy := True;
|
||||
FPosition := 0;
|
||||
BufStart := 1;
|
||||
BufEnd := 0;
|
||||
InputLock := False;
|
||||
EndOfInput := False;
|
||||
if FInput.BitsPerSample = 16 then WantedSize := BUF_SIZE else
|
||||
WantedSize := BUF_SIZE shr 1;
|
||||
if FInput.BitsPerSample = 16 then
|
||||
FSize := FInput.Size shr 1
|
||||
else FSize := FInput.Size shl 1;
|
||||
end;
|
||||
|
||||
procedure TACSSampleConverter.Flush;
|
||||
begin
|
||||
FInput.Flush;
|
||||
FBusy := False;
|
||||
end;
|
||||
|
||||
function TACSSampleConverter.GetData(Buffer : Pointer; BufferSize : Integer): Integer;
|
||||
var
|
||||
l : Integer;
|
||||
InSize : Integer;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create(strStreamnotopen);
|
||||
if BufStart > BufEnd then
|
||||
begin
|
||||
if EndOfInput then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
BufStart := 1;
|
||||
while InputLock do;
|
||||
InputLock := True;
|
||||
l := Finput.GetData(@InOutBuf[1], WantedSize);
|
||||
InputLock := False;
|
||||
if l = 0 then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
InSize := l;
|
||||
while (l<>0) and (InSize < WantedSize) do
|
||||
begin
|
||||
while InputLock do;
|
||||
InputLock := True;
|
||||
l := Finput.GetData(@InOutBuf[InSize+1], WantedSize - InSize);
|
||||
InputLock := False;
|
||||
Inc(InSize, l);
|
||||
end;
|
||||
if l = 0 then EndOfInput := True;
|
||||
if FInput.BitsPerSample = 16 then
|
||||
begin
|
||||
Convert16To8(@InOutBuf[1], InSize);
|
||||
BufEnd := InSize shr 1;
|
||||
end else
|
||||
begin
|
||||
Convert8To16(@InOutBuf[1], InSize);
|
||||
BufEnd := InSize shl 1;
|
||||
end;
|
||||
end;
|
||||
if BufferSize < (BufEnd - BufStart + 1)
|
||||
then Result := BufferSize
|
||||
else Result := BufEnd - BufStart + 1;
|
||||
Move(InOutBuf[BufStart], Buffer^, Result);
|
||||
Inc(BufStart, Result);
|
||||
FPosition := Round(FInput.Position*(FSize/FInput.Size));
|
||||
// Inc(FPosition, Result);
|
||||
end;
|
||||
|
||||
procedure TACSRateConverter.SetOutSampleRate(aSR : Integer);
|
||||
begin
|
||||
if (aSR > 0) {and (not Busy)} then FOutSampleRate := aSR;
|
||||
end;
|
||||
|
||||
procedure TACSRateConverter.SetKernelWidth;
|
||||
begin
|
||||
if (aKW > 1) and (not Busy) then FKernelWidth := aKW;
|
||||
end;
|
||||
|
||||
constructor TACSStereoBalance.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FBalance := 0.5;
|
||||
end;
|
||||
|
||||
destructor TACSStereoBalance.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TACSStereoBalance.SetBalance;
|
||||
begin
|
||||
if (a >= 0) and (a <=1) then FBalance := a;
|
||||
end;
|
||||
|
||||
function TACSStereoBalance.GetBPS : Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
Result := FInput.BitsPerSample;
|
||||
end;
|
||||
|
||||
function TACSStereoBalance.GetCh : Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
Result := 2;
|
||||
end;
|
||||
|
||||
function TACSStereoBalance.GetSR : Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
Result := FInput.SampleRate;
|
||||
end;
|
||||
|
||||
procedure TACSStereoBalance.Init;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
FInput.Init;
|
||||
FBusy := True;
|
||||
if FInput.Channels = 2 then FSize := FInput.Size
|
||||
else FSize := FInput.Size*2;
|
||||
FPosition := 0;
|
||||
InputLock := False;
|
||||
end;
|
||||
|
||||
procedure TACSStereoBalance.Flush;
|
||||
begin
|
||||
FInput.Flush;
|
||||
FBusy := False;
|
||||
end;
|
||||
|
||||
function TACSStereoBalance.GetData(Buffer : Pointer; BufferSize : Integer): Integer;
|
||||
var
|
||||
WantedSize, i : Integer;
|
||||
P16 : PACSBuffer16;
|
||||
P8 : PACSBuffer8;
|
||||
Diff : Double;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create(strStreamnotopen);
|
||||
while InputLock do;
|
||||
InputLock := True;
|
||||
if FInput.Channels = 2 then WantedSize := BufferSize
|
||||
else WantedSize := BufferSize shr 1;
|
||||
Result := Finput.GetData(Buffer, WantedSize);
|
||||
InputLock := False;
|
||||
if Result = 0 then Exit;
|
||||
if FInput.Channels = 1 then
|
||||
begin
|
||||
if FInput.BitsPerSample = 8 then
|
||||
begin
|
||||
P8 := Buffer;
|
||||
for i := Result*2-1 downto 1 do P8[i] := P8[i shr 1];
|
||||
end else
|
||||
begin
|
||||
P16 := Buffer;
|
||||
for i := Result-1 downto 1 do
|
||||
P16[i] := P16[i shr 1];
|
||||
end;
|
||||
Result := Result*2;
|
||||
end;
|
||||
if FInput.BitsPerSample = 8 then
|
||||
begin
|
||||
P8 := Buffer;
|
||||
if FBalance > 0.5 then
|
||||
begin
|
||||
Diff := 1-Balance;
|
||||
for i := 0 to (Result shr 1) -1 do
|
||||
P8[i*2] := Round(P8[i*2]*Diff);
|
||||
end else
|
||||
begin
|
||||
for i := 0 to (Result shr 1) -1 do
|
||||
P8[i*2+1] := Round(P8[i*2+1]*FBalance);
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
P16 := Buffer;
|
||||
if FBalance > 0.5 then
|
||||
begin
|
||||
Diff := 1-Balance;
|
||||
for i := 0 to (Result shr 2) -1 do
|
||||
P16[i*2] := Round(P16[i*2]*Diff);
|
||||
end else
|
||||
begin
|
||||
for i := 0 to (Result shr 2) -1 do
|
||||
P16[i*2+1] := Round(P16[i*2+1]*FBalance);
|
||||
end;
|
||||
end;
|
||||
FPosition := Round(FSize/FInput.Size)*FInput.Position;
|
||||
end;
|
||||
|
||||
end.
|
||||
674
acs/Src/classes/acs_file.pas
Normal file
674
acs/Src/classes/acs_file.pas
Normal file
@@ -0,0 +1,674 @@
|
||||
(*
|
||||
this file is a part of audio components suite.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
|
||||
$Log: acs_file.pas,v $
|
||||
Revision 1.11 2006/08/03 17:31:09 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.10 2006/07/09 16:40:34 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.9 2006/07/07 15:51:19 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.8 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.3 2006/01/01 18:46:40 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/12/26 17:31:38 z0m3ie
|
||||
fixed some problems in acs_dsfiles
|
||||
fixed some problems in acs_vorbis
|
||||
reworked all buffers
|
||||
|
||||
Revision 1.1 2005/12/19 18:34:35 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.10 2005/12/18 17:01:54 z0m3ie
|
||||
delphi compatibility
|
||||
|
||||
Revision 1.9 2005/12/04 16:54:33 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.8 2005/10/05 20:26:36 z0m3ie
|
||||
Linux changes
|
||||
|
||||
Revision 1.7 2005/10/02 16:51:46 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.6 2005/09/15 20:59:38 z0m3ie
|
||||
start translate the documentation in the source for pasdoc
|
||||
|
||||
Revision 1.5 2005/09/13 21:54:11 z0m3ie
|
||||
acs is localizeable now (ACS_Strings)
|
||||
|
||||
Revision 1.4 2005/09/13 20:14:25 z0m3ie
|
||||
driver handling classes (basic audio class)
|
||||
|
||||
Revision 1.3 2005/09/13 04:37:30 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/09/13 04:04:50 z0m3ie
|
||||
First release without Components for Fileformats
|
||||
only TFileIn and TFileOut are Visible
|
||||
*)
|
||||
|
||||
{
|
||||
@abstract(this unit introduces the base classes for acs)
|
||||
@author(Christian Ulrich (2005))
|
||||
|
||||
this unit introduces basic fileformat support
|
||||
}
|
||||
|
||||
unit acs_file;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, ACS_Classes, Dialogs, SysUtils, ACS_Strings;
|
||||
|
||||
type
|
||||
TACSFileInClass = class of TACSCustomFileIn;
|
||||
TACSFileOutClass = class of TACSCustomFileOut;
|
||||
|
||||
TACSFileCapTyp = (fcLoad,fcSave);
|
||||
TACSFileCapTyps = set of TACSFileCapTyp;
|
||||
|
||||
{ TACSFileFormat }
|
||||
|
||||
TACSFormatClass = class of TComponent;
|
||||
|
||||
TACSFileFormat = class
|
||||
public
|
||||
FileClass : TACSFormatClass;
|
||||
Extension : String;
|
||||
Description : String;
|
||||
end;
|
||||
|
||||
{ To this List all Filefomats must be added,
|
||||
use initialization section of your format units to add your format to acs
|
||||
so the user must only add your unit to the uses clausle to have support for
|
||||
your fileformat.
|
||||
}
|
||||
|
||||
{ tacsfileformatslist }
|
||||
|
||||
tacsfileformatslist = class (tlist)
|
||||
public
|
||||
destructor Destroy; override;
|
||||
procedure Add(const Ext, Desc: String; AClass: TACSFormatClass);
|
||||
function FindExt(ext : string;Typs : TACSFileCapTyps) : TACSFormatClass;
|
||||
function FindFromFileName(const fileName : String;Typs : TACSFileCapTyps) : TACSFormatClass;
|
||||
procedure Remove(AClass: TACSFormatClass);
|
||||
procedure BuildFilterStrings(var descriptions: String;Typs : TACSFileCapTyps);
|
||||
end;
|
||||
|
||||
{ This class is an wrapper for all fileformats
|
||||
}
|
||||
|
||||
{ TFileIn }
|
||||
|
||||
TACSFileIn = CLASS(TACSCustomFileIn)
|
||||
private
|
||||
FEndSample: Integer;
|
||||
FFileName: string;
|
||||
FInput : TACSCustomFileIn;
|
||||
FDialog : TOpenDialog;
|
||||
FLoop: Boolean;
|
||||
FStartSample: Integer;
|
||||
FTotalSamples: Integer;
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
function GetTime : Integer;
|
||||
function GetValid : Boolean;
|
||||
function GetTotalTime : real; override;
|
||||
procedure Reset; override;
|
||||
procedure SetFileName(const AValue : String);
|
||||
function GetSize : Integer;
|
||||
function GetPosition : Integer;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy;override;
|
||||
procedure Open;
|
||||
|
||||
procedure Flush; override;
|
||||
procedure Init; override;
|
||||
function Seek(SampleNum : Integer) : Boolean; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer;override;
|
||||
function SetStartTime(Minutes, Seconds : Integer) : Boolean;
|
||||
function SetEndTime(Minutes, Seconds : Integer) : Boolean;
|
||||
procedure Jump(Offs : real);
|
||||
property Time : Integer read GetTime;
|
||||
property TotalSamples : Integer read FTotalSamples;
|
||||
property Valid : Boolean read GetValid;
|
||||
property Size : Integer read GetSize;
|
||||
property Position : Integer read GetPosition;
|
||||
published
|
||||
property EndSample : Integer read FEndSample write FEndSample;
|
||||
property FileName : string read FFileName write SetFileName;
|
||||
property Loop : Boolean read FLoop write FLoop;
|
||||
property StartSample : Integer read FStartSample write FStartSample;
|
||||
end;
|
||||
|
||||
|
||||
{ This class is an wrapper for all fileformats
|
||||
}
|
||||
|
||||
{ TFileOut }
|
||||
|
||||
TACSFileOut = class(TComponent)
|
||||
private
|
||||
FBufferSize: Integer;
|
||||
FFileMode: TACSFileOutputMode;
|
||||
FFileName: string;
|
||||
FOnDone: TACSOutputDoneEvent;
|
||||
FOnProgress: TACSOutputProgressEvent;
|
||||
FOnThreadException: TACSThreadExceptionEvent;
|
||||
FOutput : TACSCustomFileOut;
|
||||
FDialog : TSaveDialog;
|
||||
FInput : TACSCustomInput;
|
||||
{$IFDEF LINUX}
|
||||
FAccessMask : Integer;
|
||||
{$ENDIF}
|
||||
function GetDelay: Integer;
|
||||
function GetPriority: TTPriority;
|
||||
function GetProgress: real;
|
||||
function GetStatus: TACSOutputStatus;
|
||||
function GetTE: Integer;
|
||||
procedure SetDelay(const AValue: Integer);
|
||||
procedure SetPriority(const AValue: TTPriority);
|
||||
|
||||
procedure ThreadException(Sender : TComponent;E : Exception);
|
||||
procedure OutputDone(Sender : TComponent);
|
||||
procedure OutputProgress(Sender : TComponent);
|
||||
protected
|
||||
FBaseChannel: Integer;
|
||||
procedure SetInput(vInput : TACSCustomInput);
|
||||
procedure Done;
|
||||
function DoOutput(Abort : Boolean):Boolean;
|
||||
procedure Prepare;
|
||||
procedure SetFileMode(aMode : TACSFileOutputMode); virtual;
|
||||
procedure SetFileName(const AValue: string);
|
||||
public
|
||||
destructor Destroy;override;
|
||||
procedure Open;
|
||||
property Buffersize : Integer read FBufferSize write FBufferSize;
|
||||
procedure Pause;virtual;
|
||||
procedure Resume;virtual;
|
||||
procedure Run;
|
||||
procedure Stop;
|
||||
property Delay : Integer read GetDelay write SetDelay;
|
||||
property ThreadPriority : TTPriority read GetPriority write SetPriority;
|
||||
property Progress : real read GetProgress;
|
||||
property Status : TACSOutputStatus read GetStatus;
|
||||
property TimeElapsed : Integer read GetTE;
|
||||
{$IFDEF LINUX}
|
||||
property AccessMask : Integer read FAccessMask write FAccessMask;
|
||||
{$ENDIF}
|
||||
published
|
||||
property FileMode : TACSFileOutputMode read FFileMode write SetFileMode;
|
||||
property FileName : string read FFileName write SetFileName;
|
||||
property Input : TACSCustomInput read FInput write SetInput;
|
||||
property OnDone : TACSOutputDoneEvent read FOnDone write FOndone;
|
||||
property OnProgress : TACSOutputProgressEvent read FOnProgress write FOnProgress;
|
||||
property OnThreadException : TACSThreadExceptionEvent read FOnThreadException write FOnThreadException;
|
||||
end;
|
||||
|
||||
var
|
||||
FileFormats : TACSFileFormatsList;
|
||||
|
||||
implementation
|
||||
|
||||
{ TFileIn }
|
||||
|
||||
function TACSFileIn.GetBPS: Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
Result := FInput.BitsPerSample;
|
||||
end;
|
||||
|
||||
function TACSFileIn.GetCh: Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
Result := FInput.Channels;
|
||||
end;
|
||||
|
||||
function TACSFileIn.GetSR: Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
Result := FInput.SampleRate;
|
||||
end;
|
||||
|
||||
function TACSFileIn.GetTime: Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
Result := FInput.Time;
|
||||
end;
|
||||
|
||||
function TACSFileIn.GetValid: Boolean;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
Result := FInput.Valid;
|
||||
end;
|
||||
|
||||
function TACSFileIn.GetTotalTime: real;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
exit;
|
||||
Result := FInput.TotalTime;
|
||||
end;
|
||||
|
||||
procedure TACSFileIn.Reset;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
FInput.Reset;
|
||||
end;
|
||||
|
||||
procedure TACSFileIn.SetFileName(const AValue: string);
|
||||
begin
|
||||
FFileName := AValue;
|
||||
if Assigned(FInput) then
|
||||
FInput.Free;
|
||||
FInput := nil;
|
||||
if AValue = '' then
|
||||
exit;
|
||||
FInput := TACSFileInClass(FileFormats.FindFromFileName(AValue,[fcLoad])).Create(nil);
|
||||
if Assigned(FInput) then
|
||||
FInput.FileName := FFilename;
|
||||
end;
|
||||
|
||||
function TACSFileIn.GetSize: Integer;
|
||||
begin
|
||||
Result := 1;
|
||||
if Assigned(FInput) then
|
||||
Result := FInput.Size;
|
||||
end;
|
||||
|
||||
function TACSFileIn.GetPosition: Integer;
|
||||
begin
|
||||
Result := 0;
|
||||
if Assigned(FInput) then
|
||||
Result := FInput.Position;
|
||||
end;
|
||||
|
||||
constructor TACSFileIn.Create(AOwner: TComponent);
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
end;
|
||||
|
||||
destructor TACSFileIn.Destroy;
|
||||
begin
|
||||
if Assigned(FInput) then
|
||||
FInput.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TACSFileIn.Open;
|
||||
var
|
||||
desc : string;
|
||||
begin
|
||||
FDialog := TOpenDialog.Create(nil);
|
||||
FileFormats.BuildFilterStrings(desc,[fcLoad]);
|
||||
FDialog.Filter := desc;
|
||||
if FDialog.Execute then
|
||||
begin
|
||||
if Assigned(FInput) then
|
||||
FInput.Free;
|
||||
FInput := TACSFileInClass(FileFormats.FindFromFileName(FDialog.FileName,[fcLoad])).Create(nil);
|
||||
FFileName := FDialog.FileName;
|
||||
if Assigned(FInput) then
|
||||
FInput.FileName := FFilename;
|
||||
end;
|
||||
FDialog.Free;
|
||||
end;
|
||||
|
||||
procedure TACSFileIn.Flush;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
FInput.Flush;
|
||||
end;
|
||||
|
||||
procedure TACSFileIn.Init;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
FInput.Init;
|
||||
end;
|
||||
|
||||
function TACSFileIn.Seek(SampleNum : Integer): Boolean;
|
||||
begin
|
||||
if not Assigned(Finput) then
|
||||
EACSException.Create(strnoFileOpened);
|
||||
FInput.Seek(SampleNum);
|
||||
end;
|
||||
|
||||
function TACSFileIn.GetData(Buffer: Pointer; BufferSize: Integer): Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
Result:=FInput.GetData(Buffer, BufferSize);
|
||||
end;
|
||||
|
||||
function TACSFileIn.SetStartTime(Minutes, Seconds: Integer): Boolean;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
Result := FInput.SetStartTime(Minutes,Seconds);
|
||||
end;
|
||||
|
||||
function TACSFileIn.SetEndTime(Minutes, Seconds: Integer): Boolean;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
Result := FInput.SetEndTime(Minutes,Seconds);
|
||||
end;
|
||||
|
||||
procedure TACSFileIn.Jump(Offs: real);
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
FInput.Jump(Offs);
|
||||
end;
|
||||
|
||||
{ TACSFileOut }
|
||||
|
||||
procedure TACSFileOut.SetFileName(const AValue: string);
|
||||
begin
|
||||
if FFileName=AValue then exit;
|
||||
if Assigned(FOutput) then
|
||||
FOutput.Free;
|
||||
FOutput := nil;
|
||||
FOutput := TACSFileOutClass(FileFormats.FindFromFileName(AValue,[fcSave])).Create(nil);
|
||||
if Assigned(FOutput) then
|
||||
begin
|
||||
FOutput.FileName:=AValue;
|
||||
foutput.FileMode := FFileMode; //GAK:20060731
|
||||
FOutput.Input := FInput;
|
||||
FOutput.OnDone := OutputDone;
|
||||
FOutput.OnProgress := OutputProgress;
|
||||
Foutput.OnThreadException := ThreadException;
|
||||
ffilename := avalue;//GAK:20060731
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TACSFileOut.Done;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
FOutput.Done;
|
||||
end;
|
||||
|
||||
function TACSFileOut.DoOutput(Abort: Boolean): Boolean;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
Result := FOutput.DoOutput(Abort);
|
||||
end;
|
||||
|
||||
procedure TACSFileOut.Prepare;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
FOutput.Prepare;
|
||||
end;
|
||||
|
||||
function TACSFileOut.GetDelay: Integer;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
result := FOutput.Delay;
|
||||
end;
|
||||
|
||||
function TACSFileOut.GetPriority: TTPriority;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
Result := FOutput.ThreadPriority;
|
||||
end;
|
||||
|
||||
function TACSFileOut.GetProgress: real;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
Result := FOutput.Progress;
|
||||
end;
|
||||
|
||||
function TACSFileOut.GetStatus: TACSOutputStatus;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
Result := FOutput.Status;
|
||||
end;
|
||||
|
||||
function TACSFileOut.GetTE: Integer;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
Result := FOutput.TimeElapsed;
|
||||
end;
|
||||
|
||||
procedure TACSFileOut.SetDelay(const AValue: Integer);
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
FOutput.Delay := AValue;
|
||||
end;
|
||||
|
||||
procedure TACSFileOut.SetPriority(const AValue: TTPriority);
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
FOutput.ThreadPriority := AValue;
|
||||
end;
|
||||
|
||||
procedure TACSFileOut.ThreadException(Sender : TComponent;E: Exception);
|
||||
begin
|
||||
if Assigned(OnThreadException) then
|
||||
OnThreadException(Sender,E);
|
||||
end;
|
||||
|
||||
procedure TACSFileOut.OutputDone(Sender: TComponent);
|
||||
begin
|
||||
if Assigned(OnDone) then
|
||||
OnDone(Sender);
|
||||
end;
|
||||
|
||||
procedure TACSFileOut.OutputProgress(Sender: TComponent);
|
||||
begin
|
||||
if Assigned(OnProgress) then
|
||||
OnProgress(Sender);
|
||||
end;
|
||||
|
||||
procedure TACSFileOut.SetInput(vInput: TACSCustomInput);
|
||||
begin
|
||||
FInput := vInput;
|
||||
if Assigned(FOutput) then
|
||||
FOutput.Input := FInput;
|
||||
end;
|
||||
|
||||
procedure TACSFileOut.SetFileMode(aMode: TACSFileOutputMode);
|
||||
begin
|
||||
//GAK:20060731 changed whole of this method, as it was stopping component loading/creating
|
||||
if amode <> ffilemode then
|
||||
begin
|
||||
FFileMode := amode;
|
||||
if Assigned(FOutput) then FOutput.FileMode := aMode;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TACSFileOut.Open;
|
||||
var
|
||||
desc : string;
|
||||
|
||||
begin
|
||||
FDialog := TSaveDialog.Create(nil);
|
||||
FileFormats.BuildFilterStrings(desc,[fcSave]);
|
||||
FDialog.Filter := desc;
|
||||
if FDialog.Execute then
|
||||
begin
|
||||
FOutput := TACSFileOutClass(FileFormats.FindFromFileName(FDialog.FileName,[fcSave])).Create(nil);
|
||||
FileName := FDialog.FileName;
|
||||
foutput.FileMode := ffilemode;
|
||||
FOutput.Input := FInput;
|
||||
FInput := FInput;
|
||||
FOutput.OnDone := OutputDone;
|
||||
FOutput.OnProgress := OutputProgress;
|
||||
Foutput.OnThreadException := ThreadException;
|
||||
end;
|
||||
FDialog.Free;
|
||||
end;
|
||||
|
||||
procedure TACSFileOut.Pause;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
FOutput.Pause;
|
||||
end;
|
||||
|
||||
procedure TACSFileOut.Resume;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
FOutput.Resume;
|
||||
end;
|
||||
|
||||
procedure TACSFileOut.Run;
|
||||
begin
|
||||
if not Assigned(FOutput) then
|
||||
raise EACSException.Create(strNoFileOpened);
|
||||
FOutput.Run;
|
||||
end;
|
||||
|
||||
procedure TACSFileOut.Stop;
|
||||
begin
|
||||
if Assigned(FOutput) then
|
||||
FOutput.Stop;
|
||||
end;
|
||||
|
||||
destructor TACSFileOut.Destroy;
|
||||
begin
|
||||
if Assigned(FOutput) then
|
||||
FOutput.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
{ TACSFileFormatsList }
|
||||
|
||||
destructor tacsfileformatslist.Destroy;
|
||||
var
|
||||
i: integer;
|
||||
begin
|
||||
for i:= 0 to Count-1 do
|
||||
TACSFileFormat(Items[i]).Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TACSFileFormatsList.Add(const Ext, Desc: String;AClass: TACSFormatClass);
|
||||
var
|
||||
newRec : TACSFileFormat;
|
||||
begin
|
||||
newRec:=TACSFileFormat.Create;
|
||||
with newRec do
|
||||
begin
|
||||
Extension:=LowerCase(Ext);
|
||||
FileClass:=AClass;
|
||||
Description:=Desc;
|
||||
end;
|
||||
inherited Add(newRec);
|
||||
end;
|
||||
|
||||
function TACSFileFormatsList.FindExt(ext: string;Typs : TACSFileCapTyps): TACSFormatClass;
|
||||
var
|
||||
i : Integer;
|
||||
begin
|
||||
ext:=LowerCase(ext);
|
||||
for i:=Count-1 downto 0 do
|
||||
with TACSFileFormat(Items[I]) do
|
||||
begin
|
||||
if ((fcLoad in Typs) and (TACSFileFormat(Items[I]).FileClass.InheritsFrom(TACSCustomFileIn))) or ((fcSave in Typs) and (TACSFileFormat(Items[I]).FileClass.InheritsFrom(TACSCustomFileOut))) then
|
||||
if Extension=ext then
|
||||
begin
|
||||
Result:=TACSFileFormat(Items[I]).FileClass;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
Result:=nil;
|
||||
end;
|
||||
|
||||
function TACSFileFormatsList.FindFromFileName(const fileName: String;Typs : TACSFileCapTyps): TACSFormatClass;
|
||||
var
|
||||
ext : String;
|
||||
begin
|
||||
ext:=ExtractFileExt(Filename);
|
||||
System.Delete(ext, 1, 1);
|
||||
Result:=FindExt(ext,Typs);
|
||||
if not Assigned(Result) then
|
||||
raise EACSException.CreateFmt(strUnknownExtension, [ext]);
|
||||
end;
|
||||
|
||||
procedure TACSFileFormatsList.Remove(AClass: TACSFormatClass);
|
||||
var
|
||||
i : Integer;
|
||||
begin
|
||||
for i:=Count-1 downto 0 do begin
|
||||
if TACSFileFormat(Items[i]).FileClass.InheritsFrom(AClass) then
|
||||
begin
|
||||
TACSFileFormat(Items[i]).Free;
|
||||
Delete(i);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TACSFileFormatsList.BuildFilterStrings(var descriptions : String;Typs : TACSFileCapTyps);
|
||||
var
|
||||
k, i : Integer;
|
||||
p : TACSFileFormat;
|
||||
filters : string;
|
||||
begin
|
||||
descriptions:='';
|
||||
filters := '';
|
||||
k:=0;
|
||||
for i:=0 to Count-1 do
|
||||
begin
|
||||
p:=TACSFileFormat(Items[i]);
|
||||
if ((fcLoad in Typs) and (p.FileClass.InheritsFrom(TACSCustomFileIn))) or ((fcSave in Typs) and (p.FileClass.InheritsFrom(TACSCustomFileOut))) then
|
||||
with p do
|
||||
begin
|
||||
if k<>0 then
|
||||
begin
|
||||
descriptions:=descriptions+'|';
|
||||
filters := filters+';';
|
||||
end;
|
||||
descriptions:=descriptions+Description+' (*.'+Extension+')|'+'*.'+Extension;
|
||||
filters := filters+'*.'+Extension;
|
||||
Inc(k);
|
||||
end;
|
||||
end;
|
||||
descriptions := strAllFormats+'|'+filters+'|'+descriptions;
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
||||
FileFormats := TACSFileFormatsList.Create;
|
||||
|
||||
finalization
|
||||
|
||||
FileFormats.Free;
|
||||
|
||||
end.
|
||||
|
||||
772
acs/Src/classes/acs_filters.pas
Normal file
772
acs/Src/classes/acs_filters.pas
Normal file
@@ -0,0 +1,772 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.3.
|
||||
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: acs_filters.pas,v $
|
||||
Revision 1.4 2006/08/31 20:10:54 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.3 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.1 2005/12/19 18:34:35 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.3 2005/12/04 16:54:33 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.2 2005/09/13 21:54:11 z0m3ie
|
||||
acs is localizeable now (ACS_Strings)
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
unit acs_filters;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, ACS_Types, ACS_Procs, ACS_Classes, ACS_Strings, Math;
|
||||
|
||||
const
|
||||
BUF_SIZE = $4000;
|
||||
|
||||
type
|
||||
|
||||
TACSFilterType = (ftBandPass, ftBandReject, ftHighPass, ftLowPass, ftAllPass);
|
||||
|
||||
TACSBWFilter = class(TACSCustomConverter)
|
||||
private
|
||||
a3 : array[0..2] of Double;
|
||||
b2 : array[0..1] of Double;
|
||||
x0, x1, y0, y1 : array[0..1] of Double;
|
||||
FLowFreq, FHighFreq : Integer;
|
||||
FAmplification : Word;
|
||||
FFilterType : TACSFilterType;
|
||||
InBuf : array[1..BUF_SIZE] of Byte;
|
||||
procedure SetHighFreq(aFreq : Integer);
|
||||
procedure SetLowFreq(aFreq : Integer);
|
||||
procedure SetAmplification(Ampl : Word);
|
||||
protected
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
published
|
||||
property Amplification : Word read FAmplification write SetAmplification;
|
||||
property FilterType : TACSFilterType read FFilterType write FFilterType;
|
||||
property HighFreq : Integer read FHighFreq write SetHighFreq;
|
||||
property LowFreq : Integer read FLowFreq write SetLowFreq;
|
||||
end;
|
||||
|
||||
TACSSincFilter = class(TACSCustomConverter)
|
||||
private
|
||||
Lock : Boolean;
|
||||
Kernel : array of Double;
|
||||
DA : PACSDoubleArray;
|
||||
DAS : PACSStereoBufferD;
|
||||
inBuf : array[1..BUF_SIZE] of Byte;
|
||||
FFilterType : TACSFilterType;
|
||||
FKernelWidth : Integer;
|
||||
FLowFreq, FHighFreq : Integer;
|
||||
FWindowType : TACSFilterWindowType;
|
||||
procedure SetFilterType(aFT : TACSFilterType);
|
||||
procedure SetKernelWidth(aKW : Integer);
|
||||
procedure SetWindowType(aWT : TACSFilterWindowType);
|
||||
procedure SetHighFreq(aFreq : Integer);
|
||||
procedure SetLowFreq(aFreq : Integer);
|
||||
procedure CalculateFilter;
|
||||
protected
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
procedure GetKernel(var K : PACSDoubleArray);
|
||||
published
|
||||
property FilterType : TACSFilterType read FFilterType write SetFilterType;
|
||||
property HighFreq : Integer read FHighFreq write SetHighFreq;
|
||||
property KernelWidth : Integer read FKernelWidth write SetKernelWidth;
|
||||
property LowFreq : Integer read FLowFreq write SetLowFreq;
|
||||
property WindowType : TACSFilterWindowType read FWindowType write SetWindowType;
|
||||
end;
|
||||
|
||||
TACSConvolver = class(TACSCustomConverter)
|
||||
private
|
||||
Lock : Boolean;
|
||||
Kernel : array of Double;
|
||||
DA : PACSDoubleArray;
|
||||
DAS : PACSStereoBufferD;
|
||||
inBuf : array[1..BUF_SIZE] of Byte;
|
||||
FKernelWidth : Integer;
|
||||
FAllPass : Boolean;
|
||||
procedure SetKernelWidth(a : Integer);
|
||||
protected
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
procedure SetKernel(K : PACSDoubleArray; Inverted : Boolean);
|
||||
property KrenelWidth : Integer read FKernelWidth write SetKernelWidth;
|
||||
published
|
||||
property AllPass : Boolean read FAllPass write FAllPass;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
constructor TACSBWFilter.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FFilterType := ftBandPass;
|
||||
FAmplification := 1;
|
||||
end;
|
||||
|
||||
destructor TACSBWFilter.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TACSBWFilter.GetBPS : Integer;
|
||||
begin
|
||||
Result := 16;
|
||||
end;
|
||||
|
||||
function TACSBWFilter.GetCh : Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
Result := FInput.Channels;
|
||||
end;
|
||||
|
||||
function TACSBWFilter.GetSR : Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
Result := FInput.SampleRate;
|
||||
end;
|
||||
|
||||
procedure TACSBWFilter.SetHighFreq;
|
||||
begin
|
||||
if FFilterType = ftLowPass then
|
||||
FHighFreq := 0
|
||||
else FHighFreq := aFreq;
|
||||
end;
|
||||
|
||||
procedure TACSBWFilter.SetLowFreq;
|
||||
begin
|
||||
if FFilterType = ftHighPass then
|
||||
FLowFreq := 0
|
||||
else FLowFreq := aFreq;
|
||||
end;
|
||||
|
||||
procedure TACSBWFilter.SetAmplification;
|
||||
begin
|
||||
if Ampl > 0 then FAmplification := Ampl;
|
||||
end;
|
||||
|
||||
procedure TACSBWFilter.Init;
|
||||
var
|
||||
C, D : Double;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
FInput.Init;
|
||||
if ((FHighFreq - FlowFreq) < 0) or (((FHighFreq - FlowFreq) * 2) >= FInput.SampleRate) then
|
||||
begin
|
||||
FInput.Flush;
|
||||
raise EACSException.Create(strIllegalFrequency);
|
||||
end;
|
||||
FBusy := True;
|
||||
FPosition := 0;
|
||||
BufStart := 1;
|
||||
BufEnd := 0;
|
||||
FSize := FInput.Size;
|
||||
x0[0] := 0.0;
|
||||
x0[1] := 0.0;
|
||||
x1[0] := 0.0;
|
||||
x1[1] := 0.0;
|
||||
y0[0] := 0.0;
|
||||
y0[1] := 0.0;
|
||||
y1[0] := 0.0;
|
||||
y1[1] := 0.0;
|
||||
case FFilterType of
|
||||
ftBandPass :
|
||||
begin
|
||||
C := 1 / Tan(Pi * (FHighFreq-FLowFreq+1) / FInput.SampleRate);
|
||||
D := 2 * Cos(2 * Pi * ((FHighFreq+FLowFreq) shr 1) / FInput.SampleRate);
|
||||
a3[0] := 1 / (1 + C);
|
||||
a3[1] := 0.0;
|
||||
a3[2] := -a3[0];
|
||||
b2[0] := -C * D * a3[0];
|
||||
b2[1] := (C - 1) * a3[0];
|
||||
end;
|
||||
ftBandReject: // This doesn't seem to work well
|
||||
begin
|
||||
C := Tan(Pi * (FHighFreq-FLowFreq+1) / FInput.SampleRate);
|
||||
D := 2 * Cos(2 * Pi * ((FHighFreq+FLowFreq) shr 1) / FInput.SampleRate);
|
||||
a3[0] := 1 / (1 + C);
|
||||
a3[1] := -D * a3[0];
|
||||
a3[2] := a3[0];
|
||||
b2[0] := a3[1];
|
||||
b2[1] := (1 - C) * a3[0];
|
||||
end;
|
||||
ftLowPass:
|
||||
begin
|
||||
C := 1 / Tan(Pi * FLowFreq / FInput.SampleRate);
|
||||
a3[0] := 1 / (1 + Sqrt(2) * C + C * C);
|
||||
a3[1] := 2 * a3[0];
|
||||
a3[2] := a3[0];
|
||||
b2[0] := 2 * (1 - C * C) * a3[0];
|
||||
b2[1] := (1 - Sqrt(2) * C + C * C) * a3[0];
|
||||
end;
|
||||
ftHighPass:
|
||||
begin
|
||||
C := Tan(Pi * FHighFreq / FInput.SampleRate);
|
||||
a3[0] := 1 / (1 + Sqrt(2) * C + C * C);
|
||||
a3[1] := -2 * a3[0];
|
||||
a3[2] := a3[0];
|
||||
b2[0] := 2 * (C * C - 1) * a3[0];
|
||||
b2[1] := (1 - Sqrt(2) * C + C * C) * a3[0];
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TACSBWFilter.Flush;
|
||||
begin
|
||||
FInput.Flush;
|
||||
FBusy := False;
|
||||
end;
|
||||
|
||||
function TACSBWFilter.GetData(Buffer : Pointer; BufferSize : Integer): Integer;
|
||||
var
|
||||
i : Integer;
|
||||
InBufMono : PACSBuffer16;
|
||||
InBufStereo : PACSStereoBuffer16;
|
||||
arg, res : Double;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create(strStreamnotopen);
|
||||
if BufStart > BufEnd then
|
||||
begin
|
||||
BufStart := 1;
|
||||
BufEnd := FInput.GetData(@InBuf[1], BUF_SIZE);
|
||||
if BufEnd = 0 then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
if Self.Channels = 1 then
|
||||
begin
|
||||
InBufMono := @InBuf[1];
|
||||
for i := 0 to (BufEnd shr 1) - 1 do
|
||||
begin
|
||||
arg := InBufMono[i];
|
||||
res := a3[0] * arg + a3[1] * x0[0] + a3[2] * x1[0] -
|
||||
b2[0] * y0[0] - b2[1] * y1[0];
|
||||
InBufMono[i] := Round(res);
|
||||
x1[0] := x0[0];
|
||||
x0[0] := arg;
|
||||
y1[0] := y0[0];
|
||||
y0[0] := res;
|
||||
InBufMono[i] := FAmplification * InBufMono[i];
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
InBufStereo := @InBuf[1];
|
||||
for i := 0 to (BufEnd shr 2) - 1 do
|
||||
begin
|
||||
arg := InBufStereo[i].Left;
|
||||
res := a3[0] * arg + a3[1] * x0[0] + a3[2] * x1[0] -
|
||||
b2[0] * y0[0] - b2[1] * y1[0];
|
||||
InBufStereo[i].Left := Round(res);
|
||||
x1[0] := x0[0];
|
||||
x0[0] := arg;
|
||||
y1[0] := y0[0];
|
||||
y0[0] := res;
|
||||
arg := InBufStereo[i].Right;
|
||||
res := a3[0] * arg + a3[1] * x0[1] + a3[2] * x1[1] -
|
||||
b2[0] * y0[1] - b2[1] * y1[1];
|
||||
InBufStereo[i].Right := Round(res);
|
||||
x1[1] := x0[1];
|
||||
x0[1] := arg;
|
||||
y1[1] := y0[1];
|
||||
y0[1] := res;
|
||||
InBufStereo[i].Right := FAmplification * InBufStereo[i].Right;
|
||||
InBufStereo[i].Left := FAmplification * InBufStereo[i].Left;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if BufferSize < (BufEnd - BufStart + 1)
|
||||
then Result := BufferSize
|
||||
else Result := BufEnd - BufStart + 1;
|
||||
Move(InBuf[BufStart], Buffer^, Result);
|
||||
Inc(BufStart, Result);
|
||||
FPosition := Round(FInput.Position*(FSize/FInput.Size));
|
||||
// Inc(FPosition, Result);
|
||||
end;
|
||||
|
||||
constructor TACSSincFilter.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FKernelWidth := 31;
|
||||
FWindowType := fwBlackman;
|
||||
FLowFreq := 8000;
|
||||
FHighFreq := 16000;
|
||||
DA := nil;
|
||||
DAS := nil;
|
||||
end;
|
||||
|
||||
destructor TACSSincFilter.Destroy;
|
||||
begin
|
||||
Kernel := nil;
|
||||
if DA <> nil then FreeMem(DA);
|
||||
if DAS <> nil then FreeMem(DAS);
|
||||
Inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TACSSincFilter.CalculateFilter;
|
||||
var
|
||||
Kernel1, Kernel2 : array of Double;
|
||||
CutOff : Double;
|
||||
i, j : Integer;
|
||||
Sum : Double;
|
||||
begin
|
||||
if csDesigning in ComponentState then Exit;
|
||||
if not Assigned(FInput) then Exit;
|
||||
if (FLowFreq > FInput.SampleRate/2) or (FHighFreq > FInput.SampleRate/2) then
|
||||
raise EACSException.Create(strCutofftolow);
|
||||
while Lock do;
|
||||
Lock := True;
|
||||
case FilterType of
|
||||
ftLowPass:
|
||||
begin
|
||||
SetLength(Kernel, FKernelWidth);
|
||||
CutOff := FLowFreq/FInput.SampleRate;
|
||||
CalculateSincKernel(@Kernel[0], CutOff, FKernelWidth, FWindowType);
|
||||
end;
|
||||
ftHighPass:
|
||||
begin
|
||||
if not Odd(FKernelWidth) then Inc(FKernelWidth);
|
||||
SetLength(Kernel, FKernelWidth);
|
||||
CutOff := FHighFreq/FInput.SampleRate;
|
||||
CalculateSincKernel(@Kernel[0], CutOff, FKernelWidth, FWindowType);
|
||||
for i := 0 to FKernelWidth - 1 do
|
||||
Kernel[i] := -Kernel[i];
|
||||
Kernel[(FKernelWidth shr 1)] := Kernel[(FKernelWidth shr 1)] + 1;
|
||||
end;
|
||||
ftBandPass:
|
||||
begin
|
||||
if not Odd(FKernelWidth) then Inc(FKernelWidth);
|
||||
SetLength(Kernel1, FKernelWidth);
|
||||
CutOff := FLowFreq/FInput.SampleRate;
|
||||
CalculateSincKernel(@Kernel1[0], CutOff, FKernelWidth, FWindowType);
|
||||
for i := 0 to FKernelWidth - 1 do
|
||||
Kernel1[i] := -Kernel1[i];
|
||||
Kernel1[(FKernelWidth shr 1)] := Kernel1[(FKernelWidth shr 1)] + 1;
|
||||
SetLength(Kernel2, FKernelWidth);
|
||||
CutOff := FHighFreq/FInput.SampleRate;
|
||||
CalculateSincKernel(@Kernel2[0], CutOff, FKernelWidth, FWindowType);
|
||||
SetLength(Kernel, 2*FKernelWidth);
|
||||
FillChar(Kernel[0], Length(Kernel)*SizeOf(Double), 0);
|
||||
for i := 0 to KernelWidth - 1 do
|
||||
for j := 0 to KernelWidth - 1 do
|
||||
Kernel[i+j] := Kernel[i+j] + Kernel1[i]*Kernel2[j];
|
||||
SetLength(Kernel, FKernelWidth);
|
||||
Kernel1 := nil;
|
||||
Kernel2 := nil;
|
||||
end;
|
||||
ftBandReject:
|
||||
begin
|
||||
if not Odd(FKernelWidth) then Inc(FKernelWidth);
|
||||
SetLength(Kernel1, FKernelWidth);
|
||||
CutOff := FHighFreq/FInput.SampleRate;
|
||||
CalculateSincKernel(@Kernel1[0], CutOff, FKernelWidth, FWindowType);
|
||||
for i := 0 to FKernelWidth - 1 do
|
||||
Kernel1[i] := -Kernel1[i];
|
||||
Kernel1[(FKernelWidth shr 1)] := Kernel1[(FKernelWidth shr 1)] + 1;
|
||||
SetLength(Kernel2, FKernelWidth);
|
||||
CutOff := FLowFreq/FInput.SampleRate;
|
||||
CalculateSincKernel(@Kernel2[0], CutOff, FKernelWidth, FWindowType);
|
||||
SetLength(Kernel, FKernelWidth);
|
||||
for i := 0 to FKernelWidth - 1 do
|
||||
Kernel[i] := Kernel1[i] + Kernel2[i];
|
||||
Kernel1 := nil;
|
||||
Kernel2 := nil;
|
||||
end;
|
||||
ftAllPass :
|
||||
begin
|
||||
SetLength(Kernel, FKernelWidth);
|
||||
FillChar(Kernel[0], Length(Kernel)*SizeOf(Double), 0);
|
||||
Kernel[FKernelWidth shr 1] := 1;
|
||||
end;
|
||||
end;
|
||||
Lock := False;
|
||||
end;
|
||||
|
||||
procedure TACSSincFilter.SetFilterType;
|
||||
begin
|
||||
FFilterType := aFT;
|
||||
if Busy then CalculateFilter;
|
||||
end;
|
||||
|
||||
procedure TACSSincFilter.SetKernelWidth;
|
||||
begin
|
||||
if aKW > 2 then
|
||||
if not Busy then FKernelWidth := aKW;
|
||||
end;
|
||||
|
||||
procedure TACSSincFilter.SetWindowType;
|
||||
begin
|
||||
FWindowType := aWT;
|
||||
if Busy then CalculateFilter;
|
||||
end;
|
||||
|
||||
procedure TACSSincFilter.SetHighFreq;
|
||||
begin
|
||||
if aFreq > 0 then
|
||||
FHighFreq := aFreq;
|
||||
if csDesigning in ComponentState then Exit;
|
||||
if Assigned(Finput) then
|
||||
if FHighFreq > Finput.SampleRate div 2 then
|
||||
FHighFreq := Finput.SampleRate div 2;
|
||||
if FHighFreq < FLowFreq then
|
||||
FLowFreq := FHighFreq;
|
||||
if Busy then CalculateFilter;
|
||||
end;
|
||||
|
||||
procedure TACSSincFilter.SetLowFreq;
|
||||
begin
|
||||
if aFreq > 0 then
|
||||
FLowFreq := aFreq;
|
||||
if csDesigning in ComponentState then Exit;
|
||||
if Assigned(Finput) then
|
||||
if FlowFreq > Finput.SampleRate div 2 then
|
||||
FLowFreq := Finput.SampleRate div 2;
|
||||
if FHighFreq < FLowFreq then
|
||||
FHighFreq := FLowFreq;
|
||||
if Busy then CalculateFilter;
|
||||
end;
|
||||
|
||||
function TACSSincFilter.GetBPS : Integer;
|
||||
begin
|
||||
if not Assigned(Input) then
|
||||
raise EACSException.Create(strInputnotassigned);
|
||||
Result := FInput.BitsPerSample;
|
||||
end;
|
||||
|
||||
function TACSSincFilter.GetCh : Integer;
|
||||
begin
|
||||
if not Assigned(Input) then
|
||||
raise EACSException.Create(strInputnotassigned);
|
||||
Result := FInput.Channels;
|
||||
end;
|
||||
|
||||
function TACSSincFilter.GetSR : Integer;
|
||||
begin
|
||||
if not Assigned(Input) then
|
||||
raise EACSException.Create(strInputnotassigned);
|
||||
Result := FInput.SampleRate;
|
||||
end;
|
||||
|
||||
procedure TACSSincFilter.Init;
|
||||
begin
|
||||
if not Assigned(Input) then
|
||||
raise EACSException.Create(strInputnotassigned);
|
||||
Lock := False;
|
||||
InputLock := False;
|
||||
FBusy := True;
|
||||
FInput.Init;
|
||||
FPosition := 0;
|
||||
CalculateFilter;
|
||||
if FInput.Channels = 1 then
|
||||
begin
|
||||
GetMem(DA, ((BUF_SIZE div 2)+FKernelWidth-1)*SizeOf(Double));
|
||||
FillChar(DA[0], ((BUF_SIZE div 2)+FKernelWidth-1)*SizeOf(Double), 0);
|
||||
end else
|
||||
begin
|
||||
GetMem(DAS, ((BUF_SIZE div 2)+(FKernelWidth-1)*2)*SizeOf(Double));
|
||||
FillChar(DAS[0], ((BUF_SIZE div 2)+(FKernelWidth-1)*2)*SizeOf(Double), 0);
|
||||
end;
|
||||
BufStart := 1;
|
||||
BufEnd := 0;
|
||||
FSize := FInput.Size;
|
||||
end;
|
||||
|
||||
procedure TACSSincFilter.Flush;
|
||||
begin
|
||||
FInput.Flush;
|
||||
if DA <> nil then FreeMem(DA);
|
||||
if DAS <> nil then FreeMem(DAS);
|
||||
DA := nil;
|
||||
DAS := nil;
|
||||
FBusy := False;
|
||||
end;
|
||||
|
||||
function TACSSincFilter.GetData(Buffer : Pointer; BufferSize : Integer): Integer;
|
||||
var
|
||||
i, j, NumSamples : Integer;
|
||||
InBufMono : PACSBuffer16;
|
||||
InBufStereo : PACSStereoBuffer16;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create(strStreamnotopen);
|
||||
if BufStart > BufEnd then
|
||||
begin
|
||||
while Lock do;
|
||||
Lock := True;
|
||||
BufStart := 1;
|
||||
while InputLock do;
|
||||
InputLock := True;
|
||||
BufEnd := FInput.GetData(@InBuf[1], BUF_SIZE);
|
||||
InputLock := False;
|
||||
if BufEnd = 0 then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
if FInput.Channels = 1 then
|
||||
begin
|
||||
InBufMono := @InBuf[1];
|
||||
NumSamples := BufEnd div 2;
|
||||
for i := 0 to NumSamples-1 do
|
||||
for j := 0 to FKernelWidth-1 do
|
||||
DA[i+j] := DA[i+j] + InbufMono[i]*Kernel[j];
|
||||
for i := 0 to NumSamples-1 do
|
||||
InBufMono[i] := Round(DA[i]);
|
||||
BufEnd := NumSamples*2;
|
||||
FillChar(DA[0], NumSamples*SizeOf(Double), 0);
|
||||
Move(DA[NumSamples], DA[0], (FKernelWidth-1)*SizeOf(Double));
|
||||
end else
|
||||
begin
|
||||
InBufStereo := @InBuf[1];
|
||||
NumSamples := BufEnd div 4;
|
||||
for i := 0 to NumSamples-1 do
|
||||
for j := 0 to FKernelWidth-1 do
|
||||
begin
|
||||
DAS[i+j].Left := DAS[i+j].Left + InbufStereo[i].Left*Kernel[j];
|
||||
DAS[i+j].Right := DAS[i+j].Right + InbufStereo[i].Right*Kernel[j];
|
||||
end;
|
||||
for i := 0 to NumSamples-1 do
|
||||
begin
|
||||
InBufStereo[i].Left := Round(DAS[i].Left);
|
||||
InBufStereo[i].Right := Round(DAS[i].Right);
|
||||
end;
|
||||
BufEnd := NumSamples*4;
|
||||
FillChar(DAS[0], NumSamples*2*SizeOf(Double), 0);
|
||||
for i := 0 to FKernelWidth-2 do
|
||||
begin
|
||||
DAS[i] := DAS[NumSamples+i];
|
||||
DAS[NumSamples+i].Left := 0;
|
||||
DAS[NumSamples+i].Right := 0;
|
||||
end;
|
||||
//Move(DAS[NumSamples], DAS[0], (FKernelWidth-1)*2*SizeOf(Double));
|
||||
end;
|
||||
Lock := False;
|
||||
end;
|
||||
if BufferSize < (BufEnd - BufStart + 1)
|
||||
then Result := BufferSize
|
||||
else Result := BufEnd - BufStart + 1;
|
||||
Move(InBuf[BufStart], Buffer^, Result);
|
||||
Inc(BufStart, Result);
|
||||
FPosition := Round(FInput.Position*(FSize/FInput.Size));
|
||||
end;
|
||||
|
||||
procedure TACSSincFilter.GetKernel;
|
||||
begin
|
||||
K := @Kernel[0];
|
||||
end;
|
||||
|
||||
constructor TACSConvolver.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FKernelWidth := 31;
|
||||
if csDesigning in ComponentState then Exit;
|
||||
SetLength(Kernel, FKernelWidth);
|
||||
FillChar(Kernel[1], Length(Kernel)*SizeOf(Double), 0);
|
||||
DA := nil;
|
||||
DAS := nil;
|
||||
end;
|
||||
|
||||
destructor TACSConvolver.Destroy;
|
||||
begin
|
||||
Kernel := nil;
|
||||
if DA <> nil then FreeMem(DA);
|
||||
if DAS <> nil then FreeMem(DAS);
|
||||
Inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TACSConvolver.SetKernelWidth;
|
||||
begin
|
||||
if a > 2 then
|
||||
if not Busy then FKernelWidth := a;
|
||||
end;
|
||||
|
||||
function TACSConvolver.GetBPS : Integer;
|
||||
begin
|
||||
if not Assigned(Input) then
|
||||
raise EACSException.Create(strInputnotassigned);
|
||||
Result := FInput.BitsPerSample;
|
||||
end;
|
||||
|
||||
function TACSConvolver.GetCh : Integer;
|
||||
begin
|
||||
if not Assigned(Input) then
|
||||
raise EACSException.Create(strInputnotassigned);
|
||||
Result := FInput.Channels;
|
||||
end;
|
||||
|
||||
function TACSConvolver.GetSR : Integer;
|
||||
begin
|
||||
if not Assigned(Input) then
|
||||
raise EACSException.Create(strInputnotassigned);
|
||||
Result := FInput.SampleRate;
|
||||
end;
|
||||
|
||||
procedure TACSConvolver.Init;
|
||||
begin
|
||||
if not Assigned(Input) then
|
||||
raise EACSException.Create(strInputnotassigned);
|
||||
Lock := False;
|
||||
InputLock := False;
|
||||
FBusy := True;
|
||||
FInput.Init;
|
||||
FPosition := 0;
|
||||
if FInput.Channels = 1 then
|
||||
begin
|
||||
GetMem(DA, ((BUF_SIZE div 2)+FKernelWidth-1)*SizeOf(Double));
|
||||
FillChar(DA[0], ((BUF_SIZE div 2)+FKernelWidth-1)*SizeOf(Double), 0);
|
||||
end else
|
||||
begin
|
||||
GetMem(DAS, ((BUF_SIZE div 2)+(FKernelWidth-1)*2)*SizeOf(Double));
|
||||
FillChar(DAS[0], ((BUF_SIZE div 2)+(FKernelWidth-1)*2)*SizeOf(Double), 0);
|
||||
end;
|
||||
BufStart := 1;
|
||||
BufEnd := 0;
|
||||
FSize := FInput.Size;
|
||||
end;
|
||||
|
||||
procedure TACSConvolver.Flush;
|
||||
begin
|
||||
FInput.Flush;
|
||||
if DA <> nil then FreeMem(DA);
|
||||
if DAS <> nil then FreeMem(DAS);
|
||||
DA := nil;
|
||||
DAS := nil;
|
||||
FBusy := False;
|
||||
end;
|
||||
|
||||
function TACSConvolver.GetData(Buffer : Pointer; BufferSize : Integer): Integer;
|
||||
var
|
||||
i, j, NumSamples : Integer;
|
||||
InBufMono : PACSBuffer16;
|
||||
InBufStereo : PACSStereoBuffer16;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create(strStreamNotopen);
|
||||
if BufStart > BufEnd then
|
||||
begin
|
||||
while Lock do;
|
||||
Lock := True;
|
||||
BufStart := 1;
|
||||
while InputLock do;
|
||||
InputLock := True;
|
||||
BufEnd := FInput.GetData(@InBuf[1], BUF_SIZE);
|
||||
InputLock := False;
|
||||
if BufEnd = 0 then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
if not FAllPass then
|
||||
begin
|
||||
if FInput.Channels = 1 then
|
||||
begin
|
||||
InBufMono := @InBuf[1];
|
||||
NumSamples := BufEnd div 2;
|
||||
for i := 0 to NumSamples-1 do
|
||||
for j := 0 to FKernelWidth-1 do
|
||||
DA[i+j] := DA[i+j] + InbufMono[i]*Kernel[j];
|
||||
for i := 0 to NumSamples-1 do
|
||||
InBufMono[i] := Round(DA[i]);
|
||||
BufEnd := NumSamples*2;
|
||||
FillChar(DA[0], NumSamples*SizeOf(Double), 0);
|
||||
Move(DA[NumSamples], DA[0], (FKernelWidth-1)*SizeOf(Double));
|
||||
end else
|
||||
begin
|
||||
InBufStereo := @InBuf[1];
|
||||
NumSamples := BufEnd div 4;
|
||||
for i := 0 to NumSamples-1 do
|
||||
for j := 0 to FKernelWidth-1 do
|
||||
begin
|
||||
DAS[i+j].Left := DAS[i+j].Left + InbufStereo[i].Left*Kernel[j];
|
||||
DAS[i+j].Right := DAS[i+j].Right + InbufStereo[i].Right*Kernel[j];
|
||||
end;
|
||||
for i := 0 to NumSamples-1 do
|
||||
begin
|
||||
InBufStereo[i].Left := Round(DAS[i].Left);
|
||||
InBufStereo[i].Right := Round(DAS[i].Right);
|
||||
end;
|
||||
BufEnd := NumSamples*4;
|
||||
FillChar(DAS[0], NumSamples*2*SizeOf(Double), 0);
|
||||
for i := 0 to FKernelWidth-2 do
|
||||
begin
|
||||
DAS[i] := DAS[NumSamples+i];
|
||||
DAS[NumSamples+i].Left := 0;
|
||||
DAS[NumSamples+i].Right := 0;
|
||||
end;
|
||||
//Move(DAS[NumSamples], DAS[0], (FKernelWidth-1)*2*SizeOf(Double));
|
||||
end;
|
||||
end;
|
||||
Lock := False;
|
||||
end;
|
||||
if BufferSize < (BufEnd - BufStart + 1)
|
||||
then Result := BufferSize
|
||||
else Result := BufEnd - BufStart + 1;
|
||||
Move(InBuf[BufStart], Buffer^, Result);
|
||||
Inc(BufStart, Result);
|
||||
FPosition := Round(FInput.Position*(FSize/FInput.Size));
|
||||
end;
|
||||
|
||||
procedure TACSConvolver.SetKernel;
|
||||
var
|
||||
i : Integer;
|
||||
begin
|
||||
while Lock do;
|
||||
Lock := True;
|
||||
if not Inverted then
|
||||
for i := 0 to FKernelWidth - 1 do
|
||||
Kernel[i] := K[i]
|
||||
else
|
||||
for i := 0 to FKernelWidth - 1 do
|
||||
Kernel[i] := K[FKernelWidth - 1-i];
|
||||
Lock := False;
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
207
acs/Src/classes/acs_indicator.pas
Normal file
207
acs/Src/classes/acs_indicator.pas
Normal file
@@ -0,0 +1,207 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.3.
|
||||
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: acs_indicator.pas,v $
|
||||
Revision 1.2 2006/08/31 20:10:54 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/12/19 18:34:35 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.4 2005/12/04 16:54:33 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.3 2005/10/02 16:51:46 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/09/13 21:54:11 z0m3ie
|
||||
acs is localizeable now (ACS_Strings)
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
|
||||
unit acs_indicator;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, ACS_Types, ACS_Classes, ACS_Procs, ACS_Strings;
|
||||
|
||||
type
|
||||
|
||||
TACSSoundIndicator = class(TACSCustomConverter)
|
||||
private
|
||||
Lock : Boolean;
|
||||
Window : array[0..1023] of Double;
|
||||
FValues : array[0..31] of Double;
|
||||
protected
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
procedure GetValues(var Values : array of Double);
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
constructor TACSSoundIndicator.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
HannWindow(@Window, 1024, True);
|
||||
end;
|
||||
|
||||
destructor TACSSoundIndicator.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TACSSoundIndicator.GetBPS : Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotassigned);
|
||||
Result := FInput.BitsPerSample;
|
||||
end;
|
||||
|
||||
function TACSSoundIndicator.GetCh : Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotassigned);
|
||||
Result := FInput.Channels;
|
||||
end;
|
||||
|
||||
function TACSSoundIndicator.GetSR : Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotassigned);
|
||||
Result := FInput.SampleRate;
|
||||
end;
|
||||
|
||||
procedure TACSSoundIndicator.Init;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotassigned);
|
||||
FBusy := True;
|
||||
FInput.Init;
|
||||
FSize := FInput.Size;
|
||||
FillChar(FValues[0], SizeOf(Double)*32, 0);
|
||||
Lock := False;
|
||||
FPosition := 0;
|
||||
end;
|
||||
|
||||
procedure TACSSoundIndicator.Flush;
|
||||
begin
|
||||
FInput.Flush;
|
||||
FBusy := False;
|
||||
Lock := False;
|
||||
end;
|
||||
|
||||
function TACSSoundIndicator.GetData(Buffer : Pointer; BufferSize : Integer): Integer;
|
||||
var
|
||||
i, j, k, NumSamples : Integer;
|
||||
P : Pointer;
|
||||
P8 : PACSBuffer8;
|
||||
P16 : PACSBuffer16;
|
||||
PS8 : PACSStereoBuffer8;
|
||||
PS16 : PACSStereoBuffer16;
|
||||
DA : array[0..63] of Double;
|
||||
C1 : array[0..63] of TACSComplex;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create(strStreamnotopen);
|
||||
while InputLock do;
|
||||
InputLock := True;
|
||||
Result := FInput.GetData(Buffer, BufferSize);
|
||||
InputLock := False;
|
||||
FPosition := Finput.Position;
|
||||
if Result = 0 then Exit;
|
||||
if Lock then Exit;
|
||||
Lock := True;
|
||||
k := Result;
|
||||
GetMem(P, k);
|
||||
Move(Buffer^, P^, k);
|
||||
if FInput.BitsPerSample = 8 then
|
||||
begin
|
||||
if FInput.Channels = 1 then NumSamples := k
|
||||
else NumSamples := k shr 1;
|
||||
end else
|
||||
begin
|
||||
if FInput.Channels = 1 then NumSamples := k shr 1
|
||||
else NumSamples := k shr 2;
|
||||
end;
|
||||
for i := 0 to (NumSamples div 64) - 1 do
|
||||
begin
|
||||
if FInput.BitsPerSample = 8 then
|
||||
begin
|
||||
if FInput.Channels = 1 then
|
||||
begin
|
||||
P8 := P;
|
||||
for j := 0 to 63 do DA[j] := P8[i*64+j];
|
||||
end else
|
||||
begin
|
||||
PS8 := P;
|
||||
for j := 0 to 63 do DA[j] := (PS8[i*64+j].Left+PS8[i*64+j].Right)/2;
|
||||
end
|
||||
end else
|
||||
begin
|
||||
if FInput.Channels = 1 then
|
||||
begin
|
||||
P16 := P;
|
||||
for j := 0 to 63 do DA[j] := P16[i*64+j];
|
||||
end else
|
||||
begin
|
||||
PS16 := P;
|
||||
for j := 0 to 63 do DA[j] := (PS16[i*64+j].Left+PS16[i*64+j].Right)/2;
|
||||
end
|
||||
end;
|
||||
MultDoubleArrays(@Window[0], @DA[0], 64);
|
||||
for j := 0 to 63 do
|
||||
begin
|
||||
C1[j].Re := DA[j];
|
||||
C1[j].Im := 0;
|
||||
end;
|
||||
ComplexFFT(@C1, 64, 1);
|
||||
LgMagnitude(@C1[0], @DA[0], 64, 0);
|
||||
try
|
||||
for j := 0 to 31 do FValues[j]:=FValues[j]+DA[j];
|
||||
except
|
||||
for j := 0 to 31 do FValues[j] := 0;
|
||||
end;
|
||||
end;
|
||||
for j := 0 to 31 do FValues[j]:=FValues[j]/(NumSamples div 64);
|
||||
FreeMem(P);
|
||||
Lock := False;
|
||||
end;
|
||||
|
||||
procedure TACSSoundIndicator.GetValues;
|
||||
var
|
||||
i : Integer;
|
||||
begin
|
||||
while Lock do;
|
||||
Lock := True;
|
||||
for i := 0 to 31 do Values[i] := FValues[i]*0.4; //ValCount;
|
||||
for i := 0 to 31 do FValues[i] := 0;
|
||||
Lock := False;
|
||||
end;
|
||||
|
||||
end.
|
||||
547
acs/Src/classes/acs_misc.pas
Normal file
547
acs/Src/classes/acs_misc.pas
Normal file
@@ -0,0 +1,547 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.3.
|
||||
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: acs_misc.pas,v $
|
||||
Revision 1.4 2006/08/31 20:10:54 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.3 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.1 2005/12/19 18:34:35 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.4 2005/12/04 16:54:34 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.3 2005/09/13 21:54:11 z0m3ie
|
||||
acs is localizeable now (ACS_Strings)
|
||||
|
||||
Revision 1.2 2005/09/13 04:04:50 z0m3ie
|
||||
First release without Components for Fileformats
|
||||
only TFileIn and TFileOut are Visible
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.9 2005/09/07 20:53:22 z0m3ie
|
||||
begon to add MPEG and WMA support using DirectX
|
||||
|
||||
Revision 1.8 2005/09/04 17:59:37 z0m3ie
|
||||
moving CDIn support to AKRip mostly
|
||||
begon to add mpegin support for Win with mpg123
|
||||
|
||||
Revision 1.7 2005/08/28 18:35:53 z0m3ie
|
||||
created Delphi package for 2.4
|
||||
more Mixer stuff
|
||||
updated some things for Delphi
|
||||
|
||||
Revision 1.6 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
unit acs_misc;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, ACS_Types, ACS_Classes, ACS_Strings
|
||||
{$IFDEF LINUX}
|
||||
,baseunix, LibAO
|
||||
{$ENDIF};
|
||||
|
||||
const
|
||||
BUF_SIZE = $4000;
|
||||
|
||||
type
|
||||
TACSOnBufferDone = procedure(Sender : TComponent) of object;
|
||||
|
||||
TACSAudioProcessorInitEvent = procedure(Sender : TComponent; var TotalSize : Integer) of object;
|
||||
TACSAudioProcessorFlushEvent = procedure(Sender : TComponent) of object;
|
||||
|
||||
TACSGetParameterEvent = procedure(Sender : TComponent; var Param : Integer) of object;
|
||||
|
||||
TACSGetRealParameterEvent = procedure(Sender : TComponent; var Param : real) of object;
|
||||
|
||||
TACSGetDataEvent = procedure(Sender : TComponent; Data : Pointer; var n : Integer) of object;
|
||||
|
||||
TACSMemoryIn = class(TACSCustomInput)
|
||||
private
|
||||
FBuffer : PACSBuffer8;
|
||||
FDataSize : Integer;
|
||||
FOnBufferDone : TACSOnBufferDone;
|
||||
Busy : Boolean;
|
||||
BufStart, BufEnd : Integer;
|
||||
FBPS, FSR, FChan : Integer;
|
||||
function GetBuffer : Pointer;
|
||||
procedure SetBuffer(v : Pointer);
|
||||
protected
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
property DataBuffer : Pointer read GetBuffer write SetBuffer;
|
||||
property DataSize : Integer read FDataSize write FDataSize;
|
||||
published
|
||||
property GlobalSize : Integer read FSize write FSize;
|
||||
property InBitsPerSample : Integer read GetBPS write FBPS;
|
||||
property InChannels : Integer read GetCh write FChan;
|
||||
property InSampleRate : Integer read GetSR write FSR;
|
||||
property OnBufferDone : TACSOnBufferDone read FOnBufferDone write FOnBufferDone;
|
||||
end;
|
||||
|
||||
TACSAudioProcessor = class(TACSCustomConverter)
|
||||
private
|
||||
FOnInit : TACSAudioProcessorInitEvent;
|
||||
FOnFlush : TACSAudioProcessorFlushEvent;
|
||||
FOnGetData : TACSGetDataEvent;
|
||||
FOnGetSampleRate : TACSGetParameterEvent;
|
||||
FOnGetBitsPerSample : TACSGetParameterEvent;
|
||||
FOnGetChannels : TACSGetParameterEvent;
|
||||
FOnGetTotalTime : TACSGetRealParameterEvent;
|
||||
FOnGetSize : TACSGetParameterEvent;
|
||||
protected
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
function GetTotalTime : real; override;
|
||||
public
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
published
|
||||
property OnFlush : TACSAudioProcessorFlushEvent read FOnFlush write FOnFlush;
|
||||
property OnGetBitsPerSample : TACSGetParameterEvent read FOnGetBitsPerSample write FOnGetBitsPerSample;
|
||||
property OnGetChannels : TACSGetParameterEvent read FOnGetChannels write FOnGetChannels;
|
||||
property OnGetData : TACSGetDataEvent read FOnGetData write FOnGetData;
|
||||
property OnGetSampleRate : TACSGetParameterEvent read FOnGetSampleRate write FOnGetSampleRate;
|
||||
property OnGetSize : TACSGetParameterEvent read FOnGetSize write FOnGetSize;
|
||||
property OnGetTotalTime : TACSGetrealParameterEvent read FOnGetTotalTime write FOnGetTotalTime;
|
||||
property OnInit : TACSAudioProcessorInitEvent read FOnInit write FOnInit;
|
||||
end;
|
||||
|
||||
TACSNULLOut = class(TACSCustomOutput)
|
||||
private
|
||||
Buf : array[0..BUF_SIZE-1] of Byte;
|
||||
protected
|
||||
procedure Done; override;
|
||||
function DoOutput(Abort : Boolean):Boolean; override;
|
||||
procedure Prepare; override;
|
||||
end;
|
||||
|
||||
TACSInputItem = class(TCollectionItem)
|
||||
protected
|
||||
FInput : TACSCustomInput;
|
||||
function GetOwner : TPersistent; override;
|
||||
published
|
||||
property Input : TACSCustomInput read FInput write FInput;
|
||||
end;
|
||||
|
||||
TACSInputItems = class(TOwnedCollection)
|
||||
end;
|
||||
|
||||
TACSInputChangedEvent = procedure(Sender : TComponent; var Index : Integer; var Continue : Boolean) of object;
|
||||
|
||||
TACSInputList = class(TACSCustomInput)
|
||||
private
|
||||
FCurrentInput : Integer;
|
||||
FInputItems : TACSInputItems;
|
||||
Lock : Boolean;
|
||||
FOnInputChanged : TACSInputChangedEvent;
|
||||
FIndicateProgress : Boolean;
|
||||
procedure SetCurrentInput(aInput : Integer);
|
||||
procedure SetInputItems(aItems : TACSInputItems);
|
||||
protected
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
property CurrentInput : Integer read FCurrentInput write SetCurrentInput;
|
||||
published
|
||||
property IndicateProgress : Boolean read FIndicateProgress write FIndicateProgress;
|
||||
property InputItems : TACSInputItems read FInputItems write SetInputItems;
|
||||
property OnInputChanged : TACSInputChangedEvent read FOnInputChanged write FOnInputChanged;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
{$IFDEF LINUX}
|
||||
|
||||
var
|
||||
AOInitialized : Integer = 0;
|
||||
|
||||
{$ENDIF}
|
||||
|
||||
constructor TACSMemoryIn.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FSize := -1;
|
||||
end;
|
||||
|
||||
destructor TACSMemoryIn.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TACSMemoryIn.GetBPS : Integer;
|
||||
begin
|
||||
if (FBPS in [8, 16]) = False then FBPS := 16;
|
||||
Result := FBPS;
|
||||
end;
|
||||
|
||||
function TACSMemoryIn.GetCh : Integer;
|
||||
begin
|
||||
if (FChan in [1..2]) = False then FChan := 1;
|
||||
Result := FChan;
|
||||
end;
|
||||
|
||||
function TACSMemoryIn.GetSR : Integer;
|
||||
begin
|
||||
if (FSR < 4000) or (FSR > 48000) then FSR := 8000;
|
||||
Result := FSR;
|
||||
end;
|
||||
|
||||
procedure TACSMemoryIn.Init;
|
||||
begin
|
||||
FPosition := 0;
|
||||
BufEnd := FDataSize;
|
||||
BufStart := 1;
|
||||
Busy := True;
|
||||
end;
|
||||
|
||||
procedure TACSMemoryIn.Flush;
|
||||
begin
|
||||
Busy := False;
|
||||
FDataSize := 0;
|
||||
end;
|
||||
|
||||
function TACSMemoryIn.GetData(Buffer : Pointer; BufferSize : Integer): Integer;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create(strStreamnotopen);
|
||||
if not Assigned(FBuffer) then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
if BufStart > BufEnd then
|
||||
begin
|
||||
BufStart := 1;
|
||||
if FDataSize = 0 then
|
||||
begin
|
||||
if Assigned(FOnBufferDone) then FOnBufferDone(Self)
|
||||
else
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
BufEnd := FDataSize;
|
||||
if FDataSize = 0 then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
if BufferSize < (BufEnd - BufStart + 1)
|
||||
then Result := BufferSize
|
||||
else Result := BufEnd - BufStart + 1;
|
||||
Move(FBuffer[BufStart-1], Buffer^, Result);
|
||||
Inc(BufStart, Result);
|
||||
Inc(FPosition, Result);
|
||||
Dec(FDataSize, Result);
|
||||
end;
|
||||
|
||||
function TACSMemoryIn.GetBuffer : Pointer;
|
||||
begin
|
||||
Result := Pointer(FBuffer);
|
||||
end;
|
||||
|
||||
procedure TACSMemoryIn.SetBuffer;
|
||||
begin
|
||||
FBuffer := PACSBuffer8(v);
|
||||
end;
|
||||
|
||||
function TACSAudioProcessor.GetBPS : Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
if Assigned(FOnGetBitsPerSample) then FOnGetBitsPerSample(Self, Result) else
|
||||
Result := FInput.BitsPerSample;
|
||||
end;
|
||||
|
||||
function TACSAudioProcessor.GetSR : Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
if Assigned(FOnGetSampleRate) then FOnGetSampleRate(Self, Result) else
|
||||
Result := FInput.SampleRate;
|
||||
end;
|
||||
|
||||
function TACSAudioProcessor.GetCh : Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
if Assigned(FOnGetChannels) then FOnGetChannels(Self, Result) else
|
||||
Result := FInput.Channels;
|
||||
end;
|
||||
|
||||
function TACSAudioProcessor.GetTotalTime : real;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
if Assigned(FOnGetTotalTime) then FOnGetTotalTime(Self, Result) else
|
||||
Result := FInput.TotalTime;
|
||||
end;
|
||||
|
||||
function TACSAudioProcessor.GetData(Buffer : Pointer; BufferSize : Integer): Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
Result := BufferSize;
|
||||
if Assigned(FOnGetData) then FOnGetData(Self, Buffer, Result)
|
||||
else Result := FInput.GetData(Buffer, BufferSize);
|
||||
Inc(FPosition, Result);
|
||||
// if Result = 0 then
|
||||
// Result := Result shl 1;
|
||||
end;
|
||||
|
||||
procedure TACSAudioProcessor.Init;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
if Assigned(FOnInit) then FOnInit(Self, FSize)
|
||||
else
|
||||
begin
|
||||
FInput.Init;
|
||||
if Assigned(FOnGetSize) then FOnGetSize(Self, FSize)
|
||||
else FSize := Finput.Size;
|
||||
end;
|
||||
FBusy := True;
|
||||
FPosition := 0;
|
||||
end;
|
||||
|
||||
procedure TACSAudioProcessor.Flush;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
if Assigned(FOnFlush) then FOnFlush(Self)
|
||||
else FInput.Flush;
|
||||
FBusy := False;
|
||||
end;
|
||||
|
||||
procedure TACSNULLOut.Prepare;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
FInput.Init;
|
||||
end;
|
||||
|
||||
function TACSNULLOut.DoOutput(Abort : Boolean):Boolean;
|
||||
begin
|
||||
Result := True;
|
||||
if not Busy then Exit;
|
||||
if Abort or (not CanOutput) then
|
||||
begin
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
if Finput.GetData(@Buf[0], BUF_SIZE) > 0 then Result := True
|
||||
else
|
||||
begin
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TACSNULLOut.Done;
|
||||
begin
|
||||
FInput.Flush;
|
||||
end;
|
||||
|
||||
function TACSInputItem.GetOwner : TPersistent;
|
||||
begin
|
||||
Result := Collection;
|
||||
end;
|
||||
|
||||
constructor TACSInputList.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FInputItems := TACSInputItems.Create(Self, TACSInputItem);
|
||||
FPosition := 0;
|
||||
FSize := -1;
|
||||
FIndicateProgress := True;
|
||||
end;
|
||||
|
||||
destructor TACSInputList.Destroy;
|
||||
begin
|
||||
FInputItems.Free;
|
||||
Inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TACSInputList.SetCurrentInput;
|
||||
var
|
||||
I : TACSInputItem;
|
||||
begin
|
||||
if aInput <> 0 then
|
||||
if (aInput < 0) or (aInput >= FInputItems.Count) then
|
||||
raise EACSException.Create(Format(strListIndexOOB,[aInput]));
|
||||
if Busy then
|
||||
begin
|
||||
while Lock do;
|
||||
Lock := True;
|
||||
I := TACSInputItem(InputItems.Items[FCurrentInput]);
|
||||
I.Input.Flush;
|
||||
I := TACSInputItem(InputItems.Items[aInput]);
|
||||
I.Input.Init;
|
||||
if FIndicateProgress then
|
||||
FSize := I.Input.Size
|
||||
else FSize := -1;
|
||||
FPosition := 0;
|
||||
Lock := False;
|
||||
end;
|
||||
FCurrentInput := aInput;
|
||||
end;
|
||||
|
||||
function TACSInputList.GetBPS : Integer;
|
||||
var
|
||||
I : TACSInputItem;
|
||||
begin
|
||||
if Busy then
|
||||
begin
|
||||
I := TACSInputItem(InputItems.Items[FCurrentInput]);
|
||||
Result := I.Input.BitsPerSample;
|
||||
end else
|
||||
if InputItems.Count > 0 then
|
||||
begin
|
||||
I := TACSInputItem(InputItems.Items[0]);
|
||||
Result := I.Input.BitsPerSample;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TACSInputList.GetCh : Integer;
|
||||
var
|
||||
I : TACSInputItem;
|
||||
begin
|
||||
if Busy then
|
||||
begin
|
||||
I := TACSInputItem(InputItems.Items[FCurrentInput]);
|
||||
Result := I.Input.Channels;
|
||||
end else
|
||||
if InputItems.Count > 0 then
|
||||
begin
|
||||
I := TACSInputItem(InputItems.Items[0]);
|
||||
Result := I.Input.Channels;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TACSInputList.GetSR : Integer;
|
||||
var
|
||||
I : TACSInputItem;
|
||||
begin
|
||||
if Busy then
|
||||
begin
|
||||
I := TACSInputItem(InputItems.Items[FCurrentInput]);
|
||||
Result := I.Input.SampleRate;
|
||||
end else
|
||||
if InputItems.Count > 0 then
|
||||
begin
|
||||
I := TACSInputItem(InputItems.Items[0]);
|
||||
Result := I.Input.SampleRate;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TACSInputList.Init;
|
||||
var
|
||||
I : TACSInputItem;
|
||||
begin
|
||||
if Busy then
|
||||
raise EACSException.Create(strBusy);
|
||||
if InputItems.Count = 0 then
|
||||
raise EACSException.Create(strNoInputItems);
|
||||
I := TACSInputItem(InputItems.Items[FCurrentInput]);
|
||||
if not Assigned(I.Input) then
|
||||
raise EACSException.Create(Format(strNoInputAssigned,[FCurrentInput]));
|
||||
FBusy := True;
|
||||
I.Input.Init;
|
||||
if FIndicateProgress then
|
||||
FSize := I.Input.Size
|
||||
else FSize := -1;
|
||||
FPosition := 0;
|
||||
end;
|
||||
|
||||
procedure TACSInputList.Flush;
|
||||
var
|
||||
I : TACSInputItem;
|
||||
begin
|
||||
I := TACSInputItem(InputItems.Items[FCurrentInput]);
|
||||
I.Input.Flush;
|
||||
FCurrentInput := 0;
|
||||
Lock := False;
|
||||
FBusy := False;
|
||||
end;
|
||||
|
||||
function TACSInputList.GetData(Buffer : Pointer; BufferSize : Integer): Integer;
|
||||
var
|
||||
I : TACSInputItem;
|
||||
Continue : Boolean;
|
||||
begin
|
||||
while Lock do;
|
||||
Lock := True;
|
||||
I := TACSInputItem(InputItems.Items[FCurrentInput]);
|
||||
Result := I.Input.GetData(Buffer, BufferSize);
|
||||
while Result = 0 do
|
||||
begin
|
||||
if FCurrentInput < InputItems.Count -1 then
|
||||
begin
|
||||
I.Input.Flush;
|
||||
Inc(FCurrentInput);
|
||||
Continue := True;
|
||||
if Assigned(FonInputChanged) then
|
||||
FonInputChanged(Self, FCurrentInput, Continue);
|
||||
if Continue then
|
||||
begin
|
||||
I := TACSInputItem(InputItems.Items[FCurrentInput]);
|
||||
if not Assigned(I.Input) then
|
||||
raise EACSException.Create(Format(strNoInputAssigned,[FCurrentInput]));
|
||||
I.Input.Init;
|
||||
if FIndicateProgress then
|
||||
FSize := I.Input.Size
|
||||
else FSize := -1;
|
||||
FPosition := 0;
|
||||
Result := I.Input.GetData(Buffer, BufferSize);
|
||||
end else Break;
|
||||
end else Break;
|
||||
end;
|
||||
if FIndicateProgress then
|
||||
FPosition := I.Input.Position;
|
||||
Lock := False;
|
||||
end;
|
||||
|
||||
procedure TACSInputList.SetInputItems;
|
||||
begin
|
||||
FInputItems.Assign(aItems);
|
||||
end;
|
||||
end.
|
||||
262
acs/Src/classes/acs_mixer.pas
Normal file
262
acs/Src/classes/acs_mixer.pas
Normal file
@@ -0,0 +1,262 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.4.
|
||||
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: acs_mixer.pas,v $
|
||||
Revision 1.2 2005/12/30 12:54:42 z0m3ie
|
||||
some error checks
|
||||
|
||||
Revision 1.1 2005/12/19 18:34:35 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.3 2005/12/04 16:54:34 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.2 2005/10/02 16:51:46 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.11 2005/09/01 19:55:48 z0m3ie
|
||||
again Delphi corrections
|
||||
|
||||
Revision 1.10 2005/08/31 20:30:39 z0m3ie
|
||||
Mixer Channelname work now
|
||||
minior corrections for Converters
|
||||
|
||||
Revision 1.9 2005/08/31 14:37:59 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.8 2005/08/31 14:33:16 z0m3ie
|
||||
fixed delphi issue with TControlEntry
|
||||
|
||||
Revision 1.7 2005/08/30 22:10:55 z0m3ie
|
||||
Mixer mostly completed
|
||||
|
||||
Revision 1.6 2005/08/29 21:46:43 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.5 2005/08/28 20:31:18 z0m3ie
|
||||
linux restructuring for 2.4
|
||||
|
||||
Revision 1.4 2005/08/28 18:35:53 z0m3ie
|
||||
created Delphi package for 2.4
|
||||
more Mixer stuff
|
||||
updated some things for Delphi
|
||||
|
||||
Revision 1.3 2005/08/26 17:12:56 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/08/26 17:03:20 z0m3ie
|
||||
begon to make acs resourcestring aware
|
||||
more advanced tmixer for windows
|
||||
restructured tmixer its better handleable now
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
|
||||
unit acs_mixer;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, ACS_Classes, ACS_Strings
|
||||
{$IFDEF MSWINDOWS}
|
||||
,MMSystem,Windows,Dialogs
|
||||
,Math
|
||||
{$ELSE}
|
||||
,Soundcard, baseunix
|
||||
{$ENDIF}
|
||||
;
|
||||
|
||||
type
|
||||
TACSMixerChannel = (mcUnknown,
|
||||
mcVolume,
|
||||
mcTreble,
|
||||
mcBass,
|
||||
mcSynth,
|
||||
mcPCM,
|
||||
mcSpeaker,
|
||||
mcLine,
|
||||
mcMic,
|
||||
mcCD,
|
||||
mcIMix,
|
||||
mcAltPCM,
|
||||
mcRecLev,
|
||||
mcDigital,
|
||||
mcMonitor,
|
||||
mcHeadphone,
|
||||
mcTelephone);
|
||||
|
||||
{$IFDEF MSWINDOWS}
|
||||
const
|
||||
FirstSource = MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED - MIXERLINE_COMPONENTTYPE_SRC_FIRST ;
|
||||
LastSource = MIXERLINE_COMPONENTTYPE_SRC_ANALOG - MIXERLINE_COMPONENTTYPE_SRC_FIRST ;
|
||||
FirstDest = MIXERLINE_COMPONENTTYPE_DST_FIRST;
|
||||
LastDest = MIXERLINE_COMPONENTTYPE_DST_LAST;
|
||||
|
||||
type
|
||||
{$IFDEF LCL}
|
||||
TMixerLine = MIXERLINE;
|
||||
TMixerCaps = MIXERCAPS;
|
||||
TMixerControl = MIXERCONTROL;
|
||||
TMixerLineControls = MIXERLINECONTROLS;
|
||||
TMixerControlDetails = MIXERCONTROLDETAILS;
|
||||
{$ENDIF}
|
||||
|
||||
TDataArray = ARRAY[FirstSource .. LastSource] OF MIXERCONTROLDETAILS_UNSIGNED;
|
||||
PDataArray = ^TDataArray;
|
||||
PControlEntry = ^TControlEntry;
|
||||
TControlEntry = RECORD
|
||||
IsInited : Boolean;
|
||||
CHandle : Thandle;
|
||||
CDestination : INTEGER;
|
||||
CID : INTEGER;
|
||||
CName : String[MIXER_SHORT_NAME_CHARS];
|
||||
CConnect : INTEGER;
|
||||
CCControls : INTEGER;
|
||||
CControlTyp : INTEGER;
|
||||
CKanal : INTEGER;
|
||||
CControl : INTEGER;
|
||||
CComponentTyp : DWORD;
|
||||
CMin, Cmax : INTEGER;
|
||||
Cdetails : TDataArray;
|
||||
CMultItems : INTEGER;
|
||||
CcSteps : DWORD;
|
||||
END;
|
||||
{$ENDIF}
|
||||
|
||||
TACSMixerLevel = record
|
||||
case Word of
|
||||
1 :
|
||||
(
|
||||
Left, Right : Byte;
|
||||
);
|
||||
2 : (Main : Byte;);
|
||||
end;
|
||||
|
||||
{ TACSMixer }
|
||||
|
||||
TACSMixer = class(TComponent)
|
||||
private
|
||||
FDevNum : Integer;
|
||||
FChannels : array of TACSMixerChannel;
|
||||
{$IFDEF LINUX}
|
||||
_mix_fd : Integer;
|
||||
FFileName : String;
|
||||
{$ELSE}
|
||||
FMixer : HMixer;
|
||||
FMixerCaps : TMixerCaps;
|
||||
FControls : array of TControlEntry;
|
||||
FMuteControls : array of TControlEntry;
|
||||
{$ENDIF}
|
||||
FMixerName : String;
|
||||
function GetRecSource : Integer;
|
||||
function GetVolume(vChannel : integer) : TACSMixerLevel;
|
||||
procedure SetVolume(vChannel : integer; vLevel : TACSMixerLevel);
|
||||
procedure SetRecSource(vChannel : integer);
|
||||
procedure SetDevNum(Num : Integer);
|
||||
function GetChannel(Num : Integer) : TACSMixerChannel;
|
||||
function GetDevCount : Integer;
|
||||
function GetChannelCount : Integer;
|
||||
function GetChannelName(vChannel : Integer) : string;
|
||||
function GetMute(vChannel : integer) : Boolean;
|
||||
procedure SetMute(vChannel : integer; Mute : Boolean);
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function IsStereo(vChannel : Integer) : Boolean;
|
||||
function IsRecordable(vChannel : Integer) : Boolean;
|
||||
property Channel[vChannel : Integer] : TACSMixerChannel read GetChannel;
|
||||
property Level[vChannel : Integer] : TACSMixerLevel read GetVolume write SetVolume;
|
||||
property Mute[vChannels : Integer] : Boolean read GetMute write SetMute;
|
||||
property ChannelName[vChannel : Integer] : string read GetChannelName;
|
||||
property RecordSource : Integer read GetRecSource write SetRecSource;
|
||||
property DevCount : Integer read GetDevCount;
|
||||
property Channelcount : Integer read GetChannelCount;
|
||||
published
|
||||
property DevNum : Integer read FDevNum write SetDevNum stored True;
|
||||
property MixerName : String read FMixerName;
|
||||
end;
|
||||
|
||||
var
|
||||
MixersCount : Byte;
|
||||
|
||||
function ChannelToStr(ch : TACSMixerChannel) : String;
|
||||
|
||||
implementation
|
||||
|
||||
{$I ACS_Mixer.inc}
|
||||
|
||||
function ChannelToStr(ch : TACSMixerChannel) : String;
|
||||
begin
|
||||
case ch of
|
||||
mcVolume: Result := strMixerVolume;
|
||||
mcTreble: Result := strMixerTreble;
|
||||
mcBass: Result := strMixerBass;
|
||||
mcSynth: Result := strMixerSynth;
|
||||
mcPCM: Result := strMixerPCM;
|
||||
mcSpeaker: Result := strMixerSpeaker;
|
||||
mcLine: Result := strMixerLine;
|
||||
mcMic: Result := strMixerMic;
|
||||
mcCD: Result := strMixerCD;
|
||||
mcIMix: Result := strMixerIMix;
|
||||
mcAltPCM: Result := strMixerAlt;
|
||||
mcRecLev: Result := strMixerRec;
|
||||
mcUnknown: Result := strMixerUnknown;
|
||||
else Result := IntToStr(Integer(ch));
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TACSMixer.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
if MixersCount > 0 then
|
||||
SetDevNum(0);
|
||||
end;
|
||||
|
||||
function TACSMixer.GetChannel(Num: Integer): TACSMixerChannel;
|
||||
begin
|
||||
if (Num < 0) or (Num > (length(FChannels)-1)) then
|
||||
exit;
|
||||
Result := FChannels[Num];
|
||||
end;
|
||||
|
||||
function TACSMixer.GetDevCount : Integer;
|
||||
begin
|
||||
Result := MixersCount;
|
||||
end;
|
||||
|
||||
function TACSMixer.GetChannelCount : Integer;
|
||||
begin
|
||||
result := length(FChannels);
|
||||
end;
|
||||
|
||||
function TACSMixer.GetChannelName(vChannel : Integer) : string;
|
||||
begin
|
||||
if (vChannel > -1) and (vChannel < ChannelCount) then
|
||||
Result := ChannelToStr(FChannels[vChannel]);
|
||||
end;
|
||||
|
||||
initialization
|
||||
MixersCount := CountMixers;
|
||||
end.
|
||||
299
acs/Src/classes/acs_multimix.pas
Normal file
299
acs/Src/classes/acs_multimix.pas
Normal file
@@ -0,0 +1,299 @@
|
||||
(*
|
||||
this file is a part of audio components suite,
|
||||
copyright (c) 2005 ross levis. all rights reserved.
|
||||
see the license file for more details.
|
||||
|
||||
TMultiMixer provides for an unlimited number of inputs (channels)
|
||||
to be mixed into one audio buffer. Only supports 44100/16/2
|
||||
|
||||
TMultiMixer
|
||||
- property TotalChannels: Integer; // get/set the number of channels
|
||||
- property Channel[Index: Integer]: TChannel; default
|
||||
TChannel
|
||||
- procedure Preload; // runs Input.Init to make starting faster (optional)
|
||||
- procedure Start; // Start channel
|
||||
- procedure Stop; // Stop channel
|
||||
- property Input: TACSInput
|
||||
- property Volume: Word; // 0 = silent, 32768 = 100%
|
||||
|
||||
eg.
|
||||
MultiMixer.TotalChannels := 1;
|
||||
MultiMixer[0].Input := VorbisIn1;
|
||||
AudioOut1.Run;
|
||||
MultiMixer.TotalChannels := 2; // Channels can be added or removed while playing
|
||||
MultiMixer[1].Input := WAVEIn1;
|
||||
MultiMixer[1].Volume := 16384; // 50% volume
|
||||
MultiMixer[1].Start; // while at least 1 mixer is playing, others
|
||||
MultiMixer[0].Stop; // can be started and stopped individually.
|
||||
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: acs_multimix.pas,v $
|
||||
Revision 1.3 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.1 2005/12/19 18:34:35 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.3 2005/12/04 16:54:34 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.2 2005/09/13 21:54:11 z0m3ie
|
||||
acs is localizeable now (ACS_Strings)
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.1 2005/08/25 21:02:31 z0m3ie
|
||||
TMultiMixer by Ross Levis added
|
||||
|
||||
}
|
||||
|
||||
{$hints off}
|
||||
unit acs_multimix;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, ACS_Types, ACS_Classes, ACS_Strings;
|
||||
|
||||
const
|
||||
BUF_SIZE = 8820;
|
||||
|
||||
type
|
||||
TACSMultiMixer = class;
|
||||
|
||||
TACSChannel = class
|
||||
private
|
||||
FOwner: TACSMultiMixer;
|
||||
FInput: TACSCustomInput;
|
||||
FVolume: Word;
|
||||
EndOfInput: Boolean;
|
||||
Preloaded: Boolean;
|
||||
InBuf: array[1..BUF_SIZE] of Byte;
|
||||
public
|
||||
constructor Create(AOwner: TACSMultiMixer); virtual;
|
||||
destructor Destroy; override;
|
||||
procedure Preload;
|
||||
procedure Start;
|
||||
procedure Stop;
|
||||
property Input: TACSCustomInput read FInput write FInput;
|
||||
property Volume: Word read FVolume write FVolume;
|
||||
end;
|
||||
|
||||
TACSMultiMixer = class(TACSCustomInput)
|
||||
private
|
||||
FChannel: array of TACSChannel;
|
||||
FTotalChannels: Integer;
|
||||
OutBuf: array[1..BUF_SIZE] of Byte;
|
||||
Buisy : Boolean;
|
||||
FLock: Boolean;
|
||||
function GetChannel(Index: Integer): TACSChannel;
|
||||
procedure SetTotalChannels(Num: Integer);
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
property Channel[Index: Integer]: TACSChannel read GetChannel; default;
|
||||
function GetData(Buffer: Pointer; BufferSize: Integer): Integer; override;
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
published
|
||||
property TotalChannels: Integer read FTotalChannels write SetTotalChannels;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
// TChannel
|
||||
|
||||
constructor TACSChannel.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
FOwner := AOwner;
|
||||
FVolume := 32768;
|
||||
EndOfInput := True;
|
||||
Preloaded := False;
|
||||
end;
|
||||
|
||||
destructor TACSChannel.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TACSChannel.Preload;
|
||||
begin
|
||||
if EndOfInput and not Preloaded and Assigned(FInput) then
|
||||
begin
|
||||
FInput.Init;
|
||||
Preloaded := True;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TACSChannel.Start;
|
||||
begin
|
||||
if FOwner.Buisy and EndOfInput and Assigned(FInput) then
|
||||
begin
|
||||
if not Preloaded then Preload;
|
||||
EndOfInput := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TACSChannel.Stop;
|
||||
begin
|
||||
if not EndOfInput then
|
||||
begin
|
||||
EndOfInput := True;
|
||||
Preloaded := False;
|
||||
while FOwner.Flock do;
|
||||
FOwner.FLock := True;
|
||||
FInput.Flush;
|
||||
FOwner.Flock := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
// TACSMultiMixer
|
||||
|
||||
constructor TACSMultiMixer.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FLock := False;
|
||||
end;
|
||||
|
||||
destructor TACSMultiMixer.Destroy;
|
||||
begin
|
||||
SetTotalChannels(0); // free channels
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TACSMultiMixer.SetTotalChannels(Num: Integer);
|
||||
var
|
||||
chan: Integer;
|
||||
begin
|
||||
if (Num >= 0) and (Num <> FTotalChannels) then
|
||||
begin
|
||||
while Flock do;
|
||||
FLock := True;
|
||||
if Num < FTotalChannels then // remove channels
|
||||
begin
|
||||
for chan := FTotalChannels-1 downto Num do
|
||||
with FChannel[chan] do
|
||||
begin
|
||||
if not EndOfInput then FInput.Flush;
|
||||
Free;
|
||||
end;
|
||||
SetLength(FChannel,Num);
|
||||
end
|
||||
else begin // add channels
|
||||
SetLength(FChannel,Num);
|
||||
for chan := FTotalChannels to Num-1 do
|
||||
FChannel[chan] := TACSChannel.Create(Self);
|
||||
end;
|
||||
FTotalChannels := Num;
|
||||
FLock := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TACSMultiMixer.GetBPS;
|
||||
begin
|
||||
Result := 16;
|
||||
end;
|
||||
|
||||
function TACSMultiMixer.GetCh;
|
||||
begin
|
||||
Result:= 2;
|
||||
end;
|
||||
|
||||
function TACSMultiMixer.GetSR;
|
||||
begin
|
||||
Result := 44100;
|
||||
end;
|
||||
|
||||
procedure TACSMultiMixer.Init;
|
||||
var
|
||||
chan: Integer;
|
||||
begin
|
||||
Buisy := True;
|
||||
FPosition := 0;
|
||||
for chan := 0 to FTotalChannels-1 do
|
||||
FChannel[chan].Start;
|
||||
FSize := 0;
|
||||
FLock := False;
|
||||
end;
|
||||
|
||||
procedure TACSMultiMixer.Flush;
|
||||
var
|
||||
chan: Integer;
|
||||
begin
|
||||
for chan := 0 to FTotalChannels-1 do
|
||||
with FChannel[chan] do
|
||||
begin
|
||||
if Assigned(FInput) then FInput.Flush;
|
||||
EndOfInput := True;
|
||||
Preloaded := False;
|
||||
end;
|
||||
Buisy := False;
|
||||
end;
|
||||
|
||||
function TACSMultiMixer.GetData;
|
||||
var
|
||||
i, chan, ReadSize, BufSize: Integer;
|
||||
InBuf16, OutBuf16: PACSBuffer16;
|
||||
begin
|
||||
if not Buisy then raise EACSException.Create(strStreamnotopen);
|
||||
begin
|
||||
while Flock do sleep(0);
|
||||
Flock := True;
|
||||
BufSize := 0;
|
||||
if BufferSize > BUF_SIZE then BufferSize := BUF_SIZE;
|
||||
for chan := 0 to FTotalChannels-1 do
|
||||
with FChannel[chan] do
|
||||
if not EndOfInput then
|
||||
begin
|
||||
ReadSize := FInput.GetData(@InBuf[1], BufferSize);
|
||||
while (ReadSize < BufferSize) and (ReadSize <> 0) do
|
||||
begin
|
||||
Result := FInput.GetData(@InBuf[ReadSize+1], BufferSize-ReadSize);
|
||||
Inc(ReadSize, Result);
|
||||
end;
|
||||
FillChar(InBuf[ReadSize+1], BufferSize-ReadSize, 0); // zero rest of buffer
|
||||
if ReadSize = 0 then EndOfInput := True
|
||||
else if ReadSize > BufSize then BufSize := ReadSize;
|
||||
end;
|
||||
if BufSize = 0 then
|
||||
begin
|
||||
Flock := False;
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
// mix
|
||||
FillChar(OutBuf[1], BufferSize, 0);
|
||||
OutBuf16 := @OutBuf;
|
||||
for chan := 0 to FTotalChannels-1 do
|
||||
with FChannel[chan] do
|
||||
if not EndOfInput then
|
||||
begin
|
||||
InBuf16 := @InBuf;
|
||||
for i := 0 to (BufSize shr 1) - 1 do
|
||||
OutBuf16[i] := OutBuf16[i] + (InBuf16[i] * FVolume div 32768);
|
||||
end;
|
||||
Flock := False;
|
||||
end;
|
||||
Result := BufSize;
|
||||
Move(OutBuf[1], Buffer^, Result);
|
||||
Inc(FPosition, Result);
|
||||
end;
|
||||
|
||||
function TACSMultiMixer.GetChannel(Index: Integer): TACSChannel;
|
||||
begin
|
||||
Result := FChannel[Index];
|
||||
end;
|
||||
|
||||
end.
|
||||
343
acs/Src/classes/acs_procs.pas
Normal file
343
acs/Src/classes/acs_procs.pas
Normal file
@@ -0,0 +1,343 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.3.
|
||||
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: acs_procs.pas,v $
|
||||
Revision 1.4 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.1 2005/12/19 18:34:35 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/12/04 16:54:34 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
unit acs_procs;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
SysUtils, ACS_Types, Math;
|
||||
|
||||
type
|
||||
|
||||
TACSFilterWindowType = (fwHamming, fwHann, fwBlackman);
|
||||
|
||||
{$IFDEF LINUX}
|
||||
function FindLibs(const Pattern : String) : String;
|
||||
{$ENDIF}
|
||||
|
||||
|
||||
// Direction = 1 - forward FFT, Direction = -1 - inverse FFT.
|
||||
procedure ComplexFFT(Data : PACSComplexArray; DataSize, Direction : Integer);
|
||||
|
||||
procedure HannWindow(OutData : PACSDoubleArray; Width : Integer; Symmetric : Boolean);
|
||||
|
||||
procedure HammingWindow(OutData : PACSDoubleArray; Width : Integer; Symmetric : Boolean);
|
||||
|
||||
procedure BlackmanWindow(OutData : PACSDoubleArray; Width : Integer; Symmetric : Boolean);
|
||||
|
||||
procedure CalculateSincKernel(OutData : PACSDoubleArray; CutOff : Double; Width : Integer; WType : TACSFilterWindowType);
|
||||
|
||||
procedure SmallIntArrayToDouble(InData : PSmallInt; OutData : PDouble; DataSize : Integer);
|
||||
|
||||
procedure SmallIntArrayToComplex(InData : PSmallInt; OutData : PACSComplex; DataSize : Integer);
|
||||
|
||||
|
||||
// Computes Op2[i] = Op1[i]*Op2[i], i = [0..DataSize-1]
|
||||
|
||||
procedure MultDoubleArrays(Op1, Op2 : PDouble; DataSize : Integer);
|
||||
|
||||
(*
|
||||
Performs calculation of
|
||||
/
|
||||
| Lg(Abs(InData[i])) + Shift, if Lg(Abs(InData[i])) + Shift >= 0
|
||||
OutData[i] = < 0, if Lg(Abs(InData[i])) + Shift < 0
|
||||
| 0, if Abs(InData[i]) = 0.
|
||||
\
|
||||
i = [0..DataSize-1]
|
||||
*)
|
||||
procedure LgMagnitude(InData : PACSComplex; OutData : PDouble; DataSize, Shift : Integer);
|
||||
|
||||
implementation
|
||||
|
||||
{$IFDEF LINUX}
|
||||
function FindLibs(const Pattern : String) : String;
|
||||
var
|
||||
Path : String;
|
||||
SR : TSearchRec;
|
||||
begin
|
||||
Path := '/usr/lib/';
|
||||
if FindFirst(Path + Pattern, faAnyFile, SR) = 0 then
|
||||
begin
|
||||
Result := SR.Name;
|
||||
FindClose(SR);
|
||||
Exit;
|
||||
end;
|
||||
Path := '/usr/local/lib/';
|
||||
if FindFirst(Path + Pattern, faAnyFile, SR) = 0 then
|
||||
begin
|
||||
Result := SR.Name;
|
||||
FindClose(SR);
|
||||
Exit;
|
||||
end;
|
||||
Result := '';
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
|
||||
(* This routine is converted from the original C code by P. Burke
|
||||
Direction = 1 - forward FFT, Direction = -1 - inverse FFT. *)
|
||||
procedure ComplexFFT(Data : PACSComplexArray; DataSize, Direction : Integer);
|
||||
var
|
||||
i, i1, j, k, i2, l, l1, l2, Log2n : Integer;
|
||||
c1, c2, tx, ty, t1, t2, u1, u2, z : Double;
|
||||
begin
|
||||
Log2n := Trunc(Log2(DataSize));
|
||||
// Do the bit reversal
|
||||
i2 := DataSize shr 1;
|
||||
j := 0;
|
||||
for i := 0 to DataSize-2 do
|
||||
begin
|
||||
if i < j then
|
||||
begin
|
||||
tx := Data[i].Re;
|
||||
ty := Data[i].Im;
|
||||
Data[i].Re := Data[j].Re;
|
||||
Data[i].Im := Data[j].Im;
|
||||
Data[j].Re := tx;
|
||||
Data[j].Im := ty;
|
||||
end;
|
||||
k := i2;
|
||||
while k <= j do
|
||||
begin
|
||||
Dec(j, k);
|
||||
k := k shr 1;
|
||||
end;
|
||||
Inc(j, k);
|
||||
end;
|
||||
// Compute the FFT
|
||||
c1 := -1.0;
|
||||
c2 := 0.0;
|
||||
l2 := 1;
|
||||
for l := 0 to Log2n-1 do
|
||||
begin
|
||||
l1 := l2;
|
||||
l2 := l2 shl 1;
|
||||
u1 := 1.0;
|
||||
u2 := 0.0;
|
||||
for j := 0 to l1-1 do
|
||||
begin
|
||||
i := j;
|
||||
while i < DataSize do
|
||||
begin
|
||||
i1 := i + l1;
|
||||
t1 := u1 * Data[i1].Re - u2 * Data[i1].Im;
|
||||
t2 := u1 * Data[i1].Im + u2 * Data[i1].Re;
|
||||
Data[i1].Re := Data[i].Re - t1;
|
||||
Data[i1].Im := Data[i].Im - t2;
|
||||
Data[i].Re := Data[i].Re + t1;
|
||||
Data[i].Im := Data[i].Im + t2;
|
||||
Inc(i, l2);
|
||||
end;
|
||||
z := u1*c1 - u2*c2;
|
||||
u2 := u1*c2 + u2*c1;
|
||||
u1 := z;
|
||||
end;
|
||||
c2 := Sqrt((1.0 - c1)/2.0);
|
||||
if Direction = 1 then c2 := -c2;
|
||||
c1 := Sqrt((1.0 + c1)/2.0);
|
||||
end;
|
||||
|
||||
// Scaling for forward transform
|
||||
if Direction = 1 then
|
||||
for i := 0 to DataSize-1 do
|
||||
begin
|
||||
Data[i].Re := Data[i].Re/DataSize;
|
||||
Data[i].Im := Data[i].Im/DataSize;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure HannWindow(OutData : PACSDoubleArray; Width : Integer; Symmetric : Boolean);
|
||||
var
|
||||
i, n : Integer;
|
||||
begin
|
||||
if Symmetric then n := Width-1
|
||||
else n := Width;
|
||||
for i := 0 to Width-1 do OutData[i] := (1-Cos(TwoPi*i/n))/2;
|
||||
end;
|
||||
|
||||
procedure HammingWindow(OutData : PACSDoubleArray; Width : Integer; Symmetric : Boolean);
|
||||
var
|
||||
i, n : Integer;
|
||||
begin
|
||||
if Symmetric then n := Width-1
|
||||
else n := Width;
|
||||
for i := 0 to Width-1 do OutData[i] := 0.54-0.46*Cos(TwoPi*i/n);
|
||||
end;
|
||||
|
||||
procedure BlackmanWindow(OutData : PACSDoubleArray; Width : Integer; Symmetric : Boolean);
|
||||
var
|
||||
i, n : Integer;
|
||||
begin
|
||||
if Symmetric then n := Width-1
|
||||
else n := Width;
|
||||
for i := 0 to Width-1 do OutData[i] := 0.42-0.5*Cos(TwoPi*i/n) + 0.08*Cos(2*TwoPi*i/n);
|
||||
end;
|
||||
|
||||
procedure CalculateSincKernel(OutData : PACSDoubleArray; CutOff : Double; Width : Integer; WType : TACSFilterWindowType);
|
||||
var
|
||||
i : Integer;
|
||||
S : Double;
|
||||
Window : array of Double;
|
||||
begin
|
||||
// SetLength(OutData, Width);
|
||||
SetLength(Window, Width);
|
||||
case WType of
|
||||
fwHamming : HammingWindow(@Window[0], Width, False);
|
||||
fwHann : HannWindow(@Window[0], Width, False);
|
||||
fwBlackman : BlackmanWindow(@Window[0], Width, False);
|
||||
end;
|
||||
S := 0;
|
||||
for i := 0 to Width-1 do
|
||||
begin
|
||||
if i-(Width shr 1) <> 0 then
|
||||
OutData[i] := Sin(TwoPi*CutOff*(i-(Width shr 1)))/(i-(Width shr 1))*Window[i]
|
||||
else OutData[i] := TwoPi*CutOff*Window[i];
|
||||
S := S + OutData[i];
|
||||
end;
|
||||
for i := 0 to Width-1 do OutData[i] := OutData[i]/S;
|
||||
end;
|
||||
|
||||
procedure SmallIntArrayToDouble(InData : PSmallInt; OutData : PDouble; DataSize : Integer);
|
||||
begin
|
||||
{$IFDEF CPU32}
|
||||
asm
|
||||
MOV EDX, DataSize;
|
||||
SHL EDX, 3;
|
||||
MOV ECX, OutData;
|
||||
ADD EDX, ECX;
|
||||
MOV EAX, InData;
|
||||
@test: CMP EDX, ECX;
|
||||
JE @out;
|
||||
FILD WORD[EAX];
|
||||
ADD EAX, 2;
|
||||
FSTP QWORD[ECX];
|
||||
ADD ECX, 8;
|
||||
JMP @test;
|
||||
@out: ;
|
||||
end;
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
procedure SmallIntArrayToComplex(InData : PSmallInt; OutData : PACSComplex; DataSize : Integer);
|
||||
begin
|
||||
{$IFDEF CPU32}
|
||||
asm
|
||||
MOV EDX, DataSize;
|
||||
SHR EDX, 4;
|
||||
MOV ECX, OutData;
|
||||
ADD EDX, ECX;
|
||||
MOV EAX, InData;
|
||||
@test: CMP EDX, ECX;
|
||||
JE @out;
|
||||
FILD WORD[EAX];
|
||||
ADD EAX, 2;
|
||||
FSTP QWORD[EAX];
|
||||
ADD ECX, 16;
|
||||
JMP @test;
|
||||
@out: ;
|
||||
end;
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
procedure MultDoubleArrays(Op1, Op2 : PDouble; DataSize : Integer);
|
||||
begin
|
||||
{$IFDEF CPU32}
|
||||
asm
|
||||
MOV EDX, DataSize;
|
||||
SHL EDX, 3;
|
||||
MOV ECX, Op1;
|
||||
ADD EDX, ECX;
|
||||
MOV EAX, Op2;
|
||||
@test: CMP EDX, ECX;
|
||||
JE @out;
|
||||
FLD QWORD[ECX];
|
||||
FLD QWORD[EAX];
|
||||
FMUL;
|
||||
FSTP QWORD[EAX];
|
||||
ADD ECX, 8;
|
||||
ADD EAX, 8;
|
||||
JMP @test;
|
||||
@out: ;
|
||||
end;
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
procedure LgMagnitude(InData : PACSComplex; OutData : PDouble; DataSize, Shift : Integer);
|
||||
var
|
||||
LogBase : Double;
|
||||
begin
|
||||
{$IFDEF CPU32}
|
||||
asm
|
||||
FLD1;
|
||||
FLDL2T;
|
||||
FDIVP;
|
||||
FSTP LogBase;
|
||||
MOV EDX, DataSize;
|
||||
SHL EDX, 3;
|
||||
MOV ECX, OutData;
|
||||
ADD EDX, ECX;
|
||||
MOV EAX, InData;
|
||||
@test: CMP EDX, ECX;
|
||||
JE @out;
|
||||
FLD QWORD[EAX];
|
||||
FMUL ST(0), ST(0);
|
||||
ADD EAX, 8;
|
||||
FLD QWORD[EAX];
|
||||
FMUL ST(0), ST(0);
|
||||
FADDP;
|
||||
FSQRT;
|
||||
FTST;
|
||||
PUSH EAX;
|
||||
FSTSW AX;
|
||||
SAHF;
|
||||
JE @skip;
|
||||
FLD LogBase;
|
||||
FXCH;
|
||||
FYL2X;
|
||||
FIADD Shift;
|
||||
FTST;
|
||||
FSTSW AX;
|
||||
SAHF;
|
||||
JAE @skip;
|
||||
FSTP QWORD[ECX];
|
||||
FLDZ;
|
||||
@skip: POP EAX;
|
||||
ADD EAX, 8;
|
||||
FSTP QWORD[ECX];
|
||||
ADD ECX, 8;
|
||||
JMP @test;
|
||||
@out: ;
|
||||
end;
|
||||
{$ENDIF}
|
||||
end;
|
||||
end.
|
||||
223
acs/Src/classes/acs_streams.pas
Normal file
223
acs/Src/classes/acs_streams.pas
Normal file
@@ -0,0 +1,223 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.3.
|
||||
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: acs_streams.pas,v $
|
||||
Revision 1.5 2006/08/31 20:10:54 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.4 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.1 2005/12/19 18:34:35 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.4 2005/12/04 16:54:34 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.3 2005/11/27 16:50:33 z0m3ie
|
||||
add ACS VolumeQuerry
|
||||
make ACS_VolumeQuerry localizeable
|
||||
some little errorfixes (buffersize for linuxdrivers was initially 0)
|
||||
make TAudioIn workable
|
||||
|
||||
Revision 1.2 2005/09/13 21:54:11 z0m3ie
|
||||
acs is localizeable now (ACS_Strings)
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
|
||||
unit acs_streams;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, ACS_Classes, ACS_Strings;
|
||||
|
||||
const
|
||||
|
||||
OUTBUF_SIZE = $4000;
|
||||
|
||||
|
||||
type
|
||||
|
||||
TACSStreamOut = class(TACSStreamedOutput)
|
||||
private
|
||||
function GetSR : Integer;
|
||||
function GetBPS : Integer;
|
||||
function GetCh : Integer;
|
||||
protected
|
||||
procedure Done; override;
|
||||
function DoOutput(Abort : Boolean):Boolean; override;
|
||||
procedure Prepare; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
property OutSampleRate : Integer read GetSR;
|
||||
property OutBitsPerSample : Integer read GetBPS;
|
||||
property OutChannles : Integer read GetCh;
|
||||
end;
|
||||
|
||||
TACSStreamIn = class(TACSStreamedInput)
|
||||
private
|
||||
FBPS, FChan, FFreq : Integer;
|
||||
protected
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
published
|
||||
property InBitsPerSample : Integer read FBPS write FBPS;
|
||||
property InChannels : Integer read FChan write FChan;
|
||||
property InSampleRate : Integer read FFreq write FFreq;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
procedure TACSStreamOut.Prepare;
|
||||
begin
|
||||
if not FStreamAssigned then
|
||||
raise EACSException.Create(strStreamObjectnotassigned);
|
||||
FInput.Init;
|
||||
end;
|
||||
|
||||
procedure TACSStreamOut.Done;
|
||||
begin
|
||||
FInput.Flush;
|
||||
end;
|
||||
|
||||
function TACSStreamOut.DoOutput(Abort : Boolean):Boolean;
|
||||
var
|
||||
Len : Integer;
|
||||
P : Pointer;
|
||||
begin
|
||||
// No exceptions Here
|
||||
Result := True;
|
||||
if not Busy then Exit;
|
||||
if Abort or (not CanOutput) then
|
||||
begin
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
GetMem(P, OUTBUF_SIZE);
|
||||
while InputLock do;
|
||||
InputLock := True;
|
||||
Len := Finput.GetData(P, OUTBUF_SIZE);
|
||||
InputLock := False;
|
||||
if Len > 0 then
|
||||
begin
|
||||
Result := True;
|
||||
FStream.WriteBuffer(P^, Len);
|
||||
end
|
||||
else Result := False;
|
||||
FreeMem(P);
|
||||
end;
|
||||
|
||||
constructor TACSStreamOut.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
end;
|
||||
|
||||
destructor TACSStreamOut.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
constructor TACSStreamIn.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FBPS := 8;
|
||||
FChan := 1;
|
||||
FFreq := 8000;
|
||||
FSize := -1;
|
||||
end;
|
||||
|
||||
destructor TACSStreamIn.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TACSStreamIn.Init;
|
||||
begin
|
||||
if Busy then raise EACSException.Create(strBusy);
|
||||
if not Assigned(FStream) then raise EACSException.Create(strStreamObjectnotassigned);
|
||||
FPosition := FStream.Position;
|
||||
FBusy := True;
|
||||
FSize := FStream.Size;
|
||||
end;
|
||||
|
||||
procedure TACSStreamIn.Flush;
|
||||
begin
|
||||
// FStream.Position := 0;
|
||||
FBusy := False;
|
||||
end;
|
||||
|
||||
function TACSStreamIn.GetData(Buffer : Pointer; BufferSize : Integer): Integer;
|
||||
begin
|
||||
Result := FStream.Read(Buffer^, BufferSize);
|
||||
FPosition := FStream.Position;
|
||||
// Inc(FPosition, Result);
|
||||
if FPosition >= FSize then
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function TACSStreamOut.GetSR : Integer;
|
||||
begin
|
||||
if not Assigned(Input) then
|
||||
raise EACSException.Create(strInputnotassigned);
|
||||
Result := FInput.SampleRate;
|
||||
end;
|
||||
|
||||
function TACSStreamOut.GetBPS : Integer;
|
||||
begin
|
||||
if not Assigned(Input) then
|
||||
raise EACSException.Create(strInputnotassigned);
|
||||
Result := FInput.BitsPerSample;
|
||||
end;
|
||||
|
||||
function TACSStreamOut.GetCh : Integer;
|
||||
begin
|
||||
if not Assigned(Input) then
|
||||
raise EACSException.Create(strInputnotassigned);
|
||||
Result := FInput.Channels;
|
||||
end;
|
||||
|
||||
function TACSStreamIn.GetBPS : Integer;
|
||||
begin
|
||||
Result := FBPS
|
||||
end;
|
||||
|
||||
function TACSStreamIn.GetCh : Integer;
|
||||
begin
|
||||
Result := FChan;
|
||||
end;
|
||||
|
||||
function TACSStreamIn.GetSR : Integer;
|
||||
begin
|
||||
Result := Self.FFreq;
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
61
acs/Src/classes/acs_strings.pas
Normal file
61
acs/Src/classes/acs_strings.pas
Normal file
@@ -0,0 +1,61 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.4.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
unit acs_strings;
|
||||
|
||||
interface
|
||||
|
||||
resourcestring
|
||||
strCoudntloadLib = 'Library %s could not be loaded.';
|
||||
strcoudntopendevice = 'Could not open device "%s" for input';
|
||||
strCoudntopendeviceOut = 'Could not open device "%s" for output';
|
||||
strBusy = 'The component is busy';
|
||||
strInputstartfailed = 'Failed to start input';
|
||||
strFailedtostartOutput = 'Failed to start output';
|
||||
strStreamnotopen = 'The Stream is not opened';
|
||||
strBufferoverrun = 'Buffer overrun.';
|
||||
strUnknownExtension = 'Unknown file extension %s';
|
||||
strAllFormats = 'All formats';
|
||||
strInputnotAssigned = 'Input not Assigned';
|
||||
strFilenamenotassigned = 'Filename not Assigned';
|
||||
strSeeknotImplemented = 'Seek: method not implemented';
|
||||
strNotinFBMode = 'The component is not in amFB mode.';
|
||||
strIllegalFrequency = 'Illegal frequency';
|
||||
strCutofftolow = 'Cut-off frequencies are greater than the half of the sample rate.';
|
||||
strListIndexOOB = 'List Index Out of Bounds %d';
|
||||
strNoInputItems = 'No input items in the list.';
|
||||
strNoInputAssigned = 'No input assigned to current item';
|
||||
strStreamObjectnotassigned = 'Stream object not assigned';
|
||||
strBufferunderrun = 'Buffer underrun';
|
||||
strDevnotplayable = 'Cannot play on the device "%s"';
|
||||
strTrackOutofRange = 'Track out of range';
|
||||
strNoAudioCD = 'Not an audio disc';
|
||||
strChannelNotRecordable = 'Channel %d is not recordable';
|
||||
strDrivenotready = 'The drive is not ready';
|
||||
strnoAudioTreck = 'This is no audio track';
|
||||
strChannelNotAvailable = 'Channel %d is not available';
|
||||
strFailedtoCreateDSdev = 'Failed to create DirectSound device';
|
||||
strFailedtoCreateDSbuf = 'Failed to create DirectSound buffer';
|
||||
strnoDriverselected = 'No driver is selected, please select an driver first !';
|
||||
strnoFileOpened = 'No file opened !';
|
||||
|
||||
strMixerVolume = 'Master output';
|
||||
strMixerTreble = 'Treble output';
|
||||
strMixerBass = 'Bass output';
|
||||
strMixerSynth = 'Synthesizer input';
|
||||
strMixerPCM = 'Audio output';
|
||||
strMixerSpeaker = 'Speaker output';
|
||||
strMixerLine = 'Line input';
|
||||
strMixerMic = 'Michrophone input';
|
||||
strMixerCD = 'CD input';
|
||||
strMixerIMix = 'Record monitor';
|
||||
strMixerAlt = 'Alternate output';
|
||||
strMixerRec = 'Record level';
|
||||
strMixerUnknown = 'Unknown channel';
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
||||
84
acs/Src/classes/acs_types.pas
Normal file
84
acs/Src/classes/acs_types.pas
Normal file
@@ -0,0 +1,84 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.3.
|
||||
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: acs_types.pas,v $
|
||||
Revision 1.6 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.1 2005/12/19 18:34:35 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/12/04 16:54:34 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
unit acs_types;
|
||||
|
||||
interface
|
||||
|
||||
type
|
||||
|
||||
TACSBuffer16 = array[0..0] of SmallInt;
|
||||
PACSBuffer16 = ^TACSBuffer16;
|
||||
|
||||
TACSBuffer8 = array[0..0] of Byte;
|
||||
PACSBuffer8 = ^TACSBuffer8;
|
||||
|
||||
TACSStereoSample16 = packed record
|
||||
Left, Right : SmallInt;
|
||||
end;
|
||||
|
||||
TACSStereoBuffer16 = array[0..0] of TACSStereoSample16;
|
||||
PACSStereoBuffer16 = ^TACSStereoBuffer16;
|
||||
|
||||
TACSStereoSample8 = packed record
|
||||
Left, Right : Byte;
|
||||
end;
|
||||
|
||||
TACSStereoBuffer8 = array[0..0] of TACSStereoSample8;
|
||||
PACSStereoBuffer8 = ^TACSStereoBuffer8;
|
||||
|
||||
|
||||
TACSComplex = packed record
|
||||
Re, Im : Double;
|
||||
end;
|
||||
|
||||
PACSComplex = ^TACSComplex;
|
||||
|
||||
TACSComplexArray = array[0..0] of TACSComplex;
|
||||
PACSComplexArray = ^TACSComplexArray;
|
||||
|
||||
TACSDoubleArray = array[0..0] of Double;
|
||||
PACSDoubleArray = ^TACSDoubleArray;
|
||||
|
||||
TACSStereoSampleD = record
|
||||
Left : Double;
|
||||
Right : Double;
|
||||
end;
|
||||
|
||||
TACSStereoBufferD = array[0..0] of TACSStereoSampleD;
|
||||
PACSStereoBufferD = ^TACSStereoBufferD;
|
||||
|
||||
const
|
||||
|
||||
Pi = 3.14159265359;
|
||||
TwoPi = 6.28318530718;
|
||||
HalfPi = 1.57079632679;
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
||||
227
acs/Src/classes/acs_volumequery.pas
Normal file
227
acs/Src/classes/acs_volumequery.pas
Normal file
@@ -0,0 +1,227 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.4,
|
||||
copyright (c) 2005 ross levis. all rights reserved.
|
||||
|
||||
Provides linear volume in volLeft and volRight in the range 0 (min) to 32767 (max).
|
||||
Supports 8 and 16 bit samples, mono and stereo.
|
||||
dbLeft and dbRight returns the volume in decibels.
|
||||
Delay is in blocks of 50ms and is required due to unknown output buffer size.
|
||||
Increase Delay to bring VU levels in line with output audio.
|
||||
Suggest using a 50ms Timer to read values.
|
||||
|
||||
$Log: acs_volumequery.pas,v $
|
||||
Revision 1.2 2006/08/31 20:10:54 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/12/19 18:34:35 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/12/04 16:54:34 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.1 2005/11/27 16:50:33 z0m3ie
|
||||
add ACS VolumeQuerry
|
||||
make ACS_VolumeQuerry localizeable
|
||||
some little errorfixes (buffersize for linuxdrivers was initially 0)
|
||||
make TAudioIn workable
|
||||
|
||||
*)
|
||||
|
||||
unit acs_volumequery;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, Math, ACS_Types, ACS_Classes,ACS_Strings;
|
||||
|
||||
type
|
||||
|
||||
TACSVolumeQuery = class(TACSCustomConverter)
|
||||
private
|
||||
Lock : Boolean;
|
||||
FLeft, FRight: Array of Word;
|
||||
FDelay, F50ms: Word;
|
||||
FSR,FBPS,FCh: Integer;
|
||||
protected
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function volLeft: Word;
|
||||
function volRight: Word;
|
||||
function dbLeft: Single;
|
||||
function dbRight: Single;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
published
|
||||
property Delay: Word read FDelay write FDelay;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
constructor TACSVolumeQuery.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
end;
|
||||
|
||||
destructor TACSVolumeQuery.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TACSVolumeQuery.GetBPS : Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
Result := FInput.BitsPerSample;
|
||||
end;
|
||||
|
||||
function TACSVolumeQuery.GetCh : Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
Result := FInput.Channels;
|
||||
end;
|
||||
|
||||
function TACSVolumeQuery.GetSR : Integer;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
Result := FInput.SampleRate;
|
||||
end;
|
||||
|
||||
procedure TACSVolumeQuery.Init;
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputnotAssigned);
|
||||
SetLength(FLeft,FDelay+1);
|
||||
SetLength(FRight,FDelay+1);
|
||||
FillChar(FLeft[0], SizeOf(Word)*(FDelay+1), 0);
|
||||
FillChar(FRight[0], SizeOf(Word)*(FDelay+1), 0);
|
||||
//
|
||||
FBusy := True;
|
||||
FInput.Init;
|
||||
// calc 50ms worth of data
|
||||
FSR := GetSR;
|
||||
FBPS := GetBPS;
|
||||
FCH := GetCh;
|
||||
FPosition := 0;
|
||||
FSize := FInput.Size;
|
||||
F50ms := FSR * FBPS * FCh div 160;
|
||||
Lock := False;
|
||||
end;
|
||||
|
||||
procedure TACSVolumeQuery.Flush;
|
||||
begin
|
||||
FInput.Flush;
|
||||
FBusy := False;
|
||||
Lock := False;
|
||||
end;
|
||||
|
||||
function TACSVolumeQuery.GetData(Buffer: Pointer; BufferSize: Integer): Integer;
|
||||
var
|
||||
LVol, RVol, LMax, RMax: Word;
|
||||
i, NumSamples: Integer;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create(strStreamnotopen);
|
||||
//if FOrigBufferSize = -1 then FOrigBufferSize := BufferSize
|
||||
if BufferSize > F50ms then BufferSize := F50ms;
|
||||
while InputLock do;
|
||||
InputLock := True;
|
||||
Result := FInput.GetData(Buffer, BufferSize);
|
||||
InputLock := False;
|
||||
FPosition := FInput.Position;
|
||||
if Result = 0 then Exit;
|
||||
if Lock then Exit;
|
||||
Lock := True;
|
||||
//
|
||||
if FBPS = 8 then
|
||||
begin
|
||||
if FCh = 1 then NumSamples := Result
|
||||
else NumSamples := Result shr 1;
|
||||
end
|
||||
else begin
|
||||
if FCh = 1 then NumSamples := Result shr 1
|
||||
else NumSamples := Result shr 2;
|
||||
end;
|
||||
//
|
||||
LMax := 0;
|
||||
RMax := 0;
|
||||
for i := 0 to NumSamples-1 do
|
||||
begin
|
||||
if FBPS = 8 then
|
||||
begin
|
||||
if FCh = 1 then
|
||||
begin
|
||||
LVol := ABS(PACSBuffer8(Buffer)[i]-127)*256;
|
||||
RVol := LVol;
|
||||
end
|
||||
else begin
|
||||
LVol := ABS(PACSStereoBuffer8(Buffer)[i].Left-127)*256;
|
||||
RVol := ABS(PACSStereoBuffer8(Buffer)[i].Right-127)*256;
|
||||
end;
|
||||
end
|
||||
else begin
|
||||
if FCh = 1 then
|
||||
begin
|
||||
LVol := ABS(PACSBuffer16(Buffer)[i]);
|
||||
RVol := LVol;
|
||||
end
|
||||
else begin
|
||||
LVol := ABS(PACSStereoBuffer16(Buffer)[i].Left);
|
||||
RVol := ABS(PACSStereoBuffer16(Buffer)[i].Right);
|
||||
end;
|
||||
end;
|
||||
if LVol > LMax then LMax := LVol;
|
||||
if RVol > RMax then RMax := RVol;
|
||||
end;
|
||||
if FDelay > 0 then
|
||||
begin
|
||||
Move(FLeft[1],FLeft[0],FDelay*Sizeof(Word));
|
||||
Move(FRight[1],FRight[0],FDelay*Sizeof(Word));
|
||||
end;
|
||||
FLeft[FDelay] := LMax;
|
||||
FRight[FDelay] := RMax;
|
||||
Lock := False;
|
||||
end;
|
||||
|
||||
function TACSVolumeQuery.volLeft: Word;
|
||||
begin
|
||||
Lock := True;
|
||||
if Busy then Result := FLeft[0]
|
||||
else Result := 0;
|
||||
Lock := False;
|
||||
end;
|
||||
|
||||
function TACSVolumeQuery.volRight: Word;
|
||||
begin
|
||||
Lock := True;
|
||||
if Busy then Result := FRight[0]
|
||||
else Result := 0;
|
||||
Lock := False;
|
||||
end;
|
||||
|
||||
function TACSVolumeQuery.dbLeft: Single;
|
||||
begin
|
||||
Lock := True;
|
||||
if Busy then Result := 10 * Log10((FLeft[0]+1)/32768)
|
||||
else Result := -96;
|
||||
Lock := False;
|
||||
end;
|
||||
|
||||
function TACSVolumeQuery.dbRight: Single;
|
||||
begin
|
||||
Lock := True;
|
||||
if Busy then Result := 10 * Log10((FRight[0]+1)/32768)
|
||||
else Result := -96;
|
||||
Lock := False;
|
||||
end;
|
||||
|
||||
end.
|
||||
384
acs/Src/classes/linux/acs_cdrom.inc
Normal file
384
acs/Src/classes/linux/acs_cdrom.inc
Normal file
@@ -0,0 +1,384 @@
|
||||
{
|
||||
$Log: acs_cdrom.inc,v $
|
||||
Revision 1.7 2006/08/31 20:10:56 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.6 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.2 2005/12/26 17:31:39 z0m3ie
|
||||
fixed some problems in acs_dsfiles
|
||||
fixed some problems in acs_vorbis
|
||||
reworked all buffers
|
||||
|
||||
}
|
||||
|
||||
function GetTocEntry(cd_fd, Track : Integer): TACSCDTrackInfo;
|
||||
var
|
||||
Entry : cdrom_tocentry;
|
||||
toc : cdrom_tochdr;
|
||||
frames1, frames2 : Integer;
|
||||
begin
|
||||
fpioctl(cd_fd, CDROMREADTOCHDR, @toc);
|
||||
Entry.cdte_format := CDROM_MSF;
|
||||
Entry.cdte_track := Track+toc.cdth_trk0-1;
|
||||
fpioctl(cd_fd, CDROMREADTOCENTRY, @Entry);
|
||||
frames1 := MSF2Frames(TACSCDMSF(Entry.cdte_addr.msf));
|
||||
if (Entry.cdte_adr_ctrl and CDROM_DATA_TRACK) <> 0 then
|
||||
Result.TrackType := ttData
|
||||
else Result.TrackType := ttAudio;
|
||||
if Entry.cdte_track < toc.cdth_trk1 then Inc(Entry.cdte_track)
|
||||
else Entry.cdte_track := CDROM_LEADOUT;
|
||||
fpioctl(cd_fd, CDROMREADTOCENTRY, @Entry);
|
||||
frames2 := MSF2Frames(TACSCDMSF(Entry.cdte_addr.msf));
|
||||
Frames2MSF(frames2-frames1, Result.TrackLength);
|
||||
end;
|
||||
|
||||
function GetCDStatus(cd_fd : Integer) : TACSCDStatus;
|
||||
(* not all drivers support the CDROM_DRIVE_STATUS ioctl
|
||||
we use this ioctl first and then some other tecnique
|
||||
if it is not supported. *)
|
||||
var
|
||||
sci : cdrom_subchnl;
|
||||
res :Integer;
|
||||
Data: Integer;
|
||||
begin
|
||||
Data := CDSL_CURRENT;
|
||||
res := fpioctl(cd_fd, CDROM_DRIVE_STATUS, @Data);
|
||||
case res of
|
||||
CDS_TRAY_OPEN, CDS_NO_DISC, CDS_DRIVE_NOT_READY:
|
||||
begin
|
||||
Result := cdsNotReady;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
(* Either the disc is ok or no information
|
||||
from the driver. Trying CDROMSUBCHNL.*)
|
||||
sci.cdsc_format := CDROM_MSF;
|
||||
if fpioctl(cd_fd, CDROMSUBCHNL, @sci) < 0 then
|
||||
begin
|
||||
Result := cdsNotReady;
|
||||
Exit;
|
||||
end;
|
||||
case sci.cdsc_audiostatus of
|
||||
CDROM_AUDIO_PLAY : Result := cdsPlaying;
|
||||
CDROM_AUDIO_PAUSED : Result := cdsPaused;
|
||||
CDROM_AUDIO_ERROR : Result := cdsNotReady;
|
||||
else Result := cdsReady;
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetCDInfo(cd_fd : Integer) : TACSCDInfo;
|
||||
var
|
||||
res : Integer;
|
||||
Data: Integer;
|
||||
begin
|
||||
Result := cdiUnknown;
|
||||
Data := CDSL_CURRENT;
|
||||
res := fpioctl(cd_fd, CDROM_DRIVE_STATUS, @Data);
|
||||
case res of
|
||||
CDS_TRAY_OPEN, CDS_NO_DISC: Result := cdiNoDisc;
|
||||
CDS_DISC_OK :
|
||||
begin
|
||||
res := fpioctl(cd_fd, CDROM_DISC_STATUS, @Data);
|
||||
case res of
|
||||
CDS_AUDIO : Result := cdiDiscAudio;
|
||||
CDS_MIXED : Result := cdiDiscMixed;
|
||||
else Result := cdiDiscData;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TACSCDIn.OpenCD;
|
||||
begin
|
||||
if FCurrentDrive >= length(DrivesPaths) then
|
||||
exit;
|
||||
if FOpened = 0 then
|
||||
begin
|
||||
_cd_fd := fpopen(PChar(DrivesPaths[FCurrentDrive]), O_RDONLY or O_NONBLOCK);
|
||||
if _cd_fd < 0 then
|
||||
raise EACSException.Create(IntToStr(errno));
|
||||
end;
|
||||
Inc(FOpened);
|
||||
end;
|
||||
|
||||
|
||||
procedure TACSCDIn.CloseCD;
|
||||
begin
|
||||
if FOpened = 1 then fpclose(_cd_fd);
|
||||
if FOpened > 0 then Dec(FOpened);
|
||||
end;
|
||||
|
||||
function TACSCDIn.GetInfo;
|
||||
begin
|
||||
if Busy then raise EACSException.Create(strBusy);
|
||||
OpenCD;
|
||||
Result := GetCDInfo(_cd_fd);
|
||||
CloseCD;
|
||||
end;
|
||||
|
||||
function TACSCDIn.GetStatus;
|
||||
begin
|
||||
if FCurrentDrive >= length(DrivesPaths) then
|
||||
exit;
|
||||
if Busy then raise EACSException.Create(strBusy);
|
||||
if Fopened = 0 then
|
||||
_cd_fd := fpopen(PChar(DrivesPaths[FCurrentDrive]), O_RDONLY or O_NONBLOCK);
|
||||
if _cd_fd < 0 then
|
||||
begin
|
||||
Result := cdsNotReady;
|
||||
Exit;
|
||||
end;
|
||||
Inc(FOpened);
|
||||
Result := GetCDStatus(_cd_fd);
|
||||
CloseCD;
|
||||
end;
|
||||
|
||||
function TACSCDIn.GetNumTracks;
|
||||
var
|
||||
toc : cdrom_tochdr;
|
||||
begin
|
||||
if Busy then raise EACSException.Create(strBusy);
|
||||
OpenCD;
|
||||
if GetStatus <> cdsNotReady then
|
||||
begin
|
||||
fpioctl(_cd_fd, CDROMREADTOCHDR, @toc);
|
||||
Result := toc.cdth_trk1 - toc.cdth_trk0 + 1;
|
||||
end else Result := 0;
|
||||
CloseCD;
|
||||
end;
|
||||
|
||||
function TACSCDIn.GetTrackInfo;
|
||||
begin
|
||||
if Busy then raise EACSException.Create(strBusy);
|
||||
OpenCD;
|
||||
if (vIndex in [1..GetNumTracks]) = False then
|
||||
begin
|
||||
fpclose(_cd_fd);
|
||||
FOpened := 0;
|
||||
raise EACSException.Create(strTrackOutofRange);
|
||||
end;
|
||||
Result := GetTocEntry(_cd_fd, vIndex);
|
||||
CloseCD;
|
||||
end;
|
||||
|
||||
function GetTrackMSF(cd_fd, Track : Integer) : TACSCDMSF;
|
||||
var
|
||||
entry : cdrom_tocentry;
|
||||
hdr : cdrom_tochdr;
|
||||
begin
|
||||
fpioctl(cd_fd, CDROMREADTOCHDR, @hdr);
|
||||
entry.cdte_format := CDROM_MSF;
|
||||
entry.cdte_track := Track + hdr.cdth_trk0 - 1;
|
||||
if entry.cdte_track > hdr.cdth_trk1 then
|
||||
entry.cdte_track := CDROM_LEADOUT;
|
||||
fpioctl(cd_fd, CDROMREADTOCENTRY, @entry);
|
||||
Result := TACSCDMSF(entry.cdte_addr.msf);
|
||||
end;
|
||||
|
||||
function GetPosMSF(cd_fd : Integer; Pos : TACSCDPosition) : TACSCDMSF;
|
||||
var
|
||||
msf1 : TACSCDMSF;
|
||||
frames : Integer;
|
||||
begin
|
||||
msf1 := TACSCDMSF(GetTrackMSF(cd_fd, Pos.Track));
|
||||
frames := MSF2Frames(msf1);
|
||||
frames := frames + MSF2Frames(Pos.MSF);
|
||||
Frames2MSF(frames, msf1);
|
||||
Result := msf1;
|
||||
end;
|
||||
|
||||
procedure TACSCDIn.SetST;
|
||||
begin
|
||||
if Self.Busy then raise EACSException.Create(strBusy);
|
||||
FStartTrack := Track;
|
||||
FStartPos.Track := FStartTrack;
|
||||
FillChar(FStartPos.MSF, SizeOf(FStartPos.MSF), 0);
|
||||
end;
|
||||
|
||||
procedure TACSCDIn.SetET;
|
||||
begin
|
||||
if Self.Busy then raise EACSException.Create(strBusy);
|
||||
FEndTrack := Track;
|
||||
OpenCD;
|
||||
FEndPos.Track := FEndTrack + 1;
|
||||
FillChar(FEndPos.MSF, SizeOf(FEndPos.MSF), 0);
|
||||
CloseCD;
|
||||
end;
|
||||
|
||||
procedure TACSCDIn.SetSP;
|
||||
begin
|
||||
if Self.Busy then raise EACSException.Create(strBusy);
|
||||
Self.FStartPos := Pos;
|
||||
end;
|
||||
|
||||
procedure TACSCDIn.SetEP;
|
||||
begin
|
||||
if Self.Busy then raise EACSException.Create(strBusy);
|
||||
Self.FEndPos := Pos;
|
||||
end;
|
||||
|
||||
constructor TACSCDIn.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FCurrentDrive := 0;
|
||||
end;
|
||||
|
||||
function TACSCDIn.GetSize;
|
||||
var
|
||||
msf1, msf2 : TACSCDMSF;
|
||||
begin
|
||||
if Busy then raise EACSException.Create(strBusy);
|
||||
OpenCD;
|
||||
msf1 := GetPosMSF(_cd_fd, FStartPos);
|
||||
msf2 := GetPosMSF(_cd_fd, FEndPos);
|
||||
CloseCD;
|
||||
Result := ((msf2.minute*60 + msf2.second)*75 + msf2.frame -
|
||||
((msf1.minute*60 + msf1.second)*75 + msf1.frame))*CD_FRAMESIZE_RAW;
|
||||
end;
|
||||
|
||||
procedure TACSCDIn.Init;
|
||||
begin
|
||||
if Busy then raise EACSException.Create(strBusy);
|
||||
if not (DiscInfo in [cdiDiscAudio, cdiDiscMixed]) then
|
||||
raise EACSException.Create(strNoAudioCD);
|
||||
FSize := GetSize;
|
||||
FBusy := True;
|
||||
BufStart := 1;
|
||||
BufEnd := 0;
|
||||
FPosition := 0;
|
||||
OpenCD;
|
||||
FCurPos := GetPosMSF(_cd_fd, FStartPos);
|
||||
FEndMSF := GetPosMSF(_cd_fd, FEndPos);
|
||||
// GetMem(FBuffer,BUF_SIZE * CD_FRAMESIZE_RAW);
|
||||
end;
|
||||
|
||||
procedure TACSCDIn.Flush;
|
||||
begin
|
||||
CloseCD;
|
||||
FBusy := False;
|
||||
// FreeMem(FBuffer);
|
||||
FSize := 0;
|
||||
end;
|
||||
|
||||
function TACSCDIn.GetData;
|
||||
var
|
||||
StartFrame, EndFrame : Integer;
|
||||
cdaudio : cdrom_read_audio;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create(strStreamnotopen);
|
||||
StartFrame := MSF2Frames(FCurPos);
|
||||
EndFrame := MSF2Frames(FEndMSF);
|
||||
if BufStart > BufEnd then
|
||||
begin
|
||||
if EndFrame = StartFrame then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
BufStart := 1;
|
||||
if (EndFrame - StartFrame) > (BUF_SIZE) then
|
||||
cdaudio.nframes := BUF_SIZE
|
||||
else
|
||||
cdaudio.nframes := EndFrame - StartFrame;
|
||||
cdaudio.addr_format := CDROM_MSF;
|
||||
cdaudio.addr.msf := cdrom_msf0(FCurPos);
|
||||
cdaudio.buf := Pointer(FBuffer);
|
||||
fpioctl(_cd_fd, CDROMREADAUDIO, @cdaudio);
|
||||
BufEnd := cdaudio.nframes * CD_FRAMESIZE_RAW;
|
||||
StartFrame := MSF2Frames(FCurPos) + cdaudio.nframes;
|
||||
Frames2MSF(StartFrame, FCurPos);
|
||||
end;
|
||||
if BufferSize < (BufEnd - BufStart + 1)
|
||||
then Result := BufferSize
|
||||
else Result := BufEnd - BufStart + 1;
|
||||
Move(FBuffer[BufStart], Buffer^, Result);
|
||||
Inc(BufStart, Result);
|
||||
Inc(FPosition, Result);
|
||||
end;
|
||||
|
||||
procedure TACSCDIn.Eject;
|
||||
var
|
||||
Data: Integer;
|
||||
begin
|
||||
if Busy then raise EACSException.Create(strBusy);
|
||||
OpenCD;
|
||||
Data := 0;
|
||||
fpioctl(_cd_fd, CDROMEJECT,@Data);
|
||||
CloseCD;
|
||||
end;
|
||||
|
||||
procedure TACSCDIn.CloseTray;
|
||||
var
|
||||
Data: Integer;
|
||||
begin
|
||||
OpenCD;
|
||||
Data := 0;
|
||||
fpioctl(_cd_fd, CDROMCLOSETRAY,@Data);
|
||||
CloseCD;
|
||||
end;
|
||||
|
||||
procedure CountDrives;
|
||||
var
|
||||
_cd_fd, i : Integer;
|
||||
fname : String;
|
||||
sci : cdrom_subchnl;
|
||||
res :Integer;
|
||||
Data: Integer;
|
||||
begin
|
||||
DrivesCount := 0;
|
||||
Data := CDSL_CURRENT;
|
||||
for i := 0 to 3 do
|
||||
begin
|
||||
fname := '/dev/hd'+chr(ord('a')+i);
|
||||
_cd_fd := fpopen(PChar(fname), O_RDONLY or O_NONBLOCK);
|
||||
if _cd_fd >= 0 then
|
||||
begin
|
||||
res := fpioctl(_cd_fd, CDROM_DRIVE_STATUS, @Data);
|
||||
case res of
|
||||
CDS_TRAY_OPEN, CDS_NO_DISC, CDS_DRIVE_NOT_READY:
|
||||
begin
|
||||
inc(DrivesCount);
|
||||
setlength(DrivesPaths,DrivesCount);
|
||||
DrivesPaths[DrivesCount-1] := fname;
|
||||
fpclose(_cd_fd);
|
||||
continue;
|
||||
end;
|
||||
end;
|
||||
(* Either the disc is ok or no information
|
||||
from the driver. Trying CDROMSUBCHNL.*)
|
||||
sci.cdsc_format := CDROM_MSF;
|
||||
if fpioctl(_cd_fd, CDROMSUBCHNL, @sci) >= 0 then
|
||||
begin
|
||||
inc(DrivesCount);
|
||||
setlength(DrivesPaths,DrivesCount);
|
||||
DrivesPaths[DrivesCount-1] := fname;
|
||||
end;
|
||||
fpclose(_cd_fd);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TACSCDIn.GetDrivesCount : Integer;
|
||||
begin
|
||||
Result := DrivesCount;
|
||||
end;
|
||||
|
||||
procedure TACSCDIn.SetCurrentDrive(Value : Integer);
|
||||
begin
|
||||
if Busy then raise EACSException.Create(strBusy);
|
||||
FCurrentDrive := Value;
|
||||
end;
|
||||
|
||||
function TACSCDIn.GetDriveName : String;
|
||||
begin
|
||||
Result := '';
|
||||
end;
|
||||
|
||||
destructor TACSCDIn.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
|
||||
293
acs/Src/classes/linux/acs_mixer.inc
Normal file
293
acs/Src/classes/linux/acs_mixer.inc
Normal file
@@ -0,0 +1,293 @@
|
||||
{
|
||||
$Log: acs_mixer.inc,v $
|
||||
Revision 1.2 2005/12/30 12:54:42 z0m3ie
|
||||
some error checks
|
||||
|
||||
Revision 1.1 2005/12/19 18:35:03 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.3 2005/12/04 16:54:34 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.2 2005/09/13 21:54:11 z0m3ie
|
||||
acs is localizeable now (ACS_Strings)
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.4 2005/09/09 21:33:43 z0m3ie
|
||||
linux corrections
|
||||
|
||||
Revision 1.3 2005/08/31 20:30:40 z0m3ie
|
||||
Mixer Channelname work now
|
||||
minior corrections for Converters
|
||||
|
||||
Revision 1.2 2005/08/28 20:31:18 z0m3ie
|
||||
linux restructuring for 2.4
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
}
|
||||
|
||||
|
||||
type
|
||||
TMixerInfo = record
|
||||
Path : String;
|
||||
Name : String;
|
||||
end;
|
||||
|
||||
const
|
||||
MAX_MIXERS = 5; (* There shouldn't be more than
|
||||
5 valid mixers in the system.
|
||||
Right? *)
|
||||
|
||||
var
|
||||
Mixers : array[0..MAX_MIXERS] of TMixerInfo; // one extra slot for /dev/mixer device
|
||||
|
||||
function GetChannelMask(Ch : TACSMixerChannel; Request : Integer): LongWord;
|
||||
begin
|
||||
Result := 0;
|
||||
case Request of
|
||||
0:
|
||||
case Ch of
|
||||
mcVolume: Result := SOUND_MIXER_VOLUME;
|
||||
mcTreble: Result := SOUND_MIXER_TREBLE;
|
||||
mcBass: Result := SOUND_MIXER_BASS;
|
||||
mcSynth: Result := SOUND_MIXER_SYNTH;
|
||||
mcPCM: Result := SOUND_MIXER_PCM;
|
||||
mcSpeaker: Result := SOUND_MIXER_SPEAKER;
|
||||
mcLine: Result := SOUND_MIXER_LINE;
|
||||
mcMic: Result := SOUND_MIXER_MIC;
|
||||
mcCD: Result := SOUND_MIXER_CD;
|
||||
mcIMix: Result := SOUND_MIXER_IMIX;
|
||||
mcAltPCM: Result := SOUND_MIXER_ALTPCM;
|
||||
mcRecLev: Result := SOUND_MIXER_RECLEV;
|
||||
mcUnknown: Result := 0;
|
||||
end;
|
||||
1:
|
||||
case Ch of
|
||||
mcVolume: Result := SOUND_MIXER_WRITE_VOLUME;
|
||||
mcTreble: Result := SOUND_MIXER_WRITE_TREBLE;
|
||||
mcBass: Result := SOUND_MIXER_WRITE_BASS;
|
||||
mcSynth: Result := SOUND_MIXER_WRITE_SYNTH;
|
||||
mcPCM: Result := SOUND_MIXER_WRITE_PCM;
|
||||
mcSpeaker: Result := SOUND_MIXER_WRITE_SPEAKER;
|
||||
mcLine: Result := SOUND_MIXER_WRITE_LINE;
|
||||
mcMic: Result := SOUND_MIXER_WRITE_MIC;
|
||||
mcCD: Result := SOUND_MIXER_WRITE_CD;
|
||||
mcIMix: Result := SOUND_MIXER_WRITE_IMIX;
|
||||
mcAltPCM: Result := SOUND_MIXER_WRITE_ALTPCM;
|
||||
mcRecLev: Result := SOUND_MIXER_WRITE_RECLEV;
|
||||
mcUnknown: Result := 0;
|
||||
end;
|
||||
2:
|
||||
case Ch of
|
||||
mcVolume: Result := SOUND_MIXER_READ_VOLUME;
|
||||
mcTreble: Result := SOUND_MIXER_READ_TREBLE;
|
||||
mcBass: Result := SOUND_MIXER_READ_BASS;
|
||||
mcSynth: Result := SOUND_MIXER_READ_SYNTH;
|
||||
mcPCM: Result := SOUND_MIXER_READ_PCM;
|
||||
mcSpeaker: Result := SOUND_MIXER_READ_SPEAKER;
|
||||
mcLine: Result := SOUND_MIXER_READ_LINE;
|
||||
mcMic: Result := SOUND_MIXER_READ_MIC;
|
||||
mcCD: Result := SOUND_MIXER_READ_CD;
|
||||
mcIMix: Result := SOUND_MIXER_READ_IMIX;
|
||||
mcAltPCM: Result := SOUND_MIXER_READ_ALTPCM;
|
||||
mcRecLev: Result := SOUND_MIXER_READ_RECLEV;
|
||||
mcUnknown: Result := 0;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetChannelType(Mask : Integer) : TACSMixerChannel;
|
||||
begin
|
||||
case Mask of
|
||||
SOUND_MIXER_VOLUME: Result := mcVolume;
|
||||
SOUND_MIXER_TREBLE: Result := mcTreble;
|
||||
SOUND_MIXER_BASS: Result := mcBass;
|
||||
SOUND_MIXER_SYNTH: Result := mcSynth;
|
||||
SOUND_MIXER_PCM: Result := mcPCM;
|
||||
SOUND_MIXER_SPEAKER: Result := mcSpeaker;
|
||||
SOUND_MIXER_LINE: Result := mcLine;
|
||||
SOUND_MIXER_MIC: Result := mcMic;
|
||||
SOUND_MIXER_CD: Result := mcCD;
|
||||
SOUND_MIXER_IMIX: Result := mcIMix;
|
||||
SOUND_MIXER_ALTPCM: Result := mcAltPCM;
|
||||
SOUND_MIXER_RECLEV: Result := mcRecLev;
|
||||
else Result := mcUnknown;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TACSMixer.SetDevNum(Num : Integer);
|
||||
var
|
||||
DevMask, i : Integer;
|
||||
Channel : TACSMixerChannel;
|
||||
begin
|
||||
if Num in [0..MixersCount - 1] then // check [0..0] [0..-1]
|
||||
begin
|
||||
FFileName := Mixers[Num].Path;
|
||||
FMixerName := Mixers[Num].Name;
|
||||
setlength(FChannels,0);
|
||||
_mix_fd := fpopen(PChar(FFileName), O_RDONLY);
|
||||
fpioctl(_mix_fd, SOUND_MIXER_READ_DEVMASK, @DevMask);
|
||||
fpclose(_mix_fd);
|
||||
for i:=0 to 31 do
|
||||
begin
|
||||
if (DevMask and (1 shl i)) <> 0 then
|
||||
begin
|
||||
Channel := GetChannelType(i);
|
||||
if Channel <> mcUnknown then
|
||||
begin
|
||||
setlength(FChannels,length(FChannels)+1);
|
||||
FChannels[length(FChannels)-1] := Channel;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TACSMixer.GetRecSource;
|
||||
var
|
||||
rs, pow,i : Integer;
|
||||
begin
|
||||
Result := -1;
|
||||
_mix_fd := fpopen(PChar(FFileName), O_RDONLY);
|
||||
fpioctl(_mix_fd, SOUND_MIXER_READ_RECSRC, @rs);
|
||||
fpclose(_mix_fd);
|
||||
pow := 0;
|
||||
while rs <> 1 do
|
||||
begin
|
||||
rs := rs shr 1;
|
||||
Inc(pow);
|
||||
end;
|
||||
for i := 0 to length(FChannels)-1 do
|
||||
if FChannels[i] = GetChannel(pow) then
|
||||
Result := i;
|
||||
end;
|
||||
|
||||
function TACSMixer.GetVolume;
|
||||
var
|
||||
vol, chan : Integer;
|
||||
begin
|
||||
_mix_fd := fpopen(PChar(FFileName), O_RDONLY);
|
||||
chan := GetChannelMask(FChannels[vChannel], 2);
|
||||
fpioctl(_mix_fd, chan, @vol);
|
||||
fpclose(_mix_fd);
|
||||
if vol > 255 then
|
||||
begin
|
||||
Result.Left := Lo(vol);
|
||||
Result.Right := Lo(vol shr 8);
|
||||
end else Result.Main := vol;
|
||||
end;
|
||||
|
||||
function TACSMixer.IsStereo;
|
||||
var
|
||||
mask, chan : Integer;
|
||||
begin
|
||||
_mix_fd := fpopen(PChar(FFileName), O_RDONLY);
|
||||
fpioctl(_mix_fd, SOUND_MIXER_READ_STEREODEVS, @mask);
|
||||
chan := GetChannelMask(FChannels[vChannel], 0);
|
||||
fpclose(_mix_fd);
|
||||
Result := (mask and (1 shl chan))<>0;
|
||||
end;
|
||||
|
||||
function TACSMixer.IsRecordable;
|
||||
var
|
||||
mask, chan : Integer;
|
||||
begin
|
||||
_mix_fd := fpopen(PChar(FFileName), O_RDONLY);
|
||||
fpioctl(_mix_fd, SOUND_MIXER_READ_RECMASK, @mask);
|
||||
chan := GetChannelMask(FChannels[vChannel], 0);
|
||||
fpclose(_mix_fd);
|
||||
Result := (mask and (1 shl chan))<>0;
|
||||
end;
|
||||
|
||||
procedure TACSMixer.SetRecSource;
|
||||
var
|
||||
chan : Integer;
|
||||
begin
|
||||
chan := 1 shl GetChannelMask(FChannels[vChannel], 0);
|
||||
_mix_fd := fpopen(PChar(FFileName), O_WRONLY);
|
||||
fpioctl(_mix_fd, SOUND_MIXER_WRITE_RECSRC, @chan);
|
||||
fpclose(_mix_fd);
|
||||
if chan <> (1 shl GetChannelMask(FChannels[vChannel], 0)) then
|
||||
raise EACSException.Create(Format(strChannelnotRecordable,[vChannel]));
|
||||
end;
|
||||
|
||||
function TACSMixer.GetMute(vChannel : integer) : Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
procedure TACSMixer.SetMute(vChannel : integer; Mute : Boolean);
|
||||
begin
|
||||
end;
|
||||
|
||||
procedure TACSMixer.SetVolume;
|
||||
var
|
||||
vol, chan : Integer;
|
||||
begin
|
||||
chan := GetChannelMask(FChannels[vChannel], 1);
|
||||
if IsStereo(vChannel) then
|
||||
vol := vLevel.Left + (vLevel.Right shl 8)
|
||||
else vol := vLevel.Main;
|
||||
_mix_fd := fpopen(PChar(FFileName), O_WRONLY);
|
||||
fpioctl(_mix_fd, chan, @vol);
|
||||
fpclose(_mix_fd);
|
||||
end;
|
||||
|
||||
destructor TACSMixer.Destroy;
|
||||
begin
|
||||
Setlength(FChannels,0);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function CountMixers : Byte;
|
||||
var
|
||||
fd, i, DevMask : Integer;
|
||||
fname : String;
|
||||
mi : mixer_info;
|
||||
begin
|
||||
Result := 0;
|
||||
for i := 0 to MAX_MIXERS-1 do
|
||||
begin
|
||||
fname := '/dev/mixer'+IntToStr(i-1);
|
||||
try
|
||||
fd := fpopen(PChar(fname), O_RDONLY);
|
||||
except
|
||||
Break;
|
||||
end;
|
||||
if fd = -1 then Break;
|
||||
DevMask := 0;
|
||||
fpioctl(fd, SOUND_MIXER_READ_DEVMASK, @DevMask);
|
||||
if DevMask <> 0 then
|
||||
begin
|
||||
Mixers[Result].Path := fname;
|
||||
fpioctl(fd, SOUND_MIXER_INFO, @mi);
|
||||
Mixers[Result].Name := String(mi.name);
|
||||
Inc(Result);
|
||||
end;
|
||||
fpclose(fd);
|
||||
end;
|
||||
fname := '/dev/mixer';
|
||||
try
|
||||
fd := fpopen(PChar(fname), O_RDONLY);
|
||||
except
|
||||
Exit;
|
||||
end;
|
||||
if fd = -1 then Exit;
|
||||
fpioctl(fd, SOUND_MIXER_READ_DEVMASK, @DevMask);
|
||||
if DevMask <> 0 then
|
||||
begin
|
||||
Mixers[Result].Path := fname;
|
||||
fpioctl(fd, SOUND_MIXER_INFO, @mi);
|
||||
Mixers[Result].Name := String(mi.name);
|
||||
end;
|
||||
fpclose(fd);
|
||||
Inc(Result);
|
||||
end;
|
||||
|
||||
392
acs/Src/classes/linux/cd_rom.pas
Normal file
392
acs/Src/classes/linux/cd_rom.pas
Normal file
@@ -0,0 +1,392 @@
|
||||
(* cd_rom kylix unit
|
||||
translated from cdrom.h by andrei borovsky.
|
||||
|
||||
this unit contains declarations translated
|
||||
from the huge cdrom.h header file. In fact
|
||||
cdrom.h covers a lot of stuff concerning
|
||||
CDs, DVDs, writable CDs, etc. Of all these
|
||||
there are only the declarations needed for
|
||||
reading/playing CDs in this unit. *)
|
||||
(*
|
||||
This file is a part of Audio Components Suite v 2.3.
|
||||
Copyright (c) 2002-2005 Andrei Borovsky. All rights reserved.
|
||||
See the LICENSE file for more details.
|
||||
You can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: cd_rom.pas,v $
|
||||
Revision 1.3 2005/12/19 18:35:03 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
|
||||
unit cd_rom;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
baseunix,unix;
|
||||
|
||||
type
|
||||
__U8 = Byte;
|
||||
request_sense = Byte;
|
||||
(* request_sense is a bitmask : veeeeeee
|
||||
v - valid
|
||||
eeeeeee - error code
|
||||
*)
|
||||
PRequest_sense = ^request_sense;
|
||||
|
||||
//const
|
||||
// EDRIVE_CANT_DO_THIS = EOPNOTSUPP;
|
||||
|
||||
(*
|
||||
The CD-ROM IOCTL commands -- these should be supported by }
|
||||
all the various cdrom drivers. For the CD-ROM ioctls, we }
|
||||
will commandeer byte 0x53, or 'S'. *)
|
||||
|
||||
const
|
||||
|
||||
CDROMPAUSE = $5301; // Pause Audio Operation
|
||||
CDROMRESUME = $5302; // Resume paused Audio Operation
|
||||
CDROMPLAYMSF = $5303; // Play Audio MSF (struct cdrom_msf)
|
||||
CDROMPLAYTRKIND = $5304; // Play Audio Track/index
|
||||
CDROMREADTOCHDR = $5305; // Read TOC header
|
||||
CDROMREADTOCENTRY = $5306; // Read TOC entry
|
||||
CDROMSTOP = $5307; // Stop the cdrom drive
|
||||
CDROMSTART = $5308; // Start the cdrom drive
|
||||
CDROMEJECT = $5309; // Ejects the cdrom media
|
||||
CDROMVOLCTRL = $530a; // Control output volume
|
||||
CDROMSUBCHNL = $530b; // Read subchannel data
|
||||
CDROMREADMODE2 = $530c; // Read CDROM mode 2 data (2336 Bytes)
|
||||
CDROMREADMODE1 = $530d; // Read CDROM mode 1 data (2048 Bytes)
|
||||
CDROMREADAUDIO = $530e; // (struct cdrom_read_audio)
|
||||
CDROMEJECT_SW = $530; // enable(1)/disable(0) auto-ejecting
|
||||
CDROMMULTISESSION = $5310; // Obtain the start-of-last-session
|
||||
CDROM_GET_MCN = $5311; // Obtain the "Universal Product Code"
|
||||
CDROM_GET_UPC = CDROM_GET_MCN; // depricated
|
||||
CDROMRESET = $5312; // hard-reset the drive
|
||||
CDROMVOLREAD = $5313; // Get the drive's volume setting
|
||||
CDROMREADRAW = $5314; // read data in raw mode (2352 Bytes)
|
||||
|
||||
{ These ioctls are used only used in aztcd.c and optcd.c }
|
||||
|
||||
CDROMREADCOOKED = $5315; // read data in cooked mode
|
||||
CDROMSEEK = $5316; // seek msf address
|
||||
|
||||
{ This ioctl is only used by the scsi-cd driver. }
|
||||
{ It is for playing audio in logical block addressing mode. }
|
||||
|
||||
CDROMPLAYBLK = $5317; // (struct cdrom_blk)
|
||||
|
||||
{ These ioctls are only used in optcd.c }
|
||||
|
||||
CDROMREADALL = $5318; // read all 2646 bytes
|
||||
|
||||
(* These ioctls are (now) only in ide-cd.c for controlling
|
||||
drive spindown time. They should be implemented in the
|
||||
Uniform driver, via generic packet commands, GPCMD_MODE_SELECT_10,
|
||||
GPCMD_MODE_SENSE_10 and the GPMODE_POWER_PAGE...
|
||||
-Erik *)
|
||||
|
||||
const
|
||||
|
||||
CDROMGETSPINDOWN = $531d;
|
||||
CDROMSETSPINDOWN = $531e;
|
||||
|
||||
(* These ioctls are implemented through the uniform CD-ROM driver
|
||||
They _will_ be adopted by all CD-ROM drivers, when all the CD-ROM
|
||||
drivers are eventually ported to the uniform CD-ROM driver interface. *)
|
||||
|
||||
const
|
||||
|
||||
CDROMCLOSETRAY = $5319; // pendant of CDROMEJECT
|
||||
CDROM_SET_OPTIONS = $5320; // Set behavior options
|
||||
CDROM_CLEAR_OPTIONS = $5321; // Clear behavior options
|
||||
CDROM_SELECT_SPEED = $5322; // Set the CD-ROM speed
|
||||
CDROM_SELECT_DISC = $5323; // Select disc (for juke-boxes)
|
||||
CDROM_MEDIA_CHANGED = $5325; // Check is media changed
|
||||
CDROM_DRIVE_STATUS = $5326; // Get tray position, etc.
|
||||
CDROM_DISC_STATUS = $5327; // Get disc type, etc.
|
||||
CDROM_CHANGER_NSLOTS = $5328; // Get number of slots
|
||||
CDROM_LOCKDOOR = $5329; // lock or unlock door
|
||||
CDROM_DEBUG = $5330; // Turn debug messages on/off
|
||||
CDROM_GET_CAPABILITY = $5331; // get capabilities
|
||||
|
||||
// This ioctl is only used by sbpcd at the moment
|
||||
|
||||
CDROMAUDIOBUFSIZ = $5382; // set the audio buffer size
|
||||
CDROM_SEND_PACKET = $5393; // send a packet to the drive
|
||||
CDROM_NEXT_WRITABLE = $5394; // get next writable block
|
||||
CDROM_LAST_WRITTEN = $5395; // get last block written on disc
|
||||
|
||||
//******************************************************}
|
||||
// CDROM IOCTL structures
|
||||
//******************************************************}
|
||||
|
||||
type
|
||||
|
||||
// Address in MSF format
|
||||
cdrom_msf0 = record
|
||||
minute: __U8;
|
||||
second: __U8;
|
||||
frame: __U8;
|
||||
end;
|
||||
|
||||
// Address in either MSF or logical format
|
||||
cdrom_addr = record
|
||||
case Word of
|
||||
1: (msf: cdrom_msf0;);
|
||||
2: (lba: Integer;);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
(* cdrom_msf renamed to cdrom_msf_t since there is
|
||||
also a cdrom_msf constant in this unit *)
|
||||
|
||||
// This struct is used by the CDROMPLAYMSF ioctl
|
||||
cdrom_msf_t = record
|
||||
cdmsf_min0: __U8; // start minute
|
||||
cdmsf_sec0: __U8; // start second
|
||||
cdmsf_frame0: __U8; // start frame
|
||||
cdmsf_min1: __U8; // end minute
|
||||
cdmsf_sec1: __U8; // end second
|
||||
cdmsf_frame1: __U8; // end frame
|
||||
end;
|
||||
|
||||
// This struct is used by the CDROMPLAYTRKIND ioctl
|
||||
cdrom_ti = record
|
||||
cdti_trk0: __U8; // start track
|
||||
cdti_ind0: __U8; // start index
|
||||
cdti_trk1: __U8; // end track
|
||||
cdti_ind1: __U8; // end index
|
||||
end;
|
||||
|
||||
// This struct is used by the CDROMREADTOCHDR ioctl
|
||||
cdrom_tochdr = record
|
||||
cdth_trk0: __U8; // start track
|
||||
cdth_trk1: __U8; // end track
|
||||
end;
|
||||
|
||||
// This struct is used by the CDROMVOLCTRL and CDROMVOLREAD ioctls
|
||||
cdrom_volctrl = record
|
||||
channel0: __U8;
|
||||
channel1: __U8;
|
||||
channel2: __U8;
|
||||
channel3: __U8;
|
||||
end;
|
||||
|
||||
// This struct is used by the CDROMSUBCHNL ioctl
|
||||
cdrom_subchnl = record
|
||||
cdsc_format: __U8;
|
||||
cdsc_audiostatus: __U8;
|
||||
CDSC_ADR_CTRL : __U8; // 4 bits - ADR, 4 bits - CTRL
|
||||
cdsc_trk: __U8;
|
||||
cdsc_ind: __U8;
|
||||
cdsc_absaddr: cdrom_addr;
|
||||
cdsc_reladdr: cdrom_addr;
|
||||
end;
|
||||
|
||||
|
||||
// This struct is used by the CDROMREADTOCENTRY ioctl
|
||||
cdrom_tocentry = record
|
||||
cdte_track: __U8;
|
||||
cdte_adr_ctrl: __U8;
|
||||
cdte_format: __U8;
|
||||
cdte_addr: cdrom_addr;
|
||||
cdte_datamode: __U8;
|
||||
end;
|
||||
|
||||
// This struct is used by the CDROMREADMODE1, and CDROMREADMODE2 ioctls
|
||||
cdrom_read = record
|
||||
cdread_lba: Integer;
|
||||
cdread_bufaddr: PChar;
|
||||
cdread_buflen: Integer;
|
||||
end;
|
||||
|
||||
// This struct is used by the CDROMREADAUDIO ioctl
|
||||
cdrom_read_audio = record
|
||||
addr: cdrom_addr; // frame address
|
||||
addr_format: __U8; // CDROM_LBA or CDROM_MSF
|
||||
nframes: Integer; // number of 2352-byte-frames to read at once
|
||||
buf: PChar; // frame buffer (size: nframes*2352 bytes)
|
||||
end;
|
||||
|
||||
// This struct is used with the CDROMMULTISESSION ioctl
|
||||
cdrom_multisession = record
|
||||
addr: cdrom_addr;
|
||||
(* frame address: start-of-last-session
|
||||
(not the new "frame 16"!). Only valid
|
||||
if the "xa_flag" is true. *)
|
||||
xa_flag: __U8; // 1: "is XA disk"
|
||||
addr_format: __U8; // CDROM_LBA or CDROM_MSF }
|
||||
end;
|
||||
|
||||
(* This struct is used with the CDROM_GET_MCN ioctl.
|
||||
Very few audio discs actually have Universal Product Code information,
|
||||
which should just be the Medium Catalog Number on the box. Also note
|
||||
that the way the codeis written on CD is _not_ uniform across all discs! *)
|
||||
|
||||
cdrom_mcn = record
|
||||
medium_catalog_number: array[0..13] of __U8;
|
||||
{ 13 ASCII digits, null-terminated }
|
||||
end;
|
||||
|
||||
// This is used by the CDROMPLAYBLK ioctl
|
||||
type
|
||||
cdrom_blk = record
|
||||
from: Word;
|
||||
len: Word;
|
||||
end;
|
||||
|
||||
const
|
||||
CDROM_PACKET_SIZE = 12;
|
||||
CGC_DATA_UNKNOWN = 0;
|
||||
CGC_DATA_WRITE = 1;
|
||||
CGC_DATA_READ = 2;
|
||||
CGC_DATA_NONE = 3;
|
||||
|
||||
// for CDROM_PACKET_COMMAND ioctl
|
||||
type
|
||||
cdrom_generic_command = record
|
||||
cmd: array[0..CDROM_PACKET_SIZE-1] of Byte;
|
||||
buffer: PByte;
|
||||
buflen: Word;
|
||||
stat: Integer;
|
||||
sense: PREQUEST_SENSE;
|
||||
data_direction: Byte;
|
||||
quiet: Integer;
|
||||
timeout: Integer;
|
||||
reserved: array[0..0] of Pointer;
|
||||
end;
|
||||
|
||||
// Some generally useful CD-ROM information -- mostly based on the above
|
||||
const
|
||||
|
||||
CD_MINS = 74; // max. minutes per CD, not really a limit
|
||||
CD_SECS = 60; // seconds per minute
|
||||
CD_FRAMES = 75; // frames per second
|
||||
CD_SYNC_SIZE = 12; // 12 sync bytes per raw data frame
|
||||
CD_MSF_OFFSET = 150; // MSF numbering offset of first frame
|
||||
CD_CHUNK_SIZE = 24; // lowest-level 'data bytes piece'
|
||||
CD_NUM_OF_CHUNKS = 98; // chunks per frame
|
||||
CD_FRAMESIZE_SUB = 96; // subchannel data 'frame' size
|
||||
CD_HEAD_SIZE = 4; // header (address) bytes per raw data frame
|
||||
CD_SUBHEAD_SIZE = 8; // subheader bytes per raw XA data frame
|
||||
CD_EDC_SIZE = 4; // bytes EDC per most raw data frame types
|
||||
CD_ZERO_SIZE = 8; // bytes zero per yellow book mode 1 frame
|
||||
CD_ECC_SIZE = 276; // bytes ECC per most raw data frame types
|
||||
CD_FRAMESIZE = 2048; // bytes per frame, 'cooked' mode
|
||||
CD_FRAMESIZE_RAW = 2352; // bytes per frame, 'raw' mode
|
||||
CD_FRAMESIZE_RAWER = 2646; // The maximum possible returned bytes
|
||||
|
||||
// most drives don't deliver everything:
|
||||
|
||||
CD_FRAMESIZE_RAW1 = (CD_FRAMESIZE_RAW-CD_SYNC_SIZE); //2340
|
||||
CD_FRAMESIZE_RAW0 = (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE); //2336
|
||||
CD_XA_HEAD = (CD_HEAD_SIZE+CD_SUBHEAD_SIZE); // 'before data' part of raw XA frame
|
||||
CD_XA_TAIL = (CD_EDC_SIZE+CD_ECC_SIZE); // 'after data' part of raw XA frame
|
||||
CD_XA_SYNC_HEAD = (CD_SYNC_SIZE+CD_XA_HEAD); // sync bytes + header of XA frame
|
||||
|
||||
// CD-ROM address types (cdrom_tocentry.cdte_format)
|
||||
|
||||
CDROM_LBA = $01; // 'logical block': first frame is #0
|
||||
CDROM_MSF = $02; // 'minute-second-frame': binary, not bcd here!
|
||||
|
||||
// bit to tell whether track is data or audio (cdrom_tocentry.cdte_ctrl)
|
||||
|
||||
CDROM_DATA_TRACK = $40;
|
||||
|
||||
// The leadout track is always 0xAA, regardless of # of tracks on disc
|
||||
|
||||
CDROM_LEADOUT = $AA;
|
||||
|
||||
// audio states (from SCSI-2, but seen with other drives, too)
|
||||
|
||||
CDROM_AUDIO_INVALID = $00; // audio status not supported
|
||||
CDROM_AUDIO_PLAY = $11; // audio play operation in progress
|
||||
CDROM_AUDIO_PAUSED = $12; // audio play operation paused
|
||||
CDROM_AUDIO_COMPLETED = $13; // audio play successfully completed
|
||||
CDROM_AUDIO_ERROR = $14; // audio play stopped due to error
|
||||
CDROM_AUDIO_NO_STATUS = $15; // no current audio status to return
|
||||
|
||||
// capability flags used with the uniform CD-ROM driver
|
||||
|
||||
CDC_CLOSE_TRAY = $1; // caddy systems _can't_ close
|
||||
CDC_OPEN_TRAY = $2; // but _can_ eject.
|
||||
CDC_LOCK = $4; // disable manual eject
|
||||
CDC_SELECT_SPEED = $8; // programmable speed
|
||||
CDC_SELECT_DISC = $10; // select disc from juke-box
|
||||
CDC_MULTI_SESSION = $20; // read sessions>1
|
||||
CDC_MCN = $40; // Medium Catalog Number
|
||||
CDC_MEDIA_CHANGED = $80; // media changed
|
||||
CDC_PLAY_AUDIO = $100; // audio functions
|
||||
CDC_RESET = $200; // hard reset device
|
||||
CDC_IOCTLS = $400; // driver has non-standard ioctls
|
||||
CDC_DRIVE_STATUS = $800; // driver implements drive status
|
||||
CDC_GENERIC_PACKET = $1000; // driver implements generic packets
|
||||
CDC_CD_R = $2000; // drive is a CD-R
|
||||
CDC_CD_RW = $4000; // drive is a CD-RW
|
||||
CDC_DVD = $8000; // drive is a DVD
|
||||
CDC_DVD_R = $10000; // drive can write DVD-R
|
||||
CDC_DVD_RAM = $20000; // drive can write DVD-RAM
|
||||
|
||||
// drive status possibilities returned by CDROM_DRIVE_STATUS ioctl
|
||||
|
||||
CDS_NO_INFO = 0; // if not implemented
|
||||
CDS_NO_DISC = 1;
|
||||
CDS_TRAY_OPEN = 2;
|
||||
CDS_DRIVE_NOT_READY = 3;
|
||||
CDS_DISC_OK = 4;
|
||||
|
||||
(* return values for the CDROM_DISC_STATUS ioctl
|
||||
can also return CDS_NO_[INFO|DISC], from above *)
|
||||
|
||||
CDS_AUDIO = 100;
|
||||
CDS_DATA_1 = 101;
|
||||
CDS_DATA_2 = 102;
|
||||
CDS_XA_2_1 = 103;
|
||||
CDS_XA_2_2 = 104;
|
||||
CDS_MIXED = 105;
|
||||
|
||||
// User-configurable behavior options for the uniform CD-ROM driver
|
||||
|
||||
CDO_AUTO_CLOSE = $1; // close tray on first open()
|
||||
CDO_AUTO_EJECT = $2; // open tray on last release()
|
||||
CDO_USE_FFLAGS = $4; // use O_NONBLOCK information on open
|
||||
CDO_LOCK = $8; // lock tray on open files
|
||||
CDO_CHECK_TYPE = $10; // check type on open for data
|
||||
|
||||
// Special codes used when specifying changer slots.
|
||||
|
||||
CDSL_NONE = $7FFFFFFE;
|
||||
CDSL_CURRENT = $7FFFFFFF;
|
||||
|
||||
(* For partition based multisession access. IDE can handle 64 partitions
|
||||
per drive - SCSI CD-ROM's use minors to differentiate between the
|
||||
various drives, so we can't do multisessions the same way there.
|
||||
Use the -o session=x option to mount on them. *)
|
||||
|
||||
CD_PART_MAX = 64;
|
||||
CD_PART_MASK = (CD_PART_MAX - 1);
|
||||
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
||||
336
acs/Src/classes/windows/acs_cdrom.inc
Normal file
336
acs/Src/classes/windows/acs_cdrom.inc
Normal file
@@ -0,0 +1,336 @@
|
||||
{
|
||||
$Log: acs_cdrom.inc,v $
|
||||
Revision 1.12 2006/08/31 20:10:56 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.11 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.3 2006/01/03 15:37:51 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/12/26 17:31:39 z0m3ie
|
||||
fixed some problems in acs_dsfiles
|
||||
fixed some problems in acs_vorbis
|
||||
reworked all buffers
|
||||
|
||||
Revision 1.1 2005/12/19 18:35:16 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.4 2005/12/04 16:54:34 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.3 2005/10/02 16:51:46 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/09/13 21:54:11 z0m3ie
|
||||
acs is localizeable now (ACS_Strings)
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.5 2005/09/09 21:33:43 z0m3ie
|
||||
linux corrections
|
||||
|
||||
Revision 1.4 2005/09/08 22:19:00 z0m3ie
|
||||
completed akrip based CDIn
|
||||
|
||||
Revision 1.3 2005/09/07 20:53:22 z0m3ie
|
||||
begon to add MPEG and WMA support using DirectX
|
||||
|
||||
Revision 1.2 2005/09/04 17:59:38 z0m3ie
|
||||
moving CDIn support to AKRip mostly
|
||||
begon to add mpegin support for Win with mpg123
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
}
|
||||
|
||||
type
|
||||
MSFAddr = array[0..3] of Byte;
|
||||
|
||||
function Toc2MSF(t : MSFAddr) : TACSCDMSF;
|
||||
begin
|
||||
Result.Minute := t[1];
|
||||
Result.Second := t[2];
|
||||
Result.Frame := t[3];
|
||||
end;
|
||||
|
||||
procedure TACSCDIn.OpenCD;
|
||||
var
|
||||
GetCD: GETCDHAND;
|
||||
begin
|
||||
with GetCD do
|
||||
begin
|
||||
Size := SizeOf(GETCDHAND);
|
||||
Ver := 1;
|
||||
ha := 0;
|
||||
tgt := FCurrentDrive;
|
||||
lun := 0;
|
||||
readType := CDR_ANY;
|
||||
jitterCorr := false;
|
||||
numJitter := 0;
|
||||
numOverlap := 0;
|
||||
end;
|
||||
FCDHandle := GetCDHandle(GetCD);
|
||||
end;
|
||||
|
||||
procedure TACSCDIn.CloseCD;
|
||||
begin
|
||||
if FCDHandle <> 0 then
|
||||
CloseCDHandle(FCDHandle);
|
||||
FCDHandle := 0;
|
||||
end;
|
||||
|
||||
function TACSCDIn.GetInfo : TACSCDInfo;
|
||||
var
|
||||
i : Integer;
|
||||
begin
|
||||
OpenCD;
|
||||
Result := cdiUnknown;
|
||||
ModifyCDParms(FCDHandle, CDP_MSF, DWORD(true));
|
||||
FillChar(FToc, SizeOf(FToc),0);
|
||||
if ReadTOC(FCDHandle, FTOC) <> 1 then
|
||||
begin
|
||||
Result := cdiNoDisc;
|
||||
Exit;
|
||||
end;
|
||||
for i := 0 to FToc.lastTrack-1 do
|
||||
begin
|
||||
if (FToc.Tracks[i].adr and $04) = 0 then
|
||||
begin
|
||||
case Result of
|
||||
cdiUnknown : Result := cdiDiscAudio;
|
||||
cdiDiscData : Result := cdiDiscMixed;
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
case Result of
|
||||
cdiUnknown : Result := cdiDiscData;
|
||||
cdiDiscAudio : Result := cdiDiscMixed;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
CloseCD;
|
||||
end;
|
||||
|
||||
function TACSCDIn.GetStatus : TACSCDStatus;
|
||||
var
|
||||
ms : Integer;
|
||||
AP : LongBool;
|
||||
begin
|
||||
if FPlaying then
|
||||
Result := cdsPlaying
|
||||
else if (GetInfo <> cdiNoDisc) and (GetInfo <> cdiUnknown) then
|
||||
Result := cdsReady
|
||||
else
|
||||
Result := cdsNotReady;
|
||||
end;
|
||||
|
||||
function TACSCDIn.GetNumTracks : Integer;
|
||||
begin
|
||||
OpenCD;
|
||||
if FToc.lastTrack = 0 then
|
||||
begin
|
||||
ModifyCDParms(FCDHandle, CDP_MSF, DWORD(true));
|
||||
if ReadTOC(FCDHandle, FTOC) <> 1 then
|
||||
begin
|
||||
Result := -1;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
Result := FToc.lastTrack;
|
||||
CloseCD;
|
||||
end;
|
||||
|
||||
FUNCTION TACSCDIn.GetTrackInfo(const vIndex : Integer) : TACSCDTrackInfo;
|
||||
VAR
|
||||
Frames: Integer;
|
||||
tmpmsf : TACSCDMSF;
|
||||
BEGIN
|
||||
IF Busy THEN
|
||||
RAISE EACSException.Create(strBusy);
|
||||
IF (vIndex IN [0..GetNumTracks-1]) = False THEN
|
||||
RAISE EACSException.Create(strTrackoutofrange);
|
||||
IF (FToc.Tracks[vIndex].adr and $04) = 0 THEN
|
||||
Result.TrackType := ttAudio
|
||||
ELSE
|
||||
Result.TrackType := ttData;
|
||||
Result.TrackStart.Minute := FToc.Tracks[vIndex].addr[1];
|
||||
Result.TrackStart.Second := FToc.Tracks[vIndex].addr[2];
|
||||
Result.TrackStart.Frame := FToc.Tracks[vIndex].addr[3];
|
||||
Frames := MSF2Frames(Toc2MSF(MSFAddr(FToc.Tracks[vIndex+1].addr)))-MSF2Frames(Toc2MSF(MSFAddr(FToc.Tracks[vIndex].addr)));
|
||||
Frames2MSF(Frames, Result.TrackLength);
|
||||
end;
|
||||
|
||||
procedure TACSCDIn.SetST;
|
||||
begin
|
||||
if Self.Busy then raise EACSException.Create(strBusy);
|
||||
FStartTrack := Track;
|
||||
FStartPos.Track := FStartTrack;
|
||||
FillChar(FStartPos.MSF, SizeOf(FStartPos.MSF), 0);
|
||||
end;
|
||||
|
||||
procedure TACSCDIn.SetET;
|
||||
begin
|
||||
if Self.Busy then raise EACSException.Create(strBusy);
|
||||
FEndTrack := Track;
|
||||
FEndPos.Track := FEndTrack+1;
|
||||
FillChar(FEndPos.MSF, SizeOf(FEndPos.MSF), 0);
|
||||
end;
|
||||
|
||||
procedure TACSCDIn.SetSP;
|
||||
begin
|
||||
if Self.Busy then raise EACSException.Create(strBusy);
|
||||
FStartPos := Pos;
|
||||
end;
|
||||
|
||||
procedure TACSCDIn.SetEP;
|
||||
begin
|
||||
if Self.Busy then raise EACSException.Create(strBusy);
|
||||
FEndPos := Pos;
|
||||
if Pos.Track = EndOfDisc.Track then FEndPos.Track := TracksCount + 1;
|
||||
end;
|
||||
|
||||
function TACSCDIn.GetSize : Integer;
|
||||
var
|
||||
Sect1, Sect2 : Integer;
|
||||
begin
|
||||
if Busy then
|
||||
begin
|
||||
Result := FRipEnd-FRipStart*CD_FRAMESIZE_RAW;
|
||||
Exit;
|
||||
end;
|
||||
Sect1 := MSF2Frames(Toc2MSF(MSFAddr(FToc.tracks[FStartPos.Track].addr)));
|
||||
Sect1 := Sect1 + MSF2Frames(FStartPos.MSF);
|
||||
Sect2 := MSF2Frames(Toc2MSF(MSFAddr(FToc.tracks[FEndPos.Track].addr)));
|
||||
Sect2 := Sect2 + MSF2Frames(FEndPos.MSF);
|
||||
Result := (Sect2 - Sect1)*CD_FRAMESIZE_RAW;
|
||||
end;
|
||||
|
||||
procedure TACSCDIn.Init;
|
||||
var
|
||||
Sect1, Sect2 : Integer;
|
||||
begin
|
||||
if Busy then raise EACSException.Create(strBusy);
|
||||
if Status = cdsNotReady then
|
||||
raise EACSException.Create(strDrivenotready);
|
||||
if (FStartPos.Track in [0..GetNumTracks-1]) = False then
|
||||
raise EACSException.Create(strTrackoutofRange);
|
||||
if Tracks[FStartPos.Track].TrackType = ttData then
|
||||
raise EACSException.Create(strnoAudioTreck);
|
||||
OpenCD;
|
||||
FSize := GetSize;
|
||||
FBusy := True;
|
||||
BufStart := 1;
|
||||
BufEnd := 0;
|
||||
FPosition := 0;
|
||||
Sect1 := MSF2Frames(Toc2MSF(MSFAddr(FToc.tracks[FStartPos.Track].addr)));
|
||||
Sect1 := Sect1 + MSF2Frames(FStartPos.MSF);
|
||||
Sect2 := MSF2Frames(Toc2MSF(MSFAddr(FToc.tracks[FEndPos.Track].addr)));
|
||||
Sect2 := Sect2 + MSF2Frames(FEndPos.MSF);
|
||||
FRipEnd := Sect2;
|
||||
FRipStart := Sect1;
|
||||
SetLength(FBuffer,(BUF_SIZE * CD_FRAMESIZE_RAW)+TRACKBUFEXTRA);
|
||||
end;
|
||||
|
||||
procedure TACSCDIn.Flush;
|
||||
begin
|
||||
CloseCD;
|
||||
FBusy := False;
|
||||
Setlength(FBuffer,0);
|
||||
FBuffer := nil;
|
||||
FSize := 0;
|
||||
end;
|
||||
|
||||
function TACSCDIn.GetData(Buffer : Pointer; BufferSize : Integer): Integer;
|
||||
var
|
||||
Abort : LongBool;
|
||||
fnum : Integer;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create(strStreamnotOpen);
|
||||
if BufStart > BufEnd then //Buffer clear try to fill it
|
||||
begin
|
||||
BufStart := 1;
|
||||
Abort := False;
|
||||
if FRipEnd-FRipStart > BUF_SIZE then
|
||||
fNum := BUF_SIZE
|
||||
else
|
||||
fNum := FRipEnd-FRipStart;
|
||||
FiBuffer^.startFrame := FRipStart;
|
||||
FiBuffer^.numFrames := fNum;
|
||||
FiBuffer^.maxLen := FiBuffer^.numFrames * CD_FRAMESIZE_RAW;
|
||||
FiBuffer^.len := 0;
|
||||
FiBuffer^.status := 0;
|
||||
FiBuffer^.startOffset := 0;
|
||||
if ReadCDAudioLBA(FCDHandle,FiBuffer) = 1 then
|
||||
begin
|
||||
Inc(FRipStart,FiBuffer^.numFrames);
|
||||
BufEnd := FiBuffer^.len;
|
||||
end;
|
||||
end;
|
||||
if BufferSize < (BufEnd - BufStart + 1) then
|
||||
Result := BufferSize
|
||||
else
|
||||
Result := BufEnd - BufStart + 1;
|
||||
Move(FiBuffer^.buf[BufStart-1],Buffer^, Result);
|
||||
Inc(BufStart, Result);
|
||||
Inc(FPosition, Result);
|
||||
end;
|
||||
|
||||
procedure TACSCDIn.SetCurrentDrive;
|
||||
begin
|
||||
if Value in [0..FCDList.num-1] then
|
||||
FCurrentDrive := Value;
|
||||
OpenCD;
|
||||
FillChar(FToc, SizeOf(FToc),0);
|
||||
ModifyCDParms(FCDHandle, CDP_MSF, DWORD(true));
|
||||
ReadTOC(FCDHandle, FTOC);
|
||||
CloseCD;
|
||||
end;
|
||||
|
||||
function TACSCDIn.GetDrivesCount : Integer;
|
||||
begin
|
||||
Result := FCDList.num;
|
||||
end;
|
||||
|
||||
function TACSCDIn.GetDriveName : string;
|
||||
begin
|
||||
Result := FCDList.Cd[FCurrentDrive].id;
|
||||
end;
|
||||
|
||||
procedure TACSCDIn.Eject;
|
||||
begin
|
||||
if Busy then raise EACSException.Create(strBusy);
|
||||
end;
|
||||
|
||||
procedure TACSCDIn.CloseTray;
|
||||
begin
|
||||
end;
|
||||
|
||||
constructor TACSCDIn.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
AppPath := ExtractFilePath(ParamStr(0));
|
||||
if AppPath[length(AppPath)] <> '\' then AppPath := AppPath + '\';
|
||||
CDRIPInit(AppPath);
|
||||
if not (csDesigning in ComponentState) then
|
||||
if not CDRipLoaded then
|
||||
raise EACSException.Create(akriplib + ' could not be loaded.');
|
||||
FillChar(FCDList, SizeOf(FCDList),0);
|
||||
FCDList.max := MAXCDLIST;
|
||||
GetCDList(FCDList);
|
||||
end;
|
||||
|
||||
destructor TACSCDIn.Destroy;
|
||||
begin
|
||||
if Busy then
|
||||
Flush;
|
||||
CloseCD;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
407
acs/Src/classes/windows/acs_mixer.inc
Normal file
407
acs/Src/classes/windows/acs_mixer.inc
Normal file
@@ -0,0 +1,407 @@
|
||||
{
|
||||
$Log: acs_mixer.inc,v $
|
||||
Revision 1.3 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.1 2005/12/19 18:35:16 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.3 2005/12/04 16:54:34 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.2 2005/09/13 21:54:11 z0m3ie
|
||||
acs is localizeable now (ACS_Strings)
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.10 2005/08/31 20:30:40 z0m3ie
|
||||
Mixer Channelname work now
|
||||
minior corrections for Converters
|
||||
|
||||
Revision 1.9 2005/08/31 14:37:59 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.8 2005/08/30 22:10:55 z0m3ie
|
||||
Mixer mostly completed
|
||||
|
||||
Revision 1.7 2005/08/29 22:50:33 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.6 2005/08/29 21:46:43 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.5 2005/08/28 20:33:10 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.4 2005/08/28 18:35:53 z0m3ie
|
||||
created Delphi package for 2.4
|
||||
more Mixer stuff
|
||||
updated some things for Delphi
|
||||
|
||||
Revision 1.3 2005/08/26 17:12:56 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/08/26 17:03:20 z0m3ie
|
||||
begon to make acs resourcestring aware
|
||||
more advanced tmixer for windows
|
||||
restructured tmixer its better handleable now
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
}
|
||||
|
||||
function mixerSetControlDetails(x1: HMIXEROBJ; x2: PMIXERCONTROLDETAILS; x3: DWORD): MMRESULT; stdcall;
|
||||
external 'winmm.dll' name
|
||||
'mixerSetControlDetails';
|
||||
|
||||
function GetChannelfromMask(Mask : DWORD) : TACSMixerChannel;
|
||||
begin
|
||||
case Mask of
|
||||
MIXERLINE_COMPONENTTYPE_DST_UNDEFINED : Result := mcUnknown;
|
||||
MIXERLINE_COMPONENTTYPE_DST_DIGITAL : Result := mcDigital;
|
||||
MIXERLINE_COMPONENTTYPE_DST_LINE : Result := mcLine;
|
||||
MIXERLINE_COMPONENTTYPE_DST_MONITOR : Result := mcMonitor;
|
||||
MIXERLINE_COMPONENTTYPE_DST_SPEAKERS : Result := mcVolume;
|
||||
MIXERLINE_COMPONENTTYPE_DST_HEADPHONES : Result := mcHeadphone;
|
||||
MIXERLINE_COMPONENTTYPE_DST_TELEPHONE : Result := mcTelephone;
|
||||
MIXERLINE_COMPONENTTYPE_DST_WAVEIN : Result := mcPCM;
|
||||
MIXERLINE_COMPONENTTYPE_DST_VOICEIN : Result := mcUnknown;
|
||||
MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED : Result := mcUnknown;
|
||||
MIXERLINE_COMPONENTTYPE_SRC_DIGITAL : Result := mcDigital;
|
||||
MIXERLINE_COMPONENTTYPE_SRC_LINE : Result := mcLine;
|
||||
MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE : Result := mcMic;
|
||||
MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER: Result := mcSynth;
|
||||
MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC: Result := mcCD;
|
||||
MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE : Result := mcTelephone;
|
||||
MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER : Result := mcVolume;
|
||||
MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT : Result := mcPCM;
|
||||
MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY : Result := mcAltPCM;
|
||||
MIXERLINE_COMPONENTTYPE_SRC_ANALOG : Result := mcUnknown;
|
||||
else
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TACSMixer.SetDevNum(Num : Integer);
|
||||
type
|
||||
TData = array [0..3] of MIXERCONTROLDETAILS_UNSIGNED;
|
||||
PData = ^TData;
|
||||
var
|
||||
destination,
|
||||
connection : Integer;
|
||||
data : PData;
|
||||
pmxctrl : PMixerControl;
|
||||
s : String;
|
||||
aLineInfo,
|
||||
aConnLineInfo : TMixerLine;
|
||||
error : Integer;
|
||||
|
||||
procedure GetLineControls(mixLineInfo : TMixerLine);
|
||||
var
|
||||
j, k,
|
||||
datasize : Integer;
|
||||
aLineControl : TMixerLineControls;
|
||||
aControlDetails: TMixerControlDetails;
|
||||
amixControl : PMixerControl;
|
||||
aControl : PControlEntry;
|
||||
begin
|
||||
with aLineControl do
|
||||
begin
|
||||
cbStruct := SizeOf(TMixerLineControls);
|
||||
dwLineID := mixLineInfo.dwLineID;
|
||||
cControls := mixLineInfo.cControls;
|
||||
cbmxctrl := SizeOf(TMixerControl);
|
||||
GetMem(amixControl, SizeOf(TMixerControl) * mixLineInfo.cControls);
|
||||
pamxctrl := amixControl;
|
||||
end;
|
||||
error := mixerGetLineControls(Num, @aLineControl, MIXER_GETLINECONTROLSF_ALL);
|
||||
pmxctrl := amixControl;
|
||||
for j := 0 TO aLineControl.cControls -1 do
|
||||
begin
|
||||
if (pmxctrl^.dwControlType <> MIXERCONTROL_CONTROLTYPE_VOLUME)
|
||||
and (pmxctrl^.dwControlType <> MIXERCONTROL_CONTROLTYPE_MUTE) then
|
||||
continue;
|
||||
if (pmxctrl^.fdwControl and MIXERCONTROL_CONTROLF_UNIFORM) > 0 then
|
||||
aControlDetails.cChannels := 1
|
||||
else
|
||||
aControlDetails.cChannels := mixLineInfo.cChannels;
|
||||
if (pmxctrl^.fdwControl AND MIXERCONTROL_CONTROLF_MULTIPLE) > 0 then
|
||||
begin
|
||||
aControlDetails.cMultipleItems := pmxctrl^.cMultipleItems;
|
||||
Getmem(data,pmxctrl^.cMultipleItems * SizeOf(MIXERCONTROLDETAILS_UNSIGNED));
|
||||
datasize := pmxctrl^.cMultipleItems;
|
||||
end
|
||||
else
|
||||
begin
|
||||
aControlDetails.cMultipleItems := 0;
|
||||
Getmem(data, aControlDetails.cChannels * SizeOf(MIXERCONTROLDETAILS_UNSIGNED));
|
||||
datasize := aControlDetails.cChannels;
|
||||
end;
|
||||
with aControlDetails do
|
||||
begin
|
||||
cbStruct := sizeOf(TmixerControlDetails);
|
||||
dwControlID := pmxctrl^.dwControlID;
|
||||
cbDetails := SizeOf(MIXERCONTROLDETAILS_UNSIGNED);
|
||||
paDetails := data;
|
||||
end;
|
||||
error := mixerGetControlDetails(Num, @aControlDetails, MIXER_GETCONTROLDETAILSF_VALUE );
|
||||
if (pmxctrl^.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE) then
|
||||
begin
|
||||
setlength(FMuteControls,length(FControls)+1);
|
||||
aControl := @FMuteControls[length(FControls)-1];
|
||||
end
|
||||
else
|
||||
begin
|
||||
setlength(FControls,length(FControls)+1);
|
||||
aControl := @FControls[length(FControls)-1];
|
||||
end;
|
||||
setlength(FChannels,Max(length(FControls),length(FMuteControls)));
|
||||
with aControl^, pmxctrl^, aControlDetails do
|
||||
begin
|
||||
IsInited := True;
|
||||
CDestination := mixLineInfo.dwDestination;
|
||||
CName := String(szShortname);
|
||||
CComponentTyp := mixLineInfo.dwComponentType;
|
||||
CKanal := cChannels;
|
||||
CID := dwControlID;
|
||||
CConnect := mixLineInfo.cConnections;
|
||||
CCControls := mixLineInfo.cControls;
|
||||
CControl := fdwControl;
|
||||
CControlTyp := dwControlType;
|
||||
CMultItems := cMultipleItems;
|
||||
CMax := Bounds.lMaximum;
|
||||
CMin := Bounds.lMinimum;
|
||||
CcSteps := Metrics.cSteps;
|
||||
for k := 0 to datasize -1 do
|
||||
CDetails[k].dwValue := data^[k].dwvalue;
|
||||
end;
|
||||
FChannels[length(FControls)-1] := GetChannelfromMask(aControl.CComponentTyp);
|
||||
Freemem(data);
|
||||
inc(pmxctrl);
|
||||
end;
|
||||
Freemem(amixControl);
|
||||
end;
|
||||
|
||||
begin
|
||||
if Num in [0..MixersCount - 1] then // check [0..0] [0..-1]
|
||||
begin
|
||||
setlength(FChannels,0);
|
||||
setlength(FControls,0);
|
||||
setlength(FMuteControls,0);
|
||||
error := mixerGetDevCaps(Num, @FMixerCaps, sizeof(TMixerCaps));
|
||||
FMixer := Num;
|
||||
FMixerName := StrPas(FMixerCaps.szPName);
|
||||
error := mixerOpen(@Num, 0, 0, 0, MIXER_OBJECTF_MIXER);
|
||||
if error = MMSYSERR_NOERROR then
|
||||
begin
|
||||
for destination := 0 to FMixerCaps.cDestinations - 1 do
|
||||
begin
|
||||
aLineInfo.cbStruct := SizeOf(TMixerLine);
|
||||
aLineInfo.dwDestination := destination;
|
||||
error := mixerGetLineInfo(Num, @aLineInfo, MIXER_GETLINEINFOF_DESTINATION);
|
||||
if aLineInfo.dwComponentType <> MIXERLINE_COMPONENTTYPE_DST_SPEAKERS then
|
||||
continue;
|
||||
GetLineControls(aLineInfo);
|
||||
for connection := 0 TO aLineInfo.cConnections-1 do
|
||||
begin
|
||||
with aConnLineInfo do
|
||||
begin
|
||||
cbStruct := SizeOf(TMixerLine);
|
||||
dwDestination := destination;
|
||||
dwSource := connection;
|
||||
end;
|
||||
error := mixerGetLineInfo(Num, @aConnLineInfo, MIXER_GETLINEINFOF_SOURCE);
|
||||
GetLineControls(aConnLineInfo);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TACSMixer.GetVolume(vChannel : Integer) : TACSMixerLevel;
|
||||
type
|
||||
TData = array [0..3] of MIXERCONTROLDETAILS_UNSIGNED;
|
||||
PData = ^TData;
|
||||
var
|
||||
data : PData;
|
||||
aControldetails : TMixerControlDetails;
|
||||
datasize,k : Integer;
|
||||
begin
|
||||
if vChannel >= length(FControls) then
|
||||
exit;
|
||||
if FControls[vChannel].IsInited = False then
|
||||
exit;
|
||||
if (FControls[vChannel].CControl and MIXERCONTROL_CONTROLF_UNIFORM) > 0 then
|
||||
aControlDetails.cChannels := 1
|
||||
else
|
||||
aControlDetails.cChannels := FControls[vChannel].CKanal;
|
||||
if (FControls[vChannel].CControl AND MIXERCONTROL_CONTROLF_MULTIPLE) > 0 then
|
||||
begin
|
||||
aControlDetails.cMultipleItems := FControls[vChannel].CMultItems;
|
||||
Getmem(data, FControls[vChannel].CMultItems * SizeOf(MIXERCONTROLDETAILS_UNSIGNED));
|
||||
datasize := FControls[vChannel].CMultItems;
|
||||
end
|
||||
else
|
||||
begin
|
||||
aControlDetails.cMultipleItems := 0;
|
||||
Getmem(data, aControlDetails.cChannels * SizeOf(MIXERCONTROLDETAILS_UNSIGNED));
|
||||
datasize := aControlDetails.cChannels;
|
||||
end;
|
||||
with aControlDetails do
|
||||
begin
|
||||
cbStruct := SizeOf(TMixerControlDetails);
|
||||
dwControlID := FControls[vChannel].CID;
|
||||
cChannels := FControls[vChannel].CKanal;
|
||||
cMultipleItems := FControls[vChannel].CMultItems;
|
||||
cbDetails := sizeof(MIXERCONTROLDETAILS_Signed);
|
||||
padetails := data;
|
||||
end;
|
||||
mixerGetControlDetails(FMixer, @aControlDetails,MIXER_GETCONTROLDETAILSF_VALUE );
|
||||
with FControls[vChannel] do
|
||||
begin
|
||||
for k := 0 to datasize -1 do
|
||||
CDetails[k].dwValue := data^[k].dwvalue;
|
||||
end;
|
||||
Freemem(data);
|
||||
if IsStereo(vChannel) then
|
||||
begin
|
||||
Result.Left := round((FControls[vChannel].CDetails[0].dwValue*255)/FControls[vChannel].Cmax);
|
||||
Result.Right := round((FControls[vChannel].CDetails[1].dwValue*255)/FControls[vChannel].Cmax);
|
||||
end
|
||||
else
|
||||
Result.Main := round((FControls[vChannel].CDetails[0].dwValue*255)/FControls[vChannel].Cmax);
|
||||
end;
|
||||
|
||||
procedure TACSMixer.SetVolume(vChannel : Integer; vLevel : TACSMixerLevel);
|
||||
var
|
||||
aControlDetails : TMixerControlDetails;
|
||||
begin
|
||||
if vChannel >= length(FControls) then
|
||||
exit;
|
||||
if IsStereo(vChannel) then
|
||||
begin
|
||||
FControls[vChannel].CDetails[0].dwValue := round((vLevel.Left*FControls[vChannel].CMax)/255);
|
||||
FControls[vChannel].CDetails[1].dwValue := round((vLevel.Right*FControls[vChannel].CMax)/255);
|
||||
end
|
||||
else
|
||||
FControls[vChannel].CDetails[0].dwValue := round((vLevel.Main*FControls[vChannel].CMax)/255);
|
||||
with aControlDetails do
|
||||
begin
|
||||
cbStruct := SizeOf(TMixerControlDetails);
|
||||
dwControlID := FControls[vChannel].CID;
|
||||
cChannels := FControls[vChannel].CKanal;
|
||||
cMultipleItems := 0;
|
||||
cbDetails := sizeof(MIXERCONTROLDETAILS_Signed);
|
||||
padetails := @FControls[vChannel].CDetails;
|
||||
end;
|
||||
mixerSetControlDetails(FMixer, @aControlDetails,MIXER_SETCONTROLDETAILSF_Value);
|
||||
end;
|
||||
|
||||
function TACSMixer.IsStereo(vChannel : Integer) : Boolean;
|
||||
begin
|
||||
if vChannel >= length(FControls) then
|
||||
exit;
|
||||
Result := not (FControls[vChannel].CKanal = 1);
|
||||
end;
|
||||
|
||||
function TACSMixer.GetMute(vChannel : integer) : Boolean;
|
||||
type
|
||||
TData = array [0..3] of MIXERCONTROLDETAILS_UNSIGNED;
|
||||
PData = ^TData;
|
||||
var
|
||||
data : PData;
|
||||
aControldetails : TMixerControlDetails;
|
||||
datasize,k : Integer;
|
||||
begin
|
||||
if vChannel >= length(FMuteControls) then
|
||||
exit;
|
||||
if FMuteControls[vChannel].IsInited = False then
|
||||
exit;
|
||||
if (FMuteControls[vChannel].CControl and MIXERCONTROL_CONTROLF_UNIFORM) > 0 then
|
||||
aControlDetails.cChannels := 1
|
||||
else
|
||||
aControlDetails.cChannels := FMuteControls[vChannel].CKanal;
|
||||
if (FMuteControls[vChannel].CControl AND MIXERCONTROL_CONTROLF_MULTIPLE) > 0 then
|
||||
begin
|
||||
aControlDetails.cMultipleItems := FMuteControls[vChannel].CMultItems;
|
||||
Getmem(data, FMuteControls[vChannel].CMultItems * SizeOf(MIXERCONTROLDETAILS_UNSIGNED));
|
||||
datasize := FMuteControls[vChannel].CMultItems;
|
||||
end
|
||||
else
|
||||
begin
|
||||
aControlDetails.cMultipleItems := 0;
|
||||
Getmem(data, aControlDetails.cChannels * SizeOf(MIXERCONTROLDETAILS_UNSIGNED));
|
||||
datasize := aControlDetails.cChannels;
|
||||
end;
|
||||
with aControlDetails do
|
||||
begin
|
||||
cbStruct := SizeOf(TMixerControlDetails);
|
||||
dwControlID := FMuteControls[vChannel].CID;
|
||||
cChannels := FMuteControls[vChannel].CKanal;
|
||||
cMultipleItems := FMuteControls[vChannel].CMultItems;
|
||||
cbDetails := sizeof(MIXERCONTROLDETAILS_Signed);
|
||||
padetails := data;
|
||||
end;
|
||||
mixerGetControlDetails(FMixer, @aControlDetails,MIXER_GETCONTROLDETAILSF_VALUE );
|
||||
with FMuteControls[vChannel] do
|
||||
begin
|
||||
for k := 0 to datasize -1 do
|
||||
CDetails[k].dwValue := data^[k].dwvalue;
|
||||
end;
|
||||
Freemem(data);
|
||||
Result := (FMuteControls[vChannel].CDetails[0].dwValue = 1);
|
||||
end;
|
||||
|
||||
procedure TACSMixer.SetMute(vChannel : integer; Mute : Boolean);
|
||||
var
|
||||
aControlDetails : TMixerControlDetails;
|
||||
begin
|
||||
if vChannel >= length(FMuteControls) then
|
||||
exit;
|
||||
if FMuteControls[vChannel].IsInited = False then
|
||||
exit;
|
||||
if Mute then
|
||||
FMuteControls[vChannel].CDetails[0].dwValue := 1
|
||||
else
|
||||
FMuteControls[vChannel].CDetails[0].dwValue := 0;
|
||||
with aControlDetails do
|
||||
begin
|
||||
cbStruct := SizeOf(TMixerControlDetails);
|
||||
dwControlID := FMuteControls[vChannel].CID;
|
||||
cChannels := FMuteControls[vChannel].CKanal;
|
||||
cMultipleItems := 0;
|
||||
cbDetails := sizeof(MIXERCONTROLDETAILS_Signed);
|
||||
padetails := @FMuteControls[vChannel].CDetails;
|
||||
end;
|
||||
mixerSetControlDetails(FMixer, @aControlDetails,MIXER_SETCONTROLDETAILSF_Value);
|
||||
end;
|
||||
|
||||
function TACSMixer.IsRecordable(vChannel : Integer) : Boolean;
|
||||
begin
|
||||
end;
|
||||
|
||||
procedure TACSMixer.SetRecSource(vChannel : Integer);
|
||||
begin
|
||||
end;
|
||||
|
||||
function TACSMixer.GetRecSource : Integer;
|
||||
begin
|
||||
end;
|
||||
|
||||
destructor TACSMixer.Destroy;
|
||||
begin
|
||||
Setlength(FControls,0);
|
||||
Setlength(FMuteControls,0);
|
||||
Setlength(FChannels,0);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function CountMixers : Byte;
|
||||
begin
|
||||
Result := mixerGetNumDevs;
|
||||
end;
|
||||
|
||||
332
acs/Src/classes/windows/akrip32.pas
Normal file
332
acs/Src/classes/windows/akrip32.pas
Normal file
@@ -0,0 +1,332 @@
|
||||
unit akrip32;
|
||||
{*
|
||||
* akrip32.h - copyright (c) 1999 jay a. key
|
||||
*
|
||||
* api for akrip32.dll (v0.93)
|
||||
*
|
||||
* modified for acs (dynamic loading ...) y christian ulrich (mail@z0m3ie.de)
|
||||
* translated for borland delphi by holger dors (holger@dors.de)
|
||||
*
|
||||
* history of delphi version:
|
||||
*
|
||||
* 09. january 2000: first released version
|
||||
* 05. February 2000: Updated for new function "CDDBGetServerList"
|
||||
* in V.093 of akrip32.dll
|
||||
*
|
||||
**********************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*}
|
||||
|
||||
interface
|
||||
|
||||
uses windows;
|
||||
|
||||
const
|
||||
|
||||
TRACK_AUDIO = $00;
|
||||
TRACK_DATA = $01;
|
||||
|
||||
MAXIDLEN = 64;
|
||||
MAXCDLIST = 8;
|
||||
|
||||
{*
|
||||
* TRACKBUF
|
||||
*
|
||||
* This structure should not be allocated directly. If a buffer containing
|
||||
* 27 * 2353 bytes is desired, a buffer should be allocated containing
|
||||
* the desired amount + 24 bytes. The allocated memory can then be
|
||||
* typecast to a LPTRACKBUF. It is the program's responsibility to guard
|
||||
* against reading/writing past the end of allocated memory.
|
||||
*
|
||||
* The following must always apply:
|
||||
* (len + startOffset) <= (numFrames * 2352) <= maxLen
|
||||
*}
|
||||
|
||||
type
|
||||
PTRACKBUF = ^TRACKBUF;
|
||||
TRACKBUF = record
|
||||
startFrame: DWord; {* 00: starting frame number *}
|
||||
numFrames: DWord; {* 04: number of frames read *}
|
||||
maxLen: DWord; {* 08: length of buffer itself *}
|
||||
len: DWord; {* 0C: length of data actually in buf *}
|
||||
status: DWord; {* 10: status of last read operation *}
|
||||
startOffset: Integer; {* 14: offset of valid data in buf *}
|
||||
buf: array[0..1024 * 1024 - 1] of Byte; {* 18: the data itself *}
|
||||
end;
|
||||
|
||||
TRACKBUFDUMMY = record
|
||||
startFrame: DWord; {* 00: starting frame number *}
|
||||
numFrames: DWord; {* 04: number of frames read *}
|
||||
maxLen: DWord; {* 08: length of buffer itself *}
|
||||
len: DWord; {* 0C: length of data actually in buf *}
|
||||
status: DWord; {* 10: status of last read operation *}
|
||||
startOffset: Integer; {* 14: offset of valid data in buf *}
|
||||
end;
|
||||
|
||||
const
|
||||
TRACKBUFEXTRA = SizeOf(TRACKBUFDUMMY);
|
||||
|
||||
type
|
||||
PCDINFO = ^CDINFO;
|
||||
CDINFO = record
|
||||
vendor: array[0..8] of Char;
|
||||
prodId: array[0..16] of Char;
|
||||
rev: array[0..4] of Char;
|
||||
vendSpec: array[0..20] of Char;
|
||||
end;
|
||||
|
||||
PCDREC = ^CDREC;
|
||||
CDREC = record
|
||||
ha: Byte;
|
||||
tgt: Byte;
|
||||
lun: Byte;
|
||||
pad: Byte;
|
||||
id: array[0..MAXIDLEN] of Char;
|
||||
info: CDINFO;
|
||||
end;
|
||||
|
||||
PCDLIST = ^CDLIST;
|
||||
CDLIST = record
|
||||
max: Byte;
|
||||
num: Byte;
|
||||
cd: array[0..MAXCDLIST - 1] of CDREC;
|
||||
end;
|
||||
|
||||
{*
|
||||
* TOCTRACK and TOC must be byte-aligned. If you're not using Mingw32,
|
||||
* CygWin, or some other compiler that understands the PACKED keyword,
|
||||
* you need to ensure that these structures are byte aligned. Usually,
|
||||
* this is done using a
|
||||
* #pragma pack(1)
|
||||
* See your compiler's documentation for details
|
||||
*}
|
||||
|
||||
TOCTRACK = packed record
|
||||
rsvd: Byte;
|
||||
ADR: Byte;
|
||||
trackNumber: Byte;
|
||||
rsvd2: Byte;
|
||||
addr: array[0..3] of Byte;
|
||||
end;
|
||||
|
||||
PTOC = ^TOC;
|
||||
TOC = packed record
|
||||
tocLen: Word;
|
||||
firstTrack: Byte;
|
||||
lastTrack: Byte;
|
||||
tracks: array[0..99] of TOCTRACK;
|
||||
end;
|
||||
|
||||
PTRACK = ^TRACK;
|
||||
TRACK = packed record
|
||||
trackNo: Integer;
|
||||
startLBA: DWord;
|
||||
trackLen: DWord;
|
||||
_type: Byte;
|
||||
pad: array[0..3] of Byte;
|
||||
name: ShortString;//array[0..255] of Char;
|
||||
end;
|
||||
|
||||
PREADMSF = ^READMSF;
|
||||
READMSF = record
|
||||
sm: Byte;
|
||||
ss: Byte;
|
||||
sf: Byte;
|
||||
em: Byte;
|
||||
es: Byte;
|
||||
ef: Byte;
|
||||
end;
|
||||
|
||||
const
|
||||
{*
|
||||
* Error codes set by functions in ASPILIB.C
|
||||
*}
|
||||
|
||||
ALERR_NOERROR = 0;
|
||||
ALERR_NOWNASPI = 1;
|
||||
ALERR_NOGETASPI32SUPP = 2;
|
||||
ALERR_NOSENDASPICMD = 3;
|
||||
ALERR_ASPI = 4;
|
||||
ALERR_NOCDSELECTED = 5;
|
||||
ALERR_BUFTOOSMALL = 6;
|
||||
ALERR_INVHANDLE = 7;
|
||||
ALERR_NOMOREHAND = 8;
|
||||
ALERR_BUFPTR = 9;
|
||||
ALERR_NOTACD = 10;
|
||||
ALERR_LOCK = 11;
|
||||
ALERR_DUPHAND = 12;
|
||||
ALERR_INVPTR = 13;
|
||||
ALERR_INVPARM = 14;
|
||||
ALERR_JITTER = 15;
|
||||
|
||||
{*
|
||||
* constants used for queryCDParms()
|
||||
*}
|
||||
|
||||
CDP_READCDR = $0001; // can read CD-R
|
||||
CDP_READCDE = $0002; // can read CD-E
|
||||
CDP_METHOD2 = $0003; // can read CD-R wriiten via method 2
|
||||
CDP_WRITECDR = $0004; // can write CD-R
|
||||
CDP_WRITECDE = $0005; // can write CD-E
|
||||
CDP_AUDIOPLAY = $0006; // can play audio
|
||||
CDP_COMPOSITE = $0007; // composite audio/video stream
|
||||
CDP_DIGITAL1 = $0008; // digital output (IEC958) on port 1
|
||||
CDP_DIGITAL2 = $0009; // digital output (IEC958) on port 2
|
||||
CDP_M2FORM1 = $000A; // reads Mode 2 Form 1 (XA) format
|
||||
CDP_M2FORM2 = $000B; // reads Mode 2 Form 2 format
|
||||
CDP_MULTISES = $000C; // reads multi-session or Photo-CD
|
||||
CDP_CDDA = $000D; // supports cd-da
|
||||
CDP_STREAMACC = $000E; // supports "stream is accurate"
|
||||
CDP_RW = $000F; // can return R-W info
|
||||
CDP_RWCORR = $0010; // returns R-W de-interleaved and err.
|
||||
// corrected
|
||||
CDP_C2SUPP = $0011; // C2 error pointers
|
||||
CDP_ISRC = $0012; // can return the ISRC info
|
||||
CDP_UPC = $0013; // can return the Media Catalog Number
|
||||
CDP_CANLOCK = $0014; // prevent/allow cmd. can lock the media
|
||||
CDP_LOCKED = $0015; // current lock state (TRUE = LOCKED)
|
||||
CDP_PREVJUMP = $0016; // prevent/allow jumper state
|
||||
CDP_CANEJECT = $0017; // drive can eject disk
|
||||
CDP_MECHTYPE = $0018; // type of disk loading supported
|
||||
CDP_SEPVOL = $0019; // independent audio level for channels
|
||||
CDP_SEPMUTE = $001A; // independent mute for channels
|
||||
CDP_SDP = $001B; // supports disk present (SDP)
|
||||
CDP_SSS = $001C; // Software Slot Selection
|
||||
CDP_MAXSPEED = $001D; // maximum supported speed of drive
|
||||
CDP_NUMVOL = $001E; // number of volume levels
|
||||
CDP_BUFSIZE = $001F; // size of output buffer
|
||||
CDP_CURRSPEED = $0020; // current speed of drive
|
||||
CDP_SPM = $0021; // "S" units per "M" (MSF format)
|
||||
CDP_FPS = $0022; // "F" units per "S" (MSF format)
|
||||
CDP_INACTMULT = $0023; // inactivity multiplier ( x 125 ms)
|
||||
CDP_MSF = $0024; // use MSF format for READ TOC cmd
|
||||
CDP_OVERLAP = $0025; // number of overlap frames for jitter
|
||||
CDP_JITTER = $0026; // number of frames to check for jitter
|
||||
CDP_READMODE = $0027; // mode to attempt jitter corr.
|
||||
|
||||
{*
|
||||
* defines for GETCDHAND readType
|
||||
*
|
||||
*}
|
||||
CDR_ANY = $00; // unknown
|
||||
CDR_ATAPI1 = $01; // ATAPI per spec
|
||||
CDR_ATAPI2 = $02; // alternate ATAPI
|
||||
CDR_READ6 = $03; // using SCSI READ(6)
|
||||
CDR_READ10 = $04; // using SCSI READ(10)
|
||||
CDR_READ_D8 = $05; // using command 0xD8 (Plextor?)
|
||||
CDR_READ_D4 = $06; // using command 0xD4 (NEC?)
|
||||
CDR_READ_D4_1 = $07; // 0xD4 with a mode select
|
||||
CDR_READ10_2 = $08; // different mode select w/ READ(10)
|
||||
|
||||
{*
|
||||
* defines for the read mode (CDP_READMODE)
|
||||
*}
|
||||
CDRM_NOJITTER = $00; // never jitter correct
|
||||
CDRM_JITTER = $01; // always jitter correct
|
||||
CDRM_JITTERONERR = $02; // jitter correct only after a read error
|
||||
|
||||
type
|
||||
HCDROM = THandle;
|
||||
|
||||
PGETCDHAND = ^GETCDHAND;
|
||||
GETCDHAND = packed record
|
||||
size: Byte; {* set to sizeof(GETCDHAND) *}
|
||||
ver: Byte; {* set to AKRIPVER *}
|
||||
ha: Byte; {* host adapter *}
|
||||
tgt: Byte; {* target id *}
|
||||
lun: Byte; {* LUN *}
|
||||
readType: Byte; {* read function to use *}
|
||||
jitterCorr: Bool; {* use built-in jitter correction? *}
|
||||
numJitter: Byte; {* number of frames to try to match *}
|
||||
numOverlap: Byte; {* number of frames to overlap *}
|
||||
end;
|
||||
|
||||
const
|
||||
akriplib = 'akrip32.dll';
|
||||
|
||||
var
|
||||
LibHandle : Integer;
|
||||
CDRipLoaded : Boolean;
|
||||
|
||||
type
|
||||
GetNumAdapters_t = function : Integer; cdecl;
|
||||
GetCDList_t = function (var cd: CDLIST): Integer; cdecl;
|
||||
GetAspiLibError_t = function : Integer; cdecl;
|
||||
GetAspiLibAspiError_t = function : Byte; cdecl;
|
||||
|
||||
GetCDId_t = function (hCD: HCDROM; buf: PChar; maxBuf: Integer): DWord; cdecl;
|
||||
GetDriveInfo_t = function (ha, tgt, lun: byte; var cdrec: CDREC): DWord; cdecl;
|
||||
ReadTOC_t = function (hCD: HCDROM; var MyToc: TOC): DWord; cdecl;
|
||||
ReadCDAudioLBA_t = function (hCD: HCDROM; TrackBuf: PTRACKBUF): DWord; cdecl;
|
||||
QueryCDParms_t = function (hCD: HCDROM; which: Integer; var Num: DWord): Bool; cdecl;
|
||||
ModifyCDParms_t = function (hCD: HCDROM; which: Integer; val: DWord): Bool; cdecl;
|
||||
GetCDHandle_t = function (var cd: GETCDHAND): HCDROM; cdecl;
|
||||
CloseCDHandle_t = function (hCD: HCDROM): Bool; cdecl;
|
||||
ReadCDAudioLBAEx_t = function (hCD: HCDROM; TrackBuf, Overlap: PTRACKBUF): DWord; cdecl;
|
||||
|
||||
var
|
||||
GetNumAdapters : GetNumAdapters_t;
|
||||
GetCDList : GetCDList_t;
|
||||
GetAspiLibError : GetAspiLibError_t;
|
||||
GetAspiLibAspiError : GetAspiLibAspiError_t;
|
||||
|
||||
GetCDId : GetCDId_t;
|
||||
GetDriveInfo : GetDriveInfo_t;
|
||||
ReadTOC : ReadTOC_t;
|
||||
ReadCDAudioLBA : ReadCDAudioLBA_t;
|
||||
QueryCDParms : QueryCDParms_t;
|
||||
ModifyCDParms : ModifyCDParms_t;
|
||||
GetCDHandle : GetCDHandle_t;
|
||||
CloseCDHandle : CloseCDHandle_t;
|
||||
ReadCDAudioLBAEx : ReadCDAudioLBAEx_t;
|
||||
|
||||
procedure CDRIPInit(FilePath:String);
|
||||
|
||||
implementation
|
||||
|
||||
procedure CDRIPInit(FilePath:String);
|
||||
begin
|
||||
Libhandle := LoadLibraryEx(akriplib, 0, 0);
|
||||
if Libhandle <> 0 then
|
||||
begin
|
||||
CDRipLoaded := True;
|
||||
GetNumAdapters := GetProcAddress(Libhandle, 'GetNumAdapters');
|
||||
GetCDList := GetProcAddress(Libhandle, 'GetCDList');
|
||||
GetAspiLibError := GetProcAddress(Libhandle, 'GetAspiLibError');
|
||||
GetAspiLibAspiError := GetProcAddress(Libhandle, 'GetAspiLibAspiError');
|
||||
GetCDId := GetProcAddress(Libhandle, 'GetCDId');
|
||||
GetDriveInfo := GetProcAddress(Libhandle, 'GetCDDriveInfo');
|
||||
ReadTOC := GetProcAddress(Libhandle, 'ReadTOC');
|
||||
ReadCDAudioLBA := GetProcAddress(Libhandle, 'ReadCDAudioLBA');
|
||||
QueryCDParms := GetProcAddress(Libhandle, 'QueryCDParams');
|
||||
ModifyCDParms := GetProcAddress(Libhandle, 'ModifyCDParms');
|
||||
GetCDHandle := GetProcAddress(Libhandle, 'GetCDHandle');
|
||||
CloseCDHandle := GetProcAddress(Libhandle, 'CloseCDHandle');
|
||||
ReadCDAudioLBAEx := GetProcAddress(Libhandle, 'ReadCDAudioLBAEx');
|
||||
end;
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
||||
finalization
|
||||
if Libhandle <> 0 then
|
||||
begin
|
||||
FreeLibrary(Libhandle);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
481
acs/Src/drivers/acs_alsaaudio.pas
Normal file
481
acs/Src/drivers/acs_alsaaudio.pas
Normal file
@@ -0,0 +1,481 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.3.
|
||||
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: acs_alsaaudio.pas,v $
|
||||
Revision 1.6 2006/08/30 18:59:51 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.5 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.2 2006/01/01 18:46:40 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/12/19 18:36:05 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/13 21:53:45 z0m3ie
|
||||
maked seperat driver (not complete jet)
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.3 2005/08/28 20:31:17 z0m3ie
|
||||
linux restructuring for 2.4
|
||||
|
||||
Revision 1.2 2005/08/26 17:03:20 z0m3ie
|
||||
begon to make acs resourcestring aware
|
||||
more advanced tmixer for windows
|
||||
restructured tmixer its better handleable now
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
{$ifdef mswindows}{$message error 'unit not supported'}{$endif}
|
||||
|
||||
unit acs_alsaaudio;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, ACS_Types, ACS_Classes, baseunix, alsa, ACS_Strings,ACS_Audio;
|
||||
|
||||
const
|
||||
BUF_SIZE = $4000;
|
||||
ALSAStateIdle = $ffffffff; // additional DriverState value;
|
||||
LATENCY = 60;
|
||||
|
||||
|
||||
type
|
||||
|
||||
EALSABufferUnderrun = class(EACSException);
|
||||
EALSABufferOverrun = class(EACSException);
|
||||
|
||||
{ TALSAAudioIn }
|
||||
|
||||
TALSAAudioIn = class(TACSBaseAudioIn)
|
||||
private
|
||||
FDevice : String;
|
||||
FPeriodSize, FPeriodNum : Integer;
|
||||
_audio_handle : Psnd_pcm_t;
|
||||
_hw_params : Psnd_pcm_hw_params_t;
|
||||
Busy : Boolean;
|
||||
FBPS, FChan, FFreq : Integer;
|
||||
BufStart, BufEnd : Integer;
|
||||
FOpened : Integer;
|
||||
FRecTime : Integer;
|
||||
FRecBytes : Integer;
|
||||
FLatency : Double;
|
||||
FSilentOnOverrun : Boolean;
|
||||
function GetDriverState: Integer;
|
||||
procedure OpenAudio;
|
||||
procedure CloseAudio;
|
||||
// function GetDriverState : Integer;
|
||||
protected
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
|
||||
procedure SetDevice(Ch : Integer);override;
|
||||
function GetDeviceInfo : TACSDeviceInfo;override;
|
||||
function GetTotalTime : real; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
property DriverState : Integer read GetDriverState;
|
||||
published
|
||||
property PeriodSize : Integer read FPeriodSize write FPeriodSize;
|
||||
property PeriodNum : Integer read FPeriodNum write FPeriodNum;
|
||||
property SilentOnOverrun : Boolean read FSilentOnOverrun write FSilentOnOverrun;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{ TALSAAudioOut }
|
||||
|
||||
TALSAAudioOut = class(TACSBaseAudioOut)
|
||||
|
||||
private
|
||||
FDevice : String;
|
||||
FPeriodSize, FPeriodNum : Integer;
|
||||
_audio_handle : Psnd_pcm_t;
|
||||
_hw_params : Psnd_pcm_hw_params_t;
|
||||
FBufferSize : Integer;
|
||||
FVolume : Byte;
|
||||
_audio_fd : Integer;
|
||||
Buffer : array [0..BUF_SIZE-1] of Byte;
|
||||
FLatency : Double;
|
||||
FSilentOnUnderrun : Boolean;
|
||||
function GetDriverState : Integer;
|
||||
protected
|
||||
procedure Done; override;
|
||||
function DoOutput(Abort : Boolean):Boolean; override;
|
||||
procedure Prepare; override;
|
||||
procedure SetDevice(Ch : Integer);override;
|
||||
function GetDeviceInfo : TACSDeviceInfo;override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
property DriverState : Integer read GetDriverState;
|
||||
property Latency : Double read FLatency;
|
||||
published
|
||||
property BufferSize : Integer read FBufferSize write FBufferSize;
|
||||
property Device : String read FDevice write FDevice stored True;
|
||||
property PeriodSize : Integer read FPeriodSize write FPeriodSize;
|
||||
property PeriodNum : Integer read FPeriodNum write FPeriodNum;
|
||||
property SilentOnUnderrun : Boolean read FSilentOnUnderrun write FSilentOnUnderrun;
|
||||
property Volume : Byte read FVolume write FVolume stored True;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
constructor TALSAAudioIn.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
if not (csDesigning in ComponentState) then
|
||||
if not AsoundlibLoaded then
|
||||
raise EACSException.Create(Format(strcoudntloadLib,[asoundlib_path]));
|
||||
FBPS := 8;
|
||||
FChan := 1;
|
||||
FFreq := 8000;
|
||||
FSize := -1;
|
||||
FRecTime := 600;
|
||||
FDevice := 'default';
|
||||
BufferSize := 32768;
|
||||
FSilentOnOverrun := True;
|
||||
end;
|
||||
|
||||
destructor TALSAAudioIn.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
CloseAudio;
|
||||
end;
|
||||
|
||||
procedure TALSAAudioIn.OpenAudio;
|
||||
var
|
||||
Res : Integer;
|
||||
begin
|
||||
if FOpened = 0 then
|
||||
begin
|
||||
Res := snd_pcm_open(_audio_handle, @FDevice[1], SND_PCM_STREAM_CAPTURE, 0);
|
||||
if Res < 0 then
|
||||
raise EACSException.Create(Format(strcoudntopendevice,[FDevice]));
|
||||
// snd_pcm_reset(_audio_handle);
|
||||
end;
|
||||
Inc(FOpened);
|
||||
end;
|
||||
|
||||
procedure TALSAAudioIn.CloseAudio;
|
||||
begin
|
||||
if FOpened = 1 then
|
||||
begin
|
||||
snd_pcm_drop(_audio_handle);
|
||||
snd_pcm_close(_audio_handle);
|
||||
end;
|
||||
if FOpened > 0 then Dec(FOpened);
|
||||
end;
|
||||
|
||||
(* Note on the following three methods.
|
||||
These methods simply return the values passed by the user.
|
||||
As the actual input process begins, ALSAAudioIn may return a bit different
|
||||
value of the samplerate that is actually set by the ALSA drivers.*)
|
||||
|
||||
function TALSAAudioIn.GetBPS : Integer;
|
||||
begin
|
||||
Result := FBPS;
|
||||
end;
|
||||
|
||||
function TALSAAudioIn.GetCh : Integer;
|
||||
begin
|
||||
Result := FChan;
|
||||
end;
|
||||
|
||||
function TALSAAudioIn.GetSR : Integer;
|
||||
begin
|
||||
Result := FFreq;
|
||||
end;
|
||||
|
||||
procedure TALSAAudioIn.SetDevice(Ch: Integer);
|
||||
begin
|
||||
FDevice := IntToStr(ch);
|
||||
end;
|
||||
|
||||
function TALSAAudioIn.GetDeviceInfo: TACSDeviceInfo;
|
||||
begin
|
||||
end;
|
||||
|
||||
procedure TALSAAudioIn.Init;
|
||||
var
|
||||
aBufSize : Integer;
|
||||
begin
|
||||
if Busy then raise EACSException.Create(strBusy);
|
||||
BufEnd := 0;
|
||||
BufStart := 1;
|
||||
FPosition := 0;
|
||||
OpenAudio;
|
||||
|
||||
snd_pcm_hw_params_malloc(_hw_params);
|
||||
snd_pcm_hw_params_any(_audio_handle, _hw_params);
|
||||
snd_pcm_hw_params_set_access(_audio_handle, _hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
if FBPS = 8 then snd_pcm_hw_params_set_format(_audio_handle, _hw_params, SND_PCM_FORMAT_U8)
|
||||
else snd_pcm_hw_params_set_format(_audio_handle, _hw_params, SND_PCM_FORMAT_S16_LE);
|
||||
Self.FFreq := snd_pcm_hw_params_set_rate_near(_audio_handle, _hw_params, FFreq, 0);
|
||||
snd_pcm_hw_params_set_channels(_audio_handle, _hw_params, FChan);
|
||||
if (FPeriodSize <> 0) and (FPeriodNum <> 0) then
|
||||
begin
|
||||
snd_pcm_hw_params_set_period_size_near(_audio_handle, _hw_params, FPeriodSize, 0);
|
||||
snd_pcm_hw_params_set_periods_near(_audio_handle, _hw_params, FPeriodNum, 0);
|
||||
aBufSize := (FPeriodSize * FPeriodNum) div (FChan * (FBPS shr 3));
|
||||
end
|
||||
else aBufSize := Self.BufferSize div (FChan * (FBPS shr 3));
|
||||
snd_pcm_hw_params_set_buffer_size_near(_audio_handle, _hw_params, aBufSize);
|
||||
snd_pcm_hw_params(_audio_handle, _hw_params);
|
||||
snd_pcm_hw_params_free(_hw_params);
|
||||
if snd_pcm_prepare(_audio_handle) < 0 then
|
||||
begin
|
||||
CloseAudio;
|
||||
raise EACSException.Create(strInputstartfailed);
|
||||
end;
|
||||
try
|
||||
FLatency := snd_pcm_hw_params_get_period_size(_audio_handle, 0) *
|
||||
snd_pcm_hw_params_get_periods(_audio_handle, 0)/(FFreq * FChan * (FBPS shr 3));
|
||||
except
|
||||
end;
|
||||
FRecBytes := FRecTime * (GetBPS div 8) * GetCh * GetSR;
|
||||
Busy := True;
|
||||
FSize := FRecBytes;
|
||||
end;
|
||||
|
||||
procedure TALSAAudioIn.Flush;
|
||||
begin
|
||||
snd_pcm_drain(_audio_handle);
|
||||
CloseAudio;
|
||||
Busy := False;
|
||||
end;
|
||||
|
||||
function TALSAAudioIn.GetData(Buffer : Pointer; BufferSize : Integer): Integer;
|
||||
var
|
||||
l : Integer;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create(strStreamnotopen);
|
||||
if FPosition >= FRecBytes then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
if BufStart > BufEnd then
|
||||
begin
|
||||
BufStart := 1;
|
||||
l := snd_pcm_readi(_audio_handle, @FBuffer[1], (BUF_SIZE div FChan) div (FBPS shr 3));
|
||||
while l < 0 do
|
||||
begin
|
||||
snd_pcm_prepare(_audio_handle);
|
||||
if not FSilentOnOverrun then
|
||||
raise EALSABufferOverrun.Create(strBufferoverrun);
|
||||
l := snd_pcm_readi(_audio_handle, @FBuffer[1], (BUF_SIZE div FChan) div (FBPS shr 3));
|
||||
end;
|
||||
if l <> (BUF_SIZE div FChan) div (FBPS shr 3) then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end
|
||||
else BufEnd := l*FChan*(FBPS shr 3);
|
||||
end;
|
||||
if BufferSize < (BufEnd - BufStart + 1)
|
||||
then Result := BufferSize
|
||||
else Result := BufEnd - BufStart + 1;
|
||||
Move(FBuffer[BufStart-1], Buffer^, Result);
|
||||
Inc(BufStart, Result);
|
||||
Inc(FPosition, Result);
|
||||
end;
|
||||
|
||||
|
||||
function TALSAAudioIn.GetTotalTime : real;
|
||||
begin
|
||||
Result := FRecTime;
|
||||
end;
|
||||
|
||||
function TALSAAudioIn.GetDriverState : Integer;
|
||||
|
||||
begin
|
||||
|
||||
if FOpened = 0 then Result := ALSAStateIdle
|
||||
|
||||
else Result := snd_pcm_state(_audio_handle);
|
||||
|
||||
end;
|
||||
|
||||
|
||||
constructor TALSAAudioOut.Create;
|
||||
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
if not (csDesigning in ComponentState) then
|
||||
if not AsoundlibLoaded then
|
||||
raise EACSException.Create(Format(strCoudntloadLib,[asoundlib_path]));
|
||||
FVolume := 255;
|
||||
FDevice := 'default';
|
||||
FBufferSize := 32768;
|
||||
FSilentOnUnderrun := True;
|
||||
end;
|
||||
|
||||
|
||||
destructor TALSAAudioOut.Destroy;
|
||||
|
||||
begin
|
||||
if _audio_handle <> nil then snd_pcm_close(_audio_handle);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
|
||||
procedure TALSAAudioOut.Prepare;
|
||||
|
||||
var
|
||||
Res, aBufSize : Integer;
|
||||
begin
|
||||
FInput.Init;
|
||||
Res := snd_pcm_open(_audio_handle, @FDevice[1], SND_PCM_STREAM_PLAYBACK, 0);
|
||||
if Res < 0 then
|
||||
raise EACSException.Create(Format(strCoudntopendeviceOut,[FDevice]));
|
||||
//snd_pcm_reset(_audio_handle);
|
||||
snd_pcm_hw_params_malloc(_hw_params);
|
||||
snd_pcm_hw_params_any(_audio_handle, _hw_params);
|
||||
snd_pcm_hw_params_set_access(_audio_handle, _hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
if FInput.BitsPerSample = 8 then
|
||||
snd_pcm_hw_params_set_format(_audio_handle, _hw_params, SND_PCM_FORMAT_U8)
|
||||
else
|
||||
snd_pcm_hw_params_set_format(_audio_handle, _hw_params, SND_PCM_FORMAT_S16_LE);
|
||||
snd_pcm_hw_params_set_rate_near(_audio_handle, _hw_params, FInput.SampleRate, 0);
|
||||
snd_pcm_hw_params_set_channels(_audio_handle, _hw_params, FInput.Channels);
|
||||
if (FPeriodSize <> 0) and (FPeriodNum <> 0) then
|
||||
begin
|
||||
snd_pcm_hw_params_set_period_size_near(_audio_handle, _hw_params, FPeriodSize, 0);
|
||||
snd_pcm_hw_params_set_periods_near(_audio_handle, _hw_params, FPeriodNum, 0);
|
||||
aBufSize := (FPeriodSize * FPeriodNum) div (Finput.Channels * (Finput.BitsPerSample shr 3));
|
||||
end
|
||||
else aBufSize := Self.FBufferSize div (Finput.Channels * (Finput.BitsPerSample shr 3));
|
||||
snd_pcm_hw_params_set_buffer_size_near(_audio_handle, _hw_params, aBufSize);
|
||||
snd_pcm_hw_params(_audio_handle, _hw_params);
|
||||
snd_pcm_hw_params_free(_hw_params);
|
||||
if snd_pcm_prepare(_audio_handle) < 0 then
|
||||
begin
|
||||
raise EACSException.Create(strFailedtostartoutput);
|
||||
end;
|
||||
try
|
||||
FLatency := snd_pcm_hw_params_get_period_size(_audio_handle, 0) *
|
||||
snd_pcm_hw_params_get_periods(_audio_handle, 0)/(Finput.Channels * (Finput.BitsPerSample shr 3));
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TALSAAudioOut.SetDevice(Ch: Integer);
|
||||
begin
|
||||
// FDevice := IntToStr(ch);
|
||||
end;
|
||||
|
||||
function TALSAAudioOut.GetDeviceInfo: TACSDeviceInfo;
|
||||
begin
|
||||
end;
|
||||
|
||||
procedure TALSAAudioOut.Done;
|
||||
begin
|
||||
snd_pcm_drain(_audio_handle);
|
||||
snd_pcm_close(_audio_handle);
|
||||
_audio_handle := 0;
|
||||
FInput.Flush;
|
||||
end;
|
||||
|
||||
function TALSAAudioOut.DoOutput(Abort : Boolean):Boolean;
|
||||
var
|
||||
Len, i, VCoef, l : Integer;
|
||||
P : Pointer;
|
||||
P1 : PACSBuffer8;
|
||||
P2 : PACSBuffer16;
|
||||
begin
|
||||
// No exceptions Here
|
||||
Result := True;
|
||||
if not CanOutput then Exit;
|
||||
Len := 0;
|
||||
if Abort then
|
||||
begin
|
||||
snd_pcm_drain(_audio_handle);
|
||||
snd_pcm_close(_audio_handle);
|
||||
_audio_handle := 0;
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
try
|
||||
P := @Buffer[0];
|
||||
while InputLock do;
|
||||
InputLock := True;
|
||||
Len := Finput.GetData(P, BUF_SIZE);
|
||||
InputLock := False;
|
||||
if Len = 0 then
|
||||
begin
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
if FVolume < 255 then
|
||||
begin
|
||||
VCoef := Round(FVolume/255);
|
||||
if FInput.BitsPerSample = 16 then
|
||||
begin
|
||||
P2 := @Buffer[0];
|
||||
for i := 0 to (Len shr 1) -1 do
|
||||
P2[i] := P2[i]*VCoef;
|
||||
end else
|
||||
begin
|
||||
P1 := @Buffer[0];
|
||||
for i := 0 to Len - 1 do
|
||||
P1[i] := P1[i]*VCoef;
|
||||
end;
|
||||
end;
|
||||
l := snd_pcm_writei(_audio_handle, P, (Len div Finput.Channels) div (FInput.BitsPerSample shr 3));
|
||||
while l < 0 do
|
||||
begin
|
||||
snd_pcm_prepare(_audio_handle);
|
||||
if not FSilentOnUnderrun then
|
||||
raise EALSABufferUnderrun.Create(strBufferunderrun);
|
||||
l := snd_pcm_writei(_audio_handle, P, (Len div Finput.Channels) div (FInput.BitsPerSample shr 3));
|
||||
end;
|
||||
if l = (Len div Finput.Channels) div (FInput.BitsPerSample shr 3)
|
||||
then Result := True
|
||||
else Result := False;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
function TALSAAudioOut.GetDriverState : Integer;
|
||||
begin
|
||||
|
||||
if not Busy then Result := ALSAStateIdle
|
||||
|
||||
else Result := snd_pcm_state(_audio_handle);
|
||||
|
||||
end;
|
||||
|
||||
initialization
|
||||
if AsoundlibLoaded then
|
||||
begin
|
||||
RegisterAudioOut('Alsa',TAlsaAudioOut,LATENCY);
|
||||
RegisterAudioIn('Alsa',TAlsaAudioIn,LATENCY);
|
||||
end;
|
||||
|
||||
end.
|
||||
216
acs/Src/drivers/acs_aolive.pas
Normal file
216
acs/Src/drivers/acs_aolive.pas
Normal file
@@ -0,0 +1,216 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.3.
|
||||
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
{$Log: acs_aolive.pas,v $
|
||||
{Revision 1.2 2006/01/01 18:46:40 z0m3ie
|
||||
{*** empty log message ***
|
||||
{
|
||||
{Revision 1.1 2005/12/19 18:36:05 z0m3ie
|
||||
{*** empty log message ***
|
||||
{
|
||||
{Revision 1.2 2005/09/14 21:19:37 z0m3ie
|
||||
{*** empty log message ***
|
||||
{
|
||||
{Revision 1.1 2005/09/13 21:53:45 z0m3ie
|
||||
{maked seperat driver (not complete jet)
|
||||
{}
|
||||
|
||||
unit acs_aolive;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes,ACS_Classes,ACS_Audio,libao,SysUtils,ACS_Strings,ACS_Types;
|
||||
|
||||
const
|
||||
LATENCY = 45;//how to measure ?
|
||||
|
||||
type
|
||||
|
||||
{ TAOLiveAudioOut }
|
||||
|
||||
TAOLiveAudioOut = class(TACSBaseAudioOut)
|
||||
private
|
||||
_device : PAODevice;
|
||||
FVolume : Byte;
|
||||
FDrivers : TStringList;
|
||||
FCurrentDriver,
|
||||
FDefaultDriver : String;
|
||||
function IsDevicePlayable(const Dev : String) : Boolean;
|
||||
protected
|
||||
procedure Done; override;
|
||||
function DoOutput(Abort : Boolean):Boolean; override;
|
||||
procedure Prepare; override;
|
||||
procedure SetDevice(Ch : Integer);override;
|
||||
function GetDeviceInfo : TACSDeviceInfo;override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
constructor TAOLiveAudioOut.Create;
|
||||
var
|
||||
DrList : PPAOInfo;
|
||||
DrCount, i : Integer;
|
||||
Info : PAOInfo;
|
||||
begin
|
||||
if not LibaoLoaded then
|
||||
raise EACSException.Create(Format(strCoudntloadlib,[LibaoPath]));
|
||||
inherited Create(AOwner);
|
||||
if AOInitialized = 0 then
|
||||
ao_initialize;
|
||||
Inc(AOInitialized);
|
||||
FDrivers := TStringList.Create;
|
||||
DrList := ao_driver_info_list(DrCount);
|
||||
for i := 0 to DrCount-1 do
|
||||
begin
|
||||
if DrList^._type = AO_TYPE_LIVE then
|
||||
begin
|
||||
FDrivers.Add(String(DrList^.short_name));
|
||||
end;
|
||||
Inc(DrList);
|
||||
end;
|
||||
Info := ao_driver_info(ao_default_driver_id);
|
||||
FDefaultDriver := Info.short_name;
|
||||
FVolume := 255;
|
||||
end;
|
||||
|
||||
destructor TAOLiveAudioOut.Destroy;
|
||||
begin
|
||||
FDrivers.Free;
|
||||
if AOInitialized = 1 then
|
||||
ao_shutdown;
|
||||
Dec(AOInitialized);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TAOLiveAudioOut.Prepare;
|
||||
var
|
||||
did : Integer;
|
||||
sf : ao_sample_format;
|
||||
opt : PAOOption;
|
||||
Info : PAOInfo;
|
||||
begin
|
||||
FInput.Init;
|
||||
if FCurrentDriver = '' then
|
||||
begin
|
||||
did := ao_default_driver_id;
|
||||
Info := ao_driver_info(did);
|
||||
FCurrentDriver := Info.short_name;
|
||||
end
|
||||
else did := ao_driver_id(@FCurrentDriver[1]);
|
||||
opt := nil;
|
||||
sf.bits := Finput.BitsPerSample;
|
||||
sf.rate := Finput.SampleRate;
|
||||
sf.channels := Finput.Channels;
|
||||
sf.byte_format := AO_FMT_NATIVE;
|
||||
_device := ao_open_live(did, @sf, opt);
|
||||
FreeOptionsList(Opt);
|
||||
if _device = nil then
|
||||
raise EACSException.Create(Format(strDevnotplayable,['+FCurrentDriver+']));
|
||||
end;
|
||||
|
||||
procedure TAOLiveAudioOut.SetDevice(Ch: Integer);
|
||||
begin
|
||||
if ch < FDrivers.Count-1 then
|
||||
if IsDevicePlayable(FDrivers[ch]) then
|
||||
FCurrentDriver := FDrivers[ch];
|
||||
end;
|
||||
|
||||
function TAOLiveAudioOut.GetDeviceInfo: TACSDeviceInfo;
|
||||
begin
|
||||
end;
|
||||
|
||||
procedure TAOLiveAudioOut.Done;
|
||||
begin
|
||||
Finput.Flush;
|
||||
if _device <> nil then
|
||||
ao_close(_device);
|
||||
end;
|
||||
|
||||
function TAOLiveAudioOut.DoOutput(Abort : Boolean):Boolean;
|
||||
var
|
||||
Len, i : Integer;
|
||||
P : Pointer;
|
||||
P1 : PACSBuffer8;
|
||||
P2 : PACSBuffer16;
|
||||
begin
|
||||
// No exceptions Here
|
||||
Result := True;
|
||||
if not CanOutput then Exit;
|
||||
Len := 0;
|
||||
if Abort then
|
||||
begin
|
||||
ao_close(_device);
|
||||
_device := nil;
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
try
|
||||
P := @FBuffer[0];
|
||||
while InputLock do;
|
||||
InputLock := True;
|
||||
Len := Finput.GetData(P, FBufferSize);
|
||||
InputLock := False;
|
||||
if FVolume < 255 then
|
||||
begin
|
||||
if FInput.BitsPerSample = 16 then
|
||||
begin
|
||||
P2 := @FBuffer[0];
|
||||
for i := 0 to (Len shr 1) -1 do
|
||||
P2[i] := Round(P2[i]*(FVolume/255));
|
||||
end else
|
||||
begin
|
||||
P1 := @FBuffer[0];
|
||||
for i := 0 to Len - 1 do
|
||||
P1[i] := Round(P1[i]*(FVolume/255));
|
||||
end;
|
||||
end;
|
||||
ao_play(_device, P, Len);
|
||||
except
|
||||
end;
|
||||
if Len > 0 then Result := True
|
||||
else Result := False;
|
||||
end;
|
||||
|
||||
function TAOLiveAudioOut.IsDevicePlayable(const Dev : String) : Boolean;
|
||||
var
|
||||
i, did : Integer;
|
||||
sf : ao_sample_format;
|
||||
opt : PAOOption;
|
||||
begin
|
||||
Result := True;
|
||||
if Dev = '' then Exit;
|
||||
if Busy then
|
||||
raise EACSException.Create(strBusy);
|
||||
for i := 0 to FDrivers.Count-1 do
|
||||
if FDrivers.Strings[i] = Dev then
|
||||
begin
|
||||
did := ao_driver_id(@Dev[1]);
|
||||
sf.bits := 16;
|
||||
sf.rate := 22050;
|
||||
sf.channels := 2;
|
||||
sf.byte_format := AO_FMT_NATIVE;
|
||||
opt := nil;
|
||||
_device := ao_open_live(did, @sf, opt);
|
||||
if _device <> nil then
|
||||
begin
|
||||
ao_close(_device);
|
||||
FreeOptionsList(Opt);
|
||||
Exit;
|
||||
end else Break;
|
||||
end;
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
initialization
|
||||
RegisterAudioOut('AOlive',TAOLiveAudioOut,LATENCY);
|
||||
|
||||
end.
|
||||
|
||||
563
acs/Src/drivers/acs_dxaudio.pas
Normal file
563
acs/Src/drivers/acs_dxaudio.pas
Normal file
@@ -0,0 +1,563 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.3.
|
||||
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: acs_dxaudio.pas,v $
|
||||
Revision 1.7 2006/08/31 20:10:56 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.6 2006/07/09 16:40:35 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.5 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.3 2006/01/01 18:46:40 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/12/26 17:31:39 z0m3ie
|
||||
fixed some problems in acs_dsfiles
|
||||
fixed some problems in acs_vorbis
|
||||
reworked all buffers
|
||||
|
||||
Revision 1.1 2005/12/19 18:36:05 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.9 2005/12/18 17:01:54 z0m3ie
|
||||
delphi compatibility
|
||||
|
||||
Revision 1.8 2005/12/04 16:54:34 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.7 2005/10/02 16:51:31 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.6 2005/09/23 14:04:58 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.5 2005/09/18 19:28:59 z0m3ie
|
||||
more progress on driver handling
|
||||
|
||||
Revision 1.4 2005/09/16 17:34:29 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.3 2005/09/15 20:59:38 z0m3ie
|
||||
start translate the documentation in the source for pasdoc
|
||||
|
||||
Revision 1.2 2005/09/14 21:19:37 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/13 21:53:45 z0m3ie
|
||||
maked seperat driver (not complete jet)
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
Revision 1.3 2005/08/22 20:17:02 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
{$ifdef linux}{$message error 'unit not supported'}{$endif linux}
|
||||
|
||||
unit acs_dxaudio;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
ACS_Audio,SysUtils, Classes, Forms, ACS_Types, ACS_Classes, Windows,ACS_Strings;
|
||||
|
||||
const
|
||||
LATENCY = 25;
|
||||
DS_POLLING_INTERVAL = 400; //milliseconds
|
||||
|
||||
type
|
||||
|
||||
TDSoundWrapper = record
|
||||
dsw_pDirectSound : Pointer;
|
||||
dsw_OutputBuffer : Pointer;
|
||||
dsw_WriteOffset : LongWord;
|
||||
dsw_OutputSize : Integer;
|
||||
dsw_BytesPerFrame : Integer;
|
||||
dsw_CounterTicksPerBuffer : Int64;
|
||||
dsw_LastPlayTime : Int64;
|
||||
dsw_LastPlayCursor : Int64;
|
||||
dsw_OutputUnderflows : Int64;
|
||||
dsw_OutputRunning : LongBool;
|
||||
dsw_FramesWritten : Double;
|
||||
dsw_FramesPlayed : Double;
|
||||
dsw_pDirectSoundCapture : Pointer;
|
||||
dsw_InputBuffer : Pointer;
|
||||
dsw_ReadOffset : LongWord;
|
||||
dsw_InputSize : LongWord;
|
||||
end;
|
||||
|
||||
PDSoundWrapper = ^TDSoundWrapper;
|
||||
|
||||
TDSW_DeviceInfo = record
|
||||
guid : TGUID;
|
||||
name : array[0..127] of char;
|
||||
end;
|
||||
|
||||
TDSW_Devices = record
|
||||
devcount : Integer;
|
||||
dinfo : array [0..15] of TDSW_DeviceInfo;
|
||||
end;
|
||||
|
||||
PDSW_Devices = ^TDSW_Devices;
|
||||
|
||||
{ TDXAudioOut }
|
||||
|
||||
TDXAudioOut = class(TACSBaseAudioOut)
|
||||
private
|
||||
DSW : TDSoundWrapper;
|
||||
Devices : TDSW_Devices;
|
||||
Chan, SR, BPS : Integer;
|
||||
EndOfInput, StartInput : Boolean;
|
||||
FDeviceNumber : Integer;
|
||||
FDeviceCount : Integer;
|
||||
procedure SetDevice(Ch : Integer);override;
|
||||
function GetDeviceInfo : TACSDeviceInfo;override;
|
||||
function GetDeviceCount : Integer;override;
|
||||
protected
|
||||
procedure Done; override;
|
||||
function DoOutput(Abort : Boolean):Boolean; override;
|
||||
procedure Prepare; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
procedure Pause;override;
|
||||
procedure Resume;override;
|
||||
end;
|
||||
|
||||
TDXAudioIn = class(TACSBaseAudioIn)
|
||||
private
|
||||
DSW : TDSoundWrapper;
|
||||
Devices : TDSW_Devices;
|
||||
FDeviceNumber : Integer;
|
||||
FDeviceCount : Integer;
|
||||
FBPS, FChan, FFreq : Integer;
|
||||
FOpened : Integer;
|
||||
FBytesToRead : Integer;
|
||||
FRecTime : Integer;
|
||||
procedure SetDevice(i : Integer);override;
|
||||
function GetDeviceName(Number : Integer) : String;
|
||||
procedure OpenAudio;
|
||||
procedure CloseAudio;
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
function GetTotalTime : real; override;
|
||||
procedure SetRecTime(aRecTime : Integer);
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
property DeviceCount : Integer read FDeviceCount;
|
||||
property DeviceName[Number : Integer] : String read GetDeviceName;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
type
|
||||
|
||||
DSW_Init_t = function(dsw: PDSoundWrapper) : HRESULT; cdecl;
|
||||
DSW_Term_t = procedure(dsw: PDSoundWrapper); cdecl;
|
||||
DSW_InitOutputDevice_t = function (dsw: PDSoundWrapper; const guid : TGUID) : HRESULT; cdecl;
|
||||
DSW_InitOutputBuffer_t = function (dsw: PDSoundWrapper; Wnd : HWND; bps, nFrameRate : LongWord; nChannels, bufSize : Integer): HRESULT; cdecl;
|
||||
DSW_StartOutput_t = function (dsw: PDSoundWrapper) : HRESULT; cdecl;
|
||||
DSW_StopOutput_t = function(dsw: PDSoundWrapper) : HRESULT; cdecl;
|
||||
DSW_RestartOutput_t = function(dsw: PDSoundWrapper) : HRESULT; cdecl;
|
||||
DSW_GetOutputStatus_t = function(dsw: PDSoundWrapper) : DWORD; cdecl;
|
||||
DSW_WriteBlock_t = function(dsw: PDSoundWrapper; buf : PByte; numBytes : Integer) : HRESULT; cdecl;
|
||||
DSW_ZeroEmptySpace_t = function(dsw: PDSoundWrapper) : HRESULT; cdecl;
|
||||
DSW_QueryOutputSpace_t = function(dsw: PDSoundWrapper; var bytesEmpty ) : HRESULT; cdecl;
|
||||
DSW_Enumerate_t = function(var devices : TDSW_Devices) : HRESULT; cdecl;
|
||||
|
||||
DSW_InitInputBuffer_t = function(dsw: PDSoundWrapper; bps, nFrameRate, nChannels, bufSize : Integer) : HRESULT; cdecl;
|
||||
DSW_InitInputDevice_t = function(dsw: PDSoundWrapper; const GUID : TGUID) : HRESULT; cdecl;
|
||||
DSW_StartInput_t = function(dsw: PDSoundWrapper) : HRESULT; cdecl;
|
||||
DSW_StopInput_t = function(dsw: PDSoundWrapper) : HRESULT; cdecl;
|
||||
DSW_ReadBlock_t = function(dsw: PDSoundWrapper; buf : PByte; numBytes : Integer) : HRESULT; cdecl;
|
||||
DSW_QueryInputFilled_t = function(dsw: PDSoundWrapper; var bytesFilled : Integer) : HRESULT; cdecl;
|
||||
|
||||
var
|
||||
|
||||
LibdswLoaded : Boolean = False;
|
||||
|
||||
DSW_Init : DSW_Init_t;
|
||||
DSW_Term : DSW_Term_t;
|
||||
DSW_InitOutputDevice : DSW_InitOutputDevice_t;
|
||||
DSW_InitOutputBuffer : DSW_InitOutputBuffer_t;
|
||||
DSW_StartOutput : DSW_StartOutput_t;
|
||||
DSW_StopOutput : DSW_StopOutput_t;
|
||||
DSW_RestartOutput : DSW_RestartOutput_t;
|
||||
DSW_GetOutputStatus : DSW_GetOutputStatus_t;
|
||||
DSW_WriteBlock : DSW_WriteBlock_t;
|
||||
DSW_ZeroEmptySpace : DSW_ZeroEmptySpace_t;
|
||||
DSW_QueryOutputSpace : DSW_QueryOutputSpace_t;
|
||||
DSW_Enumerate : DSW_Enumerate_t;
|
||||
|
||||
DSW_InitInputBuffer : DSW_InitInputBuffer_t;
|
||||
DSW_InitInputDevice : DSW_InitInputDevice_t;
|
||||
DSW_StartInput : DSW_StartInput_t;
|
||||
DSW_StopInput : DSW_StopInput_t;
|
||||
DSW_ReadBlock : DSW_ReadBlock_t;
|
||||
DSW_QueryInputFilled : DSW_QueryInputFilled_t;
|
||||
|
||||
Libhandle : HMODULE;
|
||||
|
||||
|
||||
procedure TDXAudioOut.Prepare;
|
||||
var
|
||||
Res : HResult;
|
||||
Wnd : HWND;
|
||||
Form : TForm;
|
||||
begin
|
||||
if (FDeviceNumber >= FDeviceCount) then raise EACSException.Create(Format(strChannelnotavailable,[FDeviceNumber]));
|
||||
FInput.Init;
|
||||
FBuffer := AllocMem(FBufferSize);
|
||||
Chan := FInput.Channels;
|
||||
SR := FInput.SampleRate;
|
||||
BPS := FInput.BitsPerSample;
|
||||
DSW_Init(@DSW);
|
||||
Res := DSW_InitOutputDevice(@DSW, Devices.dinfo[FDeviceNumber].guid);
|
||||
if Res <> 0 then raise EACSException.Create(strFailedtoCreateDSdev);
|
||||
{ if Owner is TForm then
|
||||
begin
|
||||
Form := Owner as TForm;
|
||||
Wnd := Form.Handle;
|
||||
end else }
|
||||
Wnd := 0;
|
||||
Res := DSW_InitOutputBuffer(@DSW, Wnd, BPS, SR, Chan, FBufferSize);
|
||||
if Res <> 0 then raise EACSException.Create(strFailedtoCreateDSbuf);
|
||||
StartInput := True;
|
||||
EndOfInput := False;
|
||||
end;
|
||||
|
||||
procedure TDXAudioOut.Done;
|
||||
begin
|
||||
Finput.Flush;
|
||||
DSW_Term(@DSW);
|
||||
FreeMem(FBuffer);
|
||||
end;
|
||||
|
||||
function TDXAudioOut.DoOutput(Abort : Boolean):Boolean;
|
||||
var
|
||||
Len, offs, lb : Integer;
|
||||
Stat : LongWord;
|
||||
Res : HRESULT;
|
||||
PlayTime, CTime : LongWord;
|
||||
begin
|
||||
Result := True;
|
||||
if not Busy then Exit;
|
||||
if not CanOutput then
|
||||
begin
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
if Abort then
|
||||
begin
|
||||
DSW_StopOutput(@DSW);
|
||||
CanOutput := False;
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
if StartInput then
|
||||
begin
|
||||
Len := 0;
|
||||
while Len < FBufferSize do
|
||||
begin
|
||||
offs := FInput.GetData(@FBuffer^[Len], FBufferSize-Len);
|
||||
if offs = 0 then
|
||||
begin
|
||||
EndOfInput := True;
|
||||
Break;
|
||||
end;
|
||||
Inc(Len, offs);
|
||||
end;
|
||||
DSW_WriteBlock(@DSW, @FBuffer^, Len);
|
||||
DSW_StartOutput(@DSW);
|
||||
StartInput := False;
|
||||
end;
|
||||
if EndOfInput then
|
||||
begin
|
||||
CanOutput := False;
|
||||
PlayTime := Round(FBufferSize/(Chan*(BPS div 8)*SR))*1000;
|
||||
CTime := 0;
|
||||
while CTime < PlayTime do
|
||||
begin
|
||||
Sleep(100);
|
||||
DSW_ZeroEmptySpace(@DSW);
|
||||
Inc(CTime, 100);
|
||||
end;
|
||||
DSW_StopOutput(@DSW);
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
Sleep(DS_POLLING_INTERVAL);
|
||||
DSW_QueryOutputSpace(@DSW, lb);
|
||||
lb := lb - (lb mod 1024);
|
||||
Len := 0;
|
||||
while Len < lb do
|
||||
begin
|
||||
if FInput.Busy then
|
||||
begin
|
||||
try
|
||||
offs := Finput.GetData(@FBuffer^[Len], lb-Len);
|
||||
except
|
||||
DSW_StopOutput(@DSW);
|
||||
CanOutput := False;
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
if offs = 0 then Break;
|
||||
Inc(Len, offs);
|
||||
end;
|
||||
DSW_WriteBlock(@DSW, @Fbuffer^, Len);
|
||||
if offs = 0 then
|
||||
begin
|
||||
DSW_ZeroEmptySpace(@DSW);
|
||||
EndOfInput := True;
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TDXAudioOut.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FBufferSize := $40000;
|
||||
if not (csDesigning in ComponentState) then
|
||||
begin
|
||||
if not LibdswLoaded then
|
||||
raise EACSException.Create(Format(strCoudntloadlib,['dswrapper.dll']));
|
||||
end;
|
||||
if LibdswLoaded then DSW_Enumerate(Devices);
|
||||
FDeviceCount := Devices.devcount;
|
||||
end;
|
||||
|
||||
destructor TDXAudioOut.Destroy;
|
||||
begin
|
||||
if LibdswLoaded then DSW_Term(@DSW);
|
||||
end;
|
||||
|
||||
procedure TDXAudioOut.Pause;
|
||||
begin
|
||||
if EndOfInput then Exit;
|
||||
DSW_StopOutput(@DSW);
|
||||
end;
|
||||
|
||||
procedure TDXAudioOut.Resume;
|
||||
begin
|
||||
if EndOfInput then Exit;
|
||||
DSW_RestartOutput(@DSW);
|
||||
end;
|
||||
|
||||
procedure TDXAudioOut.SetDevice(Ch: Integer);
|
||||
begin
|
||||
FBaseChannel := Ch;
|
||||
end;
|
||||
|
||||
function TDXAudioOut.GetDeviceInfo: TACSDeviceInfo;
|
||||
begin
|
||||
if (FBaseChannel >= FDeviceCount) then
|
||||
exit;
|
||||
Result.DeviceName := PChar(@(Devices.dinfo[FBaseChannel].Name[0]));
|
||||
end;
|
||||
|
||||
function TDXAudioOut.GetDeviceCount: Integer;
|
||||
begin
|
||||
Result := FDeviceCount;
|
||||
end;
|
||||
|
||||
constructor TDXAudioIn.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FBPS := 8;
|
||||
FChan := 1;
|
||||
FFreq := 8000;
|
||||
FSize := -1;
|
||||
BufferSize := $2000;
|
||||
if not (csDesigning in ComponentState) then
|
||||
begin
|
||||
if not LibdswLoaded then
|
||||
raise EACSException.Create(Format(strCoudntloadlib,['dswrapper.dll']));
|
||||
end;
|
||||
if LibdswLoaded then DSW_Enumerate(Devices);
|
||||
FDeviceCount := Devices.devcount;
|
||||
end;
|
||||
|
||||
destructor TDXAudioIn.Destroy;
|
||||
begin
|
||||
if LibdswLoaded then DSW_Term(@DSW);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TDXAudioIn.OpenAudio;
|
||||
var
|
||||
Res : HResult;
|
||||
BufSize : Integer;
|
||||
begin
|
||||
BufSize := BufferSize;
|
||||
if FOpened = 0 then
|
||||
begin
|
||||
DSW_Init(@DSW);
|
||||
if not Assigned(DSW_InitInputDevice) then raise EACSException.Create(Format(strChannelNotAvailable,[FDeviceNumber]));
|
||||
Res := DSW_InitInputDevice(@DSW, Devices.dinfo[FDeviceNumber].guid);
|
||||
if Res <> 0 then raise EACSException.Create(strFailedtoCreateDSdev);
|
||||
Res := DSW_InitInputBuffer(@DSW, FBPS, FFreq, FChan, BufSize);
|
||||
if Res <> 0 then raise EACSException.Create(strFailedtoCreateDSbuf);
|
||||
end;
|
||||
Inc(FOpened);
|
||||
end;
|
||||
|
||||
procedure TDXAudioIn.CloseAudio;
|
||||
begin
|
||||
if FOpened = 1 then DSW_Term(@DSW);
|
||||
if FOpened > 0 then Dec(FOpened);
|
||||
end;
|
||||
|
||||
function TDXAudioIn.GetBPS : Integer;
|
||||
begin
|
||||
Result := FBPS;
|
||||
end;
|
||||
|
||||
function TDXAudioIn.GetCh : Integer;
|
||||
begin
|
||||
Result := FChan;
|
||||
end;
|
||||
|
||||
function TDXAudioIn.GetSR : Integer;
|
||||
begin
|
||||
Result := FFreq;
|
||||
end;
|
||||
|
||||
procedure TDXAudioIn.Init;
|
||||
begin
|
||||
if Busy then raise EACSException.Create(strBusy);
|
||||
if (FDeviceNumber >= FDeviceCount) then raise EACSException.Create(Format(strChannelnotavailable,[FDeviceNumber]));
|
||||
if FRecTime > 0 then FBytesToRead := FRecTime*FFreq*FChan*(FBPS div 8);
|
||||
BufEnd := 0;
|
||||
BufStart := 1;
|
||||
FPosition := 0;
|
||||
FBusy := True;
|
||||
FSize := FBytesToRead;
|
||||
OpenAudio;
|
||||
DSW_StartInput(@DSW);
|
||||
end;
|
||||
|
||||
procedure TDXAudioIn.Flush;
|
||||
begin
|
||||
DSW_StopInput(@DSW);
|
||||
CloseAudio;
|
||||
FBusy := False;
|
||||
end;
|
||||
|
||||
function TDXAudioIn.GetData(Buffer : Pointer; BufferSize : Integer): Integer;
|
||||
var
|
||||
l : Integer;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create(strStreamnotopen);
|
||||
if (FBytesToRead >=0) and (FPosition >= FBytesToRead) then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
if BufStart >= BufEnd then
|
||||
begin
|
||||
BufStart := 0;
|
||||
Sleep(DS_POLLING_INTERVAL);
|
||||
DSW_QueryInputFilled(@DSW, l);
|
||||
if l > BufferSize then
|
||||
l := BufferSize; (* We have lost some data.
|
||||
Generally this shouldn't happen. *)
|
||||
l := l - (l mod 1024);
|
||||
DSW_ReadBlock(@DSW, @FBuffer, l);
|
||||
BufEnd := l;
|
||||
end;
|
||||
if BufferSize < (BufEnd - BufStart)
|
||||
then Result := BufferSize
|
||||
else Result := BufEnd - BufStart;
|
||||
Move(FBuffer[BufStart], Buffer^, Result);
|
||||
Inc(BufStart, Result);
|
||||
Inc(FPosition, Result);
|
||||
end;
|
||||
|
||||
procedure TDXAudioIn.SetRecTime;
|
||||
begin
|
||||
FRecTime := aRecTime;
|
||||
if FRecTime > 0 then
|
||||
FBytesToRead := FRecTime*FFreq*FChan*(FBPS div 8)
|
||||
else
|
||||
FBytesToRead := -1;
|
||||
end;
|
||||
|
||||
procedure TDXAudioIn.SetDevice(i : Integer);
|
||||
begin
|
||||
FDeviceNumber := i
|
||||
end;
|
||||
|
||||
function TDXAudioIn.GetDeviceName(Number : Integer) : String;
|
||||
begin
|
||||
if (Number < FDeviceCount) then Result := PChar(@(Devices.dinfo[Number].Name[0]))
|
||||
else Result := '';
|
||||
end;
|
||||
|
||||
function TDXAudioIn.GetTotalTime : real;
|
||||
var
|
||||
BytesPerSec : Integer;
|
||||
begin
|
||||
BytesPerSec := FFreq*FChan*(FBPS div 8);
|
||||
Result := FBytesToRead/BytesPerSec;
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
||||
Libhandle := LoadLibraryEx('dswrapper.dll', 0, 0);
|
||||
|
||||
if Libhandle <> 0 then
|
||||
begin
|
||||
LibdswLoaded := True;
|
||||
|
||||
DSW_Init := GetProcAddress(Libhandle, 'DSW_Init');
|
||||
DSW_Term := GetProcAddress(Libhandle, 'DSW_Term');
|
||||
DSW_InitOutputDevice := GetProcAddress(Libhandle, 'DSW_InitOutputDevice');
|
||||
DSW_InitOutputBuffer := GetProcAddress(Libhandle, 'DSW_InitOutputBuffer');
|
||||
DSW_StartOutput := GetProcAddress(Libhandle, 'DSW_StartOutput');
|
||||
DSW_StopOutput := GetProcAddress(Libhandle, 'DSW_StopOutput');
|
||||
DSW_RestartOutput := GetProcAddress(Libhandle, 'DSW_RestartOutput');
|
||||
DSW_GetOutputStatus := GetProcAddress(Libhandle, 'DSW_GetOutputStatus');
|
||||
DSW_WriteBlock := GetProcAddress(Libhandle, 'DSW_WriteBlock');
|
||||
DSW_ZeroEmptySpace := GetProcAddress(Libhandle, 'DSW_ZeroEmptySpace');
|
||||
DSW_QueryOutputSpace := GetProcAddress(Libhandle, 'DSW_QueryOutputSpace');
|
||||
DSW_Enumerate := GetProcAddress(Libhandle, 'DSW_Enumerate');
|
||||
DSW_InitInputDevice := GetProcAddress(Libhandle, 'DSW_InitInputDevice');
|
||||
DSW_InitInputBuffer := GetProcAddress(Libhandle, 'DSW_InitInputBuffer');
|
||||
DSW_StartInput := GetProcAddress(Libhandle, 'DSW_StartInput');
|
||||
DSW_StopInput := GetProcAddress(Libhandle, 'DSW_StopInput');
|
||||
DSW_ReadBlock := GetProcAddress(Libhandle, 'DSW_ReadBlock');
|
||||
DSW_QueryInputFilled := GetProcAddress(Libhandle, 'DSW_QueryInputFilled');
|
||||
|
||||
end;
|
||||
|
||||
RegisterAudioOut('DirectSound',TDXAudioOut,LATENCY);
|
||||
RegisterAudioIn('DirectSound',TDXAudioIn,LATENCY);
|
||||
|
||||
finalization
|
||||
|
||||
if Libhandle <> 0 then FreeLibrary(Libhandle);
|
||||
|
||||
end.
|
||||
232
acs/Src/drivers/acs_stdaudio.pas
Normal file
232
acs/Src/drivers/acs_stdaudio.pas
Normal file
@@ -0,0 +1,232 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.3 (delphi version).
|
||||
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
||||
see the license file for more details.
|
||||
you can contact me at acs@compiler4.net
|
||||
this is the acs for delphi (windows) version of the unit.
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: acs_stdaudio.pas,v $
|
||||
Revision 1.6 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.4 2006/01/01 18:46:40 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.3 2005/12/30 11:10:57 z0m3ie
|
||||
some corrections to lazarus-linux depending things
|
||||
|
||||
Revision 1.2 2005/12/26 17:31:39 z0m3ie
|
||||
fixed some problems in acs_dsfiles
|
||||
fixed some problems in acs_vorbis
|
||||
reworked all buffers
|
||||
|
||||
Revision 1.1 2005/12/19 18:36:05 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.8 2005/12/04 16:54:34 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.7 2005/11/27 16:50:33 z0m3ie
|
||||
add ACS VolumeQuerry
|
||||
make ACS_VolumeQuerry localizeable
|
||||
some little errorfixes (buffersize for linuxdrivers was initially 0)
|
||||
make TAudioIn workable
|
||||
|
||||
Revision 1.6 2005/10/05 20:26:36 z0m3ie
|
||||
Linux changes
|
||||
|
||||
Revision 1.5 2005/10/02 16:51:31 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.4 2005/09/23 14:04:58 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.3 2005/09/18 19:28:59 z0m3ie
|
||||
more progress on driver handling
|
||||
|
||||
Revision 1.2 2005/09/14 21:19:37 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/13 21:53:45 z0m3ie
|
||||
maked seperat driver (not complete jet)
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.3 2005/09/02 16:27:49 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/08/28 20:31:17 z0m3ie
|
||||
linux restructuring for 2.4
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
Revision 1.4 2005/08/22 20:17:02 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
unit acs_stdaudio;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, ACS_Types, ACS_Classes,ACS_Audio,ACS_Strings
|
||||
{$IFDEF MSWINDOWS}
|
||||
, Windows, MMSystem
|
||||
{$ELSE}
|
||||
, Soundcard
|
||||
{$ENDIF}
|
||||
;
|
||||
|
||||
const
|
||||
LATENCY = 110;
|
||||
|
||||
type
|
||||
{$IFDEF MSWINDOWS}
|
||||
{$IFDEF FPC}
|
||||
TWaveInCapsA = WAVEINCAPSA;
|
||||
TWaveInCaps = TWaveInCapsA;
|
||||
|
||||
TWaveHdr = WAVEHDR;
|
||||
{$ENDIF}
|
||||
|
||||
PPWaveHdr = ^PWaveHdr;
|
||||
{$ENDIF}
|
||||
|
||||
{ TStdAudioOut }
|
||||
|
||||
TStdAudioOut = class(TACSBaseAudioOut)
|
||||
private
|
||||
{$IFDEF MSWINDOWS}
|
||||
BlockChain : PWaveHdr;
|
||||
aBlock : Integer;
|
||||
EOC : PPWaveHdr;
|
||||
FReadChunks : Integer;
|
||||
{$ENDIF}
|
||||
_audio_fd : Integer;
|
||||
procedure SetDevice(Ch : Integer);override;
|
||||
function GetDeviceInfo : TACSDeviceInfo;override;
|
||||
{$IFDEF MSWINDOWS}
|
||||
procedure WriteBlock(P : Pointer; Len : Integer);
|
||||
procedure AddBlockToChain(WH : PWaveHdr);
|
||||
{$ENDIF}
|
||||
function GetDeviceCount : Integer;override;
|
||||
protected
|
||||
procedure Done; override;
|
||||
function DoOutput(Abort : Boolean):Boolean; override;
|
||||
procedure Prepare; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
end;
|
||||
|
||||
TStdAudioIn = class(TACSBaseAudioIn)
|
||||
private
|
||||
{$IFDEF MSWINDOWS}
|
||||
BlockChain : PWaveHdr;
|
||||
FBlocksCount : Integer;
|
||||
aBlock : Integer;
|
||||
EOC : PPWaveHdr;
|
||||
{$ENDIF}
|
||||
_audio_fd : Integer;
|
||||
FOpened : Integer;
|
||||
FRecBytes : Integer;
|
||||
procedure OpenAudio;
|
||||
procedure CloseAudio;
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
procedure SetDevice(Ch : Integer);override;
|
||||
function GetDeviceInfo : TACSDeviceInfo;override;
|
||||
function GetTotalTime : real; override;
|
||||
{$IFDEF MSWINDOWS}
|
||||
procedure NewBlock;
|
||||
procedure AddBlockToChain(WH : PWaveHdr);
|
||||
{$ENDIF}
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; oBufferSize : Integer): Integer; override;
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
end;
|
||||
|
||||
var
|
||||
InputChannelsCount : Integer;
|
||||
OutputChannelsCount : Integer;
|
||||
|
||||
function GetAudioDeviceInfo(DevID : Integer; OutputDev : Boolean) : TACSDeviceInfo;
|
||||
|
||||
implementation
|
||||
|
||||
var
|
||||
CrSecI, CrSecO : TRTLCriticalSection;
|
||||
|
||||
{$IFDEF MSWINDOWS}
|
||||
{$I windows\acs_audio.inc}
|
||||
{$ELSE}
|
||||
{$I linux\acs_audio.inc}
|
||||
{$ENDIF}
|
||||
|
||||
function TStdAudioOut.GetDeviceInfo : TACSDeviceInfo;
|
||||
begin
|
||||
Result := GetAudioDeviceInfo(FBaseChannel, True);
|
||||
end;
|
||||
|
||||
function TStdAudioIn.GetDeviceInfo : TACSDeviceInfo;
|
||||
begin
|
||||
Result := GetAudioDeviceInfo(FBaseChannel, False);
|
||||
end;
|
||||
|
||||
function TStdAudioIn.GetTotalTime : real;
|
||||
begin
|
||||
Result := RecTime;
|
||||
end;
|
||||
|
||||
constructor TStdAudioIn.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FBPS := 8;
|
||||
FChan := 1;
|
||||
FFreq := 8000;
|
||||
FSize := -1;
|
||||
FRecTime := 600;
|
||||
BufferSize := $1000;
|
||||
{$IFDEF MSWINDOWS}
|
||||
FBlocksCount := 4;
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
function TStdAudioOut.GetDeviceCount : Integer;
|
||||
begin
|
||||
Result := OutputChannelsCount;
|
||||
end;
|
||||
|
||||
initialization
|
||||
{$IFDEF MSWINDOWS}
|
||||
InitializeCriticalSection(CrSecI);
|
||||
InitializeCriticalSection(CrSecO);
|
||||
{$ENDIF}
|
||||
CountChannels;
|
||||
RegisterAudioOut('Wavemapper',TStdAudioOut,LATENCY);
|
||||
RegisterAudioIn('Wavemapper',TStdAudioIn,LATENCY);
|
||||
|
||||
finalization
|
||||
{$IFDEF MSWINDOWS}
|
||||
DeleteCriticalSection(CrSecI);
|
||||
DeleteCriticalSection(CrSecO);
|
||||
{$ENDIF}
|
||||
|
||||
end.
|
||||
266
acs/Src/drivers/linux/acs_audio.inc
Normal file
266
acs/Src/drivers/linux/acs_audio.inc
Normal file
@@ -0,0 +1,266 @@
|
||||
{
|
||||
$Log
|
||||
}
|
||||
|
||||
const
|
||||
MAX_CHANNELS = 16; // Maximum number of audio channels/devices
|
||||
O_RDONLY = 0;
|
||||
O_WRONLY = 1;
|
||||
libname = 'libc.so.6';
|
||||
|
||||
var
|
||||
AudioChannels : array[0..MAX_CHANNELS-1] of String;
|
||||
|
||||
(* We import libc functions directly to avoid Kylix
|
||||
Libc unit limitations *)
|
||||
|
||||
function __write(fd : Integer; data : Pointer; size : Integer): Integer; cdecl; external libname;
|
||||
function __read(Handle: Integer; var Buffer; Count: Integer): Integer; cdecl; external libname;
|
||||
function ioctl(fd : Integer; command : Integer): Integer; varargs; cdecl; external libname;
|
||||
function open(PathName: PChar; Flags: Integer): Integer; varargs; cdecl; external libname;
|
||||
function __close(Handle: Integer): Integer; cdecl; external libname;
|
||||
|
||||
|
||||
function GetAudioDeviceInfo(DevID : Integer; OutputDev : Boolean) : TACSDeviceInfo;
|
||||
begin
|
||||
Result.DeviceName := '/dev/dsp'+IntToStr(DevID);
|
||||
Result.DrvVersion := 0;
|
||||
Result.Formats := [];
|
||||
Result.Stereo := True;
|
||||
end;
|
||||
|
||||
procedure TStdAudioOut.SetDevice;
|
||||
begin
|
||||
if Busy then raise EACSException.Create(strBusy);
|
||||
if Ch < OutputChannelsCount then FBaseChannel := Ch
|
||||
else raise EACSException.Create(Format(strChannelnotavailable,[ch]));
|
||||
end;
|
||||
|
||||
procedure TStdAudioOut.Prepare;
|
||||
var
|
||||
parm : Integer;
|
||||
begin
|
||||
GetMem(FBuffer,FBufferSize);
|
||||
// No exceptions here!
|
||||
FInput.Init;
|
||||
case FInput.BitsPerSample of
|
||||
8 : parm := AFMT_U8;
|
||||
16 : parm := AFMT_S16_LE;
|
||||
end;
|
||||
_audio_fd := open(PChar(AudioChannels[FBaseChannel]), O_WRONLY);
|
||||
ioctl(_audio_fd, SNDCTL_DSP_SETFMT, @parm);
|
||||
parm := FInput.Channels;
|
||||
ioctl(_audio_fd, SNDCTL_DSP_CHANNELS, @parm);
|
||||
parm := FInput.SampleRate;
|
||||
ioctl(_audio_fd, SNDCTL_DSP_SPEED, @parm);
|
||||
end;
|
||||
|
||||
procedure TStdAudioOut.Done;
|
||||
begin
|
||||
//TODO:why this raises an exception ?? FreeMem(FBuffer);
|
||||
__close(_audio_fd);
|
||||
_audio_fd := -1;
|
||||
FInput.Flush;
|
||||
end;
|
||||
|
||||
function TStdAudioOut.DoOutput;
|
||||
var
|
||||
Len, i, VCoef : Integer;
|
||||
P : Pointer;
|
||||
P1 : PACSBuffer8;
|
||||
P2 : PACSBuffer16;
|
||||
begin
|
||||
// No exceptions Here
|
||||
Result := True;
|
||||
if not CanOutput then Exit;
|
||||
Len := 0;
|
||||
if Abort then
|
||||
begin
|
||||
__close(_audio_fd);
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
try
|
||||
P := @FBuffer[0];
|
||||
while InputLock do;
|
||||
InputLock := True;
|
||||
Len := Finput.GetData(P, FBufferSize);
|
||||
InputLock := False;
|
||||
if FVolume < 255 then
|
||||
begin
|
||||
VCoef := Round(FVolume/255);
|
||||
if FInput.BitsPerSample = 16 then
|
||||
begin
|
||||
P2 := @FBuffer[0];
|
||||
for i := 0 to (Len shr 1) -1 do
|
||||
P2[i] := P2[i]*VCoef;
|
||||
end else
|
||||
begin
|
||||
P1 := @FBuffer[0];
|
||||
for i := 0 to Len - 1 do
|
||||
P1[i] := P1[i]*VCoef;
|
||||
end;
|
||||
end;
|
||||
__write(_audio_fd, P, Len);
|
||||
except
|
||||
end;
|
||||
if Len > 0 then Result := True
|
||||
else Result := False;
|
||||
end;
|
||||
|
||||
constructor TStdAudioOut.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FVolume := 255;
|
||||
FBufferSize := $8000;
|
||||
_audio_fd := -1;
|
||||
end;
|
||||
|
||||
destructor TStdAudioOut.Destroy;
|
||||
begin
|
||||
if _audio_fd > 0 then __close(_audio_fd);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
destructor TStdAudioIn.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
__close(_audio_fd);
|
||||
end;
|
||||
|
||||
procedure TStdAudioIn.OpenAudio;
|
||||
begin
|
||||
if FOpened = 0 then
|
||||
_audio_fd := open(PChar(AudioChannels[FBaseChannel]), O_RDONLY);
|
||||
Inc(FOpened);
|
||||
end;
|
||||
|
||||
procedure TStdAudioIn.CloseAudio;
|
||||
begin
|
||||
if FOpened = 1 then __close(_audio_fd);
|
||||
if FOpened > 0 then Dec(FOpened);
|
||||
end;
|
||||
|
||||
function TStdAudioIn.GetBPS;
|
||||
var
|
||||
BPS : Integer;
|
||||
begin
|
||||
OpenAudio;
|
||||
BPS := FBPS;
|
||||
if (BPS in [8, 16]) = False then BPS := 16;
|
||||
ioctl(_audio_fd, SNDCTL_DSP_SETFMT, @BPS);
|
||||
FBPS := BPS;
|
||||
Result := BPS;
|
||||
CloseAudio;
|
||||
end;
|
||||
|
||||
function TStdAudioIn.GetCh;
|
||||
var
|
||||
Ch : Integer;
|
||||
begin
|
||||
OpenAudio;
|
||||
Ch := FChan;
|
||||
ioctl(_audio_fd, SNDCTL_DSP_CHANNELS, @Ch);
|
||||
FChan := Ch;
|
||||
Result := Ch;
|
||||
CloseAudio;
|
||||
end;
|
||||
|
||||
function TStdAudioIn.GetSR;
|
||||
var
|
||||
SR : Integer;
|
||||
begin
|
||||
OpenAudio;
|
||||
SR := FFreq;
|
||||
ioctl(_audio_fd, SNDCTL_DSP_SPEED, @SR);
|
||||
FFreq := SR;
|
||||
Result := SR;
|
||||
CloseAudio;
|
||||
end;
|
||||
|
||||
procedure TStdAudioIn.Init;
|
||||
begin
|
||||
if Busy then raise EACSException.Create(strBusy);
|
||||
BufEnd := 0;
|
||||
BufStart := 1;
|
||||
FPosition := 0;
|
||||
BufferSize := $8000;
|
||||
OpenAudio;
|
||||
FRecBytes := FRecTime * (GetBPS div 8) * GetCh * GetSR;
|
||||
FBusy := True;
|
||||
FSize := FRecBytes;
|
||||
end;
|
||||
|
||||
procedure TStdAudioIn.Flush;
|
||||
begin
|
||||
CloseAudio;
|
||||
FBusy := False;
|
||||
end;
|
||||
|
||||
procedure TStdAudioIn.SetDevice;
|
||||
begin
|
||||
if Ch > (OutputChannelsCount - 1) then
|
||||
if not (csDesigning in ComponentState) then
|
||||
raise EACSException.Create(Format(strChannelnotavailable,[Ch]));
|
||||
FBaseChannel := Ch;
|
||||
end;
|
||||
|
||||
function TStdAudioIn.GetData;
|
||||
var
|
||||
l : Integer;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create(strStreamnotOpen);
|
||||
if FRecBytes >= 0 then
|
||||
if FPosition >= FRecBytes then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
if BufStart > BufEnd then
|
||||
begin
|
||||
BufStart := 1;
|
||||
l := __read(_audio_fd, FBuffer[BufStart], BufferSize);
|
||||
if l < 1 then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end
|
||||
else BufEnd := l;
|
||||
end;
|
||||
if BufferSize < (BufEnd - BufStart + 1)
|
||||
then Result := BufferSize
|
||||
else Result := BufEnd - BufStart + 1;
|
||||
Move(FBuffer[BufStart], Buffer^, Result);
|
||||
Inc(BufStart, Result);
|
||||
Inc(FPosition, Result);
|
||||
end;
|
||||
|
||||
procedure CountChannels;
|
||||
var
|
||||
i, fd : Integer;
|
||||
fname : String;
|
||||
begin
|
||||
OutputChannelsCount := 0;
|
||||
fname := '/dev/dsp0';
|
||||
fd := open(PChar(fname), O_RDONLY);
|
||||
if fd < 0 then
|
||||
begin
|
||||
// Under ALSA there is no /dev/dsp0 device
|
||||
fname := '/dev/dsp';
|
||||
fd := open(PChar(fname), O_RDONLY);
|
||||
if fd < 0 then Exit;
|
||||
end;
|
||||
AudioChannels[OutputChannelsCount] := fname;
|
||||
__close(fd);
|
||||
Inc(OutputChannelsCount);
|
||||
for i := 1 to MAX_CHANNELS - 2 do
|
||||
begin
|
||||
fname := '/dev/dsp' + IntToStr(i);
|
||||
fd := open(PChar(fname), O_RDONLY);
|
||||
if fd < 0 then Break;
|
||||
__close(fd);
|
||||
AudioChannels[OutputChannelsCount] := fname;
|
||||
Inc(OutputChannelsCount);
|
||||
end;
|
||||
end;
|
||||
|
||||
907
acs/Src/drivers/linux/alsa.pas
Normal file
907
acs/Src/drivers/linux/alsa.pas
Normal file
@@ -0,0 +1,907 @@
|
||||
(*
|
||||
application interface library for the alsa driver
|
||||
free pascal / kylix import unit
|
||||
converted from file <alsa/asoundlib.h>
|
||||
|
||||
ALSA library is copyrighted by its authors:
|
||||
Jaroslav Kysela <perex@suse.cz>
|
||||
Abramo Bagnara <abramo@alsa-project.org>
|
||||
Takashi Iwai <tiwai@suse.de>
|
||||
|
||||
Pascal translation:
|
||||
Copyright (C) 2002, Pedro Lopez-Cabanillas <plcl@bigfoot.com>
|
||||
|
||||
Modified by Andrei Borovsky, 01-06-2003
|
||||
Note by A.B.: currently only <alsa/pcm.h> translation is included in this file.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation; either version 2.1 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
*)
|
||||
|
||||
(* attention! in this unit asoundlib is linked dynamically.
|
||||
In order to decrease loading time, only the symbols needed by ACS
|
||||
are actually resolved. *)
|
||||
|
||||
{
|
||||
$Log: alsa.pas,v $
|
||||
Revision 1.6 2006/08/30 18:59:51 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.5 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.3 2005/12/19 18:36:16 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/14 21:19:37 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
|
||||
unit alsa;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
baseunix,ACS_Procs;
|
||||
|
||||
const
|
||||
asoundlib_path = 'libasound.so*';
|
||||
|
||||
var
|
||||
AsoundlibLoaded : Boolean = False;
|
||||
|
||||
type
|
||||
Pint16_t = ^int16_t;
|
||||
|
||||
{ PCM generic info container }
|
||||
Psnd_pcm_info_t = pointer;
|
||||
{ PCM hardware configuration space container }
|
||||
Psnd_pcm_hw_params_t = pointer;
|
||||
{ PCM software configuration container }
|
||||
Psnd_pcm_sw_params_t = pointer;
|
||||
{ PCM status container }
|
||||
Psnd_pcm_status_t = pointer;
|
||||
{ PCM access types mask }
|
||||
Psnd_pcm_access_mask_t = pointer;
|
||||
{ PCM formats mask }
|
||||
Psnd_pcm_format_mask_t = pointer;
|
||||
{ PCM subformats mask }
|
||||
Psnd_pcm_subformat_mask_t = pointer;
|
||||
|
||||
Psnd_config_t = pointer;
|
||||
|
||||
Psnd_async_handler_t = pointer;
|
||||
|
||||
Psnd_output_t = Pointer;
|
||||
|
||||
{ PCM class }
|
||||
_snd_pcm_class = Longint;
|
||||
snd_pcm_class_t = _snd_pcm_class;
|
||||
const
|
||||
SND_PCM_CLASS_GENERIC = 0; { standard device }
|
||||
SND_PCM_CLASS_MULTI = 1; { multichannel device }
|
||||
SND_PCM_CLASS_MODEM = 2; { software modem device }
|
||||
SND_PCM_CLASS_DIGITIZER = 3; { digitizer device }
|
||||
SND_PCM_CLASS_LAST = SND_PCM_CLASS_DIGITIZER;
|
||||
|
||||
type
|
||||
{ PCM subclass }
|
||||
_snd_pcm_subclass = Longint;
|
||||
snd_pcm_subclass_t = _snd_pcm_subclass;
|
||||
const
|
||||
SND_PCM_SUBCLASS_GENERIC_MIX = 0; { subdevices are mixed together }
|
||||
SND_PCM_SUBCLASS_MULTI_MIX = 1; { multichannel subdevices are mixed together }
|
||||
SND_PCM_SUBCLASS_LAST = SND_PCM_SUBCLASS_MULTI_MIX;
|
||||
|
||||
type
|
||||
{ PCM stream (direction) }
|
||||
_snd_pcm_stream = Longint;
|
||||
snd_pcm_stream_t = _snd_pcm_stream;
|
||||
const
|
||||
SND_PCM_STREAM_PLAYBACK = 0; { Playback stream }
|
||||
SND_PCM_STREAM_CAPTURE = 1; { Capture stream }
|
||||
SND_PCM_STREAM_LAST = SND_PCM_STREAM_CAPTURE;
|
||||
|
||||
type
|
||||
{ PCM access type }
|
||||
_snd_pcm_access = Longint;
|
||||
snd_pcm_access_t = _snd_pcm_access;
|
||||
const
|
||||
SND_PCM_ACCESS_MMAP_INTERLEAVED = 0; { mmap access with simple interleaved channels }
|
||||
SND_PCM_ACCESS_MMAP_NONINTERLEAVED = 1; { mmap access with simple non interleaved channels }
|
||||
SND_PCM_ACCESS_MMAP_COMPLEX = 2; { mmap access with complex placement }
|
||||
SND_PCM_ACCESS_RW_INTERLEAVED = 3; { snd_pcm_readi/snd_pcm_writei access }
|
||||
SND_PCM_ACCESS_RW_NONINTERLEAVED = 4; { snd_pcm_readn/snd_pcm_writen access }
|
||||
SND_PCM_ACCESS_LAST = SND_PCM_ACCESS_RW_NONINTERLEAVED;
|
||||
|
||||
type
|
||||
{ PCM sample format }
|
||||
_snd_pcm_format = Longint;
|
||||
snd_pcm_format_t = _snd_pcm_format;
|
||||
const
|
||||
{ Unknown }
|
||||
SND_PCM_FORMAT_UNKNOWN = -1;
|
||||
{ Signed 8 bit }
|
||||
SND_PCM_FORMAT_S8 = 0;
|
||||
{ Unsigned 8 bit }
|
||||
SND_PCM_FORMAT_U8 = 1;
|
||||
{ Signed 16 bit Little Endian }
|
||||
SND_PCM_FORMAT_S16_LE = 2;
|
||||
{ Signed 16 bit Big Endian }
|
||||
SND_PCM_FORMAT_S16_BE = 3;
|
||||
{ Unsigned 16 bit Little Endian }
|
||||
SND_PCM_FORMAT_U16_LE = 4;
|
||||
{ Unsigned 16 bit Big Endian }
|
||||
SND_PCM_FORMAT_U16_BE = 5;
|
||||
{ Signed 24 bit Little Endian }
|
||||
SND_PCM_FORMAT_S24_LE = 6;
|
||||
{ Signed 24 bit Big Endian }
|
||||
SND_PCM_FORMAT_S24_BE = 7;
|
||||
{ Unsigned 24 bit Little Endian }
|
||||
SND_PCM_FORMAT_U24_LE = 8;
|
||||
{ Unsigned 24 bit Big Endian }
|
||||
SND_PCM_FORMAT_U24_BE = 9;
|
||||
{ Signed 32 bit Little Endian }
|
||||
SND_PCM_FORMAT_S32_LE = 10;
|
||||
{ Signed 32 bit Big Endian }
|
||||
SND_PCM_FORMAT_S32_BE = 11;
|
||||
{ Unsigned 32 bit Little Endian }
|
||||
SND_PCM_FORMAT_U32_LE = 12;
|
||||
{ Unsigned 32 bit Big Endian }
|
||||
SND_PCM_FORMAT_U32_BE = 13;
|
||||
{ Float 32 bit Little Endian, Range -1.0 to 1.0 }
|
||||
SND_PCM_FORMAT_FLOAT_LE = 14;
|
||||
{ Float 32 bit Big Endian, Range -1.0 to 1.0 }
|
||||
SND_PCM_FORMAT_FLOAT_BE = 15;
|
||||
{ Float 64 bit Little Endian, Range -1.0 to 1.0 }
|
||||
SND_PCM_FORMAT_FLOAT64_LE = 16;
|
||||
{ Float 64 bit Big Endian, Range -1.0 to 1.0 }
|
||||
SND_PCM_FORMAT_FLOAT64_BE = 17;
|
||||
{ IEC-958 Little Endian }
|
||||
SND_PCM_FORMAT_IEC958_SUBFRAME_LE = 18;
|
||||
{ IEC-958 Big Endian }
|
||||
SND_PCM_FORMAT_IEC958_SUBFRAME_BE = 19;
|
||||
{ Mu-Law }
|
||||
SND_PCM_FORMAT_MU_LAW = 20;
|
||||
{ A-Law }
|
||||
SND_PCM_FORMAT_A_LAW = 21;
|
||||
{ Ima-ADPCM }
|
||||
SND_PCM_FORMAT_IMA_ADPCM = 22;
|
||||
{ MPEG }
|
||||
SND_PCM_FORMAT_MPEG = 23;
|
||||
{ GSM }
|
||||
SND_PCM_FORMAT_GSM = 24;
|
||||
{ Special }
|
||||
SND_PCM_FORMAT_SPECIAL = 31;
|
||||
{ Signed 24bit Little Endian in 3bytes format }
|
||||
SND_PCM_FORMAT_S24_3LE = 32;
|
||||
{ Signed 24bit Big Endian in 3bytes format }
|
||||
SND_PCM_FORMAT_S24_3BE = 33;
|
||||
{ Unsigned 24bit Little Endian in 3bytes format }
|
||||
SND_PCM_FORMAT_U24_3LE = 34;
|
||||
{ Unsigned 24bit Big Endian in 3bytes format }
|
||||
SND_PCM_FORMAT_U24_3BE = 35;
|
||||
{ Signed 20bit Little Endian in 3bytes format }
|
||||
SND_PCM_FORMAT_S20_3LE = 36;
|
||||
{ Signed 20bit Big Endian in 3bytes format }
|
||||
SND_PCM_FORMAT_S20_3BE = 37;
|
||||
{ Unsigned 20bit Little Endian in 3bytes format }
|
||||
SND_PCM_FORMAT_U20_3LE = 38;
|
||||
{ Unsigned 20bit Big Endian in 3bytes format }
|
||||
SND_PCM_FORMAT_U20_3BE = 39;
|
||||
{ Signed 18bit Little Endian in 3bytes format }
|
||||
SND_PCM_FORMAT_S18_3LE = 40;
|
||||
{ Signed 18bit Big Endian in 3bytes format }
|
||||
SND_PCM_FORMAT_S18_3BE = 41;
|
||||
{ Unsigned 18bit Little Endian in 3bytes format }
|
||||
SND_PCM_FORMAT_U18_3LE = 42;
|
||||
{ Unsigned 18bit Big Endian in 3bytes format }
|
||||
SND_PCM_FORMAT_U18_3BE = 43;
|
||||
SND_PCM_FORMAT_LAST = SND_PCM_FORMAT_U18_3BE;
|
||||
|
||||
{$IFDEF ENDIAN_LITTLE}
|
||||
{ Signed 16 bit CPU endian }
|
||||
SND_PCM_FORMAT_S16 = SND_PCM_FORMAT_S16_LE;
|
||||
{ Unsigned 16 bit CPU endian }
|
||||
SND_PCM_FORMAT_U16 = SND_PCM_FORMAT_U16_LE;
|
||||
{ Signed 24 bit CPU endian }
|
||||
SND_PCM_FORMAT_S24 = SND_PCM_FORMAT_S24_LE;
|
||||
{ Unsigned 24 bit CPU endian }
|
||||
SND_PCM_FORMAT_U24 = SND_PCM_FORMAT_U24_LE;
|
||||
{ Signed 32 bit CPU endian }
|
||||
SND_PCM_FORMAT_S32 = SND_PCM_FORMAT_S32_LE;
|
||||
{ Unsigned 32 bit CPU endian }
|
||||
SND_PCM_FORMAT_U32 = SND_PCM_FORMAT_U32_LE;
|
||||
{ Float 32 bit CPU endian }
|
||||
SND_PCM_FORMAT_FLOAT = SND_PCM_FORMAT_FLOAT_LE;
|
||||
{ Float 64 bit CPU endian }
|
||||
SND_PCM_FORMAT_FLOAT64 = SND_PCM_FORMAT_FLOAT64_LE;
|
||||
{ IEC-958 CPU Endian }
|
||||
SND_PCM_FORMAT_IEC958_SUBFRAME = SND_PCM_FORMAT_IEC958_SUBFRAME_LE;
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF ENDIAN_BIG}
|
||||
{ Signed 16 bit CPU endian }
|
||||
SND_PCM_FORMAT_S16 = SND_PCM_FORMAT_S16_BE;
|
||||
{ Unsigned 16 bit CPU endian }
|
||||
SND_PCM_FORMAT_U16 = SND_PCM_FORMAT_U16_BE;
|
||||
{ Signed 24 bit CPU endian }
|
||||
SND_PCM_FORMAT_S24 = SND_PCM_FORMAT_S24_BE;
|
||||
{ Unsigned 24 bit CPU endian }
|
||||
SND_PCM_FORMAT_U24 = SND_PCM_FORMAT_U24_BE;
|
||||
{ Signed 32 bit CPU endian }
|
||||
SND_PCM_FORMAT_S32 = SND_PCM_FORMAT_S32_BE;
|
||||
{ Unsigned 32 bit CPU endian }
|
||||
SND_PCM_FORMAT_U32 = SND_PCM_FORMAT_U32_BE;
|
||||
{ Float 32 bit CPU endian }
|
||||
SND_PCM_FORMAT_FLOAT = SND_PCM_FORMAT_FLOAT_BE;
|
||||
{ Float 64 bit CPU endian }
|
||||
SND_PCM_FORMAT_FLOAT64 = SND_PCM_FORMAT_FLOAT64_BE;
|
||||
{ IEC-958 CPU Endian }
|
||||
SND_PCM_FORMAT_IEC958_SUBFRAME = SND_PCM_FORMAT_IEC958_SUBFRAME_BE;
|
||||
{$ENDIF}
|
||||
|
||||
type
|
||||
{ PCM sample subformat }
|
||||
_snd_pcm_subformat = Longint;
|
||||
snd_pcm_subformat_t = _snd_pcm_subformat;
|
||||
|
||||
const
|
||||
SND_PCM_SUBFORMAT_STD = 0; { Standard }
|
||||
SND_PCM_SUBFORMAT_LAST = SND_PCM_SUBFORMAT_STD;
|
||||
|
||||
type
|
||||
{ PCM state }
|
||||
_snd_pcm_state = Longint;
|
||||
snd_pcm_state_t = _snd_pcm_state;
|
||||
const
|
||||
SND_PCM_STATE_OPEN = 0; { Open }
|
||||
SND_PCM_STATE_SETUP = 1; { Setup installed }
|
||||
SND_PCM_STATE_PREPARED = 2; { Ready to start }
|
||||
SND_PCM_STATE_RUNNING = 3; { Running }
|
||||
SND_PCM_STATE_XRUN = 4; { Stopped: underrun (playback) or overrun (capture) detected }
|
||||
SND_PCM_STATE_DRAINING = 5; { Draining: running (playback) or stopped (capture) }
|
||||
SND_PCM_STATE_PAUSED = 6; { Paused }
|
||||
SND_PCM_STATE_SUSPENDED = 7; { Hardware is suspended }
|
||||
SND_PCM_STATE_LAST = SND_PCM_STATE_SUSPENDED;
|
||||
|
||||
type
|
||||
{ PCM start mode }
|
||||
_snd_pcm_start = Longint;
|
||||
snd_pcm_start_t = _snd_pcm_start;
|
||||
const
|
||||
SND_PCM_START_DATA = 0; { Automatic start on data read/write }
|
||||
SND_PCM_START_EXPLICIT = 1; { Explicit start }
|
||||
SND_PCM_START_LAST = SND_PCM_START_EXPLICIT;
|
||||
|
||||
type
|
||||
{ PCM xrun mode }
|
||||
_snd_pcm_xrun = Longint;
|
||||
snd_pcm_xrun_t = _snd_pcm_xrun;
|
||||
const
|
||||
SND_PCM_XRUN_NONE = 0; { Xrun detection disabled }
|
||||
SND_PCM_XRUN_STOP = 1; { Stop on xrun detection }
|
||||
SND_PCM_XRUN_LAST = SND_PCM_XRUN_STOP;
|
||||
|
||||
type
|
||||
{ PCM timestamp mode }
|
||||
_snd_pcm_tstamp = Longint;
|
||||
snd_pcm_tstamp_t = _snd_pcm_tstamp;
|
||||
const
|
||||
SND_PCM_TSTAMP_NONE = 0; { No timestamp }
|
||||
SND_PCM_TSTAMP_MMAP = 1; { Update mmap'ed timestamp }
|
||||
SND_PCM_TSTAMP_LAST = SND_PCM_TSTAMP_MMAP;
|
||||
|
||||
type
|
||||
{ Unsigned frames quantity }
|
||||
snd_pcm_uframes_t = LongWord;
|
||||
Psnd_pcm_uframes_t = ^snd_pcm_uframes_t;
|
||||
{ Signed frames quantity }
|
||||
snd_pcm_sframes_t = longint;
|
||||
Psnd_pcm_sframes_t = ^snd_pcm_sframes_t;
|
||||
{ Timestamp }
|
||||
snd_timestamp_t = timeval;
|
||||
Psnd_timestamp_t = ^snd_timestamp_t;
|
||||
|
||||
const
|
||||
{ Non blocking mode (flag for open mode) \hideinitializer }
|
||||
SND_PCM_NONBLOCK = $0001;
|
||||
{ Async notification (flag for open mode) \hideinitializer }
|
||||
SND_PCM_ASYNC = $0002;
|
||||
|
||||
type
|
||||
{ PCM handle }
|
||||
Psnd_pcm_t = pointer;
|
||||
|
||||
{ PCM type }
|
||||
_snd_pcm_type = Longint;
|
||||
snd_pcm_type_t = _snd_pcm_type;
|
||||
const
|
||||
{ PCM type }
|
||||
SND_PCM_TYPE_HW = 0; { Kernel level PCM }
|
||||
SND_PCM_TYPE_HOOKS = 1; { Hooked PCM }
|
||||
SND_PCM_TYPE_MULTI = 2; { One ore more linked PCM with exclusive access to selected channels }
|
||||
SND_PCM_TYPE_FILE = 3; { File writing plugin }
|
||||
SND_PCM_TYPE_NULL = 4; { Null endpoint PCM }
|
||||
SND_PCM_TYPE_SHM = 5; { Shared memory client PCM }
|
||||
SND_PCM_TYPE_INET = 6; { INET client PCM (not yet implemented) }
|
||||
SND_PCM_TYPE_COPY = 7; { Copying plugin }
|
||||
SND_PCM_TYPE_LINEAR = 8; { Linear format conversion PCM }
|
||||
SND_PCM_TYPE_ALAW = 9; { A-Law format conversion PCM }
|
||||
SND_PCM_TYPE_MULAW = 10; { Mu-Law format conversion PCM }
|
||||
SND_PCM_TYPE_ADPCM = 11; { IMA-ADPCM format conversion PCM }
|
||||
SND_PCM_TYPE_RATE = 12; { Rate conversion PCM }
|
||||
SND_PCM_TYPE_ROUTE = 13; { Attenuated static route PCM }
|
||||
SND_PCM_TYPE_PLUG = 14; { Format adjusted PCM }
|
||||
SND_PCM_TYPE_SHARE = 15; { Sharing PCM }
|
||||
SND_PCM_TYPE_METER = 16; { Meter plugin }
|
||||
SND_PCM_TYPE_MIX = 17; { Mixing PCM }
|
||||
SND_PCM_TYPE_DROUTE = 18; { Attenuated dynamic route PCM (not yet implemented) }
|
||||
SND_PCM_TYPE_LBSERVER = 19; { Loopback server plugin (not yet implemented) }
|
||||
SND_PCM_TYPE_LINEAR_FLOAT = 20; { Linear Integer <-> Linear Float format conversion PCM }
|
||||
SND_PCM_TYPE_LADSPA = 21; { LADSPA integration plugin }
|
||||
|
||||
|
||||
type
|
||||
|
||||
{ PCM area specification }
|
||||
_snd_pcm_channel_area = record
|
||||
addr : pointer; { base address of channel samples }
|
||||
first : LongWord; { offset to first sample in bits }
|
||||
step : LongWord; { samples distance in bits }
|
||||
end;
|
||||
snd_pcm_channel_area_t = _snd_pcm_channel_area;
|
||||
Psnd_pcm_channel_area_t = ^snd_pcm_channel_area_t;
|
||||
|
||||
{ PCM synchronization ID }
|
||||
_snd_pcm_sync_id = record
|
||||
case longint of
|
||||
0 : ( id : array[0..15] of byte ); { 8-bit ID }
|
||||
1 : ( id16 : array[0..7] of word ); { 16-bit ID }
|
||||
2 : ( id32 : array[0..3] of LongWord ); { 32-bit ID }
|
||||
end;
|
||||
snd_pcm_sync_id_t = _snd_pcm_sync_id;
|
||||
|
||||
{ #SND_PCM_TYPE_METER scope handle }
|
||||
Psnd_pcm_scope_t = pointer;
|
||||
|
||||
type
|
||||
snd_pcm_open_t = function(var pcm:Psnd_pcm_t; name:Pchar; stream:snd_pcm_stream_t; mode:longint):longint;cdecl;
|
||||
snd_pcm_open_lconf_t = function(var pcm:Psnd_pcm_t; name:Pchar; stream:snd_pcm_stream_t; mode:longint; lconf:Psnd_config_t):longint;cdecl;
|
||||
snd_pcm_close_t = function(pcm:Psnd_pcm_t):longint;cdecl;
|
||||
snd_pcm_name_t = function(pcm:Psnd_pcm_t):Pchar;cdecl;
|
||||
snd_pcm_type_t_t = function(pcm:Psnd_pcm_t):snd_pcm_type_t;cdecl;
|
||||
snd_pcm_stream_t_t = function(pcm:Psnd_pcm_t):snd_pcm_stream_t;cdecl;
|
||||
snd_pcm_poll_descriptors_count_t = function(pcm:Psnd_pcm_t):longint;cdecl;
|
||||
snd_pcm_poll_descriptors_t = function(pcm:Psnd_pcm_t; var pfds:pollfd; space:LongWord):longint;cdecl;
|
||||
snd_pcm_poll_descriptors_revents_t = function(pcm:Psnd_pcm_t; var pfds:pollfd; nfds:LongWord; revents:Pword):longint;cdecl;
|
||||
snd_pcm_set_nonblock_t = function(pcm:Psnd_pcm_t; nonblock:longint):longint;cdecl;
|
||||
// snd_async_add_pcm_handler_t = function(var handler:Psnd_async_handler_t; pcm:Psnd_pcm_t; callback:snd_async_callback_t; private_data:pointer):longint;cdecl;
|
||||
snd_async_handler_get_pcm_t = function(handler:Psnd_async_handler_t):Psnd_pcm_t;cdecl;
|
||||
snd_pcm_info_t = function(pcm:Psnd_pcm_t; info:Psnd_pcm_info_t):longint;cdecl;
|
||||
snd_pcm_hw_params_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t):longint;cdecl;
|
||||
snd_pcm_hw_params_current_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t):longint;cdecl;
|
||||
snd_pcm_hw_free_t = function(pcm:Psnd_pcm_t):longint;cdecl;
|
||||
snd_pcm_sw_params_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_sw_params_t):longint;cdecl;
|
||||
snd_pcm_sw_params_current_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_sw_params_t):longint;cdecl;
|
||||
snd_pcm_prepare_t = function(pcm:Psnd_pcm_t):longint;cdecl;
|
||||
snd_pcm_reset_t = function(pcm:Psnd_pcm_t):longint;cdecl;
|
||||
snd_pcm_status_t = function(pcm:Psnd_pcm_t; status:Psnd_pcm_status_t):longint;cdecl;
|
||||
snd_pcm_start_t_t = function(pcm:Psnd_pcm_t):longint;cdecl;
|
||||
snd_pcm_drop_t = function(pcm:Psnd_pcm_t):longint;cdecl;
|
||||
snd_pcm_drain_t = function(pcm:Psnd_pcm_t):longint;cdecl;
|
||||
snd_pcm_pause_t = function(pcm:Psnd_pcm_t; enable:longint):longint;cdecl;
|
||||
snd_pcm_state_t_t = function(pcm:Psnd_pcm_t):snd_pcm_state_t;cdecl;
|
||||
snd_pcm_hwsync_t = function(pcm: Psnd_pcm_t):longint;cdecl;
|
||||
snd_pcm_delay_t = function(pcm:Psnd_pcm_t; delayp:Psnd_pcm_sframes_t):longint;cdecl;
|
||||
snd_pcm_resume_t = function(pcm:Psnd_pcm_t):longint;cdecl;
|
||||
snd_pcm_avail_update_t = function(pcm:Psnd_pcm_t):snd_pcm_sframes_t;cdecl;
|
||||
snd_pcm_rewind_t = function(pcm:Psnd_pcm_t; frames:snd_pcm_uframes_t):snd_pcm_sframes_t;cdecl;
|
||||
snd_pcm_writei_t = function(pcm:Psnd_pcm_t; buffer:pointer; size:snd_pcm_uframes_t):snd_pcm_sframes_t;cdecl;
|
||||
snd_pcm_readi_t = function(pcm:Psnd_pcm_t; buffer:pointer; size:snd_pcm_uframes_t):snd_pcm_sframes_t;cdecl;
|
||||
snd_pcm_writen_t = function(pcm:Psnd_pcm_t; bufs:Ppointer; size:snd_pcm_uframes_t):snd_pcm_sframes_t;cdecl;
|
||||
snd_pcm_readn_t = function(pcm:Psnd_pcm_t; bufs:Ppointer; size:snd_pcm_uframes_t):snd_pcm_sframes_t;cdecl;
|
||||
snd_pcm_wait_t = function(pcm:Psnd_pcm_t; timeout:longint):longint;cdecl;
|
||||
snd_pcm_link_t = function(pcm1:Psnd_pcm_t; pcm2:Psnd_pcm_t):longint;cdecl;
|
||||
snd_pcm_unlink_t = function(pcm:Psnd_pcm_t):longint;cdecl;
|
||||
|
||||
snd_pcm_info_sizeof_t = function:size_t;cdecl;
|
||||
snd_pcm_info_malloc_t = function(var obj:Psnd_pcm_info_t):LongInt;cdecl;
|
||||
snd_pcm_info_free_t = procedure(obj:Psnd_pcm_info_t);cdecl;
|
||||
snd_pcm_info_copy_t = procedure(dst:Psnd_pcm_info_t; src:Psnd_pcm_info_t);cdecl;
|
||||
snd_pcm_info_get_device_t = function(obj:Psnd_pcm_info_t):LongWord;cdecl;
|
||||
snd_pcm_info_get_subdevice_t = function(obj:Psnd_pcm_info_t):LongWord;cdecl;
|
||||
snd_pcm_info_get_stream_t = function(obj:Psnd_pcm_info_t):snd_pcm_stream_t;cdecl;
|
||||
snd_pcm_info_get_card_t = function(obj:Psnd_pcm_info_t):longint;cdecl;
|
||||
snd_pcm_info_get_id_t = function(obj:Psnd_pcm_info_t):Pchar;cdecl;
|
||||
snd_pcm_info_get_name_t = function(obj:Psnd_pcm_info_t):Pchar;cdecl;
|
||||
snd_pcm_info_get_subdevice_name_t = function(obj:Psnd_pcm_info_t):Pchar;cdecl;
|
||||
snd_pcm_info_get_class_t = function(obj:Psnd_pcm_info_t):snd_pcm_class_t;cdecl;
|
||||
snd_pcm_info_get_subclass_t = function(obj:Psnd_pcm_info_t):snd_pcm_subclass_t;cdecl;
|
||||
snd_pcm_info_get_subdevices_count_t = function(obj:Psnd_pcm_info_t):LongWord;cdecl;
|
||||
snd_pcm_info_get_subdevices_avail_t = function(obj:Psnd_pcm_info_t):LongWord;cdecl;
|
||||
snd_pcm_info_get_sync_t = function(obj:Psnd_pcm_info_t):snd_pcm_sync_id_t;cdecl;
|
||||
snd_pcm_info_set_device_t = procedure(obj:Psnd_pcm_info_t; val:LongWord);cdecl;
|
||||
snd_pcm_info_set_subdevice_t = procedure(obj:Psnd_pcm_info_t; val:LongWord);cdecl;
|
||||
snd_pcm_info_set_stream_t = procedure(obj:Psnd_pcm_info_t; val:snd_pcm_stream_t);cdecl;
|
||||
{
|
||||
Hardware Parameters
|
||||
See the \ref pcm page for more details.
|
||||
}
|
||||
snd_pcm_hw_params_any_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t):longint;cdecl;
|
||||
snd_pcm_hw_params_can_mmap_sample_resolution_t = function(params:Psnd_pcm_hw_params_t):longint;cdecl;
|
||||
snd_pcm_hw_params_is_double_t = function(params:Psnd_pcm_hw_params_t):longint;cdecl;
|
||||
snd_pcm_hw_params_is_batch_t = function(params:Psnd_pcm_hw_params_t):longint;cdecl;
|
||||
snd_pcm_hw_params_is_block_transfer_t = function(params:Psnd_pcm_hw_params_t):longint;cdecl;
|
||||
snd_pcm_hw_params_can_overrange_t = function(params:Psnd_pcm_hw_params_t):longint;cdecl;
|
||||
snd_pcm_hw_params_can_pause_t = function(params:Psnd_pcm_hw_params_t):longint;cdecl;
|
||||
snd_pcm_hw_params_can_resume_t = function(params:Psnd_pcm_hw_params_t):longint;cdecl;
|
||||
snd_pcm_hw_params_is_half_duplex_t = function(params:Psnd_pcm_hw_params_t):longint;cdecl;
|
||||
snd_pcm_hw_params_is_joint_duplex_t = function(params:Psnd_pcm_hw_params_t):longint;cdecl;
|
||||
snd_pcm_hw_params_can_sync_start_t = function(params:Psnd_pcm_hw_params_t):longint;cdecl;
|
||||
snd_pcm_hw_params_get_rate_numden_t = function(params:Psnd_pcm_hw_params_t; rate_num:PLongWord; rate_den:PLongWord):longint;cdecl;
|
||||
snd_pcm_hw_params_get_sbits_t = function(params:Psnd_pcm_hw_params_t):longint;cdecl;
|
||||
snd_pcm_hw_params_get_fifo_size_t = function(params:Psnd_pcm_hw_params_t):longint;cdecl;
|
||||
|
||||
snd_pcm_hw_params_sizeof_t = function:size_t;cdecl;
|
||||
snd_pcm_hw_params_malloc_t = function(var obj:Psnd_pcm_hw_params_t):LongInt;cdecl;
|
||||
snd_pcm_hw_params_free_t = procedure(obj:Psnd_pcm_hw_params_t);cdecl;
|
||||
snd_pcm_hw_params_copy_t = procedure(dst:Psnd_pcm_hw_params_t; src:Psnd_pcm_hw_params_t);cdecl;
|
||||
snd_pcm_hw_params_get_access_t = function(params:Psnd_pcm_hw_params_t):longint;cdecl;
|
||||
snd_pcm_hw_params_test_access_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:snd_pcm_access_t):longint;cdecl;
|
||||
snd_pcm_hw_params_set_access_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:snd_pcm_access_t):longint;cdecl;
|
||||
snd_pcm_hw_params_set_access_first_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t):snd_pcm_access_t;cdecl;
|
||||
snd_pcm_hw_params_set_access_last_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t):snd_pcm_access_t;cdecl;
|
||||
snd_pcm_hw_params_set_access_mask_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; mask:Psnd_pcm_access_mask_t):longint;cdecl;
|
||||
snd_pcm_hw_params_get_access_mask_t = procedure(params:Psnd_pcm_hw_params_t; mask:Psnd_pcm_access_mask_t);cdecl;
|
||||
snd_pcm_hw_params_get_format_t = function(params:Psnd_pcm_hw_params_t):longint;cdecl;
|
||||
snd_pcm_hw_params_test_format_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:snd_pcm_format_t):longint;cdecl;
|
||||
snd_pcm_hw_params_set_format_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:snd_pcm_format_t):longint;cdecl;
|
||||
snd_pcm_hw_params_set_format_first_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t):snd_pcm_format_t;cdecl;
|
||||
snd_pcm_hw_params_set_format_last_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t):snd_pcm_format_t;cdecl;
|
||||
snd_pcm_hw_params_set_format_mask_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; mask:Psnd_pcm_format_mask_t):longint;cdecl;
|
||||
snd_pcm_hw_params_get_format_mask_t = procedure(params:Psnd_pcm_hw_params_t; mask:Psnd_pcm_format_mask_t);cdecl;
|
||||
snd_pcm_hw_params_test_subformat_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:snd_pcm_subformat_t):longint;cdecl;
|
||||
snd_pcm_hw_params_get_subformat_t = function(params:Psnd_pcm_hw_params_t):longint;cdecl;
|
||||
snd_pcm_hw_params_set_subformat_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:snd_pcm_subformat_t):longint;cdecl;
|
||||
snd_pcm_hw_params_set_subformat_first_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t):snd_pcm_subformat_t;cdecl;
|
||||
snd_pcm_hw_params_set_subformat_last_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t):snd_pcm_subformat_t;cdecl;
|
||||
snd_pcm_hw_params_set_subformat_mask_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; mask:Psnd_pcm_subformat_mask_t):longint;cdecl;
|
||||
snd_pcm_hw_params_get_subformat_mask_t = procedure(params:Psnd_pcm_hw_params_t; mask:Psnd_pcm_subformat_mask_t);cdecl;
|
||||
snd_pcm_hw_params_get_channels_t = function(params:Psnd_pcm_hw_params_t):longint;cdecl;
|
||||
snd_pcm_hw_params_get_channels_min_t = function(params:Psnd_pcm_hw_params_t):LongWord;cdecl;
|
||||
snd_pcm_hw_params_get_channels_max_t = function(params:Psnd_pcm_hw_params_t):LongWord;cdecl;
|
||||
snd_pcm_hw_params_test_channels_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:LongWord):longint;cdecl;
|
||||
snd_pcm_hw_params_set_channels_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:LongWord):longint;cdecl;
|
||||
snd_pcm_hw_params_set_channels_min_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:PLongWord):longint;cdecl;
|
||||
snd_pcm_hw_params_set_channels_max_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:PLongWord):longint;cdecl;
|
||||
snd_pcm_hw_params_set_channels_minmax_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; min:PLongWord; max:PLongWord):longint;cdecl;
|
||||
snd_pcm_hw_params_set_channels_near_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:LongWord):LongWord;cdecl;
|
||||
snd_pcm_hw_params_set_channels_first_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t):LongWord;cdecl;
|
||||
snd_pcm_hw_params_set_channels_last_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t):LongWord;cdecl;
|
||||
snd_pcm_hw_params_get_rate_t = function(params:Psnd_pcm_hw_params_t; dir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_get_rate_min_t = function(params:Psnd_pcm_hw_params_t; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_get_rate_max_t = function(params:Psnd_pcm_hw_params_t; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_test_rate_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:LongWord; dir:longint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_rate_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:LongWord; dir:longint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_rate_min_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:PLongWord; dir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_rate_max_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:PLongWord; dir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_rate_minmax_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; min:PLongWord; mindir:Plongint; max:PLongWord;
|
||||
maxdir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_rate_near_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:LongWord; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_set_rate_first_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_set_rate_last_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_get_period_time_t = function(params:Psnd_pcm_hw_params_t; dir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_get_period_time_min_t = function(params:Psnd_pcm_hw_params_t; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_get_period_time_max_t = function(params:Psnd_pcm_hw_params_t; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_test_period_time_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:LongWord; dir:longint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_period_time_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:LongWord; dir:longint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_period_time_min_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:PLongWord; dir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_period_time_max_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:PLongWord; dir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_period_time_minmax_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; min:PLongWord; mindir:Plongint; max:PLongWord;
|
||||
maxdir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_period_time_near_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:LongWord; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_set_period_time_first_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_set_period_time_last_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_get_period_size_t = function(params:Psnd_pcm_hw_params_t; dir:Plongint):snd_pcm_sframes_t;cdecl;
|
||||
snd_pcm_hw_params_get_period_size_min_t = function(params:Psnd_pcm_hw_params_t; dir:Plongint):snd_pcm_uframes_t;cdecl;
|
||||
snd_pcm_hw_params_get_period_size_max_t = function(params:Psnd_pcm_hw_params_t; dir:Plongint):snd_pcm_uframes_t;cdecl;
|
||||
snd_pcm_hw_params_test_period_size_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:snd_pcm_uframes_t; dir:longint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_period_size_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:snd_pcm_uframes_t; dir:longint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_period_size_min_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:Psnd_pcm_uframes_t; dir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_period_size_max_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:Psnd_pcm_uframes_t; dir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_period_size_minmax_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; min:Psnd_pcm_uframes_t; mindir:Plongint; max:Psnd_pcm_uframes_t;
|
||||
maxdir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_period_size_near_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:snd_pcm_uframes_t; dir:Plongint):snd_pcm_uframes_t;cdecl;
|
||||
snd_pcm_hw_params_set_period_size_first_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; dir:Plongint):snd_pcm_uframes_t;cdecl;
|
||||
snd_pcm_hw_params_set_period_size_last_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; dir:Plongint):snd_pcm_uframes_t;cdecl;
|
||||
snd_pcm_hw_params_set_period_size_integer_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t):longint;cdecl;
|
||||
snd_pcm_hw_params_get_periods_t = function(params:Psnd_pcm_hw_params_t; dir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_get_periods_min_t = function(params:Psnd_pcm_hw_params_t; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_get_periods_max_t = function(params:Psnd_pcm_hw_params_t; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_test_periods_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:LongWord; dir:longint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_periods_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:LongWord; dir:longint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_periods_min_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:PLongWord; dir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_periods_max_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:PLongWord; dir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_periods_minmax_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; min:PLongWord; mindir:Plongint; max:PLongWord;
|
||||
maxdir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_periods_near_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:LongWord; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_set_periods_first_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_set_periods_last_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_set_periods_integer_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t):longint;cdecl;
|
||||
snd_pcm_hw_params_get_buffer_time_t = function(params:Psnd_pcm_hw_params_t; dir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_get_buffer_time_min_t = function(params:Psnd_pcm_hw_params_t; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_get_buffer_time_max_t = function(params:Psnd_pcm_hw_params_t; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_test_buffer_time_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:LongWord; dir:longint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_buffer_time_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:LongWord; dir:longint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_buffer_time_min_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:PLongWord; dir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_buffer_time_max_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:PLongWord; dir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_buffer_time_minmax_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; min:PLongWord; mindir:Plongint; max:PLongWord;
|
||||
maxdir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_buffer_time_near_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:LongWord; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_set_buffer_time_first_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_set_buffer_time_last_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_get_buffer_size_t = function(params:Psnd_pcm_hw_params_t):snd_pcm_sframes_t;cdecl;
|
||||
snd_pcm_hw_params_get_buffer_size_min_t = function(params:Psnd_pcm_hw_params_t):snd_pcm_uframes_t;cdecl;
|
||||
snd_pcm_hw_params_get_buffer_size_max_t = function(params:Psnd_pcm_hw_params_t):snd_pcm_uframes_t;cdecl;
|
||||
snd_pcm_hw_params_test_buffer_size_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:snd_pcm_uframes_t):longint;cdecl;
|
||||
snd_pcm_hw_params_set_buffer_size_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:snd_pcm_uframes_t):longint;cdecl;
|
||||
snd_pcm_hw_params_set_buffer_size_min_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:Psnd_pcm_uframes_t):longint;cdecl;
|
||||
snd_pcm_hw_params_set_buffer_size_max_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:Psnd_pcm_uframes_t):longint;cdecl;
|
||||
snd_pcm_hw_params_set_buffer_size_minmax_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; min:Psnd_pcm_uframes_t; max:Psnd_pcm_uframes_t):longint;cdecl;
|
||||
snd_pcm_hw_params_set_buffer_size_near_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:snd_pcm_uframes_t):snd_pcm_uframes_t;cdecl;
|
||||
snd_pcm_hw_params_set_buffer_size_first_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t):snd_pcm_uframes_t;cdecl;
|
||||
snd_pcm_hw_params_set_buffer_size_last_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t):snd_pcm_uframes_t;cdecl;
|
||||
snd_pcm_hw_params_get_tick_time_t = function(params:Psnd_pcm_hw_params_t; dir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_get_tick_time_min_t = function(params:Psnd_pcm_hw_params_t; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_get_tick_time_max_t = function(params:Psnd_pcm_hw_params_t; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_test_tick_time_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:LongWord; dir:longint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_tick_time_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:LongWord; dir:longint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_tick_time_min_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:PLongWord; dir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_tick_time_max_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:PLongWord; dir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_tick_time_minmax_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; min:PLongWord; mindir:Plongint; max:PLongWord;
|
||||
maxdir:Plongint):longint;cdecl;
|
||||
snd_pcm_hw_params_set_tick_time_near_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; val:LongWord; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_set_tick_time_first_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; dir:Plongint):LongWord;cdecl;
|
||||
snd_pcm_hw_params_set_tick_time_last_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_hw_params_t; dir:Plongint):LongWord;cdecl;
|
||||
{ New function added in alsa-lib-0.9.0-rc5 }
|
||||
snd_pcm_hw_params_get_min_align_t = function(params: Psnd_pcm_hw_params_t; var val: snd_pcm_uframes_t):longint;cdecl;
|
||||
|
||||
{
|
||||
Software Parameters
|
||||
}
|
||||
// function snd_pcm_sw_params_current(pcm:Psnd_pcm_t; params:Psnd_pcm_sw_params_t):longint;cdecl;external asoundlib_name;
|
||||
snd_pcm_sw_params_sizeof_t = function:size_t;cdecl;
|
||||
snd_pcm_sw_params_malloc_t = function(var obj:Psnd_pcm_sw_params_t):LongInt;cdecl;
|
||||
snd_pcm_sw_params_free_t = procedure(obj:Psnd_pcm_sw_params_t);cdecl;
|
||||
snd_pcm_sw_params_copy_t = procedure(dst:Psnd_pcm_sw_params_t; src:Psnd_pcm_sw_params_t);cdecl;
|
||||
snd_pcm_sw_params_set_tstamp_mode_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_sw_params_t; val:snd_pcm_tstamp_t):longint;cdecl;
|
||||
snd_pcm_sw_params_get_tstamp_mode_t = function(params:Psnd_pcm_sw_params_t):snd_pcm_tstamp_t;cdecl;
|
||||
|
||||
snd_pcm_sw_params_set_sleep_min_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_sw_params_t; val:LongWord):longint;cdecl;
|
||||
snd_pcm_sw_params_get_sleep_min_t = function(params:Psnd_pcm_sw_params_t):LongWord;cdecl;
|
||||
snd_pcm_sw_params_set_avail_min_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_sw_params_t; val:snd_pcm_uframes_t):longint;cdecl;
|
||||
snd_pcm_sw_params_get_avail_min_t = function(params:Psnd_pcm_sw_params_t):snd_pcm_uframes_t;cdecl;
|
||||
snd_pcm_sw_params_set_xfer_align_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_sw_params_t; val:snd_pcm_uframes_t):longint;cdecl;
|
||||
snd_pcm_sw_params_get_xfer_align_t = function(params:Psnd_pcm_sw_params_t):snd_pcm_uframes_t;cdecl;
|
||||
snd_pcm_sw_params_set_start_threshold_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_sw_params_t; val:snd_pcm_uframes_t):longint;cdecl;
|
||||
snd_pcm_sw_params_get_start_threshold_t = function(params:Psnd_pcm_sw_params_t):snd_pcm_uframes_t;cdecl;
|
||||
snd_pcm_sw_params_set_stop_threshold_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_sw_params_t; val:snd_pcm_uframes_t):longint;cdecl;
|
||||
snd_pcm_sw_params_get_stop_threshold_t = function(params:Psnd_pcm_sw_params_t):snd_pcm_uframes_t;cdecl;
|
||||
|
||||
snd_pcm_sw_params_set_silence_threshold_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_sw_params_t; val:snd_pcm_uframes_t):longint;cdecl;
|
||||
snd_pcm_sw_params_get_silence_threshold_t = function(params:Psnd_pcm_sw_params_t):snd_pcm_uframes_t;cdecl;
|
||||
snd_pcm_sw_params_set_silence_size_t = function(pcm:Psnd_pcm_t; params:Psnd_pcm_sw_params_t; val:snd_pcm_uframes_t):longint;cdecl;
|
||||
snd_pcm_sw_params_get_silence_size_t = function(params:Psnd_pcm_sw_params_t):snd_pcm_uframes_t;cdecl;
|
||||
|
||||
{
|
||||
Access Mask Functions
|
||||
}
|
||||
snd_pcm_access_mask_sizeof_t = function:size_t;cdecl;
|
||||
snd_pcm_access_mask_malloc_t = function(var obj:Psnd_pcm_access_mask_t):LongInt;cdecl;
|
||||
snd_pcm_access_mask_free_t = procedure(obj:Psnd_pcm_access_mask_t);cdecl;
|
||||
snd_pcm_access_mask_copy_t = procedure(dst:Psnd_pcm_access_mask_t; src:Psnd_pcm_access_mask_t);cdecl;
|
||||
snd_pcm_access_mask_none_t = procedure(mask:Psnd_pcm_access_mask_t);cdecl;
|
||||
snd_pcm_access_mask_any_t = procedure(mask:Psnd_pcm_access_mask_t);cdecl;
|
||||
snd_pcm_access_mask_test_t = function(mask:Psnd_pcm_access_mask_t; val:snd_pcm_access_t):longint;cdecl;
|
||||
snd_pcm_access_mask_empty_t = function(mask:Psnd_pcm_access_mask_t):longint;cdecl;
|
||||
snd_pcm_access_mask_set_t = procedure(mask:Psnd_pcm_access_mask_t; val:snd_pcm_access_t);cdecl;
|
||||
snd_pcm_access_mask_reset_t = procedure(mask:Psnd_pcm_access_mask_t; val:snd_pcm_access_t);cdecl;
|
||||
{
|
||||
Format Mask Functions
|
||||
}
|
||||
snd_pcm_format_mask_sizeof_t = function:size_t;cdecl;
|
||||
snd_pcm_format_mask_malloc_t = function(var obj:Psnd_pcm_format_mask_t):LongInt;cdecl;
|
||||
snd_pcm_format_mask_free_t = procedure(obj:Psnd_pcm_format_mask_t);cdecl;
|
||||
snd_pcm_format_mask_copy_t = procedure(dst:Psnd_pcm_format_mask_t; src:Psnd_pcm_format_mask_t);cdecl;
|
||||
snd_pcm_format_mask_none_t = procedure(mask:Psnd_pcm_format_mask_t);cdecl;
|
||||
snd_pcm_format_mask_any_t = procedure(mask:Psnd_pcm_format_mask_t);cdecl;
|
||||
snd_pcm_format_mask_test_t = function(mask:Psnd_pcm_format_mask_t; val:snd_pcm_format_t):longint;cdecl;
|
||||
snd_pcm_format_mask_empty_t = function(mask:Psnd_pcm_format_mask_t):longint;cdecl;
|
||||
snd_pcm_format_mask_set_t = procedure(mask:Psnd_pcm_format_mask_t; val:snd_pcm_format_t);cdecl;
|
||||
snd_pcm_format_mask_reset_t = procedure(mask:Psnd_pcm_format_mask_t; val:snd_pcm_format_t);cdecl;
|
||||
{
|
||||
Subformat Mask Functions
|
||||
}
|
||||
snd_pcm_subformat_mask_sizeof_t = function:size_t;cdecl;
|
||||
snd_pcm_subformat_mask_malloc_t = function(var obj:Psnd_pcm_subformat_mask_t):LongInt;cdecl;
|
||||
snd_pcm_subformat_mask_free_t = procedure(obj:Psnd_pcm_subformat_mask_t);cdecl;
|
||||
snd_pcm_subformat_mask_copy_t = procedure(dst:Psnd_pcm_subformat_mask_t; src:Psnd_pcm_subformat_mask_t);cdecl;
|
||||
snd_pcm_subformat_mask_none_t = procedure(mask:Psnd_pcm_subformat_mask_t);cdecl;
|
||||
snd_pcm_subformat_mask_any_t = procedure(mask:Psnd_pcm_subformat_mask_t);cdecl;
|
||||
snd_pcm_subformat_mask_test_t = function(mask:Psnd_pcm_subformat_mask_t; val:snd_pcm_subformat_t):longint;cdecl;
|
||||
snd_pcm_subformat_mask_empty_t = function(mask:Psnd_pcm_subformat_mask_t):longint;cdecl;
|
||||
snd_pcm_subformat_mask_set_t = procedure(mask:Psnd_pcm_subformat_mask_t; val:snd_pcm_subformat_t);cdecl;
|
||||
snd_pcm_subformat_mask_reset_t = procedure(mask:Psnd_pcm_subformat_mask_t; val:snd_pcm_subformat_t);cdecl;
|
||||
{
|
||||
Status Functions
|
||||
}
|
||||
snd_pcm_status_sizeof_t = function:size_t;cdecl;
|
||||
snd_pcm_status_malloc_t = function(var obj:Psnd_pcm_status_t):LongInt;cdecl;
|
||||
snd_pcm_status_free_t = procedure(obj:Psnd_pcm_status_t);cdecl;
|
||||
snd_pcm_status_copy_t = procedure(dst:Psnd_pcm_status_t; src:Psnd_pcm_status_t);cdecl;
|
||||
snd_pcm_status_get_state_t = function(obj:Psnd_pcm_status_t):snd_pcm_state_t;cdecl;
|
||||
snd_pcm_status_get_trigger_tstamp_t = procedure(obj:Psnd_pcm_status_t; ptr:Psnd_timestamp_t);cdecl;
|
||||
snd_pcm_status_get_tstamp_t = procedure(obj:Psnd_pcm_status_t; ptr:Psnd_timestamp_t);cdecl;
|
||||
snd_pcm_status_get_delay_t = function(obj:Psnd_pcm_status_t):snd_pcm_sframes_t;cdecl;
|
||||
snd_pcm_status_get_avail_t = function(obj:Psnd_pcm_status_t):snd_pcm_uframes_t;cdecl;
|
||||
snd_pcm_status_get_avail_max_t = function(obj:Psnd_pcm_status_t):snd_pcm_uframes_t;cdecl;
|
||||
snd_pcm_status_get_overrange_t = function(obj:Psnd_pcm_status_t):snd_pcm_uframes_t;cdecl;
|
||||
{
|
||||
Description Functions
|
||||
}
|
||||
snd_pcm_stream_name_t = function(stream:snd_pcm_stream_t):Pchar;cdecl;
|
||||
snd_pcm_access_name_t = function(_access:snd_pcm_access_t):Pchar;cdecl;
|
||||
snd_pcm_format_name_t = function(format:snd_pcm_format_t):Pchar;cdecl;
|
||||
snd_pcm_format_description_t = function(format:snd_pcm_format_t):Pchar;cdecl;
|
||||
snd_pcm_subformat_name_t = function(subformat:snd_pcm_subformat_t):Pchar;cdecl;
|
||||
snd_pcm_subformat_description_t = function(subformat:snd_pcm_subformat_t):Pchar;cdecl;
|
||||
snd_pcm_format_value_t = function(name:Pchar):snd_pcm_format_t;cdecl;
|
||||
snd_pcm_tstamp_mode_name_t = function(mode:snd_pcm_tstamp_t):Pchar;cdecl;
|
||||
snd_pcm_state_name_t = function(state:snd_pcm_state_t):Pchar;cdecl;
|
||||
{
|
||||
Debug Functions
|
||||
}
|
||||
snd_pcm_dump_t = function(pcm:Psnd_pcm_t; mout:Psnd_output_t):longint;cdecl;
|
||||
snd_pcm_dump_hw_setup_t = function(pcm:Psnd_pcm_t; mout:Psnd_output_t):longint;cdecl;
|
||||
snd_pcm_dump_sw_setup_t = function(pcm:Psnd_pcm_t; mout:Psnd_output_t):longint;cdecl;
|
||||
snd_pcm_dump_setup_t = function(pcm:Psnd_pcm_t; mout:Psnd_output_t):longint;cdecl;
|
||||
snd_pcm_hw_params_dump_t = function(params:Psnd_pcm_hw_params_t; mout:Psnd_output_t):longint;cdecl;
|
||||
snd_pcm_sw_params_dump_t = function(params:Psnd_pcm_sw_params_t; mout:Psnd_output_t):longint;cdecl;
|
||||
snd_pcm_status_dump_t = function(status:Psnd_pcm_status_t; mout:Psnd_output_t):longint;cdecl;
|
||||
{
|
||||
Direct Access (MMAP) Functions
|
||||
}
|
||||
snd_pcm_mmap_begin_t = function(pcm:Psnd_pcm_t; var areas:Psnd_pcm_channel_area_t; offset:Psnd_pcm_uframes_t; frames:Psnd_pcm_uframes_t):longint;cdecl;
|
||||
snd_pcm_mmap_commit_t = function(pcm:Psnd_pcm_t; offset:snd_pcm_uframes_t; frames:snd_pcm_uframes_t):snd_pcm_sframes_t;cdecl;
|
||||
snd_pcm_mmap_writei_t = function(pcm:Psnd_pcm_t; buffer:pointer; size:snd_pcm_uframes_t):snd_pcm_sframes_t;cdecl;
|
||||
snd_pcm_mmap_readi_t = function(pcm:Psnd_pcm_t; buffer:pointer; size:snd_pcm_uframes_t):snd_pcm_sframes_t;cdecl;
|
||||
snd_pcm_mmap_writen_t = function(pcm:Psnd_pcm_t; bufs:Ppointer; size:snd_pcm_uframes_t):snd_pcm_sframes_t;cdecl;
|
||||
snd_pcm_mmap_readn_t = function(pcm:Psnd_pcm_t; bufs:Ppointer; size:snd_pcm_uframes_t):snd_pcm_sframes_t;cdecl;
|
||||
{
|
||||
Helper Functions
|
||||
}
|
||||
snd_pcm_format_signed_t = function(format:snd_pcm_format_t):longint;cdecl;
|
||||
snd_pcm_format_unsigned_t = function(format:snd_pcm_format_t):longint;cdecl;
|
||||
snd_pcm_format_linear_t = function(format:snd_pcm_format_t):longint;cdecl;
|
||||
snd_pcm_format_is_float_t = function(format:snd_pcm_format_t):longint;cdecl;
|
||||
snd_pcm_format_little_endian_t = function(format:snd_pcm_format_t):longint;cdecl;
|
||||
snd_pcm_format_big_endian_t = function(format:snd_pcm_format_t):longint;cdecl;
|
||||
snd_pcm_format_cpu_endian_t = function(format:snd_pcm_format_t):longint;cdecl;
|
||||
snd_pcm_format_width_t = function(format:snd_pcm_format_t):longint;cdecl;
|
||||
{ in bits }
|
||||
snd_pcm_format_physical_width_t = function(format:snd_pcm_format_t):longint;cdecl;
|
||||
{ in bits }
|
||||
snd_pcm_build_linear_format_t = function(width:longint; pwidth:longint; unsignd:longint; big_endian:longint):snd_pcm_format_t;cdecl;
|
||||
snd_pcm_format_size_t = function(format:snd_pcm_format_t; samples:size_t):ssize_t;cdecl;
|
||||
snd_pcm_format_silence_t = function(format:snd_pcm_format_t):u_int8_t;cdecl;
|
||||
snd_pcm_format_silence_16_t = function(format:snd_pcm_format_t):u_int16_t;cdecl;
|
||||
snd_pcm_format_silence_32_t = function(format:snd_pcm_format_t):u_int32_t;cdecl;
|
||||
// snd_pcm_format_silence_64_t = function(format:snd_pcm_format_t):u_int64_t;cdecl;
|
||||
snd_pcm_format_set_silence_t = function(format:snd_pcm_format_t; buf:pointer; samples:LongWord):longint;cdecl;
|
||||
snd_pcm_bytes_to_frames_t = function(pcm:Psnd_pcm_t; bytes:ssize_t):snd_pcm_sframes_t;cdecl;
|
||||
snd_pcm_frames_to_bytes_t = function(pcm:Psnd_pcm_t; frames:snd_pcm_sframes_t):ssize_t;cdecl;
|
||||
snd_pcm_bytes_to_samples_t = function(pcm:Psnd_pcm_t; bytes:ssize_t):longint;cdecl;
|
||||
snd_pcm_samples_to_bytes_t = function(pcm:Psnd_pcm_t; samples:longint):ssize_t;cdecl;
|
||||
snd_pcm_area_silence_t = function(dst_channel:Psnd_pcm_channel_area_t; dst_offset:snd_pcm_uframes_t; samples:LongWord; format:snd_pcm_format_t):longint;cdecl;
|
||||
snd_pcm_areas_silence_t = function(dst_channels:Psnd_pcm_channel_area_t; dst_offset:snd_pcm_uframes_t; channels:LongWord; frames:snd_pcm_uframes_t; format:snd_pcm_format_t):longint;cdecl;
|
||||
snd_pcm_area_copy_t = function(dst_channel:Psnd_pcm_channel_area_t; dst_offset:snd_pcm_uframes_t; src_channel:Psnd_pcm_channel_area_t; src_offset:snd_pcm_uframes_t; samples:LongWord;
|
||||
format:snd_pcm_format_t):longint;cdecl;
|
||||
snd_pcm_areas_copy_t = function(dst_channels:Psnd_pcm_channel_area_t; dst_offset:snd_pcm_uframes_t; src_channels:Psnd_pcm_channel_area_t; src_offset:snd_pcm_uframes_t; channels:LongWord;
|
||||
frames:snd_pcm_uframes_t; format:snd_pcm_format_t):longint;cdecl;
|
||||
{
|
||||
Hook Extension
|
||||
}
|
||||
type
|
||||
{ type of pcm hook }
|
||||
_snd_pcm_hook_type = Longint;
|
||||
snd_pcm_hook_type_t = _snd_pcm_hook_type;
|
||||
const
|
||||
SND_PCM_HOOK_TYPE_HW_PARAMS = 0;
|
||||
SND_PCM_HOOK_TYPE_HW_FREE = 1;
|
||||
SND_PCM_HOOK_TYPE_CLOSE = 2;
|
||||
SND_PCM_HOOK_TYPE_LAST = SND_PCM_HOOK_TYPE_CLOSE;
|
||||
|
||||
type
|
||||
{ PCM hook container }
|
||||
Psnd_pcm_hook_t = pointer;
|
||||
{ PCM hook callback function }
|
||||
snd_pcm_hook_func_t = function (hook:Psnd_pcm_hook_t):longint;cdecl;
|
||||
type
|
||||
|
||||
snd_pcm_hook_get_pcm_t = function(hook:Psnd_pcm_hook_t):Psnd_pcm_t;cdecl;
|
||||
snd_pcm_hook_get_private_t = function(hook:Psnd_pcm_hook_t):pointer;cdecl;
|
||||
snd_pcm_hook_set_private_t = procedure(hook:Psnd_pcm_hook_t; private_data:pointer);cdecl;
|
||||
snd_pcm_hook_add_t = function(var hookp:Psnd_pcm_hook_t; pcm:Psnd_pcm_t; _type:snd_pcm_hook_type_t; func:snd_pcm_hook_func_t; private_data:pointer):longint;cdecl;
|
||||
snd_pcm_hook_remove_t = function(hook:Psnd_pcm_hook_t):longint;cdecl;
|
||||
{
|
||||
Scope Plugin Extension
|
||||
}
|
||||
type
|
||||
{ #SND_PCM_TYPE_METER scope functions }
|
||||
_snd_pcm_scope_ops = record
|
||||
enable : function (scope:Psnd_pcm_scope_t):longint;cdecl; { Enable and prepare it using current params }
|
||||
disable : procedure (scope:Psnd_pcm_scope_t); { Disable }
|
||||
start : procedure (scope:Psnd_pcm_scope_t); { PCM has been started }
|
||||
stop : procedure (scope:Psnd_pcm_scope_t); { PCM has been stopped }
|
||||
update : procedure (scope:Psnd_pcm_scope_t); { New frames are present }
|
||||
reset : procedure (scope:Psnd_pcm_scope_t); { Reset status }
|
||||
close : procedure (scope:Psnd_pcm_scope_t); { PCM is closing }
|
||||
end;
|
||||
snd_pcm_scope_ops_t = _snd_pcm_scope_ops;
|
||||
Psnd_pcm_scope_ops_t = ^snd_pcm_scope_ops_t;
|
||||
|
||||
snd_pcm_meter_get_bufsize_t = function(pcm:Psnd_pcm_t):snd_pcm_uframes_t;cdecl;
|
||||
snd_pcm_meter_get_channels_t = function(pcm:Psnd_pcm_t):LongWord;cdecl;
|
||||
snd_pcm_meter_get_rate_t = function(pcm:Psnd_pcm_t):LongWord;cdecl;
|
||||
snd_pcm_meter_get_now_t = function(pcm:Psnd_pcm_t):snd_pcm_uframes_t;cdecl;
|
||||
snd_pcm_meter_get_boundary_t = function(pcm:Psnd_pcm_t):snd_pcm_uframes_t;cdecl;
|
||||
snd_pcm_meter_add_scope_t = function(pcm:Psnd_pcm_t; scope:Psnd_pcm_scope_t):longint;cdecl;
|
||||
snd_pcm_meter_search_scope_t = function(pcm:Psnd_pcm_t; name:Pchar):Psnd_pcm_scope_t;cdecl;
|
||||
snd_pcm_scope_malloc_t = function(var ptr:Psnd_pcm_scope_t):longint;cdecl;
|
||||
snd_pcm_scope_set_ops_t = procedure(scope:Psnd_pcm_scope_t; val:Psnd_pcm_scope_ops_t);cdecl;
|
||||
snd_pcm_scope_set_name_t = procedure(scope:Psnd_pcm_scope_t; val:Pchar);cdecl;
|
||||
snd_pcm_scope_get_name_t = function(scope:Psnd_pcm_scope_t):Pchar;cdecl;
|
||||
snd_pcm_scope_get_callback_private_t = function(scope:Psnd_pcm_scope_t):pointer;cdecl;
|
||||
snd_pcm_scope_set_callback_private_t = procedure(scope:Psnd_pcm_scope_t; val:pointer);cdecl;
|
||||
snd_pcm_scope_s16_open_t = function(pcm:Psnd_pcm_t; name:Pchar; var scopep:Psnd_pcm_scope_t):longint;cdecl;
|
||||
snd_pcm_scope_s16_get_channel_buffer_t = function(scope:Psnd_pcm_scope_t; channel:LongWord):Pint16_t;cdecl;
|
||||
|
||||
var
|
||||
|
||||
snd_pcm_close : snd_pcm_close_t;
|
||||
snd_pcm_drop : snd_pcm_drop_t;
|
||||
snd_pcm_drain : snd_pcm_drain_t;
|
||||
snd_pcm_hw_params_malloc : snd_pcm_hw_params_malloc_t;
|
||||
snd_pcm_hw_params_any : snd_pcm_hw_params_any_t;
|
||||
snd_pcm_hw_params_get_periods : snd_pcm_hw_params_get_periods_t;
|
||||
snd_pcm_hw_params_get_period_size : snd_pcm_hw_params_get_period_size_t;
|
||||
snd_pcm_hw_params_get_rate : snd_pcm_hw_params_get_rate_t;
|
||||
snd_pcm_hw_params_set_access : snd_pcm_hw_params_set_access_t;
|
||||
snd_pcm_hw_params_set_buffer_size : snd_pcm_hw_params_set_buffer_size_t;
|
||||
snd_pcm_hw_params_set_buffer_size_near : snd_pcm_hw_params_set_buffer_size_near_t;
|
||||
snd_pcm_hw_params_set_channels : snd_pcm_hw_params_set_channels_t;
|
||||
snd_pcm_hw_params_set_format : snd_pcm_hw_params_set_format_t;
|
||||
snd_pcm_hw_params_set_period_size_near : snd_pcm_hw_params_set_period_size_near_t;
|
||||
snd_pcm_hw_params_set_periods_near : snd_pcm_hw_params_set_periods_near_t;
|
||||
snd_pcm_hw_params_set_rate_near : snd_pcm_hw_params_set_rate_near_t;
|
||||
snd_pcm_hw_params : snd_pcm_hw_params_t;
|
||||
snd_pcm_hw_params_free : snd_pcm_hw_params_free_t;
|
||||
snd_pcm_info_get_device : snd_pcm_info_get_device_t;
|
||||
snd_pcm_info_get_name : snd_pcm_info_get_name_t;
|
||||
snd_pcm_info_set_device : snd_pcm_info_set_device_t;
|
||||
snd_pcm_mmap_readi : snd_pcm_mmap_readi_t;
|
||||
snd_pcm_mmap_writei : snd_pcm_mmap_writei_t;
|
||||
snd_pcm_open : snd_pcm_open_t;
|
||||
snd_pcm_pause : snd_pcm_pause_t;
|
||||
snd_pcm_prepare : snd_pcm_prepare_t;
|
||||
snd_pcm_readi : snd_pcm_readi_t;
|
||||
snd_pcm_reset : snd_pcm_reset_t;
|
||||
snd_pcm_resume : snd_pcm_resume_t;
|
||||
snd_pcm_state : snd_pcm_state_t_t;
|
||||
snd_pcm_stream : snd_pcm_stream_t_t;
|
||||
snd_pcm_writei : snd_pcm_writei_t;
|
||||
|
||||
// Mixer types
|
||||
|
||||
type
|
||||
|
||||
psnd_ctl_card_info_t = Pointer;
|
||||
ppsnd_ctl_card_info_t = ^psnd_ctl_card_info_t;
|
||||
psnd_ctl_t = Pointer;
|
||||
ppsnd_ctl_t = ^psnd_ctl_t;
|
||||
|
||||
|
||||
type
|
||||
|
||||
snd_ctl_card_info_sizeof_t = function : Integer; cdecl;
|
||||
snd_ctl_card_info_malloc_t = function(ptr : ppsnd_ctl_card_info_t) : Integer; cdecl;
|
||||
snd_ctl_card_info_free_t = procedure(obj : psnd_ctl_card_info_t); cdecl;
|
||||
snd_ctl_card_info_clear_t = procedure(obj : psnd_ctl_card_info_t); cdecl;
|
||||
snd_ctl_card_info_copy_t = procedure(dst, src : psnd_ctl_card_info_t); cdecl;
|
||||
snd_ctl_card_info_get_card_t = function(obj : psnd_ctl_card_info_t) : Integer; cdecl;
|
||||
snd_ctl_card_info_get_id_t = function(obj : psnd_ctl_card_info_t) : PChar; cdecl;
|
||||
snd_ctl_card_info_get_driver_t = function(obj : psnd_ctl_card_info_t) : PChar; cdecl;
|
||||
snd_ctl_card_info_get_name_t = function(obj : psnd_ctl_card_info_t) : PChar; cdecl;
|
||||
snd_ctl_card_info_get_longname_t = function(obj : psnd_ctl_card_info_t) : PChar; cdecl;
|
||||
snd_ctl_card_info_get_mixername_t = function(obj : psnd_ctl_card_info_t) : PChar; cdecl;
|
||||
snd_ctl_card_info_get_components_t = function(obj : psnd_ctl_card_info_t) : PChar; cdecl;
|
||||
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
var
|
||||
Path : string;
|
||||
Libhandle : Pointer;
|
||||
|
||||
initialization
|
||||
|
||||
Path := FindLibs(asoundlib_path);
|
||||
if Path <> '' then Libhandle := dlopen(@Path[1], RTLD_NOW or RTLD_GLOBAL);
|
||||
if Libhandle <> nil then
|
||||
begin
|
||||
AsoundlibLoaded := True;
|
||||
snd_pcm_close := dlsym(Libhandle, 'snd_pcm_close');
|
||||
snd_pcm_drop := dlsym(Libhandle, 'snd_pcm_drop');
|
||||
snd_pcm_drain := dlsym(Libhandle, 'snd_pcm_drain');
|
||||
snd_pcm_hw_params_malloc := dlsym(Libhandle, 'snd_pcm_hw_params_malloc');
|
||||
snd_pcm_hw_params_any := dlsym(Libhandle, 'snd_pcm_hw_params_any');
|
||||
snd_pcm_hw_params_get_periods := dlsym(Libhandle, 'snd_pcm_hw_params_get_periods');
|
||||
snd_pcm_hw_params_get_period_size := dlsym(Libhandle, 'snd_pcm_hw_params_get_period_size');
|
||||
snd_pcm_hw_params_get_rate := dlsym(Libhandle, 'snd_pcm_hw_params_get_rate');
|
||||
snd_pcm_hw_params_set_access := dlsym(Libhandle, 'snd_pcm_hw_params_set_access');
|
||||
snd_pcm_hw_params_set_buffer_size := dlsym(Libhandle, 'snd_pcm_hw_params_set_buffer_size');
|
||||
snd_pcm_hw_params_set_buffer_size_near := dlsym(Libhandle, 'snd_pcm_hw_params_set_buffer_size_near');
|
||||
snd_pcm_hw_params_set_channels := dlsym(Libhandle, 'snd_pcm_hw_params_set_channels');
|
||||
snd_pcm_hw_params_set_format := dlsym(Libhandle, 'snd_pcm_hw_params_set_format');
|
||||
snd_pcm_hw_params_set_period_size_near := dlsym(Libhandle, 'snd_pcm_hw_params_set_period_size_near');
|
||||
snd_pcm_hw_params_set_periods_near := dlsym(Libhandle, 'snd_pcm_hw_params_set_periods_near');
|
||||
snd_pcm_hw_params_set_rate_near := dlsym(Libhandle, 'snd_pcm_hw_params_set_rate_near');
|
||||
snd_pcm_hw_params := dlsym(Libhandle, 'snd_pcm_hw_params');
|
||||
snd_pcm_hw_params_free := dlsym(Libhandle, 'snd_pcm_hw_params_free');
|
||||
snd_pcm_info_get_device := dlsym(Libhandle, 'snd_pcm_info_get_device');
|
||||
snd_pcm_info_get_name := dlsym(Libhandle, 'snd_pcm_info_get_name');
|
||||
snd_pcm_info_set_device := dlsym(Libhandle, 'snd_pcm_info_set_device');
|
||||
snd_pcm_mmap_readi := dlsym(Libhandle, 'snd_pcm_mmap_readi');
|
||||
snd_pcm_mmap_writei := dlsym(Libhandle, 'snd_pcm_mmap_writei');
|
||||
snd_pcm_open := dlsym(Libhandle, 'snd_pcm_open');
|
||||
snd_pcm_pause := dlsym(Libhandle, 'snd_pcm_pause');
|
||||
snd_pcm_prepare := dlsym(Libhandle, 'snd_pcm_prepare');
|
||||
snd_pcm_readi := dlsym(Libhandle, 'snd_pcm_readi');
|
||||
snd_pcm_reset := dlsym(Libhandle, 'snd_pcm_reset');
|
||||
snd_pcm_resume := dlsym(Libhandle, 'snd_pcm_resume');
|
||||
snd_pcm_state := dlsym(Libhandle, 'snd_pcm_state');
|
||||
snd_pcm_stream := dlsym(Libhandle, 'snd_pcm_stream');
|
||||
snd_pcm_writei := dlsym(Libhandle, 'snd_pcm_writei');
|
||||
end;
|
||||
|
||||
finalization
|
||||
|
||||
if Libhandle <> nil then dlclose(Libhandle);
|
||||
|
||||
|
||||
end.
|
||||
256
acs/Src/drivers/linux/libao.pas
Normal file
256
acs/Src/drivers/linux/libao.pas
Normal file
@@ -0,0 +1,256 @@
|
||||
(*
|
||||
kylix header for libao library.
|
||||
translated from ao.h header file
|
||||
by andrei borovsky, aborovsky@mtu-net.ru
|
||||
the original header is
|
||||
original copyright (c) aaron holtzman - may 1999
|
||||
modifications copyright (c) stan seibert - july 2000, july 2001
|
||||
more modifications copyright (c) jack moffitt - october 2000
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: libao.pas,v $
|
||||
Revision 1.2 2006/01/01 18:46:40 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/12/19 18:36:16 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/14 21:19:37 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
|
||||
unit libao;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
baseunix,dl, ACS_Procs;
|
||||
|
||||
var
|
||||
LibaoLoaded : Boolean = False;
|
||||
|
||||
const
|
||||
|
||||
LibaoPath = 'libao.so*'; // '/usr/lib/libao.so';
|
||||
{$DEFINE SEARCH_LIBS}
|
||||
|
||||
AO_TYPE_LIVE = 1;
|
||||
AO_TYPE_FILE = 2;
|
||||
AO_ENODRIVER = 1;
|
||||
AO_ENOTFILE = 2;
|
||||
AO_ENOTLIVE = 3;
|
||||
AO_EBADOPTION = 4;
|
||||
AO_EOPENDEVICE = 5;
|
||||
AO_EOPENFILE = 6;
|
||||
AO_EFILEEXISTS = 7;
|
||||
|
||||
AO_EFAIL = 100;
|
||||
|
||||
AO_FMT_LITTLE = 1;
|
||||
AO_FMT_BIG = 2;
|
||||
AO_FMT_NATIVE = 4;
|
||||
|
||||
type
|
||||
|
||||
PPChar = array[0..0] of PChar;
|
||||
|
||||
PAOInfo = ^ao_info;
|
||||
PPAOInfo = ^PAOInfo;
|
||||
ao_info = record
|
||||
_type : Integer; // live output or file output?
|
||||
name : PChar; // full name of driver
|
||||
short_name : PChar; // short name of driver */
|
||||
author : PChar; // driver author
|
||||
comment : PChar; // driver comment
|
||||
preferred_byte_format : Integer;
|
||||
priority : Integer;
|
||||
options : PPChar;
|
||||
option_count : Integer;
|
||||
end;
|
||||
|
||||
PAOFunctions = ^ao_functions;
|
||||
|
||||
PAODevice = ^ao_device;
|
||||
ao_device = packed record
|
||||
_type : Integer; // live output or file output?
|
||||
driver_id : Integer;
|
||||
funcs : PAOFunctions;
|
||||
_file : Pointer; // File for output if this is a file driver
|
||||
client_byte_format : Integer;
|
||||
machine_byte_format : Integer;
|
||||
driver_byte_format : Integer;
|
||||
swap_buffer : PChar;
|
||||
swap_buffer_size : Integer; // Bytes allocated to swap_buffer
|
||||
internal : Pointer; // Pointer to driver-specific data
|
||||
end;
|
||||
|
||||
PAOSampleFormat = ^ao_sample_format;
|
||||
ao_sample_format = record
|
||||
bits : Integer; // bits per sample
|
||||
rate : Integer; // samples per second (in a single channel)
|
||||
channels : Integer; // number of audio channels
|
||||
byte_format : Integer; // Byte ordering in sample, see constants below
|
||||
end;
|
||||
|
||||
f_test = function : Integer; cdecl;
|
||||
f_driver_info = function : PAOInfo; cdecl;
|
||||
f_device_init = function(device : PAODevice) : Integer; cdecl;
|
||||
f_set_option = function(device : PAODevice; const key, value : PChar) : Integer; cdecl;
|
||||
f_open = function(device : PAODevice) : Integer; cdecl;
|
||||
f_play = function(device : PAODevice; const output_samples : PChar; num_bytes : LongWord) : Integer; cdecl;
|
||||
f_close = function(device : PAODevice) : Integer; cdecl;
|
||||
f_device_clear = procedure(device : PAODevice); cdecl;
|
||||
f_file_extension = function : PChar; cdecl;
|
||||
|
||||
ao_functions = packed record
|
||||
test : f_test;
|
||||
driver_info : f_driver_info;
|
||||
device_init : f_device_init;
|
||||
set_option : f_set_option;
|
||||
open : f_open;
|
||||
play : f_play;
|
||||
close : f_close;
|
||||
device_clear : f_device_clear;
|
||||
file_extension : f_file_extension;
|
||||
end;
|
||||
|
||||
PPAOOption = ^PAOOption;
|
||||
PAOOption = ^ao_option;
|
||||
ao_option = record
|
||||
key : PChar;
|
||||
value : PChar;
|
||||
next : PAOOption;
|
||||
end;
|
||||
|
||||
(* --- Functions --- *)
|
||||
|
||||
(* library setup/teardown *)
|
||||
|
||||
ao_initialize_t = procedure; cdecl;
|
||||
ao_shutdown_t = procedure; cdecl;
|
||||
|
||||
(* device setup/playback/teardown *)
|
||||
ao_append_option_t = function(options : PPAOOption; const key, value : PChar) : Integer; cdecl;
|
||||
ao_free_options_t = procedure(options : PAOOption); cdecl;
|
||||
ao_open_live_t = function(driver_id : Integer; format : PAOSampleFormat; option : PAOOption) : PAODevice; cdecl;
|
||||
ao_open_file_t = function(driver_id : Integer; const filename : PChar; overwrite : Integer; format : PAOSampleFormat; option : PAOOption) : PAODevice; cdecl;
|
||||
|
||||
ao_play_t = function(device : PAODevice; output_samples : PChar; num_bytes : LongWord) : Integer; cdecl;
|
||||
ao_close_t = function(device : PAODevice) : Integer; cdecl;
|
||||
|
||||
(* driver information *)
|
||||
ao_driver_id_t = function(const short_name : PChar) : Integer; cdecl;
|
||||
ao_default_driver_id_t = function : Integer; cdecl;
|
||||
ao_driver_info_t = function(driver_id : Integer) : PAOInfo; cdecl;
|
||||
ao_driver_info_list_t = function(var driver_count : Integer) : PPAOInfo; cdecl;
|
||||
// The following function is declared in ao.h but not exported by libao.
|
||||
//ao_file_extension_t = function(driver_id : Integer) : PChar; cdecl;
|
||||
|
||||
(* miscellaneous *)
|
||||
ao_is_big_endian_t = function : Integer; cdecl;
|
||||
|
||||
var
|
||||
|
||||
ao_initialize : ao_initialize_t;
|
||||
ao_shutdown : ao_shutdown_t;
|
||||
ao_append_option : ao_append_option_t;
|
||||
ao_free_options : ao_free_options_t;
|
||||
ao_open_live : ao_open_live_t;
|
||||
ao_open_file : ao_open_file_t;
|
||||
ao_play : ao_play_t;
|
||||
ao_close : ao_close_t;
|
||||
ao_driver_id : ao_driver_id_t;
|
||||
ao_default_driver_id : ao_default_driver_id_t;
|
||||
ao_driver_info : ao_driver_info_t;
|
||||
ao_driver_info_list : ao_driver_info_list_t;
|
||||
//ao_file_extension : ao_file_extension_t;
|
||||
ao_is_big_endian : ao_is_big_endian_t;
|
||||
|
||||
AOInitialized : Integer = 0;
|
||||
|
||||
procedure FreeOptionsList(var OL : PAOOption);
|
||||
|
||||
implementation
|
||||
|
||||
var
|
||||
Libhandle : Pointer;
|
||||
|
||||
{$IFDEF SEARCH_LIBS}
|
||||
Path : String;
|
||||
{$ENDIF}
|
||||
|
||||
|
||||
procedure FreeOptionsList(var OL : PAOOption);
|
||||
var
|
||||
NextOpt, tmp : PAOOption;
|
||||
begin
|
||||
if OL = nil then Exit;
|
||||
NextOpt := OL;
|
||||
repeat
|
||||
tmp := NextOpt;
|
||||
NextOpt := NextOpt.next;
|
||||
FreeMem(tmp);
|
||||
until NextOpt = nil;
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
||||
{$IFDEF SEARCH_LIBS}
|
||||
|
||||
Libhandle := nil;
|
||||
Path := FindLibs(LibaoPath);
|
||||
if Path <> '' then Libhandle := dlopen(@Path[1], RTLD_NOW or RTLD_GLOBAL);
|
||||
|
||||
{$ELSE}
|
||||
|
||||
Libhandle := dlopen(LibaoPath, RTLD_NOW or RTLD_GLOBAL);
|
||||
|
||||
{$ENDIF}
|
||||
|
||||
if Libhandle <> nil then
|
||||
begin
|
||||
LibaoLoaded := True;
|
||||
ao_initialize := dlsym(Libhandle, 'ao_initialize');
|
||||
ao_shutdown := dlsym(Libhandle, 'ao_shutdown');
|
||||
ao_append_option := dlsym(Libhandle, 'ao_append_option');
|
||||
ao_free_options := dlsym(Libhandle, 'ao_free_options');
|
||||
ao_open_live := dlsym(Libhandle, 'ao_open_live');
|
||||
ao_open_file := dlsym(Libhandle, 'ao_open_file');
|
||||
ao_play := dlsym(Libhandle, 'ao_play');
|
||||
ao_close := dlsym(Libhandle, 'ao_close');
|
||||
ao_driver_id := dlsym(Libhandle, 'ao_driver_id');
|
||||
ao_default_driver_id := dlsym(Libhandle, 'ao_default_driver_id');
|
||||
ao_driver_info := dlsym(Libhandle, 'ao_driver_info');
|
||||
ao_driver_info_list := dlsym(Libhandle, 'ao_driver_info_list');
|
||||
//ao_file_extension := dlsym(Libhandle, 'ao_file_extension');
|
||||
ao_is_big_endian := dlsym(Libhandle, 'ao_is_big_endian');
|
||||
end;
|
||||
|
||||
finalization
|
||||
|
||||
if Libhandle <> nil then
|
||||
begin
|
||||
dlclose(Libhandle);
|
||||
end;
|
||||
|
||||
end.
|
||||
515
acs/Src/drivers/linux/soundcard.pas
Normal file
515
acs/Src/drivers/linux/soundcard.pas
Normal file
@@ -0,0 +1,515 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.3.
|
||||
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: soundcard.pas,v $
|
||||
Revision 1.1 2005/12/19 18:36:16 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/14 21:19:37 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
unit soundcard;
|
||||
|
||||
interface
|
||||
|
||||
|
||||
// Supported card ID numbers (OBSOLETE. NOT USED ANY MORE)
|
||||
|
||||
const
|
||||
|
||||
SNDCARD_ADLIB = 1;
|
||||
SNDCARD_SB = 2;
|
||||
SNDCARD_PAS = 3;
|
||||
SNDCARD_GUS = 4;
|
||||
SNDCARD_MPU401 = 5;
|
||||
SNDCARD_SB16 = 6;
|
||||
SNDCARD_SB16MIDI = 7;
|
||||
SNDCARD_UART6850 = 8;
|
||||
SNDCARD_GUS16 = 9;
|
||||
SNDCARD_MSS = 10;
|
||||
SNDCARD_PSS = 11;
|
||||
SNDCARD_SSCAPE = 12;
|
||||
SNDCARD_PSS_MPU = 13;
|
||||
SNDCARD_PSS_MSS = 14;
|
||||
SNDCARD_SSCAPE_MSS = 15;
|
||||
SNDCARD_TRXPRO = 16;
|
||||
SNDCARD_TRXPRO_SB = 17;
|
||||
SNDCARD_TRXPRO_MPU = 18;
|
||||
SNDCARD_MAD16 = 19;
|
||||
SNDCARD_MAD16_MPU = 20;
|
||||
SNDCARD_CS4232 = 21;
|
||||
SNDCARD_CS4232_MPU = 22;
|
||||
SNDCARD_MAUI = 23;
|
||||
SNDCARD_PSEUDO_MSS = 24;
|
||||
SNDCARD_GUSPNP = 25;
|
||||
SNDCARD_UART401 = 26;
|
||||
|
||||
// Sound card numbers 27 to N are reserved. Don't add more numbers here
|
||||
|
||||
//**********************************
|
||||
|
||||
// IOCTL commands for /dev/dsp and /dev/audio
|
||||
|
||||
const
|
||||
|
||||
SNDCTL_DSP_RESET = $5000;
|
||||
SNDCTL_DSP_SPEED = $c0045002;
|
||||
SNDCTL_DSP_STEREO = $c0045003;
|
||||
SNDCTL_DSP_GETBLKSIZE = $c0045004;
|
||||
SNDCTL_DSP_SAMPLESIZE = $c0045005;
|
||||
SNDCTL_DSP_CHANNELS = $c0045006;
|
||||
SOUND_PCM_WRITE_CHANNELS = $c0045006;
|
||||
SOUND_PCM_WRITE_FILTER = $c0045007;
|
||||
SNDCTL_DSP_POST = $5008;
|
||||
SNDCTL_DSP_SUBDIVIDE = $c0045009;
|
||||
SNDCTL_DSP_SETFRAGMENT = $c004500a;
|
||||
|
||||
// Audio data formats (Note! U8=8 and S16_LE=16 for compatibility)*/ }
|
||||
|
||||
SNDCTL_DSP_GETFMTS = $8004500b;
|
||||
SNDCTL_DSP_SETFMT = $c0045005;
|
||||
|
||||
AFMT_QUERY = 0;
|
||||
AFMT_MU_LAW = 1;
|
||||
AFMT_A_LAW = 2;
|
||||
AFMT_IMA_ADPCM = 4;
|
||||
AFMT_U8 = 8;
|
||||
AFMT_S16_LE = $10;
|
||||
AFMT_S16_BE = $20;
|
||||
AFMT_S8 = $40;
|
||||
AFMT_U16_LE = $80;
|
||||
AFMT_U16_BE = $100;
|
||||
AFMT_MPEG = $200;
|
||||
|
||||
// 32 bit formats (MSB aligned) formats
|
||||
|
||||
AFMT_S32_LE = $1000;
|
||||
AFMT_S32_BE = $2000;
|
||||
|
||||
// AC3 _compressed_ bitstreams (See Programmer's Guide for details).
|
||||
|
||||
AFMT_AC3 = $4000;
|
||||
|
||||
// 24 bit formats (LSB aligned in 32 bit word) formats*/ }
|
||||
AFMT_S24_LE = $8000;
|
||||
AFMT_S24_BE = $10000;
|
||||
|
||||
(* S/PDIF raw format. In this format the S/PDIF frames (including all
|
||||
control and user bits) are included in the data stream. Each sample
|
||||
is stored in a 32 bit frame (see IEC-958 for more info). This format
|
||||
is supported by very few devices and it's only usable for purposes
|
||||
where full access to the control/user bits is required (real time control).
|
||||
*)
|
||||
|
||||
AFMT_SPDIF_RAW = $20000;
|
||||
|
||||
type
|
||||
audio_buf_info = record
|
||||
fragments: Integer; // of available fragments (partially usend ones not counted)
|
||||
fragstotal: Integer; // Total # of fragments allocated
|
||||
fragsize: Integer; // Size of a fragment in bytes
|
||||
bytes: Integer; // Available space in bytes (includes partially used fragments)
|
||||
// Note! 'bytes' could be more than fragments*fragsize*/
|
||||
end;
|
||||
|
||||
const
|
||||
|
||||
SNDCTL_DSP_GETOSPACE = $8010500c;
|
||||
SNDCTL_DSP_GETISPACE = $8010500d;
|
||||
SNDCTL_DSP_NONBLOCK = $500e;
|
||||
SNDCTL_DSP_GETCAPS = $8004500f;
|
||||
|
||||
DSP_CAP_REVISION = $ff; // Bits for revision level (0 to 255)
|
||||
DSP_CAP_DUPLEX = $100; // Full duplex record/playback
|
||||
DSP_CAP_REALTIME = $200; // Not in use
|
||||
DSP_CAP_BATCH = $400; (* Device has some kind of
|
||||
internal buffers which may
|
||||
cause some delays and
|
||||
decrease precision of timing *)
|
||||
|
||||
DSP_CAP_COPROC = $800; // Has a coprocessor
|
||||
(* Sometimes it's a DSP
|
||||
but usually not *)
|
||||
|
||||
DSP_CAP_TRIGGER = $1000; // Supports SETTRIGGER
|
||||
DSP_CAP_MMAP = $2000; // Supports mmap()
|
||||
DSP_CAP_MULTI = $4000; // Supports multiple open
|
||||
DSP_CAP_BIND = $8000; // Supports binding to front/rear/center/lfe
|
||||
DSP_CAP_INPUT = $10000; // Supports recording
|
||||
DSP_CAP_OUTPUT = $20000; // Supports playback
|
||||
DSP_CAP_VIRTUAL = $40000; // Virtuial device
|
||||
// Analog/digital control capabilities
|
||||
DSP_CAP_ANALOGOUT = $100000;
|
||||
DSP_CAP_ANALOGIN = $200000;
|
||||
DSP_CAP_DIGITALOUT = $400000;
|
||||
DSP_CAP_DIGITALIN = $800000;
|
||||
DSP_CAP_ADMASK = $f00000;
|
||||
(* NOTE! (capabilities & DSP_CAP_ADMASK)==0 means just that the
|
||||
digital/analog interface control features are not supported by the
|
||||
device/driver. However the device still supports analog, digital or
|
||||
both inputs/outputs (depending on the device). See the OSS Programmer's
|
||||
Guide for full details. *)
|
||||
|
||||
SNDCTL_DSP_GETTRIGGER = $80045010;
|
||||
SNDCTL_DSP_SETTRIGGER = $40045010;
|
||||
|
||||
PCM_ENABLE_INPUT = 1;
|
||||
PCM_ENABLE_OUTPUT = 2;
|
||||
|
||||
type
|
||||
count_info = record
|
||||
bytes: Integer; // Total # of bytes processed
|
||||
blocks : Integer; // # of fragment transitions since last time
|
||||
ptr: Integer; // Current DMA pointer value }
|
||||
end;
|
||||
|
||||
const
|
||||
SNDCTL_DSP_GETIPTR = $800c5011;
|
||||
SNDCTL_DSP_GETOPTR = $800c5012;
|
||||
|
||||
type
|
||||
buffmem_desc = record
|
||||
buffer: PWord;
|
||||
size: Integer;
|
||||
end;
|
||||
|
||||
const
|
||||
SNDCTL_DSP_MAPINBUF = $80085013;
|
||||
SNDCTL_DSP_MAPOUTBUF = $80085014;
|
||||
SNDCTL_DSP_SETSYNCRO = $5015;
|
||||
SNDCTL_DSP_SETDUPLEX = $5016;
|
||||
|
||||
// Application's profile defines the way how playback underrun situations should be handled.
|
||||
|
||||
(* APF_NORMAL (the default) and APF_NETWORK make the driver to cleanup the
|
||||
playback buffer whenever an underrun occurs. This consumes some time
|
||||
prevents looping the existing buffer.
|
||||
APF_CPUINTENS is intended to be set by CPU intensive applications which
|
||||
are likely to run out of time occasionally. In this mode the buffer cleanup is
|
||||
disabled which saves CPU time but also let's the previous buffer content to
|
||||
be played during the "pause" after the underrun. *)
|
||||
|
||||
const
|
||||
SNDCTL_DSP_PROFILE = $40045017;
|
||||
|
||||
APF_NORMAL = 0; // Normal applications
|
||||
APF_NETWORK = 1; // Underruns probably caused by an 'external' delay
|
||||
APF_CPUINTENS = 2; // Underruns probably caused by 'overheating' the CPU
|
||||
|
||||
SNDCTL_DSP_GETODELAY = $80045017;
|
||||
|
||||
|
||||
type
|
||||
audio_errinfo = record
|
||||
play_underruns: Integer;
|
||||
rec_overruns: Integer;
|
||||
play_ptradjust: Word;
|
||||
rec_ptradjust: Word;
|
||||
play_errorcount: Integer;
|
||||
rec_errorcount: Integer;
|
||||
play_lasterror: Integer;
|
||||
rec_lasterror: Integer;
|
||||
play_errorparm: LongInt;
|
||||
rec_errorparm: LongInt;
|
||||
filler: array[0..15] of Integer;
|
||||
end;
|
||||
|
||||
|
||||
type
|
||||
oss_digital_control = record
|
||||
caps: LongWord; // To be defined }
|
||||
valid : LongWord;
|
||||
cbitin: array[0..23] of Byte;
|
||||
ubitin: array[0..23] of Byte;
|
||||
cbitout: array[0..23] of Byte;
|
||||
ubitout: array[0..23] of Byte;
|
||||
outsel: LongWord;
|
||||
in_data: Integer; // Audio/data if autodetectable by the receiver
|
||||
in_locked: Integer; // Receiver locked
|
||||
in_quality: Integer; // Input signal quality
|
||||
in_vbit, out_vbit: Integer; // V bits
|
||||
in_errors: LongWord; // Various input errro conditions
|
||||
end;
|
||||
|
||||
const
|
||||
|
||||
DIG_CBITIN_LIMITED = $00000001;
|
||||
DIG_CBITIN_DATA = $00000002;
|
||||
DIG_CBITIN_BYTE0 = $00000004;
|
||||
DIG_CBITIN_FULL = $00000008;
|
||||
DIG_CBITIN_MASK = $0000000;
|
||||
DIG_CBITOUT_LIMITED = $00000010;
|
||||
DIG_CBITOUT_BYTE0 = $00000020;
|
||||
DIG_CBITOUT_FULL = $00000040;
|
||||
DIG_CBITOUT_DATA = $00000080;
|
||||
DIG_CBITOUT_MASK = $000000f0;
|
||||
DIG_UBITIN = $00000100;
|
||||
DIG_UBITOUT = $00000200;
|
||||
|
||||
VAL_CBITIN = $01;
|
||||
VAL_UBITIN = $02;
|
||||
VAL_CBITOUT = $04;
|
||||
VAL_UBITOUT = $08;
|
||||
VAL_ISTATUS = $10;
|
||||
|
||||
OUTSEL_DIGITAL = 1;
|
||||
OUTSEL_ANALOG = 2;
|
||||
OUTSEL_BOTH = (OUTSEL_DIGITAL or OUTSEL_ANALOG);
|
||||
|
||||
IND_UNKNOWN = 0;
|
||||
IND_AUDIO = 1;
|
||||
IND_DATA = 2;
|
||||
|
||||
LOCK_NOT_INDICATED = 0;
|
||||
LOCK_UNLOCKED = 1;
|
||||
LOCK_LOCKED = 2;
|
||||
IN_QUAL_NOT_INDICATED = 0;
|
||||
IN_QUAL_POOR = 1;
|
||||
IN_QUAL_GOOD = 2;
|
||||
|
||||
VBIT_NOT_INDICATED = 0;
|
||||
VBIT_OFF = 1;
|
||||
VBIT_ON = 2;
|
||||
|
||||
INERR_CRC = $0001;
|
||||
INERR_QCODE_CRC = $0002;
|
||||
INERR_PARITY = $0004;
|
||||
INERR_BIPHASE = $0008;
|
||||
|
||||
type
|
||||
oss_syncgroup = record
|
||||
id: Integer;
|
||||
mode: Integer;
|
||||
end;
|
||||
|
||||
const
|
||||
|
||||
SNDCTL_DSP_GETCHANNELMASK = $c0045040;
|
||||
SNDCTL_DSP_BIND_CHANNEL = $c0045041;
|
||||
|
||||
DSP_BIND_QUERY = 0;
|
||||
DSP_BIND_FRONT = 1;
|
||||
DSP_BIND_SURR = 2;
|
||||
DSP_BIND_CENTER_LFE = 4;
|
||||
DSP_BIND_HANDSET = 8;
|
||||
DSP_BIND_MIC = $10;
|
||||
DSP_BIND_MODEM1 = $20;
|
||||
DSP_BIND_MODEM2 = $40;
|
||||
DSP_BIND_I2S = $80;
|
||||
DSP_BIND_SPDIF = $100;
|
||||
|
||||
// Mixer devices
|
||||
|
||||
(* There can be up to 20 different analog mixer channels. The }
|
||||
SOUND_MIXER_NRDEVICES gives the currently supported maximum.
|
||||
The SOUND_MIXER_READ_DEVMASK returns a bitmask which tells
|
||||
the devices supported by the particular mixer.
|
||||
*)
|
||||
|
||||
const
|
||||
|
||||
SOUND_MIXER_NRDEVICES = 28;
|
||||
SOUND_MIXER_VOLUME = 0;
|
||||
SOUND_MIXER_BASS = 1;
|
||||
SOUND_MIXER_TREBLE = 2;
|
||||
SOUND_MIXER_SYNTH = 3;
|
||||
SOUND_MIXER_PCM = 4;
|
||||
SOUND_MIXER_SPEAKER = 5;
|
||||
SOUND_MIXER_LINE = 6;
|
||||
SOUND_MIXER_MIC = 7;
|
||||
SOUND_MIXER_CD = 8;
|
||||
SOUND_MIXER_IMIX = 9; // Recording monitor
|
||||
SOUND_MIXER_ALTPCM = 10;
|
||||
SOUND_MIXER_RECLEV = 11; // Recording level
|
||||
SOUND_MIXER_IGAIN = 12; // Input gain
|
||||
SOUND_MIXER_OGAIN = 13; // Output gain
|
||||
|
||||
(* The AD1848 codec and compatibles have three line level inputs
|
||||
(line, aux1 and aux2). Since each card manufacturer have assigned
|
||||
different meanings to these inputs, it's inpractical to assign
|
||||
specific meanings (line, cd, synth etc.) to them. *)
|
||||
|
||||
SOUND_MIXER_LINE1 = 14; // Input source 1 (aux1)
|
||||
SOUND_MIXER_LINE2 = 15; // Input source 2 (aux2)
|
||||
SOUND_MIXER_LINE3 = 16; // Input source 3 (line)
|
||||
SOUND_MIXER_DIGITAL1 = 17; // Digital (input)
|
||||
SOUND_MIXER_DIGITAL2 = 18; // Digital (input) 2
|
||||
SOUND_MIXER_DIGITAL3 = 19; // Digital (input) 3
|
||||
SOUND_MIXER_PHONEIN = 20; // Phone input
|
||||
SOUND_MIXER_PHONEOUT = 21; // Phone output
|
||||
SOUND_MIXER_VIDEO = 22; // Video/TV (audio) in
|
||||
SOUND_MIXER_RADIO = 23; // Radio in
|
||||
SOUND_MIXER_MONITOR = 24; // Monitor (usually mic) volume
|
||||
SOUND_MIXER_DEPTH = 25; // 3D 'depth'/'space' parameter
|
||||
SOUND_MIXER_CENTER = 26; // 3D 'center' parameter
|
||||
SOUND_MIXER_MIDI = 27; // Alternative for 'synth'
|
||||
|
||||
(* Some on/off settings (SOUND_SPECIAL_MIN - SOUND_SPECIAL_MAX)
|
||||
Not counted to SOUND_MIXER_NRDEVICES, but use the same number space *)
|
||||
|
||||
SOUND_ONOFF_MIN = 28;
|
||||
SOUND_ONOFF_MAX = 30;
|
||||
|
||||
// Note! Number 31 cannot be used since the sign bit is reserved
|
||||
|
||||
SOUND_MIXER_NONE = 31;
|
||||
|
||||
(* The following unsupported macros are no longer functional.
|
||||
Use SOUND_MIXER_PRIVATE# macros in future. *)
|
||||
|
||||
SOUND_MIXER_ENHANCE = SOUND_MIXER_NONE;
|
||||
SOUND_MIXER_MUTE = SOUND_MIXER_NONE;
|
||||
SOUND_MIXER_LOUD = SOUND_MIXER_NONE;
|
||||
|
||||
|
||||
|
||||
SOUND_DEVICE_LABELS : array[0..27] of PChar = ('Vol ', 'Bass ', 'Trebl', 'Synth', 'Pcm ', 'Spkr ', 'Line ',
|
||||
'Mic ', 'CD ', 'Mix ', 'Pcm2 ', 'Rec ', 'IGain', 'OGain',
|
||||
'Line1', 'Line2', 'Line3', 'Digital1', 'Digital2', 'Digital3',
|
||||
'PhoneIn', 'PhoneOut', 'Video', 'Radio', 'Monitor',
|
||||
'Depth', 'Center', 'MIDI');
|
||||
|
||||
|
||||
SOUND_DEVICE_NAMES : array[0..27] of PChar = ('vol', 'bass', 'treble', 'synth', 'pcm', 'speaker', 'line',
|
||||
'mic', 'cd', 'mix', 'pcm2', 'rec', 'igain', 'ogain',
|
||||
'line1', 'line2', 'line3', 'dig1', 'dig2', 'dig3',
|
||||
'phin', 'phout', 'video', 'radio', 'monitor',
|
||||
'depth', 'center', 'midi');
|
||||
|
||||
// Device bitmask identifiers
|
||||
|
||||
SOUND_MIXER_RECSRC = $ff; // Arg contains a bit for each recording source
|
||||
SOUND_MIXER_DEVMASK = $fe; // Arg contains a bit for each supported device
|
||||
SOUND_MIXER_RECMASK = $fd; // Arg contains a bit for each supported recording source
|
||||
SOUND_MIXER_CAPS = $fc;
|
||||
SOUND_CAP_EXCL_INPUT = $1; // Only one recording source at a time
|
||||
|
||||
SOUND_MIXER_STEREODEVS = $fb; // Mixer channels supporting stereo
|
||||
|
||||
// OSS/Free ONLY
|
||||
SOUND_MIXER_OUTSRC = $fa; // Arg contains a bit for each input source to output
|
||||
SOUND_MIXER_OUTMASK = $f9; // Arg contains a bit for each supported input source to output
|
||||
// OSS/Free ONLY
|
||||
|
||||
// Device mask bits
|
||||
|
||||
SOUND_MASK_VOLUME = 1 shl SOUND_MIXER_VOLUME;
|
||||
SOUND_MASK_BASS = 1 shl SOUND_MIXER_BASS;
|
||||
SOUND_MASK_TREBLE = 1 shl SOUND_MIXER_TREBLE;
|
||||
SOUND_MASK_SYNTH = 1 shl SOUND_MIXER_SYNTH;
|
||||
SOUND_MASK_PCM = 1 shl SOUND_MIXER_PCM;
|
||||
SOUND_MASK_SPEAKER = 1 shl SOUND_MIXER_SPEAKER;
|
||||
SOUND_MASK_LINE = 1 shl SOUND_MIXER_LINE;
|
||||
SOUND_MASK_MIC = 1 shl SOUND_MIXER_MIC;
|
||||
SOUND_MASK_CD = 1 shl SOUND_MIXER_CD;
|
||||
SOUND_MASK_IMIX = 1 shl SOUND_MIXER_IMIX;
|
||||
SOUND_MASK_ALTPCM = 1 shl SOUND_MIXER_ALTPCM;
|
||||
SOUND_MASK_RECLEV = 1 shl SOUND_MIXER_RECLEV;
|
||||
SOUND_MASK_IGAIN = 1 shl SOUND_MIXER_IGAIN;
|
||||
SOUND_MASK_OGAIN = 1 shl SOUND_MIXER_OGAIN;
|
||||
SOUND_MASK_LINE1 = 1 shl SOUND_MIXER_LINE1;
|
||||
SOUND_MASK_LINE2 = 1 shl SOUND_MIXER_LINE2;
|
||||
SOUND_MASK_LINE3 = 1 shl SOUND_MIXER_LINE3;
|
||||
SOUND_MASK_DIGITAL1 = 1 shl SOUND_MIXER_DIGITAL1;
|
||||
SOUND_MASK_DIGITAL2 = 1 shl SOUND_MIXER_DIGITAL2;
|
||||
SOUND_MASK_DIGITAL3 = 1 shl SOUND_MIXER_DIGITAL3;
|
||||
SOUND_MASK_PHONEIN = 1 shl SOUND_MIXER_PHONEIN;
|
||||
SOUND_MASK_PHONEOUT = 1 shl SOUND_MIXER_PHONEOUT;
|
||||
SOUND_MASK_RADIO = 1 shl SOUND_MIXER_RADIO;
|
||||
SOUND_MASK_VIDEO = 1 shl SOUND_MIXER_VIDEO;
|
||||
SOUND_MASK_MONITOR = 1 shl SOUND_MIXER_MONITOR;
|
||||
SOUND_MASK_DEPTH = 1 shl SOUND_MIXER_DEPTH;
|
||||
SOUND_MASK_CENTER = 1 shl SOUND_MIXER_CENTER;
|
||||
SOUND_MASK_MIDI = 1 shl SOUND_MIXER_MIDI;
|
||||
|
||||
SOUND_MIXER_READ_VOLUME = $80044d00;
|
||||
SOUND_MIXER_READ_BASS = $80044d01;
|
||||
SOUND_MIXER_READ_TREBLE = $80044d02;
|
||||
SOUND_MIXER_READ_SYNTH = $80044d03;
|
||||
SOUND_MIXER_READ_PCM = $80044d04;
|
||||
SOUND_MIXER_READ_SPEAKER = $80044d05;
|
||||
SOUND_MIXER_READ_LINE = $80044d06;
|
||||
SOUND_MIXER_READ_MIC = $80044d07;
|
||||
SOUND_MIXER_READ_CD = $80044d08;
|
||||
SOUND_MIXER_READ_IMIX = $80044d09;
|
||||
SOUND_MIXER_READ_ALTPCM = $80044d0a;
|
||||
SOUND_MIXER_READ_RECLEV = $80044d0b;
|
||||
SOUND_MIXER_READ_IGAIN = $80044d0c;
|
||||
SOUND_MIXER_READ_OGAIN = $80044d0d;
|
||||
SOUND_MIXER_READ_LINE1 = $80044d0e;
|
||||
SOUND_MIXER_READ_LINE2 = $80044d0f;
|
||||
SOUND_MIXER_READ_LINE3 = $80044d10;
|
||||
SOUND_MIXER_READ_RECSRC = $80044dff;
|
||||
SOUND_MIXER_READ_RECMASK = $80044dfd;
|
||||
SOUND_MIXER_READ_DEVMASK = $80044dfe;
|
||||
SOUND_MIXER_READ_STEREODEVS = $80044dfb;
|
||||
SOUND_MIXER_READ_CAPS = $80044dfc;
|
||||
|
||||
SOUND_MIXER_WRITE_VOLUME = $c0044d00;
|
||||
SOUND_MIXER_WRITE_BASS = $c0044d01;
|
||||
SOUND_MIXER_WRITE_TREBLE = $c0044d02;
|
||||
SOUND_MIXER_WRITE_SYNTH = $c0044d03;
|
||||
SOUND_MIXER_WRITE_PCM = $c0044d04;
|
||||
SOUND_MIXER_WRITE_SPEAKER = $c0044d05;
|
||||
SOUND_MIXER_WRITE_LINE = $c0044d06;
|
||||
SOUND_MIXER_WRITE_MIC = $c0044d07;
|
||||
SOUND_MIXER_WRITE_CD = $c0044d08;
|
||||
SOUND_MIXER_WRITE_IMIX = $c0044d09;
|
||||
SOUND_MIXER_WRITE_ALTPCM = $c0044d0a;
|
||||
SOUND_MIXER_WRITE_RECLEV = $c0044d0b;
|
||||
SOUND_MIXER_WRITE_IGAIN = $c0044d0c;
|
||||
SOUND_MIXER_WRITE_OGAIN = $c0044d0d;
|
||||
SOUND_MIXER_WRITE_LINE1 = $c0044d0e;
|
||||
SOUND_MIXER_WRITE_LINE2 = $c0044d0f;
|
||||
SOUND_MIXER_WRITE_LINE3 = $c0044d10;
|
||||
SOUND_MIXER_WRITE_RECSRC = $c0044dff;
|
||||
SOUND_MIXER_INFO = $805c4d65;
|
||||
|
||||
type
|
||||
mixer_info = record
|
||||
id: array[0..15] of Char;
|
||||
name: array[0..31] of Char;
|
||||
modify_counter: Integer;
|
||||
fillers: array[0..9] of Integer;
|
||||
end;
|
||||
|
||||
const
|
||||
SOUND_MIXER_ACCESS = $c0804d66;
|
||||
SOUND_MIXER_GETLEVELS = $c0a44d74;
|
||||
SOUND_MIXER_SETLEVELS = $c0a44d75;
|
||||
|
||||
(* SOUND_MIXER_GETLEVELS and SOUND_MIXER_SETLEVELS calls can be used
|
||||
for querying current mixer settings from the driver and for loading
|
||||
default volume settings _prior_ activating the mixer (loading
|
||||
doesn't affect current state of the mixer hardware). These calls
|
||||
are for internal use only. *)
|
||||
|
||||
type
|
||||
mixer_vol_table = record
|
||||
num: Integer; // Index to volume table
|
||||
name: array[0..31] of Char;
|
||||
levels: array[0..31] of Integer;
|
||||
end;
|
||||
|
||||
implementation
|
||||
end.
|
||||
408
acs/Src/drivers/windows/acs_audio.inc
Normal file
408
acs/Src/drivers/windows/acs_audio.inc
Normal file
@@ -0,0 +1,408 @@
|
||||
{
|
||||
$Log: acs_audio.inc,v $
|
||||
Revision 1.7 2006/08/31 20:10:56 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.6 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.3 2006/01/01 18:46:40 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/12/26 17:31:39 z0m3ie
|
||||
fixed some problems in acs_dsfiles
|
||||
fixed some problems in acs_vorbis
|
||||
reworked all buffers
|
||||
|
||||
Revision 1.1 2005/12/19 18:36:26 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.6 2005/12/18 17:01:54 z0m3ie
|
||||
delphi compatibility
|
||||
|
||||
Revision 1.5 2005/12/04 16:54:34 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.4 2005/11/27 16:50:34 z0m3ie
|
||||
add ACS VolumeQuerry
|
||||
make ACS_VolumeQuerry localizeable
|
||||
some little errorfixes (buffersize for linuxdrivers was initially 0)
|
||||
make TAudioIn workable
|
||||
|
||||
Revision 1.3 2005/10/02 16:51:31 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/09/18 19:29:00 z0m3ie
|
||||
more progress on driver handling
|
||||
|
||||
}
|
||||
|
||||
|
||||
function GetAudioDeviceInfo(DevID : Integer; OutputDev : Boolean) : TACSDeviceInfo;
|
||||
var
|
||||
WIC : TWaveInCaps;
|
||||
i : Integer;
|
||||
begin
|
||||
if OutputDev then
|
||||
begin
|
||||
if DevID >= OutputChannelsCount then
|
||||
raise EACSException.Create(Format(strChannelnotavailable,[DevId]));
|
||||
end else
|
||||
begin
|
||||
if DevID >= InputChannelsCount then
|
||||
raise EACSException.Create(Format(strChannelnotavailable,[DevId]));
|
||||
end;
|
||||
if OutputDev then waveOutGetDevCaps(DevID, @WIC, SizeOf(WIC))
|
||||
else waveInGetDevCaps(DevID, @WIC, SizeOf(WIC));
|
||||
i := 0;
|
||||
while WIC.szPname[i] <> #0 do Inc(i);
|
||||
SetLength(Result.DeviceName, i);
|
||||
Move(WIC.szPname[0], Result.DeviceName[1], i);
|
||||
Result.Formats := [];
|
||||
if (WIC.dwFormats and WAVE_FORMAT_1M08) <> 0 then Result.Formats := Result.Formats + [af1M08];
|
||||
if (WIC.dwFormats and WAVE_FORMAT_1M16) <> 0 then Result.Formats := Result.Formats + [af1M16];
|
||||
if (WIC.dwFormats and WAVE_FORMAT_1S08) <> 0 then Result.Formats := Result.Formats + [af1S08];
|
||||
if (WIC.dwFormats and WAVE_FORMAT_1S16) <> 0 then Result.Formats := Result.Formats + [af1S16];
|
||||
if (WIC.dwFormats and WAVE_FORMAT_2M08) <> 0 then Result.Formats := Result.Formats + [af2M08];
|
||||
if (WIC.dwFormats and WAVE_FORMAT_2M16) <> 0 then Result.Formats := Result.Formats + [af2M16];
|
||||
if (WIC.dwFormats and WAVE_FORMAT_2S08) <> 0 then Result.Formats := Result.Formats + [af2S08];
|
||||
if (WIC.dwFormats and WAVE_FORMAT_2S16) <> 0 then Result.Formats := Result.Formats + [af2S16];
|
||||
if (WIC.dwFormats and WAVE_FORMAT_4M08) <> 0 then Result.Formats := Result.Formats + [af4M08];
|
||||
if (WIC.dwFormats and WAVE_FORMAT_4M16) <> 0 then Result.Formats := Result.Formats + [af4M16];
|
||||
if (WIC.dwFormats and WAVE_FORMAT_4S08) <> 0 then Result.Formats := Result.Formats + [af4S08];
|
||||
if (WIC.dwFormats and WAVE_FORMAT_4S16) <> 0 then Result.Formats := Result.Formats + [af4S16];
|
||||
Result.DrvVersion := WIC.vDriverVersion;
|
||||
if WIC.wChannels = 1 then Result.Stereo := False else Result.Stereo := True;
|
||||
end;
|
||||
|
||||
procedure WaveOutProc(hwo, Msg : LongWord; Instance : Pointer; Param1, Param2 : LongWord); stdcall;
|
||||
var
|
||||
Audio : TStdAudioOut;
|
||||
begin
|
||||
EnterCriticalSection(CrSecO);
|
||||
if Msg = WOM_DONE then
|
||||
begin
|
||||
Audio := TStdAudioOut(Instance);
|
||||
Audio.AddBlockToChain(PWaveHdr(Param1));
|
||||
end;
|
||||
LeaveCriticalSection(CrSecO);
|
||||
end;
|
||||
|
||||
procedure WaveInProc(hwi, Msg : LongWord; Instance : Pointer; Param1, Param2 : LongWord); stdcall;
|
||||
var
|
||||
Audio : TStdAudioIn;
|
||||
begin
|
||||
EnterCriticalSection(CrSecI);
|
||||
if Msg = WIM_DATA then
|
||||
begin
|
||||
Audio := TStdAudioIn(Instance);
|
||||
Audio.AddBlockToChain(PWaveHdr(Param1));
|
||||
end;
|
||||
LeaveCriticalSection(CrSecI);
|
||||
end;
|
||||
|
||||
procedure TStdAudioOut.AddBlockToChain(WH : PWaveHdr);
|
||||
begin
|
||||
WH.lpNext := nil;
|
||||
EOC^ := WH;
|
||||
EOC := @WH.lpNext;
|
||||
Dec(aBlock);
|
||||
end;
|
||||
|
||||
procedure TStdAudioOut.SetDevice;
|
||||
begin
|
||||
if Busy then raise EACSException.Create(strBusy);
|
||||
if OutputChannelsCount = 0 then FBaseChannel := 0 else
|
||||
if Ch < OutputChannelsCount then FBaseChannel := Ch
|
||||
else raise EACSException.Create(Format(strChannelnotavailable,[Ch]));
|
||||
end;
|
||||
|
||||
procedure TStdAudioOut.Prepare;
|
||||
var
|
||||
WF : TPCMWaveFormat;
|
||||
begin
|
||||
// No exceptions here!
|
||||
FInput.Init;
|
||||
WF.wf.wFormatTag := WAVE_FORMAT_PCM;
|
||||
WF.wf.nChannels := FInput.Channels;
|
||||
WF.wf.nSamplesPerSec := FInput.SampleRate;
|
||||
WF.wBitsPerSample := FInput.BitsPerSample;
|
||||
WF.wf.nAvgBytesPerSec := WF.wf.nSamplesPerSec*WF.wBitsPerSample div 8;
|
||||
WF.wf.nBlockAlign := WF.wf.nChannels * WF.wBitsPerSample div 8;
|
||||
waveOutOpen(@_audio_fd, FBaseChannel, @WF, DWORD(@WaveOutProc), DWORD(Self), CALLBACK_FUNCTION or WAVE_MAPPED);
|
||||
aBlock := 0;
|
||||
FBuffer := AllocMem(FBufferSize);
|
||||
EOC := @BlockChain;
|
||||
end;
|
||||
|
||||
procedure TStdAudioOut.Done;
|
||||
var
|
||||
Tmp : PWaveHdr;
|
||||
begin
|
||||
if _audio_fd <> -1 then
|
||||
begin
|
||||
while aBlock > 0 do;
|
||||
Tmp := BlockChain;
|
||||
while Tmp <> nil do
|
||||
begin
|
||||
BlockChain := Tmp.lpNext;
|
||||
waveOutUnprepareHeader(_audio_fd, Tmp, SizeOf(TWaveHdr));
|
||||
FreeMem(Tmp.lpData);
|
||||
Dispose(Tmp);
|
||||
Tmp := BlockChain;
|
||||
end;
|
||||
EOC := @BlockChain;
|
||||
waveOutClose(_audio_fd);
|
||||
FreeMem(FBuffer);
|
||||
_audio_fd := -1;
|
||||
end;
|
||||
FInput.Flush;
|
||||
end;
|
||||
|
||||
function TStdAudioOut.DoOutput(Abort : Boolean):Boolean;
|
||||
var
|
||||
Len, i, k, vCoef : Integer;
|
||||
P : Pointer;
|
||||
P1 : PACSBuffer8;
|
||||
P2 : PACSBuffer16;
|
||||
Tmp : PWaveHdr;
|
||||
begin
|
||||
// No exceptions Here
|
||||
Result := True;
|
||||
if not Busy then Exit;
|
||||
if Abort or (not CanOutput) then
|
||||
begin
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
Tmp := BlockChain; // clear pending data blocks
|
||||
while Tmp <> nil do
|
||||
begin
|
||||
BlockChain := Tmp.lpNext;
|
||||
waveOutUnprepareHeader(_audio_fd, Tmp, SizeOf(TWaveHdr));
|
||||
FreeMem(Tmp.lpData);
|
||||
Dispose(Tmp);
|
||||
Tmp := BlockChain;
|
||||
end;
|
||||
EOC := @BlockChain;
|
||||
(* Write more than one block. This is needed for audio sources like
|
||||
Vorbis codec that return data in small chunks. *)
|
||||
for k := aBlock to FReadChunks do
|
||||
begin
|
||||
GetMem(P, FBufferSize div FReadChunks);
|
||||
while InputLock do;
|
||||
InputLock := True;
|
||||
Len := Finput.GetData(P, FBufferSize div FReadChunks);
|
||||
InputLock := False;
|
||||
if Len > 0 then Result := True
|
||||
else
|
||||
begin
|
||||
Result := False;
|
||||
FreeMem(P);
|
||||
Exit;
|
||||
end;
|
||||
if FVolume < 255 then
|
||||
begin
|
||||
vCoef := Round(FVolume/255);
|
||||
if FInput.BitsPerSample = 16 then
|
||||
begin
|
||||
P2 := P;
|
||||
for i := 0 to (Len shr 1) -1 do
|
||||
P2[i] := P2[i]*vCoef;
|
||||
end else
|
||||
begin
|
||||
P1 := P;
|
||||
for i := 0 to Len - 1 do
|
||||
P1[i] := P1[i]*vCoef;
|
||||
end;
|
||||
end;
|
||||
WriteBlock(P, Len);
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TStdAudioOut.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FBaseChannel := 0;
|
||||
FVolume := 255;
|
||||
_audio_fd := -1;
|
||||
Delay := 6;
|
||||
FReadChunks := 8;
|
||||
FBufferSize := $8000;
|
||||
end;
|
||||
|
||||
destructor TStdAudioOut.Destroy;
|
||||
begin
|
||||
if _audio_fd <> -1 then WaveOutClose(_audio_fd);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
destructor TStdAudioIn.Destroy;
|
||||
begin
|
||||
waveInClose(_audio_fd);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TStdAudioIn.OpenAudio;
|
||||
var
|
||||
WF : TPCMWaveFormat;
|
||||
begin
|
||||
WF.wf.wFormatTag := WAVE_FORMAT_PCM;
|
||||
WF.wf.nChannels := FChan;
|
||||
WF.wf.nSamplesPerSec := FFreq;
|
||||
WF.wBitsPerSample := FBPS;
|
||||
WF.wf.nAvgBytesPerSec := WF.wf.nSamplesPerSec*WF.wBitsPerSample div 8;
|
||||
WF.wf.nBlockAlign := WF.wf.nChannels * WF.wBitsPerSample div 8;
|
||||
if FOpened = 0 then
|
||||
begin
|
||||
waveInOpen(@_audio_fd, FBaseChannel, @WF, DWORD(@WaveInProc), DWORD(Self), CALLBACK_FUNCTION or WAVE_MAPPED);
|
||||
end;
|
||||
Inc(FOpened);
|
||||
end;
|
||||
|
||||
procedure TStdAudioIn.CloseAudio;
|
||||
begin
|
||||
if FOpened = 1 then
|
||||
begin
|
||||
waveInClose(_audio_fd);
|
||||
FreeMem(FBuffer);
|
||||
end;
|
||||
if FOpened > 0 then Dec(FOpened);
|
||||
end;
|
||||
|
||||
function TStdAudioIn.GetBPS : Integer;
|
||||
begin
|
||||
Result := FBPS;
|
||||
end;
|
||||
|
||||
function TStdAudioIn.GetCh : Integer;
|
||||
begin
|
||||
Result := FChan;
|
||||
end;
|
||||
|
||||
function TStdAudioIn.GetSR : Integer;
|
||||
begin
|
||||
Result := FFreq;
|
||||
end;
|
||||
|
||||
procedure TStdAudioIn.Init;
|
||||
begin
|
||||
if Busy then raise EACSException.Create(strBusy);
|
||||
BufEnd := 0;
|
||||
BufStart := 1;
|
||||
FPosition := 0;
|
||||
FRecBytes := FRecTime * (GetBPS div 8) * GetCh * GetSR;
|
||||
FBusy := True;
|
||||
OpenAudio;
|
||||
waveInStart(_audio_fd);
|
||||
BlockChain := nil;
|
||||
FSize := FRecBytes;
|
||||
aBlock := 0;
|
||||
EOC := @BlockChain;
|
||||
end;
|
||||
|
||||
procedure TStdAudioIn.Flush;
|
||||
var
|
||||
Tmp : PWaveHdr;
|
||||
begin
|
||||
while aBlock > 0 do; // wait until pending data blocks are put to the chain
|
||||
waveInReset(_audio_fd); // return all pending data blocks
|
||||
sleep(10);
|
||||
Tmp := BlockChain; // clear pending data blocks
|
||||
while Tmp <> nil do
|
||||
begin
|
||||
BlockChain := Tmp.lpNext;
|
||||
waveInUnprepareHeader(_audio_fd, Tmp, SizeOf(TWaveHdr));
|
||||
FreeMem(Tmp.lpData);
|
||||
Dispose(Tmp);
|
||||
Tmp := BlockChain;
|
||||
end;
|
||||
CloseAudio;
|
||||
FBusy := False;
|
||||
end;
|
||||
|
||||
procedure TStdAudioIn.SetDevice;
|
||||
begin
|
||||
if Busy then raise EACSException.Create(strBusy);
|
||||
if Ch < InputChannelsCount then FBaseChannel := Ch
|
||||
else raise EACSException.Create(Format(strChannelnotavailable,[Ch]));
|
||||
end;
|
||||
|
||||
function TStdAudioIn.GetData(Buffer : Pointer; oBufferSize : Integer): Integer;
|
||||
var
|
||||
Tmp : PWaveHdr;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create(strStreamnotopen);
|
||||
if FRecBytes >= 0 then
|
||||
if (FPosition >= FRecBytes) then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
while aBlock < FBlocksCount do
|
||||
NewBlock;
|
||||
if BufStart > BufEnd then
|
||||
begin
|
||||
BufStart := 1;
|
||||
while BlockChain = nil do
|
||||
sleep(10);
|
||||
TMP := BlockChain;
|
||||
BlockChain := BlockChain.lpNext;
|
||||
if BlockChain = nil then
|
||||
EOC := @BlockChain;
|
||||
Move(Tmp.lpData[0], FBuffer[1], Tmp.dwBytesRecorded);
|
||||
BufEnd := Tmp.dwBytesRecorded;
|
||||
waveInUnprepareHeader(_audio_fd, Tmp, SizeOf(TWaveHdr));
|
||||
FreeMem(Tmp.lpData);
|
||||
Dispose(Tmp);
|
||||
end;
|
||||
if BufferSize < (BufEnd - BufStart + 1) then
|
||||
Result := BufferSize
|
||||
else
|
||||
Result := BufEnd - BufStart + 1;
|
||||
Move(FBuffer[BufStart], Buffer^, Result);
|
||||
Inc(BufStart, Result);
|
||||
Inc(FPosition, Result);
|
||||
end;
|
||||
|
||||
procedure TStdAudioOut.WriteBlock;
|
||||
var
|
||||
WH : PWaveHdr;
|
||||
begin
|
||||
Inc(aBlock);
|
||||
New(WH);
|
||||
WH.lpData := P;
|
||||
WH.dwBufferLength := Len;
|
||||
WH.dwLoops := 0;
|
||||
WH.dwFlags := 0;
|
||||
waveOutPrepareHeader(_audio_fd, WH, SizeOf(TWaveHdr));
|
||||
waveOutWrite(_audio_fd, WH, SizeOf(TWaveHdr));
|
||||
end;
|
||||
|
||||
procedure TStdAudioIn.NewBlock;
|
||||
var
|
||||
WH : PWaveHdr;
|
||||
begin
|
||||
New(WH);
|
||||
GetMem(WH.lpData, BufferSize div FBlocksCount);
|
||||
WH.dwBufferLength := BufferSize div FBlocksCount;
|
||||
WH.dwFlags := 0;
|
||||
waveInPrepareHeader(_audio_fd, WH, SizeOf(TWaveHdr));
|
||||
waveInAddBuffer(_audio_fd, WH, SizeOf(TWaveHdr));
|
||||
Inc(aBlock);
|
||||
end;
|
||||
|
||||
function CountChannels : Integer;
|
||||
begin
|
||||
OutputChannelsCount := waveOutGetNumDevs;
|
||||
InputChannelsCount := waveInGetNumDevs;
|
||||
end;
|
||||
|
||||
procedure TStdAudioIn.AddBlockToChain(WH : PWaveHdr);
|
||||
begin
|
||||
WH.lpNext := nil;
|
||||
EOC^ := WH;
|
||||
EOC := @WH.lpNext;
|
||||
Dec(aBlock);
|
||||
end;
|
||||
|
||||
20
acs/Src/fileformats/acs_allformats.pas
Normal file
20
acs/Src/fileformats/acs_allformats.pas
Normal file
@@ -0,0 +1,20 @@
|
||||
unit acs_allformats;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
ACS_Vorbis,
|
||||
{$IFDEF MSWINDOWS}
|
||||
ACS_DSFiles,
|
||||
ACS_MAC,
|
||||
{$ELSE}
|
||||
acs_mpeg,
|
||||
{$ENDIF}
|
||||
ACS_FLAC,
|
||||
ACS_LAME,
|
||||
ACS_Wave;
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
||||
|
||||
336
acs/Src/fileformats/acs_dsaudio.pas
Normal file
336
acs/Src/fileformats/acs_dsaudio.pas
Normal file
@@ -0,0 +1,336 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.4.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: acs_dsaudio.pas,v $
|
||||
Revision 1.1 2005/12/19 18:36:38 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.3 2005/11/28 21:57:24 z0m3ie
|
||||
mostly FileOut fixes
|
||||
moved PBuffer to PBuffer8
|
||||
set all to dynamically Buffering
|
||||
|
||||
Revision 1.2 2005/09/13 04:04:50 z0m3ie
|
||||
First release without Components for Fileformats
|
||||
only TFileIn and TFileOut are Visible
|
||||
|
||||
Revision 1.1 2005/09/13 03:13:57 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.4 2005/09/11 18:06:26 z0m3ie
|
||||
first working Version
|
||||
|
||||
Revision 1.3 2005/09/10 08:25:40 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/09/07 21:13:24 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/07 20:53:22 z0m3ie
|
||||
begon to add MPEG and WMA support using DirectX
|
||||
|
||||
}
|
||||
unit acs_dsaudio;
|
||||
|
||||
{$ifdef linux}{$message error 'unit not supported'}{$endif linux}
|
||||
|
||||
{$DEFINE DYNAMIC_LINK_ALL}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
ACS_File,ACS_Classes,DirectShow9,Classes,ActiveX,MMSystem,Windows;
|
||||
|
||||
const
|
||||
BUF_SIZE = $8000; // 32k
|
||||
|
||||
type
|
||||
{ TDSIn }
|
||||
|
||||
TDSIn = class(TACSFileIn)
|
||||
private
|
||||
buf : PBuffer8; // ring buffer
|
||||
FxFormat: TWaveFormatEx;
|
||||
FxAMMultiMediaStream: IAMMultiMediaStream;
|
||||
FxGraphBuilder: IGraphBuilder;
|
||||
FxMediaSeeking: IMediaSeeking;
|
||||
FxMediaControl: IMediaControl;
|
||||
FxAudioMediaStream: IAudioMediaStream;
|
||||
FxMediaStream: IMediaStream;
|
||||
FxAudioStreamSample: IAudioStreamSample;
|
||||
FxAudioData: IAudioData;
|
||||
FxBuffer: Pointer;
|
||||
FxBufferSize: DWord;
|
||||
FDuration,
|
||||
FxPosition,
|
||||
FxSelStart,
|
||||
FxSelLength,
|
||||
FxLastReadingStartTime,
|
||||
FxLastReadingEndTime : Stream_Time;
|
||||
FSeekScale : Integer;
|
||||
function Read(const Buffer; xSize: DWord): DWord;
|
||||
procedure SetPosition( Value: STREAM_TIME );
|
||||
protected
|
||||
procedure OpenFile; override;
|
||||
procedure CloseFile; override;
|
||||
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
function Seek(SampleNum : Integer) : Boolean; override;
|
||||
end;
|
||||
|
||||
const
|
||||
DSUSER_HRESULT = HResult($08000000);
|
||||
DSUSER_INVALIDSIZE = DSUSER_HRESULT + 1;
|
||||
|
||||
function ErrorCheck( Value: HRESULT ): HRESULT; { Check the result of a COM operation }
|
||||
|
||||
implementation
|
||||
|
||||
procedure TDSIn.OpenFile;
|
||||
var
|
||||
v : WideString;
|
||||
begin
|
||||
FValid := True;
|
||||
if FOpened = 0 then
|
||||
begin
|
||||
ErrorCheck( CoCreateInstance( CLSID_AMMultiMediaStream, nil, CLSCTX_INPROC_SERVER,IID_IAMMultiMediaStream, FxAMMultiMediaStream ) );
|
||||
ErrorCheck( FxAMMultiMediaStream.Initialize(STREAMTYPE_READ, AMMSF_NOGRAPHTHREAD, nil) );
|
||||
ErrorCheck( FxAMMultiMediaStream.AddMediaStream(nil, @MSPID_PrimaryAudio, 0, FxMediaStream) );
|
||||
ErrorCheck( FxAMMultiMediaStream.GetMediaStream(MSPID_PrimaryAudio, FxMediaStream) );
|
||||
v := FFileName;
|
||||
ErrorCheck( FxAMMultiMediaStream.OpenFile(PWideChar(v), 0) );
|
||||
ErrorCheck( FxAMMultiMediaStream.GetFilterGraph(FxGraphBuilder) );
|
||||
ErrorCheck( FxGraphBuilder.QueryInterface(IID_IMediaControl, FxMediaControl) );
|
||||
ErrorCheck( FxGraphBuilder.QueryInterface(IID_IMediaSeeking, FxMediaSeeking) );
|
||||
ErrorCheck( FxMediaStream.QueryInterface(IID_IAudioMediaStream, FxAudioMediaStream) );
|
||||
ErrorCheck( FxAudioMediaStream.GetFormat(FxFormat) );
|
||||
ErrorCheck( CoCreateInstance(CLSID_AMAudioData, nil, CLSCTX_INPROC_SERVER,IID_IAudioData, FxAudioData) );
|
||||
ErrorCheck( FxAudioData.SetFormat(FxFormat) );
|
||||
ErrorCheck( FxAudioMediaStream.CreateSample(FxAudioData, 0, FxAudioStreamSample) );
|
||||
ErrorCheck( FxAMMultiMediaStream.GetDuration(FDuration) );
|
||||
ErrorCheck( FxAMMultiMediaStream.SetState( STREAMSTATE_RUN ) );
|
||||
FxSelLength := 0;
|
||||
FSR := FxFormat.nSamplesPerSec;
|
||||
FBPS := FxFormat.wBitsPerSample;
|
||||
FChan := FxFormat.nChannels;
|
||||
FTotalSamples := FSize;
|
||||
FSeekable := TRUE;
|
||||
FSize := (FDuration div 10000000) *
|
||||
FxFormat.nSamplesPerSec *
|
||||
FxFormat.nChannels *
|
||||
FxFormat.wBitsPerSample div 8;
|
||||
FSeekScale := FDuration div FSize;
|
||||
end;
|
||||
Inc(FOpened);
|
||||
end;
|
||||
|
||||
procedure TDSIn.CloseFile;
|
||||
begin
|
||||
if FOpened = 1 then
|
||||
begin
|
||||
if Assigned(FxAMMultiMediaStream) then
|
||||
ErrorCheck( FxAMMultiMediaStream.SetState( STREAMSTATE_STOP ) );
|
||||
FxAudioStreamSample := nil;
|
||||
FxAudioData := nil;
|
||||
FxAudioMediaStream := nil;
|
||||
FxMediaStream := nil;
|
||||
FxMediaSeeking := nil;
|
||||
FxMediaControl := nil;
|
||||
FxGraphBuilder := nil;
|
||||
FxAMMultiMediaStream := nil;
|
||||
end;
|
||||
if FOpened > 0 then Dec(FOpened);
|
||||
end;
|
||||
|
||||
function TDSIn.GetData(Buffer: Pointer; BufferSize: Integer): Integer;
|
||||
var
|
||||
nDone : Integer;
|
||||
nOffs : Integer;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create('The Stream is not opened');
|
||||
if BufStart > BufEnd then
|
||||
begin
|
||||
if FOffset <> 0 then
|
||||
begin
|
||||
FPosition := FOffset;
|
||||
if FPosition < 0 then
|
||||
FPosition := 0
|
||||
else if FPosition > FSize then
|
||||
FPosition := FSize;
|
||||
SetPosition(Int64(FPosition) * FSeekScale);
|
||||
FOffset := 0;
|
||||
end;
|
||||
BufStart := 1;
|
||||
nDone := Read(Buf^, BUF_SIZE);
|
||||
if nDone = 0 then
|
||||
begin
|
||||
if FLoop then
|
||||
begin
|
||||
SetPosition(0); // just rewind
|
||||
nDone := Read(Buf^, BUF_SIZE);
|
||||
end else
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
BufEnd := nDone;
|
||||
end;
|
||||
|
||||
if BufferSize < (BufEnd - BufStart + 1) then
|
||||
Result := BufferSize
|
||||
else
|
||||
Result := BufEnd - BufStart + 1;
|
||||
|
||||
Move(Buf^[BufStart], Buffer^, Result);
|
||||
Inc(BufStart, Result);
|
||||
Inc(FPosition, Result);
|
||||
end;
|
||||
|
||||
constructor TDSIn.Create(AOwner: TComponent);
|
||||
var
|
||||
AMovie: IGraphBuilder;
|
||||
begin
|
||||
QzInitialize(nil);
|
||||
ErrorCheck(CoCreateInstance( CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER,IID_IGraphBuilder, AMovie));
|
||||
inherited Create(AOwner);
|
||||
end;
|
||||
|
||||
destructor TDSIn.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TDSIn.Init;
|
||||
begin
|
||||
inherited Init;
|
||||
GetMem(Buf, BUF_SIZE);
|
||||
end;
|
||||
|
||||
procedure TDSIn.Flush;
|
||||
begin
|
||||
FreeMem(Buf);
|
||||
inherited Flush;
|
||||
end;
|
||||
|
||||
function TDSIn.Seek(SampleNum: Integer): Boolean;
|
||||
begin
|
||||
FOffset := SampleNum;
|
||||
end;
|
||||
|
||||
function TDSIn.Read(const Buffer; xSize: DWord): DWord;
|
||||
var
|
||||
hr : DWord;
|
||||
Tmp: STREAM_TIME;
|
||||
begin
|
||||
Result := 0;
|
||||
if (xSize <= 0) then ErrorCheck(DSUSER_INVALIDSIZE);
|
||||
if (FxSelLength <> 0) and (FxPosition >= FxSelStart + FxSelLength) then exit;
|
||||
if (@Buffer <> FxBuffer) or (xSize <> FxBufferSize) then
|
||||
begin
|
||||
FxBuffer := @Buffer;
|
||||
FxBufferSize := xSize;
|
||||
ErrorCheck( FxAudioData.SetBuffer( FxBufferSize, FxBuffer, 0 ) );
|
||||
end;
|
||||
hr := FxAudioStreamSample.Update(0, 0, nil, 0);
|
||||
if (hr = MS_S_ENDOFSTREAM) or (hr = MS_E_NOSTREAM) then exit;
|
||||
ErrorCheck(hr);
|
||||
ErrorCheck( FxAudioData.GetInfo(FxBufferSize, FxBuffer, Result) );
|
||||
ErrorCheck( FxAudioStreamSample.GetSampleTimes( FxLastReadingStartTime,FxLastReadingEndTime, Tmp ) );
|
||||
if FxLastReadingStartTime > FxLastReadingEndTime then
|
||||
FxLastReadingStartTime := FxLastReadingEndTime;
|
||||
if (FxSelLength <> 0) and (FxLastReadingEndTime > FxLastReadingStartTime) and
|
||||
(FxSelStart + FxSelLength < FxLastReadingEndTime) then
|
||||
begin
|
||||
Result := DWord(Trunc(((Result *
|
||||
(FxSelStart + FxSelLength - FxLastReadingStartTime)) /
|
||||
(FxLastReadingEndTime - FxLastReadingStartTime)))) and
|
||||
(not(FxFormat.nBlockAlign-1));
|
||||
FxLastReadingEndTime := FxSelStart + FxSelLength;
|
||||
end;
|
||||
FxPosition := FxLastReadingEndTime;
|
||||
end;
|
||||
|
||||
procedure TDSIn.SetPosition( Value: STREAM_TIME );
|
||||
var pfs: TFilterState;
|
||||
begin
|
||||
if (Value <> FxPosition) then
|
||||
begin
|
||||
if (Value < FxSelStart) then
|
||||
Value := FxSelStart
|
||||
else
|
||||
if (Value > FDuration) then
|
||||
Value := FDuration
|
||||
else
|
||||
if (FxSelLength <> 0) and (Value > FxSelStart + FxSelLength) then
|
||||
Value := FxSelStart + FxSelLength;
|
||||
ErrorCheck(FxMediaControl.StopWhenReady );
|
||||
ErrorCheck(FxMediaSeeking.SetPositions(Value,AM_SEEKING_AbsolutePositioning, Value, AM_SEEKING_NoPositioning));
|
||||
ErrorCheck(FxMediaControl.Run );
|
||||
ErrorCheck(FxMediaControl.GetState(INFINITE, pfs) );
|
||||
FxPosition := Value;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ErrorCheck( Value: HRESULT ): HRESULT; { Check the result of a COM operation }
|
||||
var
|
||||
S: String;
|
||||
S2: array [0..300] of Char;
|
||||
begin
|
||||
Result := Value;
|
||||
if (Value <> S_OK) then
|
||||
begin
|
||||
Case DWord(Value) of
|
||||
DSUSER_INVALIDSIZE: S:='Invalid buffer size.';
|
||||
DWord(REGDB_E_CLASSNOTREG): S:='A specified class is not registered in the registration database.';
|
||||
DWord(CLASS_E_NOAGGREGATION): S:='This class cannot be created as part of an aggregate.';
|
||||
DWord(E_ABORT): S:='The update aborted.';
|
||||
DWOrd(E_INVALIDARG): S:='One of the parameters is invalid.';
|
||||
DWord(E_POINTER): S:='This method tried to access an invalid pointer.';
|
||||
DWord(E_NOINTERFACE): S:='No interface.';
|
||||
MS_S_PENDING: S:='The asynchronous update is pending.';
|
||||
MS_S_NOUPDATE: S:='Sample was not updated after forced completion.';
|
||||
MS_S_ENDOFSTREAM: S:='Reached the end of the stream; the sample wasn''t updated.';
|
||||
MS_E_SAMPLEALLOC: S:='An IMediaStream object could not be removed from an IMultiMediaStream object because it still contains at least one allocated sample.';
|
||||
MS_E_PURPOSEID: S:='The specified purpose ID can''t be used for the call.';
|
||||
MS_E_NOSTREAM: S:='No stream can be found with the specified attributes.';
|
||||
MS_E_NOSEEKING: S:='One or more media streams don''t support seeking.';
|
||||
MS_E_INCOMPATIBLE: S:='The stream formats are not compatible.';
|
||||
MS_E_BUSY: S:='This sample already has a pending update.';
|
||||
MS_E_NOTINIT: S:='The object can''t accept the call because its initialize function or equivalent has not been called.';
|
||||
MS_E_SOURCEALREADYDEFINED: S:='Source already defined.';
|
||||
MS_E_INVALIDSTREAMTYPE: S:='The stream type is not valid for this operation.';
|
||||
MS_E_NOTRUNNING: S:='The IMultiMediaStream object is not in running state.';
|
||||
Else
|
||||
begin
|
||||
if AMGetErrorText( Value, s2, High(s2) ) = 0 then
|
||||
S:='Unrecognized error value.'
|
||||
else
|
||||
S:=String( s2 );
|
||||
end;
|
||||
end;
|
||||
raise EACSException.Create(S);
|
||||
end;
|
||||
end ;
|
||||
|
||||
initialization
|
||||
FileFormats.Add('mp3','Mpeg Audio Layer III',TDSIn);
|
||||
FileFormats.Add('mp2','Mpeg Audio Layer II',TDSIn);
|
||||
FileFormats.Add('mpeg','Mpeg Audio',TDSIn);
|
||||
FileFormats.Add('wma','Windows Media Audio',TDSIn);
|
||||
|
||||
end.
|
||||
|
||||
362
acs/Src/fileformats/acs_dsfiles.pas
Normal file
362
acs/Src/fileformats/acs_dsfiles.pas
Normal file
@@ -0,0 +1,362 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.4.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: acs_dsfiles.pas,v $
|
||||
Revision 1.17 2006/09/04 14:40:16 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.16 2006/08/31 20:10:56 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.15 2006/08/03 17:31:35 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.14 2006/07/09 16:40:35 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.13 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.9 2006/01/01 18:46:40 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.8 2005/12/26 17:31:39 z0m3ie
|
||||
fixed some problems in acs_dsfiles
|
||||
fixed some problems in acs_vorbis
|
||||
reworked all buffers
|
||||
|
||||
Revision 1.7 2005/12/19 18:36:38 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.5 2005/12/18 17:01:54 z0m3ie
|
||||
delphi compatibility
|
||||
|
||||
Revision 1.4 2005/12/04 16:54:34 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.3 2005/11/29 18:32:51 z0m3ie
|
||||
bugfixes for win32 version
|
||||
|
||||
Revision 1.2 2005/11/28 21:57:24 z0m3ie
|
||||
mostly FileOut fixes
|
||||
moved PBuffer to PBuffer8
|
||||
set all to dynamically Buffering
|
||||
|
||||
Revision 1.1 2005/09/23 14:04:58 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/09/13 04:04:50 z0m3ie
|
||||
First release without Components for Fileformats
|
||||
only TFileIn and TFileOut are Visible
|
||||
|
||||
Revision 1.1 2005/09/13 03:13:57 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.4 2005/09/11 18:06:26 z0m3ie
|
||||
first working Version
|
||||
|
||||
Revision 1.3 2005/09/10 08:25:40 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/09/07 21:13:24 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/07 20:53:22 z0m3ie
|
||||
begon to add MPEG and WMA support using DirectX
|
||||
|
||||
}
|
||||
unit acs_dsfiles;
|
||||
|
||||
{$ifdef linux}{$message error 'unit not supported'}{$endif linux}
|
||||
|
||||
{$DEFINE DYNAMIC_LINK_ALL}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
ACS_File,ACS_Classes,DirectShow9,Classes,ActiveX,MMSystem,Windows,ACS_Types;
|
||||
|
||||
type
|
||||
{ TDSIn }
|
||||
|
||||
TDSIn = class(TACSCustomFileIn)
|
||||
private
|
||||
{$ifdef fpc}
|
||||
FxFormat: _WAVEFORMATEX;
|
||||
{$else}
|
||||
FxFormat: TWaveFormatEx;
|
||||
{$endif}
|
||||
FxAMMultiMediaStream: IAMMultiMediaStream;
|
||||
FxGraphBuilder: IGraphBuilder;
|
||||
FxMediaSeeking: IMediaSeeking;
|
||||
FxMediaControl: IMediaControl;
|
||||
FxAudioMediaStream: IAudioMediaStream;
|
||||
FxMediaStream: IMediaStream;
|
||||
FxAudioStreamSample: IAudioStreamSample;
|
||||
FxAudioData: IAudioData;
|
||||
FxBuffer: Pointer;
|
||||
FxBufferSize: DWord;
|
||||
FDuration,
|
||||
FxPosition,
|
||||
FxSelStart,
|
||||
FxSelLength,
|
||||
FxLastReadingStartTime,
|
||||
FxLastReadingEndTime : Stream_Time;
|
||||
FSeekScale : Integer;
|
||||
function Read(Buffer : Pointer; xSize: DWord): DWord;
|
||||
procedure SetPosition( Value: STREAM_TIME );
|
||||
protected
|
||||
procedure OpenFile; override;
|
||||
procedure CloseFile; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
function Seek(SampleNum : Integer) : Boolean; override;
|
||||
end;
|
||||
|
||||
const
|
||||
DSUSER_HRESULT = HResult($08000000);
|
||||
DSUSER_INVALIDSIZE = DSUSER_HRESULT + 1;
|
||||
|
||||
function ErrorCheck( Value: HRESULT ): HRESULT; { Check the result of a COM operation }
|
||||
|
||||
implementation
|
||||
|
||||
procedure TDSIn.OpenFile;
|
||||
var
|
||||
v : WideString;
|
||||
begin
|
||||
FValid := True;
|
||||
if FOpened = 0 then
|
||||
begin
|
||||
QzInitialize(nil);
|
||||
ErrorCheck( CoCreateInstance( CLSID_AMMultiMediaStream, nil, CLSCTX_INPROC_SERVER,IID_IAMMultiMediaStream, FxAMMultiMediaStream ) );
|
||||
ErrorCheck( FxAMMultiMediaStream.Initialize(STREAMTYPE_READ, AMMSF_NOGRAPHTHREAD, nil) );
|
||||
ErrorCheck( FxAMMultiMediaStream.AddMediaStream(nil, @MSPID_PrimaryAudio, 0, FxMediaStream) );
|
||||
ErrorCheck( FxAMMultiMediaStream.GetMediaStream(MSPID_PrimaryAudio, FxMediaStream) );
|
||||
v := FFileName;
|
||||
ErrorCheck( FxAMMultiMediaStream.OpenFile(PWideChar(v), 0) );
|
||||
ErrorCheck( FxAMMultiMediaStream.GetFilterGraph(FxGraphBuilder) );
|
||||
ErrorCheck( FxGraphBuilder.QueryInterface(IID_IMediaControl, FxMediaControl) );
|
||||
ErrorCheck( FxGraphBuilder.QueryInterface(IID_IMediaSeeking, FxMediaSeeking) );
|
||||
ErrorCheck( FxMediaStream.QueryInterface(IID_IAudioMediaStream, FxAudioMediaStream) );
|
||||
ErrorCheck( FxAudioMediaStream.GetFormat(FxFormat) );
|
||||
ErrorCheck( CoCreateInstance(CLSID_AMAudioData, nil, CLSCTX_INPROC_SERVER,IID_IAudioData, FxAudioData) );
|
||||
ErrorCheck( FxAudioData.SetFormat(FxFormat) );
|
||||
ErrorCheck( FxAudioMediaStream.CreateSample(FxAudioData, 0, FxAudioStreamSample) );
|
||||
ErrorCheck( FxAMMultiMediaStream.GetDuration(FDuration) );
|
||||
ErrorCheck( FxAMMultiMediaStream.SetState( STREAMSTATE_RUN ) );
|
||||
FxSelLength := 0;
|
||||
FSR := FxFormat.nSamplesPerSec;
|
||||
FBPS := FxFormat.wBitsPerSample;
|
||||
FChan := FxFormat.nChannels;
|
||||
FTotalSamples := FSize;
|
||||
FSeekable := TRUE;
|
||||
if fDuration = 0 then exit;
|
||||
FSize :=(FDuration div 10000000) *
|
||||
FSR *
|
||||
FChan *
|
||||
FBPS div 8;
|
||||
FSeekScale := FDuration div FSize;
|
||||
end;
|
||||
Inc(FOpened);
|
||||
end;
|
||||
|
||||
procedure TDSIn.CloseFile;
|
||||
begin
|
||||
if FOpened = 1 then
|
||||
begin
|
||||
if Assigned(FxAMMultiMediaStream) then
|
||||
ErrorCheck( FxAMMultiMediaStream.SetState( STREAMSTATE_STOP ) );
|
||||
FxAudioStreamSample := nil;
|
||||
FxAudioData := nil;
|
||||
FxAudioMediaStream := nil;
|
||||
FxMediaStream := nil;
|
||||
FxMediaSeeking := nil;
|
||||
FxMediaControl := nil;
|
||||
FxGraphBuilder := nil;
|
||||
FxAMMultiMediaStream := nil;
|
||||
end;
|
||||
if FOpened > 0 then Dec(FOpened);
|
||||
end;
|
||||
|
||||
function TDSIn.GetData(Buffer: Pointer; BufferSize: Integer): Integer;
|
||||
var
|
||||
nDone : Integer;
|
||||
nOffs : Integer;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create('The Stream is not opened');
|
||||
if BufStart > BufEnd then
|
||||
begin
|
||||
if FOffset <> 0 then
|
||||
begin
|
||||
FPosition := FPosition+Round((FOffset/100)*FSize);
|
||||
if FPosition < 0 then
|
||||
FPosition := 0
|
||||
else if FPosition > FSize then
|
||||
FPosition := FSize;
|
||||
SetPosition(Int64(FPosition) * FSeekScale);
|
||||
FOffset := 0;
|
||||
end;
|
||||
BufStart := 1;
|
||||
nDone := Read(FBuffer, BufferSize);
|
||||
if nDone = 0 then
|
||||
begin
|
||||
if FLoop then
|
||||
begin
|
||||
SetPosition(0); // just rewind
|
||||
nDone := Read(FBuffer, BufferSize);
|
||||
end else
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
BufEnd := nDone;
|
||||
end;
|
||||
|
||||
if BufferSize < (BufEnd - BufStart + 1) then
|
||||
Result := BufferSize
|
||||
else
|
||||
Result := BufEnd - BufStart + 1;
|
||||
|
||||
Move(FBuffer[BufStart-1], Buffer^, Result);
|
||||
Inc(BufStart, Result);
|
||||
Inc(FPosition, Result);
|
||||
end;
|
||||
|
||||
constructor TDSIn.Create(AOwner: TComponent);
|
||||
var
|
||||
AMovie: IGraphBuilder;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
BufferSize := $8000;
|
||||
QzInitialize(nil);
|
||||
ErrorCheck(CoCreateInstance( CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER,IID_IGraphBuilder, AMovie));
|
||||
end;
|
||||
|
||||
destructor TDSIn.Destroy;
|
||||
begin
|
||||
QzUninitialize;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TDSIn.Seek(SampleNum : Integer): Boolean;
|
||||
begin
|
||||
FPosition := SampleNum;
|
||||
end;
|
||||
|
||||
function TDSIn.Read(Buffer : Pointer; xSize: DWord): DWord;
|
||||
var
|
||||
hr : DWord;
|
||||
Tmp: STREAM_TIME;
|
||||
begin
|
||||
Result := 0;
|
||||
if (xSize <= 0) then
|
||||
ErrorCheck(DSUSER_INVALIDSIZE);
|
||||
if (FxSelLength <> 0) and (FxPosition >= FxSelStart + FxSelLength) then
|
||||
exit;
|
||||
if (Buffer <> FxBuffer) or (xSize <> FxBufferSize) then
|
||||
begin
|
||||
FxBuffer := Buffer;
|
||||
FxBufferSize := xSize;
|
||||
ErrorCheck( FxAudioData.SetBuffer( FxBufferSize, FxBuffer, 0 ) );
|
||||
end;
|
||||
hr := FxAudioStreamSample.Update(0, 0, nil, 0);
|
||||
if (hr = MS_S_ENDOFSTREAM) or (hr = MS_E_NOSTREAM) then exit;
|
||||
ErrorCheck(hr);
|
||||
ErrorCheck( FxAudioData.GetInfo(FxBufferSize, FxBuffer, Result) );
|
||||
ErrorCheck( FxAudioStreamSample.GetSampleTimes( FxLastReadingStartTime,FxLastReadingEndTime, Tmp ) );
|
||||
if FxLastReadingStartTime > FxLastReadingEndTime then
|
||||
FxLastReadingStartTime := FxLastReadingEndTime;
|
||||
if (FxSelLength <> 0) and (FxLastReadingEndTime > FxLastReadingStartTime) and
|
||||
(FxSelStart + FxSelLength < FxLastReadingEndTime) then
|
||||
begin
|
||||
Result := DWord(Trunc(((Result *
|
||||
(FxSelStart + FxSelLength - FxLastReadingStartTime)) /
|
||||
(FxLastReadingEndTime - FxLastReadingStartTime)))) and
|
||||
(not(FxFormat.nBlockAlign-1));
|
||||
FxLastReadingEndTime := FxSelStart + FxSelLength;
|
||||
end;
|
||||
FxPosition := FxLastReadingEndTime;
|
||||
end;
|
||||
|
||||
procedure TDSIn.SetPosition( Value: STREAM_TIME );
|
||||
var pfs: TFilterState;
|
||||
begin
|
||||
if (Value <> FxPosition) then
|
||||
begin
|
||||
if (Value < FxSelStart) then
|
||||
Value := FxSelStart
|
||||
else
|
||||
if (Value > FDuration) then
|
||||
Value := FDuration
|
||||
else
|
||||
if (FxSelLength <> 0) and (Value > FxSelStart + FxSelLength) then
|
||||
Value := FxSelStart + FxSelLength;
|
||||
ErrorCheck(FxMediaControl.StopWhenReady );
|
||||
ErrorCheck(FxMediaSeeking.SetPositions(Value,AM_SEEKING_AbsolutePositioning, Value, AM_SEEKING_NoPositioning));
|
||||
ErrorCheck(FxMediaControl.Run );
|
||||
ErrorCheck(FxMediaControl.GetState(INFINITE, pfs) );
|
||||
FxPosition := Value;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ErrorCheck( Value: HRESULT ): HRESULT; { Check the result of a COM operation }
|
||||
var
|
||||
S: String;
|
||||
S2: array [0..300] of Char;
|
||||
begin
|
||||
Result := Value;
|
||||
if (Value <> S_OK) then
|
||||
begin
|
||||
Case DWord(Value) of
|
||||
DSUSER_INVALIDSIZE: S:='Invalid buffer size.';
|
||||
DWord(REGDB_E_CLASSNOTREG): S:='A specified class is not registered in the registration database.';
|
||||
DWord(CLASS_E_NOAGGREGATION): S:='This class cannot be created as part of an aggregate.';
|
||||
DWord(E_ABORT): S:='The update aborted.';
|
||||
DWOrd(E_INVALIDARG): S:='One of the parameters is invalid.';
|
||||
DWord(E_POINTER): S:='This method tried to access an invalid pointer.';
|
||||
DWord(E_NOINTERFACE): S:='No interface.';
|
||||
MS_S_PENDING: S:='The asynchronous update is pending.';
|
||||
MS_S_NOUPDATE: S:='Sample was not updated after forced completion.';
|
||||
MS_S_ENDOFSTREAM: S:='Reached the end of the stream; the sample wasn''t updated.';
|
||||
MS_E_SAMPLEALLOC: S:='An IMediaStream object could not be removed from an IMultiMediaStream object because it still contains at least one allocated sample.';
|
||||
MS_E_PURPOSEID: S:='The specified purpose ID can''t be used for the call.';
|
||||
MS_E_NOSTREAM: S:='No stream can be found with the specified attributes.';
|
||||
MS_E_NOSEEKING: S:='One or more media streams don''t support seeking.';
|
||||
MS_E_INCOMPATIBLE: S:='The stream formats are not compatible.';
|
||||
MS_E_BUSY: S:='This sample already has a pending update.';
|
||||
MS_E_NOTINIT: S:='The object can''t accept the call because its initialize function or equivalent has not been called.';
|
||||
MS_E_SOURCEALREADYDEFINED: S:='Source already defined.';
|
||||
MS_E_INVALIDSTREAMTYPE: S:='The stream type is not valid for this operation.';
|
||||
MS_E_NOTRUNNING: S:='The IMultiMediaStream object is not in running state.';
|
||||
Else
|
||||
begin
|
||||
if AMGetErrorText( Value, s2, High(s2) ) = 0 then
|
||||
S:='Unrecognized error value.'
|
||||
else
|
||||
S:=String( s2 );
|
||||
end;
|
||||
end;
|
||||
// raise EACSException.Create(S);
|
||||
end;
|
||||
end ;
|
||||
|
||||
initialization
|
||||
FileFormats.Add('mp3','Mpeg Audio Layer III',TDSIn);
|
||||
FileFormats.Add('mp2','Mpeg Audio Layer II',TDSIn);
|
||||
FileFormats.Add('mpeg','Mpeg Audio',TDSIn);
|
||||
FileFormats.Add('wma','Windows Media Audio',TDSIn);
|
||||
|
||||
end.
|
||||
|
||||
595
acs/Src/fileformats/acs_flac.pas
Normal file
595
acs/Src/fileformats/acs_flac.pas
Normal file
@@ -0,0 +1,595 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.3.
|
||||
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: acs_flac.pas,v $
|
||||
Revision 1.7 2006/07/09 16:40:35 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.6 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.2 2005/12/30 11:10:57 z0m3ie
|
||||
some corrections to lazarus-linux depending things
|
||||
|
||||
Revision 1.1 2005/12/19 18:36:38 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.4 2005/12/04 16:54:34 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.3 2005/11/28 21:57:24 z0m3ie
|
||||
mostly FileOut fixes
|
||||
moved PBuffer to PBuffer8
|
||||
set all to dynamically Buffering
|
||||
|
||||
Revision 1.2 2005/09/13 04:04:50 z0m3ie
|
||||
First release without Components for Fileformats
|
||||
only TFileIn and TFileOut are Visible
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
unit acs_flac;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
|
||||
ACS_File,Classes, SysUtils, ACS_Types, ACS_Classes, FLAC,
|
||||
{$IFDEF LINUX}
|
||||
baseunix;
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF WINDOWS}
|
||||
Windows;
|
||||
{$ENDIF}
|
||||
|
||||
type
|
||||
|
||||
TFLACOut = class(TACSCustomFileOut)
|
||||
private
|
||||
_encoder : PFLAC__SeekableStreamEncoder;
|
||||
FBufSize : Integer;
|
||||
FVerify : Boolean;
|
||||
FBlockSize : Word;
|
||||
FBestModelSearch : Boolean;
|
||||
FEnableMidSideStereo : Boolean;
|
||||
FMaxLPCOrder : Word;
|
||||
EndOfInput : Boolean;
|
||||
FEnableLooseMidSideStereo : Boolean;
|
||||
FQLPCoeffPrecision : Word;
|
||||
FQLPCoeffPrecisionSearch : Boolean;
|
||||
FMaxResidualPartitionOrder : Word;
|
||||
FMinResidualPartitionOrder : Word;
|
||||
procedure SetEnableLooseMidSideStereo(val : Boolean);
|
||||
procedure SetBestModelSearch(val : Boolean);
|
||||
protected
|
||||
procedure Done; override;
|
||||
function DoOutput(Abort : Boolean):Boolean; override;
|
||||
procedure Prepare; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
published
|
||||
property BestModelSearch : Boolean read FBestModelSearch write SetBestModelSearch;
|
||||
property BlockSize : Word read FBlockSize write FBlockSize;
|
||||
property EnableMidSideStereo : Boolean read FEnableMidSideStereo write FEnableMidSideStereo;
|
||||
property EnableLooseMidSideStereo : Boolean read FEnableLooseMidSideStereo write SetEnableLooseMidSideStereo;
|
||||
property MaxLPCOrder : Word read FMaxLPCOrder write FMaxLPCOrder;
|
||||
property MaxResidualPartitionOrder : Word read FMaxResidualPartitionOrder write FMaxResidualPartitionOrder;
|
||||
property MinResidualPartitionOrder : Word read FMinResidualPartitionOrder write FMinResidualPartitionOrder;
|
||||
property QLPCoeffPrecision : Word read FQLPCoeffPrecision write FQLPCoeffPrecision;
|
||||
property QLPCoeffPrecisionSearch : Boolean read FQLPCoeffPrecisionSearch write FQLPCoeffPrecisionSearch;
|
||||
property Verify : Boolean read FVerify write FVerify;
|
||||
end;
|
||||
|
||||
TFLACIn = class(TACSCustomFileIn)
|
||||
private
|
||||
Buff : PACSBuffer8;
|
||||
_decoder : PFLAC__SeekableStreamDecoder;
|
||||
FBlockSize: Integer;
|
||||
BytesPerBlock : Integer;
|
||||
EndOfStream : Boolean;
|
||||
MinFrameSize : Integer;
|
||||
protected
|
||||
procedure OpenFile; override;
|
||||
procedure CloseFile; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
function Seek(SampleNum : Integer) : Boolean; override;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
type
|
||||
|
||||
FLACBuf = array[0..0] of FLAC__int32;
|
||||
PFLACBuf = ^FLACBuf;
|
||||
|
||||
function EncWriteCBFunc(encoder : PFLAC__SeekableStreamEncoder;
|
||||
buffer : PFLAC__byte;
|
||||
bytes, samples, current_frame : LongWord;
|
||||
client_data : Pointer) : Integer; cdecl;
|
||||
var
|
||||
FLACOut : TFLACOut;
|
||||
begin
|
||||
FLACOut := TFLACOut(client_data);
|
||||
Result := FLAC__SEEKABLE_STREAM_ENCODER_OK;
|
||||
try
|
||||
FLACOut.FStream.Write(buffer^, bytes);
|
||||
except
|
||||
Result := FLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR;
|
||||
end;
|
||||
end;
|
||||
|
||||
function EncSeekCBFunc(encoder : PFLAC__SeekableStreamEncoder;
|
||||
absolute_byte_offset : FLAC__uint64;
|
||||
client_data : Pointer) : Integer; cdecl;
|
||||
var
|
||||
FLACOut : TFLACOut;
|
||||
begin
|
||||
FLACOut := TFLACOut(client_data);
|
||||
Result := FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK;
|
||||
try
|
||||
FLACOut.FStream.Seek(absolute_byte_offset, soFromBeginning);
|
||||
except
|
||||
Result := FLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR;
|
||||
end;
|
||||
end;
|
||||
|
||||
function DecReadCBFunc(decoder : PFLAC__SeekableStreamDecoder;
|
||||
buffer : PFLAC__byte;
|
||||
var bytes : LongWord;
|
||||
client_data : Pointer) : Integer; cdecl;
|
||||
var
|
||||
FLACIn : TFLACIn;
|
||||
begin
|
||||
FLACIn := TFLACIn(client_data);
|
||||
Result := FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
|
||||
if FLACIn.FStream.Position >= FLACIn.FStream.Size then
|
||||
begin
|
||||
Result := FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
|
||||
Exit;
|
||||
end;
|
||||
try
|
||||
bytes := FLACIn.FStream.Read(buffer^, bytes);
|
||||
except
|
||||
Result := FLAC__SEEKABLE_STREAM_DECODER_READ_ERROR;
|
||||
end;
|
||||
end;
|
||||
|
||||
function DecSeekCBFunc(decoder : PFLAC__SeekableStreamDecoder;
|
||||
absolute_byte_offset : FLAC__uint64;
|
||||
client_data : Pointer) : Integer; cdecl;
|
||||
var
|
||||
FLACIn : TFLACIn;
|
||||
begin
|
||||
FLACIn := TFLACIn(client_data);
|
||||
Result := FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
|
||||
try
|
||||
FLACIn.FStream.Seek(absolute_byte_offset, soFromBeginning);
|
||||
except
|
||||
Result := FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
|
||||
end;
|
||||
end;
|
||||
|
||||
function DecTellCBFunc(decoder : PFLAC__SeekableStreamDecoder;
|
||||
var absolute_byte_offset : FLAC__uint64;
|
||||
client_data : Pointer) : Integer; cdecl;
|
||||
var
|
||||
FLACIn : TFLACIn;
|
||||
begin
|
||||
FLACIn := TFLACIn(client_data);
|
||||
Result := FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
|
||||
try
|
||||
absolute_byte_offset := FLACIn.FStream.Position;
|
||||
except
|
||||
Result := FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
|
||||
end;
|
||||
end;
|
||||
|
||||
function DecLengthCBFunc(decoder : PFLAC__SeekableStreamDecoder;
|
||||
var stream_length : FLAC__uint64;
|
||||
client_data : Pointer) : Integer; cdecl;
|
||||
var
|
||||
FLACIn : TFLACIn;
|
||||
begin
|
||||
FLACIn := TFLACIn(client_data);
|
||||
Result := FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
|
||||
try
|
||||
stream_length := FLACIn.FStream.Size;
|
||||
except
|
||||
Result := FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
|
||||
end;
|
||||
end;
|
||||
|
||||
function DecEOFCBFunc(decoder : PFLAC__SeekableStreamDecoder;
|
||||
client_data : Pointer) : Boolean; cdecl;
|
||||
var
|
||||
FLACIn : TFLACIn;
|
||||
begin
|
||||
FLACIn := TFLACIn(client_data);
|
||||
if FLACIn.FStream.Position >= FLACIn.FStream.Size then Result := True
|
||||
else Result := False;
|
||||
end;
|
||||
|
||||
function DecWriteCBFunc(decoder : PFLAC__SeekableStreamDecoder;
|
||||
frame : PFLAC__Frame;
|
||||
buffer : PFLACChannels;
|
||||
client_data : Pointer) : Integer; cdecl;
|
||||
var
|
||||
FLACIn : TFLACIn;
|
||||
Header : PFLAC__FrameHeader;
|
||||
buffer1 : PFLACIntBuf;
|
||||
buffer2 : PFLACIntBuf;
|
||||
B16 : PACSBuffer16;
|
||||
i : Integer;
|
||||
begin
|
||||
FLACIn := TFLACIn(client_data);
|
||||
Header := PFLAC__FrameHeader(frame);
|
||||
FLACIn.FBlockSize := Header.blocksize;
|
||||
FLACIn.BytesPerBlock := FLACIn.FBlockSize*(FLACIn.FBPS shr 3)*FLACIn.FChan;
|
||||
GetMem(FLACIn.Buff, FLACIn.BytesPerBlock);
|
||||
// FillChar(FLACIn.Buff[0], FLACIn.BytesPerBlock, 255);
|
||||
if FLACIn.FBPS = 16 then
|
||||
begin
|
||||
B16 := PACSBuffer16(FLACIn.Buff);
|
||||
if FLACIn.FChan = 1 then
|
||||
begin
|
||||
buffer1 := buffer[0];
|
||||
for i := 0 to FLACIn.FBlockSize-1 do B16[i] := buffer1[i]
|
||||
end else
|
||||
begin
|
||||
buffer1 := buffer[0];
|
||||
buffer2 := buffer[1];
|
||||
for i := 0 to FLACIn.FBlockSize-1 do
|
||||
begin
|
||||
B16[i shl 1] := buffer1[i];
|
||||
B16[(i shl 1)+1] := buffer2[i];
|
||||
end;
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
if FLACIn.FChan = 1 then
|
||||
begin
|
||||
buffer1 := buffer[0];
|
||||
for i := 0 to FLACIn.FBlockSize-1 do FLACIn.Buff[i] := buffer1[i];
|
||||
end else
|
||||
begin
|
||||
buffer1 := buffer[0];
|
||||
buffer2 := buffer[1];
|
||||
for i := 0 to FLACIn.FBlockSize-1 do
|
||||
begin
|
||||
FLACIn.Buff[i shl 1] := buffer1[i];
|
||||
FLACIn.Buff[(i shl 1)+1] := buffer2[i];
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
Result := FLAC__SEEKABLE_STREAM_ENCODER_OK;
|
||||
end;
|
||||
|
||||
procedure DecMetadataCBProc(decoder : PFLAC__SeekableStreamDecoder;
|
||||
metadata : PFLAC__StreamMetadata;
|
||||
client_data : Pointer); cdecl;
|
||||
var
|
||||
FLACIn : TFLACIn;
|
||||
P : Pointer;
|
||||
FI : PFLACInfo;
|
||||
begin
|
||||
if LongWord(metadata^) <> 0 then Exit;
|
||||
P := metadata;
|
||||
(*
|
||||
STREAMINFO block format differs in different
|
||||
FLAC codec versions, so we are trying to be flexible here.
|
||||
*)
|
||||
while LongWord(P^) = 0 do Inc(P, 4);
|
||||
Inc(P, 4);
|
||||
if LongWord(P^) = 0 then Inc(P, 4);
|
||||
FI := PFLACInfo(P);
|
||||
FLACIn := TFLACIn(client_data);
|
||||
FLACIn.FSR := FI.sample_rate;
|
||||
FLACIn.FChan := FI.channels;
|
||||
if FLACIn.FChan > 2 then FLACIn.FValid := False;
|
||||
FLACIn.FBPS := FI.bits_per_sample;
|
||||
if FLACIn.FChan > 16 then FLACIn.FValid := False;
|
||||
FLACIn.FTotalSamples := FI.total_samples1;
|
||||
if FLACIn.FTotalSamples = 0 then
|
||||
FLACIn.FTotalSamples := FI.total_samples2;
|
||||
FLACIn.FSize := FLACIn.FTotalSamples*(FLACIn.FBPS shr 3)*FLACIn.FChan;
|
||||
FLACIn.MinFrameSize := FI.min_framesize;
|
||||
end;
|
||||
|
||||
procedure DecErrorCBProc(decoder : PFLAC__SeekableStreamDecoder;
|
||||
status : Integer;
|
||||
client_data : Pointer); cdecl;
|
||||
var
|
||||
FLACIn : TFLACIn;
|
||||
begin
|
||||
FLACIn := TFLACIn(client_data);
|
||||
FLACIn.FValid := False;
|
||||
end;
|
||||
|
||||
constructor TFLACOut.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FVerify := False;
|
||||
FBufferSize := $6000;
|
||||
FBlockSize := 4608;
|
||||
FBestModelSearch := False;
|
||||
FEnableMidSideStereo := True;
|
||||
if not (csDesigning in ComponentState) then
|
||||
if not LibFLACLoaded then
|
||||
raise EACSException.Create(LibFLACPath + ' library could not be loaded.');
|
||||
end;
|
||||
|
||||
destructor TFLACOut.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TFLACOut.Prepare;
|
||||
begin
|
||||
if not FStreamAssigned then
|
||||
begin
|
||||
if FFileName = '' then raise EACSException.Create('File name is not assigned.');
|
||||
if (not FileExists(FFileName)) or (FFileMode = foRewrite) then
|
||||
FStream := TFileStream.Create(FFileName, fmCreate or fmShareExclusive, FAccessMask)
|
||||
else FStream := TFileStream.Create(FFileName, fmOpenReadWrite or fmShareExclusive, FAccessMask);
|
||||
end;
|
||||
EndOfInput := False;
|
||||
_encoder := FLAC__seekable_stream_encoder_new;
|
||||
if _encoder = nil then
|
||||
raise EACSException.Create('Failed to initialize FLAC encoder.');
|
||||
FInput.Init;
|
||||
FLAC__seekable_stream_encoder_set_verify(_encoder, FVerify);
|
||||
FLAC__seekable_stream_encoder_set_channels(_encoder, FInput.Channels);
|
||||
FLAC__seekable_stream_encoder_set_bits_per_sample(_encoder, FInput.BitsPerSample);
|
||||
FLAC__seekable_stream_encoder_set_sample_rate(_encoder, FInput.SampleRate);
|
||||
if FInput.Channels = 2 then
|
||||
begin
|
||||
FLAC__seekable_stream_encoder_set_do_mid_side_stereo(_encoder, FEnableMidSideStereo);
|
||||
FLAC__seekable_stream_encoder_set_loose_mid_side_stereo(_encoder, FEnableLooseMidSideStereo);
|
||||
end;
|
||||
FLAC__seekable_stream_encoder_set_blocksize(_encoder, FBlockSize);
|
||||
FLAC__seekable_stream_encoder_set_max_lpc_order(_encoder, FMaxLPCOrder);
|
||||
if FQLPCoeffPrecision + FInput.BitsPerSample > 31 then FQLPCoeffPrecision := 31 - FInput.BitsPerSample;
|
||||
FLAC__seekable_stream_encoder_set_qlp_coeff_precision(_encoder, FQLPCoeffPrecision);
|
||||
FLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search(_encoder, FQLPCoeffPrecisionSearch);
|
||||
FLAC__seekable_stream_encoder_set_min_residual_partition_order(_encoder, FMinResidualPartitionOrder);
|
||||
FLAC__seekable_stream_encoder_set_max_residual_partition_order(_encoder, FMaxResidualPartitionOrder);
|
||||
FLAC__seekable_stream_encoder_set_do_exhaustive_model_search(_encoder, FBestModelSearch);
|
||||
if FInput.Size > 0 then
|
||||
FLAC__seekable_stream_encoder_set_total_samples_estimate(_encoder, Round(FInput.Size/(FInput.BitsPerSample shr 3)/FInput.Channels));
|
||||
FLAC__seekable_stream_encoder_set_seek_callback(_encoder, EncSeekCBFunc);
|
||||
FLAC__seekable_stream_encoder_set_write_callback(_encoder, EncWriteCBFunc);
|
||||
FLAC__seekable_stream_encoder_set_client_data(_encoder, Self);
|
||||
if FLAC__seekable_stream_encoder_init(_encoder) <>
|
||||
FLAC__SEEKABLE_STREAM_ENCODER_OK then
|
||||
begin
|
||||
FInput.Flush;
|
||||
raise EACSException.Create('Failed to initialize FLAC encoder.');
|
||||
end;
|
||||
//TODO: Recreate this stuff with uffersize more equal to FBufferSize
|
||||
FBufSize := FBufferSize div FBlockSize;
|
||||
FBufSize := FBufSize * (FInput.BitsPerSample shr 3) * FInput.Channels;
|
||||
GetMem(FBuffer, FBufSize);
|
||||
end;
|
||||
|
||||
procedure TFLACOut.Done;
|
||||
begin
|
||||
if not FStreamAssigned then
|
||||
FLAC__seekable_stream_encoder_finish(_encoder);
|
||||
FLAC__seekable_stream_encoder_delete(_encoder);
|
||||
if FBuffer <> nil then
|
||||
FreeMem(FBuffer);
|
||||
FBuffer := nil;
|
||||
FStream.Free;
|
||||
FInput.Flush;
|
||||
end;
|
||||
|
||||
function TFLACOut.DoOutput(Abort : Boolean):Boolean;
|
||||
var
|
||||
Len, i, l, samples : Integer;
|
||||
FB : PFLACBuf;
|
||||
B16 : PACSBuffer16;
|
||||
begin
|
||||
Result := True;
|
||||
if not CanOutput then Exit;
|
||||
if Abort or EndOfInput then
|
||||
begin
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
while InputLock do;
|
||||
InputLock := True;
|
||||
Len := 0;
|
||||
while Len < FBufSize do
|
||||
begin
|
||||
l := Finput.GetData(@FBuffer[Len], FBufSize-Len);
|
||||
Inc(Len, l);
|
||||
if l = 0 then
|
||||
begin
|
||||
EndOfInput := True;
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
InputLock := False;
|
||||
if Len = 0 then
|
||||
begin
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
samples := (Len shl 3) div Finput.BitsPerSample;
|
||||
GetMem(FB, samples*SizeOF(FLAC__int32));
|
||||
if FInput.BitsPerSample = 16 then
|
||||
begin
|
||||
B16 := @FBuffer[0];
|
||||
for i := 0 to samples - 1 do FB[i] := B16[i];
|
||||
end else
|
||||
for i := 0 to samples - 1 do FB[i] := FBuffer[i];
|
||||
if not FLAC__seekable_stream_encoder_process_interleaved(_encoder, @FB[0], samples div FInput.Channels) then
|
||||
raise EACSException.Create('Failed to encode data.');
|
||||
FreeMem(FB);
|
||||
end;
|
||||
|
||||
procedure TFLACOut.SetEnableLooseMidSideStereo;
|
||||
begin
|
||||
if Val then FEnableMidSideStereo := True;
|
||||
FEnableLooseMidSideStereo := Val;
|
||||
end;
|
||||
|
||||
procedure TFLACOut.SetBestModelSearch;
|
||||
begin
|
||||
if Val then
|
||||
begin
|
||||
FEnableMidSideStereo := True;
|
||||
FEnableLooseMidSideStereo := False;
|
||||
end;
|
||||
FBestModelSearch := Val;
|
||||
end;
|
||||
|
||||
constructor TFLACIn.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
if not (csDesigning in ComponentState) then
|
||||
if not LibFLACLoaded then
|
||||
raise EACSException.Create(LibFLACPath + ' library could not be loaded.');
|
||||
end;
|
||||
|
||||
destructor TFLACIn.Destroy;
|
||||
begin
|
||||
CloseFile;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TFLACIn.OpenFile;
|
||||
begin
|
||||
Inc(FOpened);
|
||||
if FOpened = 1 then
|
||||
begin
|
||||
if (not FStreamAssigned) and (FFileName = '') then
|
||||
raise EACSException.Create('File name is not assigned');
|
||||
if not FStreamAssigned then FStream := TFileStream.Create(FFileName, fmOpenRead, fmShareDenyNone);
|
||||
FValid := True;
|
||||
_decoder := FLAC__seekable_stream_decoder_new;
|
||||
if _decoder = nil then
|
||||
raise EACSException.Create('Failed to initialize FLAC decoder.');
|
||||
// FLAC__seekable_stream_decoder_set_metadata_ignore_all(_decoder);
|
||||
FLAC__seekable_stream_decoder_set_read_callback(_decoder, DecReadCBFunc);
|
||||
FLAC__seekable_stream_decoder_set_seek_callback(_decoder, DecSeekCBFunc);
|
||||
FLAC__seekable_stream_decoder_set_tell_callback(_decoder, DecTellCBFunc);
|
||||
FLAC__seekable_stream_decoder_set_length_callback(_decoder, DecLengthCBFunc);
|
||||
FLAC__seekable_stream_decoder_set_eof_callback(_decoder, DecEOFCBFunc);
|
||||
FLAC__seekable_stream_decoder_set_write_callback(_decoder, DecWriteCBFunc);
|
||||
FLAC__seekable_stream_decoder_set_metadata_callback(_decoder, DecMetadataCBProc);
|
||||
FLAC__seekable_stream_decoder_set_error_callback(_decoder, DecErrorCBProc);
|
||||
FLAC__seekable_stream_decoder_set_client_data(_decoder, Self);
|
||||
if FLAC__seekable_stream_decoder_init(_decoder) <> FLAC__SEEKABLE_STREAM_DECODER_OK then
|
||||
raise EACSException.Create('Failed to initialize FLAC decoder.');
|
||||
if not FLAC__seekable_stream_decoder_process_until_end_of_metadata(_decoder) then
|
||||
FValid := False;
|
||||
EndOfStream := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TFlacIn.CloseFile;
|
||||
begin
|
||||
if FOpened = 1 then
|
||||
begin
|
||||
if _decoder <> nil then
|
||||
begin
|
||||
FLAC__seekable_stream_decoder_flush(_decoder);
|
||||
FLAC__seekable_stream_decoder_finish(_decoder);
|
||||
FLAC__seekable_stream_decoder_delete(_decoder);
|
||||
_decoder := nil;
|
||||
end;
|
||||
if Buff <> nil then FreeMem(Buff);
|
||||
Buff := nil;
|
||||
if not FStreamAssigned then FStream.Free
|
||||
else FStream.Seek(0, soFromBeginning);
|
||||
end;
|
||||
if FOpened > 0 then Dec(FOpened);
|
||||
end;
|
||||
|
||||
function TFLACIn.GetData(Buffer : Pointer; BufferSize : Integer): Integer;
|
||||
var
|
||||
dec_state, offs : Integer;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create('The Stream is not opened');
|
||||
if BufStart >= BufEnd then
|
||||
begin
|
||||
if FOffset <> 0 then
|
||||
begin
|
||||
offs := Round((FOffset/100)*Self.FTotalSamples);
|
||||
FPosition := FPosition + offs*(FBPS shr 3)*FChan;
|
||||
if FPosition < 0 then FPosition := 0
|
||||
else if FPosition > FSize then FPosition := FSize;
|
||||
Seek((FPosition div (FBPS shr 3)) div FChan);
|
||||
FOffset := 0;
|
||||
end;
|
||||
BufStart := 0;
|
||||
BufEnd := 0;
|
||||
if FPosition+MinFrameSize > FSize then EndOfStream := True;
|
||||
if EndOfStream then
|
||||
begin
|
||||
if FLoop then
|
||||
begin
|
||||
Flush;
|
||||
Init;
|
||||
end else
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
if Buff <> nil then FreeMem(Buff);
|
||||
Buff := nil;
|
||||
if not FLAC__seekable_stream_decoder_process_single(_decoder) then
|
||||
begin
|
||||
dec_state := FLAC__seekable_stream_decoder_get_state(_decoder);
|
||||
if dec_state = FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM then
|
||||
begin
|
||||
EndOfStream := True;
|
||||
Result := 0;
|
||||
Exit;
|
||||
end
|
||||
else raise EACSException.Create('Error reading FLAC file');
|
||||
end else BufEnd := Self.BytesPerBlock;
|
||||
end;
|
||||
if BufferSize < (BufEnd - BufStart)
|
||||
then Result := BufferSize
|
||||
else Result := BufEnd - BufStart;
|
||||
Move(Buff[BufStart], Buffer^, Result);
|
||||
Inc(BufStart, Result);
|
||||
Inc(FPosition, Result);
|
||||
end;
|
||||
|
||||
function TFLACIn.Seek(SampleNum : Integer) : Boolean;
|
||||
begin
|
||||
Result := FLAC__seekable_stream_decoder_seek_absolute(_decoder, Samplenum);
|
||||
end;
|
||||
|
||||
initialization
|
||||
FileFormats.Add('flac','Free Lossless Audio Codec',TFLACIn);
|
||||
FileFormats.Add('flac','Free Lossless Audio Codec',TFLACOut);
|
||||
|
||||
end.
|
||||
350
acs/Src/fileformats/acs_lame.pas
Normal file
350
acs/Src/fileformats/acs_lame.pas
Normal file
@@ -0,0 +1,350 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.3.
|
||||
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: acs_lame.pas,v $
|
||||
Revision 1.5 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.2 2006/01/01 18:46:40 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/12/19 18:36:38 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.6 2005/12/18 17:01:54 z0m3ie
|
||||
delphi compatibility
|
||||
|
||||
Revision 1.5 2005/12/04 16:54:34 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.4 2005/11/28 21:57:24 z0m3ie
|
||||
mostly FileOut fixes
|
||||
moved PBuffer to PBuffer8
|
||||
set all to dynamically Buffering
|
||||
|
||||
Revision 1.3 2005/11/28 19:10:14 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/09/13 04:04:50 z0m3ie
|
||||
First release without Components for Fileformats
|
||||
only TFileIn and TFileOut are Visible
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
unit acs_lame;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
ACS_File,Classes, SysUtils, ACS_Classes, lame,
|
||||
{$IFDEF LINUX}
|
||||
baseunix;
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF WINDOWS}
|
||||
Windows;
|
||||
{$ENDIF}
|
||||
|
||||
type
|
||||
|
||||
TMP3Quality = (ql0, ql1, ql2, ql3, ql4, ql5,
|
||||
ql6, ql7, ql8, ql9);
|
||||
|
||||
TMP3Mode = (STEREO = 0,
|
||||
JOINT_STEREO,
|
||||
DUAL_CHANNEL, // LAME doesn't supports this!
|
||||
MONO);
|
||||
|
||||
TMP3SampleRate = (srDefault, sr32kHz, sr41kHz, sr48kHz);
|
||||
|
||||
TMP3BitRate = (br8, br16, br24, br32, br40, br48, br56, br64, br80, br96,
|
||||
br112, br128, br144, br160, br192, br224, br256, br320);
|
||||
|
||||
BOOL = Boolean;
|
||||
|
||||
TMP3Out = class(TACSCustomFileOut)
|
||||
private
|
||||
FBitRate : TMP3BitRate;
|
||||
_plgf : PLame_global_flags;
|
||||
mp3buf : PByte;
|
||||
mp3buf_size : Integer;
|
||||
FTitle : String;
|
||||
FArtist : String;
|
||||
FAlbum : String;
|
||||
FYear : String;
|
||||
FTrack : String;
|
||||
FComment : String;
|
||||
FGenre : String;
|
||||
FCopyright: BOOL;
|
||||
FOriginal: BOOL;
|
||||
FEnableVBR: BOOL;
|
||||
FWriteVBRHeader: BOOL;
|
||||
FCRC: BOOL;
|
||||
FVBRQuality: TMP3Quality;
|
||||
FVBRMinBitrate: integer;
|
||||
FVBRMaxBitrate: integer;
|
||||
FQuality: TMP3Quality;
|
||||
FMode: TMP3Mode;
|
||||
FSampleRate: TMP3SampleRate;
|
||||
protected
|
||||
procedure Done; override;
|
||||
function DoOutput(Abort : Boolean):Boolean; override;
|
||||
procedure Prepare; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
published
|
||||
property BitRate : TMP3BitRate read FBitRate write FBitRate stored True;
|
||||
property Id3TagTitle : String read FTitle write FTitle;
|
||||
property Id3TagArtist : String read FArtist write FArtist;
|
||||
property Id3TagAlbum : String read FAlbum write FAlbum;
|
||||
property Id3TagYear : String read FYear write FYear;
|
||||
property Id3TagTrack : String read FTrack write FTrack;
|
||||
property Id3TagComment : String read FComment write FComment;
|
||||
property Id3TagGenre : String read FGenre write FGenre;
|
||||
property Quality : TMP3Quality read FQuality write FQuality default ql5;
|
||||
|
||||
property SampleRate : TMP3SampleRate read FSampleRate write FSampleRate default srDefault;
|
||||
property Mode : TMP3Mode read FMode write FMode default STEREO;
|
||||
|
||||
//Extras
|
||||
property CRC : BOOL read FCRC write FCRC default false;
|
||||
property Copyright : BOOL read FCopyright write FCopyright default false;
|
||||
property Original : BOOL read FOriginal write FOriginal default true;
|
||||
|
||||
//VBR encoding
|
||||
property WriteVBRHeader : BOOL read FWriteVBRHeader write FWriteVBRHeader default false;
|
||||
property EnableVBR : BOOL read FEnableVBR write FEnableVBR default false;
|
||||
property VBRQuality : TMP3Quality read FVBRQuality write FVBRQuality default ql5;
|
||||
property VBRMinBitrate : integer read FVBRMinBitrate write FVBRMinBitrate default 128;
|
||||
property VBRMaxBitrate : integer read FVBRMaxBitrate write FVBRMaxBitrate default 192;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
constructor TMP3Out.Create(AOwner: TComponent);
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
LoadLAME;
|
||||
FBitRate := br128;
|
||||
|
||||
FBufferSize := $4000;
|
||||
FQuality := ql5;
|
||||
FSampleRate := srDefault;
|
||||
FMode := STEREO;
|
||||
FCRC := false;
|
||||
FCopyright := false;
|
||||
FOriginal := true;
|
||||
|
||||
FWriteVBRHeader := false;
|
||||
FEnableVBR := false;
|
||||
FVBRQuality := ql5;
|
||||
FVBRMinBitrate := 128;
|
||||
FVBRMaxBitrate := 192;
|
||||
|
||||
if not (csDesigning in ComponentState) then
|
||||
if not LameLoaded then
|
||||
raise EACSException.Create(LAME_PATH + ' library could not be loaded.');
|
||||
end;
|
||||
|
||||
destructor TMP3Out.Destroy;
|
||||
begin
|
||||
UnloadLAME;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TMP3Out.Prepare;
|
||||
var
|
||||
samples, br, tbr, sr, ql : Integer;
|
||||
begin
|
||||
GetMem(FBuffer,FBufferSize);
|
||||
if not FStreamAssigned then
|
||||
begin
|
||||
if FFileName = '' then raise EACSException.Create('File name is not assigned.');
|
||||
FStream := TFileStream.Create(FFileName, fmCreate or fmShareExclusive, FAccessMask);
|
||||
end;
|
||||
FInput.Init;
|
||||
_plgf := lame_init;
|
||||
if FInput.Size > 0 then
|
||||
samples := FInput.Size div ((Finput.BitsPerSample shr 3)*Finput.Channels);
|
||||
lame_set_num_samples(_plgf, samples);
|
||||
lame_set_in_samplerate(_plgf, Finput.SampleRate);
|
||||
lame_set_num_channels(_plgf, 2); // not Finput.Channels see the note below
|
||||
case FBitRate of
|
||||
br8 : br := 8;
|
||||
br16 : br := 16;
|
||||
br24 : br := 24;
|
||||
br32 : br := 32;
|
||||
br40 : br := 40;
|
||||
br48 : br := 48;
|
||||
br56 : br := 56;
|
||||
br64 : br := 64;
|
||||
br80 : br := 80;
|
||||
br96 : br := 96;
|
||||
br112 : br := 112;
|
||||
br128 : br := 128;
|
||||
br144 : br := 144;
|
||||
br160 : br := 160;
|
||||
br192 : br := 192;
|
||||
br224 : br := 224;
|
||||
br256 : br := 256;
|
||||
br320 : br := 320;
|
||||
end;
|
||||
case FSampleRate of
|
||||
srDefault: sr := 0;
|
||||
sr32kHz: sr := 32000;
|
||||
sr41kHz: sr := 41000;
|
||||
sr48kHz: sr := 48000;
|
||||
end;
|
||||
lame_set_out_samplerate(_plgf,sr);
|
||||
{ lame_set_mode(_plgf, Integer(FMode));
|
||||
if FCopyright then
|
||||
lame_set_copyright(_plgf,1)
|
||||
else
|
||||
lame_set_copyright(_plgf,0);
|
||||
if FOriginal then
|
||||
lame_set_original(_plgf,1)
|
||||
else
|
||||
lame_set_original(_plgf,0);
|
||||
if FCRC then
|
||||
lame_set_error_protection(_plgf,1)
|
||||
else
|
||||
lame_set_error_protection(_plgf,0);
|
||||
|
||||
if not EnableVBR then
|
||||
begin
|
||||
lame_set_brate(_plgf, br);
|
||||
case FQuality of
|
||||
ql0: ql:=0;
|
||||
ql1: ql:=1;
|
||||
ql2: ql:=2;
|
||||
ql3: ql:=3;
|
||||
ql4: ql:=4;
|
||||
ql5: ql:=5;
|
||||
ql6: ql:=6;
|
||||
ql7: ql:=7;
|
||||
ql8: ql:=8;
|
||||
ql9: ql:=9;
|
||||
end;
|
||||
lame_set_quality(_plgf,ql);
|
||||
end
|
||||
else
|
||||
begin
|
||||
if FWriteVBRHeader then
|
||||
lame_set_bWriteVbrTag(_plgf,1);
|
||||
lame_set_VBR(_plgf,2);
|
||||
case FVBRQuality of
|
||||
ql0: ql:=0;
|
||||
ql1: ql:=1;
|
||||
ql2: ql:=2;
|
||||
ql3: ql:=3;
|
||||
ql4: ql:=4;
|
||||
ql5: ql:=5;
|
||||
ql6: ql:=6;
|
||||
ql7: ql:=7;
|
||||
ql8: ql:=8;
|
||||
ql9: ql:=9;
|
||||
end;
|
||||
lame_set_VBR_q(_plgf,ql);
|
||||
if FVBRMinBitrate > FVBRMaxBitrate then
|
||||
begin
|
||||
tbr := FVBRMinBitrate;
|
||||
FVBRMinBitrate := FVBRMaxBitrate;
|
||||
FVBRMinBitrate := tbr;
|
||||
end;
|
||||
lame_set_VBR_min_bitrate_kbps(_plgf,FVBRMinBitrate);
|
||||
lame_set_VBR_max_bitrate_kbps(_plgf,FVBRMaxBitrate);
|
||||
end;
|
||||
}
|
||||
lame_init_params(_plgf);
|
||||
mp3buf_size := (FBufferSize shr 1) + (FBufferSize shr 3) + 7200;
|
||||
GetMem(mp3buf, mp3buf_size);
|
||||
end;
|
||||
|
||||
procedure TMP3Out.Done;
|
||||
var
|
||||
res : Integer;
|
||||
begin
|
||||
id3tag_init(_plgf);
|
||||
id3tag_set_title(_plgf, PChar(FTitle));
|
||||
id3tag_set_artist(_plgf, PChar(FArtist));
|
||||
id3tag_set_album(_plgf, PChar(FAlbum));
|
||||
id3tag_set_year(_plgf, PChar(FYear));
|
||||
id3tag_set_track(_plgf, PChar(FTrack));
|
||||
id3tag_set_comment(_plgf, PChar(FComment));
|
||||
id3tag_set_genre(_plgf, PChar(FGenre));
|
||||
res := lame_encode_flush(_plgf, mp3buf, mp3buf_size);
|
||||
FStream.Write(mp3buf^, res);
|
||||
if not FStreamAssigned then FStream.Free;
|
||||
lame_close(_plgf);
|
||||
FreeMem(mp3buf);
|
||||
FInput.Flush;
|
||||
FreeMem(FBuffer);
|
||||
end;
|
||||
|
||||
function TMP3Out.DoOutput(Abort : Boolean):Boolean;
|
||||
var
|
||||
Len, res, ns : Integer;
|
||||
begin
|
||||
// No exceptions Here
|
||||
Result := True;
|
||||
if not CanOutput then Exit;
|
||||
if Abort then
|
||||
begin
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
while InputLock do;
|
||||
InputLock := True;
|
||||
Len := Finput.GetData(@FBuffer, FBufferSize);
|
||||
InputLock := False;
|
||||
if Len <> 0 then
|
||||
begin
|
||||
if FInput.Channels = 2 then
|
||||
begin
|
||||
ns := Len shr 2;
|
||||
res := lame_encode_buffer_interleaved(_plgf, @FBuffer, ns, mp3buf, mp3buf_size);
|
||||
end else
|
||||
begin
|
||||
(* If the input stream is mono we turn it into stereo here.
|
||||
This is the way to bypass some pour performance on mono streams,
|
||||
maybe not the best way, but for a while ...*)
|
||||
ns := Len shr 1;
|
||||
res := lame_encode_buffer(_plgf, @FBuffer, @FBuffer, ns, mp3buf, mp3buf_size);
|
||||
end;
|
||||
if res < 0 then
|
||||
begin
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
FStream.Write(mp3buf^, res);
|
||||
end else
|
||||
begin
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
||||
FileFormats.Add('mp3','Mpeg Layer III',TMP3Out);
|
||||
|
||||
|
||||
end.
|
||||
475
acs/Src/fileformats/acs_mac.pas
Normal file
475
acs/Src/fileformats/acs_mac.pas
Normal file
@@ -0,0 +1,475 @@
|
||||
(*
|
||||
the original version of this file is written by thomas la cour,
|
||||
http://www.top-house.dk/~nr161/delphi/
|
||||
|
||||
This file is a part of Audio Components Suite v 2.4
|
||||
Copyright (c) 2002, 2003 Andrei Borovsky. All rights reserved.
|
||||
See the LICENSE file for more details.
|
||||
You can contact me at acs@compiler4.net
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: acs_mac.pas,v $
|
||||
Revision 1.7 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.3 2005/12/30 11:10:57 z0m3ie
|
||||
some corrections to lazarus-linux depending things
|
||||
|
||||
Revision 1.2 2005/12/26 17:31:39 z0m3ie
|
||||
fixed some problems in acs_dsfiles
|
||||
fixed some problems in acs_vorbis
|
||||
reworked all buffers
|
||||
|
||||
Revision 1.1 2005/12/19 18:36:38 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.6 2005/12/18 17:01:54 z0m3ie
|
||||
delphi compatibility
|
||||
|
||||
Revision 1.5 2005/12/04 16:54:34 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.4 2005/11/29 18:32:51 z0m3ie
|
||||
bugfixes for win32 version
|
||||
|
||||
Revision 1.3 2005/11/28 21:57:24 z0m3ie
|
||||
mostly FileOut fixes
|
||||
moved PBuffer to PBuffer8
|
||||
set all to dynamically Buffering
|
||||
|
||||
Revision 1.2 2005/09/13 04:04:50 z0m3ie
|
||||
First release without Components for Fileformats
|
||||
only TFileIn and TFileOut are Visible
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
}
|
||||
|
||||
unit acs_mac;
|
||||
|
||||
{$ifdef linux}{$message error 'unit not supported'}{$endif linux}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
ACS_File,Classes, SysUtils, Windows, ACS_Classes, MACDll;
|
||||
|
||||
type
|
||||
|
||||
// Note by A.B.: It seems that APE compressor supports file output only.
|
||||
|
||||
TMACOut = class(TACSCustomFileOut)
|
||||
private
|
||||
APECompress: TAPECompress;
|
||||
WaveFormatEx: TWaveFormatEx;
|
||||
EndOfStream: Boolean;
|
||||
FCompressionLevel: Integer;
|
||||
FMaxAudioBytes: Integer;
|
||||
procedure SetCompressionLevel(Value: Integer);
|
||||
protected
|
||||
procedure Done; override;
|
||||
function DoOutput(Abort: Boolean): Boolean; override;
|
||||
procedure Prepare; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
published
|
||||
property CompressionLevel: LongInt read FCompressionLevel write SetCompressionLevel stored True;
|
||||
property MaxAudioBytes: Integer read FMaxAudioBytes write FMaxAudioBytes;
|
||||
end;
|
||||
|
||||
(* Note by A.B.: Due to the reasons described above this component
|
||||
ignores streamed input *)
|
||||
|
||||
TMACIn = class(TACSCustomFileIn)
|
||||
private
|
||||
APEDecompress: TAPEDecompress;
|
||||
EndOfStream: Boolean;
|
||||
function GetAverageBitrate: Integer;
|
||||
function GetCurrentBitrate: Integer;
|
||||
function GetCurrentBlock: Integer;
|
||||
function GetCurrentMS: Integer;
|
||||
function GetLengthMS: Integer;
|
||||
function GetTotalBlocks: Integer;
|
||||
protected
|
||||
function GetBPS: Integer; override;
|
||||
function GetCh: Integer; override;
|
||||
function GetSR: Integer; override;
|
||||
function GetTotalTime: real; override;
|
||||
procedure OpenFile; override;
|
||||
procedure CloseFile; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer: Pointer; BufferSize: Integer): Integer; override;
|
||||
|
||||
function Seek(Sample : Integer) : Boolean; override;
|
||||
|
||||
procedure Flush; override;
|
||||
procedure Init; override;
|
||||
|
||||
property AverageBitrate: Integer read GetAverageBitrate;
|
||||
property CurrentBitrate: Integer read GetCurrentBitrate;
|
||||
property CurrentBlock: Integer read GetCurrentBlock;
|
||||
property CurrentMS: Integer read GetCurrentMS;
|
||||
property LengthMS: Integer read GetLengthMS;
|
||||
property TotalBlocks: Integer read GetTotalBlocks;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
constructor TMACOut.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FBufferSize := $10000;
|
||||
FCompressionLevel := COMPRESSION_LEVEL_NORMAL;
|
||||
FMaxAudioBytes := MAX_AUDIO_BYTES_UNKNOWN;
|
||||
if not (csDesigning in ComponentState) then
|
||||
begin
|
||||
if not MACLoaded then
|
||||
raise EACSException.Create(MACPath + ' library could not be loaded.');
|
||||
end;
|
||||
end;
|
||||
|
||||
destructor TMACOut.Destroy;
|
||||
begin
|
||||
if Assigned(APECompress) then
|
||||
APECompress.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TMACOut.Prepare;
|
||||
var
|
||||
r: Integer;
|
||||
begin
|
||||
GetMem(FBuffer,FBufferSize);
|
||||
if FFileName = '' then raise EACSException.Create('File name is not assigned.');
|
||||
FInput.Init;
|
||||
EndOfStream := False;
|
||||
|
||||
APECompress := TAPECompress.Create;
|
||||
|
||||
macFillWaveFormatEx(WaveFormatEx, FInput.SampleRate, FInput.BitsPerSample, FInput.Channels);
|
||||
|
||||
r := APECompress.Start(
|
||||
PChar(FFileName),
|
||||
@WaveFormatEx,
|
||||
FMaxAudioBytes,
|
||||
FCompressionLevel,
|
||||
nil,
|
||||
CREATE_WAV_HEADER_ON_DECOMPRESSION);
|
||||
|
||||
CanOutput := (r = 0);
|
||||
|
||||
if r <> 0 then
|
||||
raise EACSException.Create('Error starting APECompress.' + #13#10 +
|
||||
macErrorExplanation(r));
|
||||
end;
|
||||
|
||||
procedure TMACOut.Done;
|
||||
begin
|
||||
APECompress.Finish(nil, 0, 0);
|
||||
APECompress.Free;
|
||||
APECompress := nil;
|
||||
FInput.Flush;
|
||||
FreeMem(FBuffer);
|
||||
end;
|
||||
|
||||
function TMACOut.DoOutput(Abort: Boolean): Boolean;
|
||||
var
|
||||
Len, i, x, z: Integer;
|
||||
pBuffer: PByteArray;
|
||||
nAudioBytesLeft, nBufferBytesAvailable, nNoiseBytes, nRetVal: Integer;
|
||||
begin
|
||||
// No exceptions Here
|
||||
Result := True;
|
||||
if not CanOutput then Exit;
|
||||
if Abort or EndOfStream then
|
||||
begin
|
||||
(* We don't close file here to avoide exceptions
|
||||
if output componenet's Stop method is called *)
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
Len := Finput.GetData(@FBuffer[0], FBufferSize);
|
||||
x := 0;
|
||||
if Len <> 0 then
|
||||
begin
|
||||
nAudioBytesLeft := Len;
|
||||
while (nAudioBytesLeft > 0) do
|
||||
begin
|
||||
nBufferBytesAvailable := 0;
|
||||
pBuffer := APECompress.LockBuffer(nBufferBytesAvailable);
|
||||
|
||||
nNoiseBytes := nBufferBytesAvailable;
|
||||
if nNoiseBytes > nAudioBytesLeft then
|
||||
nNoiseBytes := nAudioBytesLeft;
|
||||
|
||||
//whats this ? schoult System.Move not be faster ?
|
||||
for z := 0 to nNoiseBytes - 1 do
|
||||
begin
|
||||
pBuffer[z] := FBuffer[x];
|
||||
inc(x);
|
||||
end;
|
||||
|
||||
nRetVal := APECompress.UnlockBuffer(nNoiseBytes, TRUE);
|
||||
if (nRetVal <> 0) then
|
||||
raise EACSException.Create('APECompress.UnlockBuffer Error: ' + inttostr(nRetVal));
|
||||
|
||||
dec(nAudioBytesLeft, nNoiseBytes);
|
||||
end
|
||||
end
|
||||
else
|
||||
EndOfStream := True;
|
||||
end;
|
||||
|
||||
|
||||
constructor TMACIn.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
BufferSize := $2000;
|
||||
if not (csDesigning in ComponentState) then
|
||||
begin
|
||||
if not MACLoaded then
|
||||
raise EACSException.Create(MACPath + ' library could not be loaded.');
|
||||
end;
|
||||
end;
|
||||
|
||||
destructor TMACIn.Destroy;
|
||||
begin
|
||||
if Assigned(APEDecompress) then
|
||||
APEDecompress.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TMACIn.OpenFile;
|
||||
begin
|
||||
FValid := True;
|
||||
if FOpened = 0 then
|
||||
begin
|
||||
EndOfStream := False;
|
||||
|
||||
APEDecompress := TAPEDecompress.Create(FileName);
|
||||
if APEDecompress.Handle <> 0 then
|
||||
begin
|
||||
FSize := APEDecompress.InfoWavTotalBytes;
|
||||
FSR := APEDecompress.InfoSampleRate;
|
||||
FBPS := APEDecompress.InfoBitsPerSample;
|
||||
FChan := APEDecompress.InfoChannels;
|
||||
FTime := APEDecompress.InfoLengthMS div 1000; // Round(ov_time_total(VFile, 0));
|
||||
FTotalSamples := (FSize div (FBPS shr 3)) div FChan;
|
||||
end
|
||||
else
|
||||
begin
|
||||
FValid := False;
|
||||
FOpened := -1;
|
||||
end;
|
||||
end;
|
||||
Inc(FOpened);
|
||||
end;
|
||||
|
||||
procedure TMACIn.CloseFile;
|
||||
begin
|
||||
if FOpened = 1 then
|
||||
begin
|
||||
if Assigned(APEDecompress) then
|
||||
APEDecompress.Free;
|
||||
APEDecompress := nil;
|
||||
end;
|
||||
if FOpened > 0 then Dec(FOpened);
|
||||
end;
|
||||
|
||||
function TMACIn.GetData(Buffer: Pointer; BufferSize: Integer): Integer;
|
||||
var
|
||||
l, csize, offs: Integer;
|
||||
blocks: Integer;
|
||||
tmp: Double;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create('The Stream is not opened');
|
||||
if BufStart > BufEnd then
|
||||
begin
|
||||
if FOffset <> 0 then
|
||||
begin
|
||||
offs := Round((FOffset / 100) * FSize);
|
||||
FPosition := FPosition + offs;
|
||||
if FPosition < 0 then FPosition := 0
|
||||
else if FPosition > FSize then FPosition := FSize;
|
||||
APEDecompress.Seek(FPosition shr 2);
|
||||
FOffset := 0;
|
||||
end;
|
||||
BufStart := 1;
|
||||
BufEnd := 0;
|
||||
if not EndOfStream then
|
||||
begin
|
||||
while BufEnd < BufferSize do
|
||||
begin
|
||||
//l := ov_read(VFile, @buf[BufEnd + 1], BUF_SIZE - BufEnd, 0, 2, 1, @cursec);
|
||||
blocks := (BufferSize - BufEnd) div 4;
|
||||
APEDecompress.GetData(@FBuffer[BufEnd], blocks, l);
|
||||
l := l * 4;
|
||||
if l <= 0 then
|
||||
begin
|
||||
EndOfStream := True;
|
||||
Break;
|
||||
end;
|
||||
Inc(BufEnd, l);
|
||||
if (FEndSample <> -1) then
|
||||
begin
|
||||
csize := (FEndSample-FStartSample)*(FBPS shr 3)*FChan;
|
||||
if (csize - FPosition) <= 0 then
|
||||
begin
|
||||
EndOfStream := True;
|
||||
Break;
|
||||
end;
|
||||
if (csize - FPosition) < BufEnd then
|
||||
begin
|
||||
BufEnd := csize - FPosition;
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if EndOfStream and FLoop then
|
||||
begin
|
||||
Flush;
|
||||
Init;
|
||||
EndOfStream := False;
|
||||
while BufEnd < BufferSize do
|
||||
begin
|
||||
//l := ov_read(VFile, @buf[BufEnd + 1], BUF_SIZE - BufEnd, 0, 2, 1, @cursec);
|
||||
blocks := (BufferSize - BufEnd) div 4;
|
||||
APEDecompress.GetData(@FBuffer[BufEnd], blocks, l);
|
||||
l := l * 4;
|
||||
if l <= 0 then
|
||||
begin
|
||||
EndOfStream := True;
|
||||
Break;
|
||||
end;
|
||||
Inc(BufEnd, l);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if BufferSize < (BufEnd - BufStart + 1) then
|
||||
Result := BufferSize
|
||||
else
|
||||
Result := BufEnd - BufStart + 1;
|
||||
Move(FBuffer[BufStart - 1], Buffer^, Result);
|
||||
Inc(BufStart, Result);
|
||||
Inc(FPosition, Result);
|
||||
end;
|
||||
|
||||
function TMACIn.GetTotalTime: real;
|
||||
begin
|
||||
OpenFile;
|
||||
if Assigned(APEDecompress) then
|
||||
Result := APEDecompress.LengthMS / 1000;
|
||||
CloseFile;
|
||||
end;
|
||||
|
||||
function TMACIn.GetAverageBitrate: Integer;
|
||||
begin
|
||||
if Assigned(APEDecompress) then
|
||||
Result := APEDecompress.AverageBitrate;
|
||||
end;
|
||||
|
||||
function TMACIn.GetCurrentBitrate: Integer;
|
||||
begin
|
||||
if Assigned(APEDecompress) then
|
||||
Result := APEDecompress.CurrentBitrate;
|
||||
end;
|
||||
|
||||
function TMACIn.GetCurrentBlock: Integer;
|
||||
begin
|
||||
if Assigned(APEDecompress) then
|
||||
Result := APEDecompress.CurrentBlock;
|
||||
end;
|
||||
|
||||
function TMACIn.GetCurrentMS: Integer;
|
||||
begin
|
||||
if Assigned(APEDecompress) then
|
||||
Result := APEDecompress.CurrentMS;
|
||||
end;
|
||||
|
||||
function TMACIn.GetLengthMS: Integer;
|
||||
begin
|
||||
if Assigned(APEDecompress) then
|
||||
Result := APEDecompress.LengthMS;
|
||||
end;
|
||||
|
||||
function TMACIn.GetTotalBlocks: Integer;
|
||||
begin
|
||||
if Assigned(APEDecompress) then
|
||||
Result := APEDecompress.TotalBlocks;
|
||||
end;
|
||||
|
||||
function TMACIn.GetBPS: Integer;
|
||||
begin
|
||||
OpenFile;
|
||||
Result := FBPS;
|
||||
CloseFile;
|
||||
end;
|
||||
|
||||
function TMACIn.GetCh: Integer;
|
||||
begin
|
||||
OpenFile;
|
||||
Result := FChan;
|
||||
CloseFile;
|
||||
end;
|
||||
|
||||
function TMACIn.GetSR: Integer;
|
||||
begin
|
||||
OpenFile;
|
||||
Result := FSR;
|
||||
CloseFile;
|
||||
end;
|
||||
|
||||
procedure TMACOut.SetCompressionLevel(Value: Integer);
|
||||
begin
|
||||
case Value of
|
||||
COMPRESSION_LEVEL_FAST,
|
||||
COMPRESSION_LEVEL_NORMAL,
|
||||
COMPRESSION_LEVEL_HIGH,
|
||||
COMPRESSION_LEVEL_EXTRA_HIGH: FCompressionLevel := Value;
|
||||
else
|
||||
FCompressionLevel := COMPRESSION_LEVEL_NORMAL;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMACIn.Flush;
|
||||
begin
|
||||
inherited Flush;
|
||||
end;
|
||||
|
||||
procedure TMACIn.Init;
|
||||
begin
|
||||
inherited Init;
|
||||
BufStart := 1;
|
||||
BufEnd := 0;
|
||||
end;
|
||||
|
||||
function TMACIn.Seek(Sample : Integer) : Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
if not FSeekable then Exit;
|
||||
Result := True;
|
||||
OpenFile;
|
||||
APEDecompress.Seek(Sample);
|
||||
CloseFile;
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
||||
FileFormats.Add('mac','Monkey Audio',TMACOut);
|
||||
FileFormats.Add('mac','Monkey Audio',TMACIn);
|
||||
|
||||
|
||||
end.
|
||||
|
||||
242
acs/Src/fileformats/acs_mad.pas
Normal file
242
acs/Src/fileformats/acs_mad.pas
Normal file
@@ -0,0 +1,242 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.3.
|
||||
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: acs_mad.pas,v $
|
||||
Revision 1.1 2005/12/19 18:36:38 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/12/04 16:54:34 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.3 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
unit acs_mad;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
|
||||
ACS_Types, Classes, SysUtils, Math, MAD;
|
||||
|
||||
type
|
||||
|
||||
TRawPCMWaveHeader = record
|
||||
RIFF: array [0..3] of Char;
|
||||
FileSize: Integer;
|
||||
RIFFType: array [0..3] of Char;
|
||||
FmtChunkId: array [0..3] of Char;
|
||||
FmtChunkSize: Integer;
|
||||
FormatTag: Word;
|
||||
Channels: Word;
|
||||
SampleRate: Integer;
|
||||
BytesPerSecond: Integer;
|
||||
BlockAlign: Word;
|
||||
BitsPerSample: Word;
|
||||
DataChunkId: array [0..3] of Char;
|
||||
DataSize: Integer;
|
||||
end;
|
||||
|
||||
TMADProgressEvent = procedure(Sender : TComponent) of object;
|
||||
TMADDoneEvent = procedure(Sender : TComponent; Success : Boolean) of object;
|
||||
|
||||
TMADThread = class(TThread)
|
||||
private
|
||||
_Free : Boolean;
|
||||
Progr : Integer;
|
||||
Owner : TComponent;
|
||||
FDecoder : mad_decoder;
|
||||
FInputStream : TStream;
|
||||
FOutputStream : TStream;
|
||||
HasFirstFrame : Boolean;
|
||||
FSR : Integer;
|
||||
FChan : Integer;
|
||||
FBitrate : Integer;
|
||||
FValid : Boolean;
|
||||
Data : PACSBuffer8;
|
||||
InputDone : Boolean;
|
||||
WaveHdr : TRawPCMWaveHeader;
|
||||
FSize : Integer;
|
||||
FMADProgress : TMADProgressEvent;
|
||||
FMADDone : TMADDoneEvent;
|
||||
WhenDone : procedure of object;
|
||||
protected
|
||||
procedure Execute; override;
|
||||
public
|
||||
constructor Create(AOwner : TComponent; InputStream, OutputStream : TStream);
|
||||
destructor Destroy; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
function InputFunc(CData : Pointer; Stream : p_mad_stream) : Integer; cdecl;
|
||||
var
|
||||
MT : TMADThread;
|
||||
Len : Integer;
|
||||
begin
|
||||
|
||||
MT := TMADThread(CData);
|
||||
|
||||
if MT.InputDone then
|
||||
begin
|
||||
Result := MAD_FLOW_STOP;
|
||||
Exit;
|
||||
end;
|
||||
MT.InputDone := True;
|
||||
// Len := MT.FInputStream.Read(Data^, MT.FInputStream.Size);
|
||||
Len := MT.FInputStream.Size;
|
||||
mad_stream_buffer(Stream, MT.Data, Len);
|
||||
if not MT.Terminated then Result := MAD_FLOW_CONTINUE
|
||||
else Result := MAD_FLOW_STOP;
|
||||
end;
|
||||
|
||||
function OutputFunc(CData : Pointer; Header : p_mad_header; pcm : p_mad_pcm) : Integer; cdecl;
|
||||
var
|
||||
MT : TMADThread;
|
||||
i, framesize : Integer;
|
||||
outsamples : array[0..2303] of SmallInt;
|
||||
text : array[0..4] of Char;
|
||||
CProgr : Integer;
|
||||
begin
|
||||
MT := TMADThread(CData);
|
||||
if not MT.HasFirstFrame then
|
||||
begin
|
||||
MT.FSR := pcm.samplerate;
|
||||
MT.FChan := pcm.channels;
|
||||
MT.FBitrate := Header.bitrate;
|
||||
framesize := Ceil(144*MT.FBitrate/MT.FSR);
|
||||
MT.FSize := Round(MT.FInputStream.Size/framesize*1152)*MT.FChan*2;
|
||||
MT.FValid := True;
|
||||
text := 'RIFF';
|
||||
Move(text[0], MT.WaveHdr.RIFF[0], 4);
|
||||
MT.WaveHdr.FileSize := MT.FSize + 44;
|
||||
text := 'WAVE';
|
||||
Move(text[0], MT.WaveHdr.RIFFType[0], 4);
|
||||
text := 'fmt ';
|
||||
Move(text[0], MT.WaveHdr.FmtChunkId[0], 4);
|
||||
MT.WaveHdr.FmtChunkSize := 16;
|
||||
MT.WaveHdr.FormatTag := 1;
|
||||
MT.WaveHdr.Channels := MT.FChan;
|
||||
MT.WaveHdr.SampleRate := MT.FSR;
|
||||
MT.WaveHdr.BitsPerSample := 16;
|
||||
MT.WaveHdr.BlockAlign := 2*MT.FChan;
|
||||
MT.WaveHdr.BytesPerSecond := MT.FSR * MT.WaveHdr.BlockAlign;
|
||||
text := 'data';
|
||||
Move(text[0], MT.WaveHdr.DataChunkId[0], 4);
|
||||
MT.WaveHdr.DataSize := MT.FSize;
|
||||
if MT.FOutputStream is TMemoryStream then
|
||||
begin
|
||||
MT.FOutputStream.Size :=MT.FSize + 44;
|
||||
MT.FOutputStream.Seek(0, soFromBeginning);
|
||||
end;
|
||||
MT.FOutputStream.Write(MT.WaveHdr, 44);
|
||||
MT.HasFirstFrame := True;
|
||||
end;
|
||||
if pcm.channels = 2 then
|
||||
begin
|
||||
for i := 0 to pcm.length -1 do
|
||||
begin
|
||||
if pcm.samples[0][i] >= MAD_F_ONE then
|
||||
pcm.samples[0][i] := MAD_F_ONE - 1;
|
||||
if pcm.samples[0][i] < -MAD_F_ONE then
|
||||
pcm.samples[0][i] := -MAD_F_ONE;
|
||||
pcm.samples[0][i] := pcm.samples[0][i] shr (MAD_F_FRACBITS + 1 - 16);
|
||||
outsamples[i shl 1] := pcm.samples[0][i];
|
||||
if pcm.samples[1][i] >= MAD_F_ONE then
|
||||
pcm.samples[1][i] := MAD_F_ONE - 1;
|
||||
if pcm.samples[1][i] < -MAD_F_ONE then
|
||||
pcm.samples[1][i] := -MAD_F_ONE;
|
||||
pcm.samples[1][i] := pcm.samples[1][i] shr (MAD_F_FRACBITS + 1 - 16);
|
||||
outsamples[(i shl 1)+1] := pcm.samples[1][i];
|
||||
end;
|
||||
MT.FOutputStream.Write(outsamples[0], pcm.length*4);
|
||||
end else
|
||||
begin
|
||||
for i := 0 to pcm.length -1 do
|
||||
begin
|
||||
if pcm.samples[0][i] >= MAD_F_ONE then
|
||||
pcm.samples[0][i] := MAD_F_ONE - 1;
|
||||
if pcm.samples[0][i] < -MAD_F_ONE then
|
||||
pcm.samples[0][i] := -MAD_F_ONE;
|
||||
pcm.samples[0][i] := pcm.samples[0][i] shr (MAD_F_FRACBITS + 1 - 16);
|
||||
outsamples[i] := pcm.samples[0][i];
|
||||
end;
|
||||
MT.FOutputStream.Write(outsamples[0], pcm.length*2);
|
||||
end;
|
||||
if MT.FSize <> 0 then
|
||||
begin
|
||||
CProgr := Round(MT.FOutputStream.Position/MT.FSize*100);
|
||||
if MT.Progr <> CProgr then
|
||||
begin
|
||||
MT.Progr := CProgr;
|
||||
if Assigned(MT.FMADProgress) then
|
||||
MT.FMADProgress(MT.Owner);
|
||||
end;
|
||||
end;
|
||||
if not MT.Terminated then Result := MAD_FLOW_CONTINUE
|
||||
else Result := MAD_FLOW_STOP;
|
||||
end;
|
||||
|
||||
function ErrorFunc(CData : Pointer; Stream : p_mad_stream; Frame : p_mad_frame) : Integer; cdecl;
|
||||
begin
|
||||
Result := MAD_FLOW_CONTINUE;
|
||||
end;
|
||||
|
||||
constructor TMADThread.Create;
|
||||
begin
|
||||
inherited Create(True);
|
||||
Owner := AOwner;
|
||||
FInputStream := InputStream;
|
||||
FOutputStream := OutputStream;
|
||||
FreeOnTerminate := False;
|
||||
end;
|
||||
|
||||
destructor TMADThread.Destroy;
|
||||
begin
|
||||
if not _Free then
|
||||
begin
|
||||
Terminate;
|
||||
{$IFDEF WIN32}
|
||||
while not _Free do;
|
||||
{$ENDIF}
|
||||
end;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TMADThread.Execute;
|
||||
begin
|
||||
try
|
||||
GetMem(Data, FInputStream.Size);
|
||||
FInputStream.Read(Data[0], FInputStream.Size);
|
||||
mad_decoder_init(@FDecoder, Self, InputFunc, nil, nil, OutputFunc, ErrorFunc, nil);
|
||||
mad_decoder_run(@FDecoder, MAD_DECODER_MODE_SYNC);
|
||||
mad_decoder_finish(@FDecoder);
|
||||
FreeMem(Data);
|
||||
WhenDone;
|
||||
if Assigned(FMADDone) then FMADDone(Owner, FValid);
|
||||
_Free := True;
|
||||
except
|
||||
FreeMem(Data);
|
||||
WhenDone;
|
||||
_Free := True;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
153
acs/Src/fileformats/acs_mpeg.pas
Normal file
153
acs/Src/fileformats/acs_mpeg.pas
Normal file
@@ -0,0 +1,153 @@
|
||||
unit acs_mpeg;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils,ACS_file,ACS_classes, smpeg;
|
||||
|
||||
type
|
||||
TMPEGIn = class(TACSCustomFileIn)
|
||||
private
|
||||
_M : Pointer;
|
||||
protected
|
||||
procedure OpenFile; override;
|
||||
procedure CloseFile; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
procedure Init; override;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
constructor TMPEGIn.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
BufferSize := $2000;
|
||||
end;
|
||||
|
||||
destructor TMPEGIn.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TMPEGIn.Init;
|
||||
begin
|
||||
inherited Init;
|
||||
SMPEG_play(_M);
|
||||
end;
|
||||
|
||||
procedure TMPEGIn.OpenFile;
|
||||
var
|
||||
info : SMPEG_info;
|
||||
spec : SDL_AudioSpec;
|
||||
begin
|
||||
if FOpened = 0 then
|
||||
begin
|
||||
(* the next call is needed just to make sure
|
||||
the SDL library is loaded *)
|
||||
_M := SMPEG_new(PChar(FFileName), info, 1);
|
||||
SMPEG_delete(_M);
|
||||
FValid := True;
|
||||
_M := SMPEG_new(PChar(FFileName), info, 0);
|
||||
if info.has_audio <> 1 then
|
||||
begin
|
||||
FValid := False;
|
||||
Exit;
|
||||
end;
|
||||
FTime := Round(info.total_time);
|
||||
SMPEG_wantedSpec(_M, spec);
|
||||
FSR := spec.freq;
|
||||
FBPS := 16;
|
||||
FChan := spec.channels;
|
||||
FSize := FTime*2*FChan*FSR;
|
||||
end;
|
||||
Inc(FOpened);
|
||||
end;
|
||||
|
||||
procedure TMPEGIn.CloseFile;
|
||||
begin
|
||||
if FOpened = 1 then
|
||||
begin
|
||||
if SMPEG_status(_M) = SMPEG_PLAYING then
|
||||
SMPEG_stop(_M);
|
||||
SMPEG_delete(_M);
|
||||
end;
|
||||
if FOpened > 0 then Dec(FOpened);
|
||||
end;
|
||||
|
||||
function TMPEGIn.GetData(Buffer : Pointer; BufferSize : Integer): Integer;
|
||||
var
|
||||
l, offs : Integer;
|
||||
tmp : Single;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create('The Stream is not opened');
|
||||
if BufStart > BufEnd then
|
||||
begin
|
||||
if FOffset <> 0 then
|
||||
begin
|
||||
offs := Round((FOffset/100)*FSize);
|
||||
FPosition := FPosition + offs;
|
||||
if FPosition < 0 then FPosition := 0
|
||||
else if FPosition > FSize then FPosition := FSize;
|
||||
if FOffset < 0 then
|
||||
begin
|
||||
SMPEG_rewind(_M);
|
||||
SMPEG_play(_M);
|
||||
tmp := (FPosition/FSize)*FTime;
|
||||
SMPEG_skip(_M, tmp);
|
||||
end;
|
||||
tmp := (FOffset/100)*FTime;
|
||||
SMPEG_skip(_M, tmp);
|
||||
FOffset := 0;
|
||||
end;
|
||||
BufStart := 1;
|
||||
FillChar(FBuffer, BufferSize, 0);
|
||||
l := Buffersize;
|
||||
l := SMPEG_playAudio(_M, @FBuffer[BufEnd + 1], BufferSize - BufEnd);
|
||||
if l = 0 then
|
||||
begin
|
||||
if FLoop then
|
||||
begin
|
||||
Flush;
|
||||
Init;
|
||||
SMPEG_rewind(_M);
|
||||
SMPEG_play(_M);
|
||||
FPosition := 0;
|
||||
l := SMPEG_playAudio(_M, @FBuffer[BufEnd + 1], BufferSize - BufEnd);
|
||||
end else
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
BufEnd := l;
|
||||
end;
|
||||
if BufferSize < (BufEnd - BufStart + 1)
|
||||
then Result := BufferSize
|
||||
else Result := BufEnd - BufStart + 1;
|
||||
Move(FBuffer[BufStart], Buffer^, Result);
|
||||
Inc(BufStart, Result);
|
||||
Inc(FPosition, Result);
|
||||
end;
|
||||
|
||||
initialization
|
||||
LoadMPEGLibrary;
|
||||
if LibsmpegLoaded then
|
||||
begin
|
||||
FileFormats.Add('mp3','Mpeg Audio Layer III',TMPEGIn);
|
||||
FileFormats.Add('mp2','Mpeg Audio Layer II',TMPEGIn);
|
||||
FileFormats.Add('mpeg','Mpeg Audio',TMPEGIn);
|
||||
end;
|
||||
|
||||
finalization
|
||||
UnLoadMPEGLibrary;
|
||||
|
||||
end.
|
||||
|
||||
673
acs/Src/fileformats/acs_vorbis.pas
Normal file
673
acs/Src/fileformats/acs_vorbis.pas
Normal file
@@ -0,0 +1,673 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.3.
|
||||
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: acs_vorbis.pas,v $
|
||||
Revision 1.8 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.4 2006/01/01 18:46:40 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.3 2005/12/29 20:45:59 z0m3ie
|
||||
fixed some problems with vorbis in lazarus
|
||||
|
||||
Revision 1.2 2005/12/26 17:31:39 z0m3ie
|
||||
fixed some problems in acs_dsfiles
|
||||
fixed some problems in acs_vorbis
|
||||
reworked all buffers
|
||||
|
||||
Revision 1.1 2005/12/19 18:36:38 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.5 2005/12/04 16:54:34 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.4 2005/11/28 21:57:24 z0m3ie
|
||||
mostly FileOut fixes
|
||||
moved PBuffer to PBuffer8
|
||||
set all to dynamically Buffering
|
||||
|
||||
Revision 1.3 2005/10/02 16:51:01 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/09/13 04:04:50 z0m3ie
|
||||
First release without Components for Fileformats
|
||||
only TFileIn and TFileOut are Visible
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.3 2005/09/10 08:25:40 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
unit acs_vorbis;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
{$DEFINE USE_VORBIS_11}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
ACS_File,Classes, SysUtils, ACS_Classes, ogg, vorbiscodec, VorbisFile, VorbisEnc,ACS_Strings
|
||||
{$IFDEF LINUX}
|
||||
,baseunix;
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF WINDOWS}
|
||||
,Windows,Dialogs;
|
||||
{$ENDIF}
|
||||
|
||||
type
|
||||
|
||||
TVorbisBitRate = (brAutoSelect, br45, br48, br56, br64, br80, br96,
|
||||
br112, br128, br144, br160, br192, br224, br256, br320, br499);
|
||||
|
||||
TVorbisOut = class(TACSCustomFileOut)
|
||||
private
|
||||
FComments : TStringList;
|
||||
FSerial : Integer;
|
||||
FDesiredNominalBitrate : TVorbisBitRate;
|
||||
FDesiredMaximumBitrate : TVorbisBitRate;
|
||||
FMinimumBitrate : TVorbisBitRate;
|
||||
OggSS : ogg_stream_state;
|
||||
OggPg : ogg_page;
|
||||
OggPk : ogg_packet;
|
||||
VInfo : vorbis_info;
|
||||
VComm : vorbis_comment;
|
||||
Vdsp : vorbis_dsp_state;
|
||||
VBlock : vorbis_block;
|
||||
header, header_comm, header_code : ogg_packet;
|
||||
FCompression : Single;
|
||||
EndOfStream : Boolean;
|
||||
procedure SetComments(vComments : TStringList);
|
||||
procedure SetDesiredNominalBitrate(Value : TVorbisBitRate);
|
||||
procedure SetDesiredMaximumBitrate(Value : TVorbisBitRate);
|
||||
procedure SetMinimumBitrate(Value : TVorbisBitRate);
|
||||
protected
|
||||
procedure Done; override;
|
||||
function DoOutput(Abort : Boolean):Boolean; override;
|
||||
procedure Prepare; override;
|
||||
procedure SetFileMode(aMode : TACSFileOutputMode); override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
published
|
||||
property Compression : Single read FCompression write FCompression stored True;
|
||||
property Comments : TStringList read FComments write SetComments stored True;
|
||||
property DesiredMaximumBitrate : TVorbisBitRate read FDesiredMaximumBitrate write SetDesiredMaximumBitrate;
|
||||
property DesiredNominalBitrate : TVorbisBitRate read FDesiredNominalBitrate write SetDesiredNominalBitrate;
|
||||
property MinimumBitrate : TVorbisBitRate read FMinimumBitrate write SetMinimumBitrate;
|
||||
property Serial : Integer read FSerial write FSerial;
|
||||
//property Vendor : String read FVendor write FVendor;
|
||||
end;
|
||||
|
||||
TVorbisIn = class(TACSCustomFileIn)
|
||||
private
|
||||
FComments : TStringList;
|
||||
// FVendor : String;
|
||||
VFile : OggVorbis_File;
|
||||
cursec : Integer;
|
||||
FMaxBitrate: Integer;
|
||||
FNominalBitrate: Integer;
|
||||
FMinBitrate : Integer;
|
||||
EndOfStream : Boolean;
|
||||
function GetMaxBitrate: Integer;
|
||||
function GetNominalBitrate: Integer;
|
||||
function GetMinBitrate : Integer;
|
||||
function GetComments : TStringList;
|
||||
function GetBitStreams : Integer;
|
||||
function GetInstantBitRate : Integer;
|
||||
function GetCurrentBitStream : Integer;
|
||||
procedure SetCurrentBitStream(BS : Integer);
|
||||
protected
|
||||
procedure OpenFile; override;
|
||||
procedure CloseFile; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
function Seek(SampleNum : Integer) : Boolean; override;
|
||||
property BitStreams : Integer read GetBitStreams;
|
||||
property Comments : TStringList read GetComments;
|
||||
property CurrentBitStream : Integer read GetCurrentBitStream write SetCurrentBitStream;
|
||||
property InstantBitRate : Integer read GetInstantBitRate;
|
||||
//property Vendor : String read FVendor;
|
||||
property MaxBitrate: Integer read GetMaxBitrate;
|
||||
property MinBitrate: Integer read GetMinBitrate;
|
||||
property NominalBitrate: Integer read GetNominalBitrate;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
function cbRead(ptr : Pointer; size, nmemb : Cardinal;const datasource : Pointer) : Cardinal; cdecl;
|
||||
var
|
||||
VI : TVorbisIn;
|
||||
Buffer : array of Byte;
|
||||
begin
|
||||
VI := TVorbisIn(datasource);
|
||||
SetLength(Buffer, size*nmemb);
|
||||
Result := VI.FStream.Read(Buffer[0], size*nmemb);
|
||||
Move(Buffer[0], ptr^, Result);
|
||||
Setlength(Buffer,0);
|
||||
Buffer := nil;
|
||||
end;
|
||||
|
||||
function cbSeek(const datasource : Pointer; offset : ogg_int64_t; whence : Integer) : Integer; cdecl;
|
||||
var
|
||||
VI : TVorbisIn;
|
||||
Origin : TSeekOrigin;
|
||||
begin
|
||||
VI := TVorbisIn(datasource);
|
||||
if not VI.Seekable then
|
||||
begin
|
||||
Result := -1;
|
||||
Exit;
|
||||
end;
|
||||
case whence of
|
||||
SEEK_SET : Origin := TSeekOrigin(soFromBeginning);
|
||||
SEEK_CUR : Origin := TSeekOrigin(soFromCurrent);
|
||||
SEEK_END : Origin := TSeekOrigin(soFromEnd);
|
||||
end;
|
||||
Result := VI.FStream.Seek(offset, Origin);
|
||||
end;
|
||||
|
||||
function cbClose(const datasource : Pointer) : Integer; cdecl;
|
||||
var
|
||||
VI : TVorbisIn;
|
||||
begin
|
||||
VI := TVorbisIn(datasource);
|
||||
if not VI.FStreamAssigned then VI.FStream.Free
|
||||
else VI.FStream.Seek(0, soFromBeginning);
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function cbTell(const datasource : Pointer) : Integer; cdecl;
|
||||
var
|
||||
VI : TVorbisIn;
|
||||
begin
|
||||
VI := TVorbisIn(datasource);
|
||||
Result := VI.FStream.Position
|
||||
end;
|
||||
|
||||
function VorbisBitrateToInt(Bitrate : TVorbisBitrate) : Integer;
|
||||
begin
|
||||
case Bitrate of
|
||||
br45 : Result := 45000;
|
||||
br48 : Result := 48000;
|
||||
br56 : Result := 46000;
|
||||
br64 : Result := 64000;
|
||||
br80 : Result := 80000;
|
||||
br96 : Result := 96000;
|
||||
br112 : Result := 112000;
|
||||
br128 : Result := 128000;
|
||||
br144 : Result := 144000;
|
||||
br160 : Result := 160000;
|
||||
br192 : Result := 192000;
|
||||
br224 : Result := 224000;
|
||||
br256 : Result := 256000;
|
||||
br320 : Result := 320000;
|
||||
br499 : Result := 499000;
|
||||
else Result := -1;
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TVorbisOut.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FBufferSize := $10000;
|
||||
VORBISLoadLibrary;
|
||||
FCompression := 0.2;
|
||||
FComments := TStringList.Create;
|
||||
FDesiredNominalBitrate := br64;
|
||||
FDesiredMaximumBitrate := br112;
|
||||
FMinimumBitrate := br48;
|
||||
if not (csDesigning in ComponentState) then
|
||||
begin
|
||||
VORBISLoadLibrary;
|
||||
if not LiboggLoaded then
|
||||
raise EACSException.Create(Format(strCoudntloadLib,[Liboggpath]));
|
||||
if not LibvorbisLoaded then
|
||||
raise EACSException.Create(Format(strCoudntloadLib,[LibvorbisPath]));
|
||||
if not LibvorbisfileLoaded then
|
||||
raise EACSException.Create(Format(strCoudntloadLib,[LibvorbisfilePath]));
|
||||
//if not LibvorbisencLoaded then
|
||||
//raise EACSException.Create(Format(strCoudntloadLib,[LibvorbisencPath]));
|
||||
end;
|
||||
end;
|
||||
|
||||
destructor TVorbisOut.Destroy;
|
||||
begin
|
||||
FComments.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TVorbisOut.SetComments;
|
||||
begin
|
||||
FComments.Assign(vComments);
|
||||
end;
|
||||
|
||||
procedure TVorbisOut.Prepare;
|
||||
var
|
||||
i, maxbr, minbr, nombr : Integer;
|
||||
Name, Value : String;
|
||||
rm : ovectl_ratemanage2_arg;
|
||||
begin
|
||||
GetMem(FBuffer,FBufferSize);
|
||||
if not FStreamAssigned then
|
||||
begin
|
||||
if not Assigned(FInput) then
|
||||
raise EACSException.Create(strInputNotAssigned);
|
||||
if FFileName = '' then raise EACSException.Create(strNoFileOpened);
|
||||
if (not FileExists(FFileName)) or (FFileMode = foRewrite) then
|
||||
FStream := TFileStream.Create(FFileName, fmCreate or fmShareExclusive, FAccessMask)
|
||||
else FStream := TFileStream.Create(FFileName, fmOpenReadWrite or fmShareExclusive, FAccessMask);
|
||||
end;
|
||||
FInput.Init;
|
||||
if FFileMode = foAppend then
|
||||
FStream.Seek(0, soFromEnd);
|
||||
EndOfStream := False;
|
||||
vorbis_info_init(VInfo);
|
||||
if DesiredNominalBitrate = brAutoSelect then
|
||||
begin
|
||||
{$IFNDEF USE_VORBIS_11}
|
||||
vorbis_encode_init_vbr(VInfo, FInput.Channels, FInput.SampleRate, FCompression);
|
||||
{$ENDIF}
|
||||
{$IFDEF USE_VORBIS_11}
|
||||
vorbis_encode_setup_vbr(VInfo, FInput.Channels, FInput.SampleRate, FCompression);
|
||||
vorbis_encode_setup_init(VInfo);
|
||||
{$ENDIF}
|
||||
end else
|
||||
begin
|
||||
nombr := VorbisBitrateToInt(FDesiredNominalBitrate);
|
||||
maxbr := VorbisBitrateToInt(FDesiredMaximumBitrate);
|
||||
if maxbr < nombr then maxbr := nombr;
|
||||
minbr := VorbisBitrateToInt(Self.FMinimumBitrate);
|
||||
if minbr < 0 then minbr := nombr;
|
||||
vorbis_encode_init(VInfo, FInput.Channels, FInput.SampleRate, maxbr, nombr, minbr);
|
||||
end;
|
||||
vorbis_comment_init(VComm);
|
||||
for i := 0 to FComments.Count - 1 do
|
||||
begin
|
||||
Name := FComments.Names[i];
|
||||
Value := FComments.Values[Name];
|
||||
vorbis_comment_add_tag(VComm, PChar(Name), PChar(Value));
|
||||
end;
|
||||
vorbis_analysis_init(Vdsp, VInfo);
|
||||
vorbis_block_init(Vdsp, VBlock);
|
||||
ogg_stream_init(OggSS, FSerial);
|
||||
vorbis_analysis_headerout(Vdsp, VComm, header, header_comm, header_code);
|
||||
ogg_stream_packetin(OggSS, header);
|
||||
ogg_stream_packetin(OggSS, header_comm);
|
||||
ogg_stream_packetin(OggSS, header_code);
|
||||
while ogg_stream_flush(OggSS, OggPg) <> 0 do
|
||||
begin
|
||||
FStream.Write(OggPg.header^, OggPg.header_len);
|
||||
FStream.Write(OggPg.body^, OggPg.body_len);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TVorbisOut.Done;
|
||||
begin
|
||||
if not FStreamAssigned then
|
||||
FStream.Free;
|
||||
FInput.Flush;
|
||||
FComments.Clear;
|
||||
ogg_stream_clear(OggSS);
|
||||
vorbis_block_clear(VBlock);
|
||||
vorbis_dsp_clear(Vdsp);
|
||||
vorbis_comment_clear(VComm);
|
||||
vorbis_info_clear(VInfo);
|
||||
FreeMem(FBuffer);
|
||||
end;
|
||||
|
||||
function TVorbisOut.DoOutput(Abort : Boolean):Boolean;
|
||||
var
|
||||
Len, i,chc : Integer;
|
||||
out_buf : PPFloat;
|
||||
tmpBuf1, tmpBuf2 : PFloat;
|
||||
begin
|
||||
// No exceptions Here
|
||||
Result := True;
|
||||
if not CanOutput then Exit;
|
||||
if Abort or EndOfStream then
|
||||
begin
|
||||
(* We don't close file here to avoide exceptions
|
||||
if output componenet's Stop method is called *)
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
while InputLock do;
|
||||
InputLock := True;
|
||||
chc := Finput.Channels;
|
||||
Len := Finput.GetData(@FBuffer[0], FBufferSize);
|
||||
InputLock := False;
|
||||
if Len <> 0 then
|
||||
begin
|
||||
if chc = 2 then
|
||||
begin
|
||||
out_buf := vorbis_analysis_buffer(Vdsp, FBufferSize shr 2);
|
||||
(* A bit of pointer arithmetics. What is easy in C
|
||||
is not so easy in Pascal. *)
|
||||
tmpBuf1 := out_buf^;
|
||||
Inc(out_buf);
|
||||
tmpBuf2 := out_buf^;
|
||||
for i:=0 to (Len shr 2)-1 do
|
||||
begin
|
||||
tmpBuf1[i] := FBuffer[i*2]/$8000;
|
||||
tmpBuf2[i] := FBuffer[i*2+1]/$8000;
|
||||
end;
|
||||
vorbis_analysis_wrote(Vdsp, Len shr 2);
|
||||
end else
|
||||
begin
|
||||
out_buf := vorbis_analysis_buffer(Vdsp, FBufferSize shr 1);
|
||||
for i:=0 to (Len shr 1)-1 do
|
||||
out_buf^[i] := FBuffer[i]/$8000;
|
||||
vorbis_analysis_wrote(Vdsp, Len shr 1);
|
||||
end;
|
||||
end else
|
||||
vorbis_analysis_wrote(Vdsp, 0);
|
||||
while vorbis_analysis_blockout(Vdsp, VBlock) = 1 do
|
||||
begin
|
||||
vorbis_analysis(VBlock, nil);
|
||||
vorbis_bitrate_addblock(VBlock);
|
||||
while vorbis_bitrate_flushpacket(Vdsp, OggPk) = 1 do
|
||||
begin
|
||||
ogg_stream_packetin(OggSS, OggPk);
|
||||
while not EndOfStream do
|
||||
begin
|
||||
if ogg_stream_pageout(OggSS, OggPg) = 0 then Break;
|
||||
FStream.Write(OggPg.header^, OggPg.header_len);
|
||||
FStream.Write(OggPg.body^, OggPg.body_len);
|
||||
if ogg_page_eos(OggPg) <> 0 then EndOfStream := True;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TVorbisIn.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
BufferSize := $2000;
|
||||
FComments := TStringList.Create;
|
||||
if not (csDesigning in ComponentState) then
|
||||
begin
|
||||
VORBISLoadLibrary;
|
||||
if not LiboggLoaded then
|
||||
raise EACSException.Create(Format(strCoudntloadLib,[LiboggPath]));
|
||||
if not LibvorbisLoaded then
|
||||
raise EACSException.Create(Format(strCoudntloadLib,[LibvorbisPath]));
|
||||
if not LibvorbisfileLoaded then
|
||||
raise EACSException.Create(Format(strCoudntloadLib,[LibvorbisfilePath]));
|
||||
//if not LibvorbisencLoaded then
|
||||
//raise EACSException.Create(Format(strCoudntloadLib,[LibvorbisencPath]));
|
||||
end;
|
||||
end;
|
||||
|
||||
destructor TVorbisIn.Destroy;
|
||||
begin
|
||||
FComments.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TVorbisIn.OpenFile;
|
||||
var
|
||||
PVComm : PVORBIS_COMMENT;
|
||||
PVInfo : PVORBIS_INFO;
|
||||
PComment : PPChar;
|
||||
Comment : PChar;
|
||||
Callbacks : OV_CALLBACKS;
|
||||
begin
|
||||
if FOpened = 0 then
|
||||
begin
|
||||
FValid := True;
|
||||
EndOfStream := False;
|
||||
if not FStreamAssigned then
|
||||
try
|
||||
Stream := TFileStream.Create(FileName, fmOpenRead) as TFileStream;
|
||||
except
|
||||
FValid := False;
|
||||
Exit;
|
||||
end;
|
||||
Callbacks.read_func := cbRead;
|
||||
Callbacks.close_func := cbClose;
|
||||
Callbacks.seek_func := cbSeek;
|
||||
Callbacks.tell_func := cbTell;
|
||||
ov_open_callbacks(Self, VFile, nil, 0, Callbacks);
|
||||
FComments.Clear;
|
||||
{ PVComm := ov_comment(VFile, -1);
|
||||
PComment := PVComm.user_comments;
|
||||
Comment := PComment^;
|
||||
while Comment <> nil do
|
||||
begin
|
||||
FComments.Add(String(Comment));
|
||||
Inc(LongWord(PComment), 4);
|
||||
Comment := PComment^;
|
||||
end;}
|
||||
// FVendor := PVComm.vendor;
|
||||
PVInfo := ov_info(VFile, -1);
|
||||
FChan := PVInfo.channels;
|
||||
FSR := PVInfo.rate;
|
||||
FBPS := 16;
|
||||
FMaxBitrate := PVInfo.bitrate_upper;
|
||||
FNominalBitrate := PVInfo.bitrate_nominal;
|
||||
FMinBitrate := PVInfo.bitrate_lower;
|
||||
FTotalSamples := ov_pcm_total(VFile, -1);
|
||||
FSize := (FTotalSamples shl 1) * PVInfo.channels;
|
||||
cursec := -1;
|
||||
FTime := Round(ov_time_total(VFile, -1));
|
||||
// ov_pcm_seek(VFile, FOffset);
|
||||
end;
|
||||
Inc(FOpened);
|
||||
end;
|
||||
|
||||
procedure TVorbisIn.CloseFile;
|
||||
begin
|
||||
if FOpened = 1 then
|
||||
begin
|
||||
if ov_seekable(VFile) <> 0 then
|
||||
ov_pcm_seek(VFile, 0);
|
||||
ov_clear(VFile);
|
||||
end;
|
||||
if FOpened > 0 then Dec(FOpened);
|
||||
end;
|
||||
|
||||
function TVorbisIn.GetData(Buffer : Pointer; BufferSize : Integer): Integer;
|
||||
var
|
||||
l, offs : Integer;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create('The Stream is not opened');
|
||||
if BufStart > BufEnd then
|
||||
begin
|
||||
if FOffset <> 0 then
|
||||
begin
|
||||
offs := Round((FOffset/100)*FSize);
|
||||
FPosition := FPosition + offs;
|
||||
if FPosition < 0 then FPosition := 0
|
||||
else if FPosition > FSize then FPosition := FSize;
|
||||
// tmp := (FPosition/FSize)*FTime;
|
||||
if ov_seekable(VFile) <> 0 then
|
||||
ov_pcm_seek(VFile, (FPosition shr 1) div FChan);
|
||||
FOffset := 0;
|
||||
end;
|
||||
BufStart := 1;
|
||||
BufEnd := 0;
|
||||
if not EndOfStream then
|
||||
begin
|
||||
(* The ov_read function can return data in quite small chunks
|
||||
(of about 512 bytes). We keep reading data until the buffer is filled
|
||||
or there is no more data to read. *)
|
||||
while BufEnd < BufferSize do
|
||||
begin
|
||||
l := ov_read(VFile, @FBuffer[BufEnd + 1], BufferSize - BufEnd, 0, 2, 1, @cursec);
|
||||
if l <= 0 then
|
||||
begin
|
||||
EndOfStream := True;
|
||||
Break;
|
||||
end;
|
||||
Inc(BufEnd, l);
|
||||
if (FPosition + BufEnd) >= FSize then
|
||||
begin
|
||||
BufEnd := FSize - FPosition;
|
||||
if BufEnd <= 0 then EndOfStream := True;
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if EndOfStream and FLoop then
|
||||
begin
|
||||
Flush;
|
||||
Init;
|
||||
EndOfStream := False;
|
||||
while BufEnd < BufferSize do
|
||||
begin
|
||||
l := ov_read(VFile, @FBuffer[BufEnd + 1], BufferSize - BufEnd, 0, 2, 1, @cursec);
|
||||
if l <= 0 then
|
||||
begin
|
||||
EndOfStream := True;
|
||||
Break;
|
||||
end;
|
||||
Inc(BufEnd, l);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if BufferSize < (BufEnd - BufStart + 1)
|
||||
then Result := BufferSize
|
||||
else Result := BufEnd - BufStart + 1;
|
||||
Move(FBuffer[BufStart], Buffer^, Result);
|
||||
Inc(BufStart, Result);
|
||||
Inc(FPosition, Result);
|
||||
end;
|
||||
|
||||
function TVorbisIn.GetMaxBitrate : Integer;
|
||||
begin
|
||||
OpenFile;
|
||||
Result := FMaxBitrate;
|
||||
CloseFile;
|
||||
end;
|
||||
|
||||
function TVorbisIn.GetNominalBitrate : Integer;
|
||||
begin
|
||||
OpenFile;
|
||||
Result := FNominalBitrate;
|
||||
CloseFile;
|
||||
end;
|
||||
|
||||
function TVorbisIn.GetComments : TStringList;
|
||||
begin
|
||||
OpenFile;
|
||||
Result := FComments;
|
||||
CloseFile;
|
||||
end;
|
||||
|
||||
function TVorbisIn.GetMinBitrate : Integer;
|
||||
begin
|
||||
OpenFile;
|
||||
Result := FMinBitrate;
|
||||
CloseFile;
|
||||
end;
|
||||
|
||||
procedure TVorbisOut.SetFileMode;
|
||||
begin
|
||||
FFileMode := aMode;
|
||||
end;
|
||||
|
||||
function TVorbisIn.GetBitStreams : Integer;
|
||||
begin
|
||||
Result := 0;
|
||||
if Busy then
|
||||
begin
|
||||
if ov_seekable(VFile)<>0 then
|
||||
Result := ov_streams(VFile);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TVorbisIn.GetInstantBitRate : Integer;
|
||||
begin
|
||||
Result := 0;
|
||||
if Busy then
|
||||
begin
|
||||
Result := ov_bitrate_instant(VFile);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TVorbisIn.GetCurrentBitStream : Integer;
|
||||
begin
|
||||
Result := -1;
|
||||
if Busy then
|
||||
begin
|
||||
if ov_seekable(VFile)<>0 then
|
||||
Result := VFile.current_link;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TVorbisIn.SetCurrentBitStream;
|
||||
var
|
||||
Offset : POGG_INT64_T;
|
||||
begin
|
||||
if Busy then
|
||||
begin
|
||||
if ov_seekable(VFile)<>0 then
|
||||
if (BS >= 0) and (BS < ov_streams(VFile)) then
|
||||
begin
|
||||
Offset := VFile.offsets;
|
||||
Inc(Offset, BS);
|
||||
FStream.Seek(Offset^, soFromBeginning);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TVorbisOut.SetDesiredNominalBitrate;
|
||||
begin
|
||||
FDesiredNominalBitrate := Value;
|
||||
if FMinimumBitrate > FDesiredNominalBitrate then
|
||||
FMinimumBitrate := FDesiredNominalBitrate;
|
||||
if FDesiredMaximumBitrate < FDesiredNominalBitrate then
|
||||
FDesiredMaximumBitrate := FDesiredNominalBitrate;
|
||||
if FDesiredNominalBitrate = brAutoSelect then
|
||||
FDesiredMaximumBitrate := brAutoSelect;
|
||||
end;
|
||||
|
||||
procedure TVorbisOut.SetDesiredMaximumBitrate;
|
||||
begin
|
||||
if FDesiredNominalBitrate = brAutoSelect then Exit;
|
||||
if (Value = brAutoSelect) or (Value >= FDesiredNominalBitrate) then
|
||||
FDesiredMaximumBitrate := Value;
|
||||
end;
|
||||
|
||||
procedure TVorbisOut.SetMinimumBitrate;
|
||||
begin
|
||||
if Value <= FDesiredNominalBitrate then
|
||||
FMinimumBitrate := Value;
|
||||
end;
|
||||
|
||||
function TVorbisIn.Seek(SampleNum : Integer) : Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
if not FSeekable then Exit;
|
||||
Result := True;
|
||||
OpenFile;
|
||||
ov_pcm_seek(VFile, SampleNum);
|
||||
CloseFile;
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
||||
FileFormats.Add('ogg','Ogg Vorbis',TVorbisOut);
|
||||
FileFormats.Add('ogg','Ogg Vorbis',TVorbisIn);
|
||||
|
||||
end.
|
||||
1843
acs/Src/fileformats/acs_wave.pas
Normal file
1843
acs/Src/fileformats/acs_wave.pas
Normal file
File diff suppressed because it is too large
Load Diff
606
acs/Src/fileformats/general/flac.pas
Normal file
606
acs/Src/fileformats/general/flac.pas
Normal file
@@ -0,0 +1,606 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.3.
|
||||
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: flac.pas,v $
|
||||
Revision 1.1 2005/12/19 18:36:56 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:53 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
unit flac;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
{$IFDEF WINDOWS}
|
||||
Windows;
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF LINUX}
|
||||
baseunix,dl, ACS_Procs;
|
||||
{$ENDIF}
|
||||
|
||||
var
|
||||
|
||||
LibFLACLoaded : Boolean = False;
|
||||
|
||||
const
|
||||
|
||||
{$IFDEF WINDOWS}
|
||||
LibFLACPath = 'libFLAC.dll';
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF LINUX}
|
||||
LibFLACPath = 'libFLAC.so*'; // libFLAC.so
|
||||
{$DEFINE SEARCH_LIBS}
|
||||
{$ENDIF}
|
||||
|
||||
FLAC__SEEKABLE_STREAM_ENCODER_OK = 0;
|
||||
FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR = 1;
|
||||
FLAC__SEEKABLE_STREAM_ENCODER_MEMORY_ALLOCATION_ERROR = 2;
|
||||
FLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR = 3;
|
||||
FLAC__SEEKABLE_STREAM_ENCODER_READ_ERROR = 4;
|
||||
FLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR = 5;
|
||||
FLAC__SEEKABLE_STREAM_ENCODER_ALREADY_INITIALIZED = 6;
|
||||
FLAC__SEEKABLE_STREAM_ENCODER_INVALID_CALLBACK = 7;
|
||||
FLAC__SEEKABLE_STREAM_ENCODER_INVALID_SEEKTABLE = 8;
|
||||
FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED = 9;
|
||||
|
||||
FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK = 0;
|
||||
FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_ERROR = 1;
|
||||
|
||||
FLAC__SEEKABLE_STREAM_DECODER_OK = 0;
|
||||
FLAC__SEEKABLE_STREAM_DECODER_SEEKING = 1;
|
||||
FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM = 2;
|
||||
FLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR = 3;
|
||||
FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR = 4;
|
||||
FLAC__SEEKABLE_STREAM_DECODER_READ_ERROR = 5;
|
||||
FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR = 6;
|
||||
FLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED = 7;
|
||||
FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK = 8;
|
||||
FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED = 10;
|
||||
|
||||
FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK = 0;
|
||||
FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR = 1;
|
||||
|
||||
FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK = 0;
|
||||
FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR = 1;
|
||||
|
||||
FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK = 0;
|
||||
FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR = 1;
|
||||
|
||||
FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK = 0;
|
||||
FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR = 1;
|
||||
|
||||
type
|
||||
|
||||
FLAC__byte = Byte;
|
||||
PFLAC__byte = ^FLAC__byte;
|
||||
|
||||
FLAC__uint64 = Int64;
|
||||
PFLAC__uint64 = ^FLAC__uint64;
|
||||
|
||||
FLAC__uint32 = LongWord;
|
||||
PFLAC__uint32 = ^FLAC__uint32;
|
||||
|
||||
FLAC__int32 = Integer;
|
||||
PFLAC__int32 = ^FLAC__int32;
|
||||
|
||||
PFLAC__SeekableStreamEncoder = Pointer;
|
||||
|
||||
PFLAC__SeekableStreamDecoder = Pointer;
|
||||
|
||||
FLAC__MetadataType = Integer;
|
||||
|
||||
PFLAC__Frame = Pointer;
|
||||
|
||||
FLAC__FrameHeader = packed record
|
||||
blocksize : LongWord;
|
||||
sample_rate : LongWord;
|
||||
channels : LongWord;
|
||||
channel_assignment : Integer;
|
||||
bits_per_sample : LongWord;
|
||||
frame_number : FLAC__uint32;
|
||||
crc : Byte;
|
||||
end;
|
||||
|
||||
FLACInfo = record
|
||||
min_blocksize : LongWord;
|
||||
max_blocksize : LongWord;
|
||||
min_framesize : LongWord;
|
||||
max_framesize : LongWord;
|
||||
sample_rate : LongWord;
|
||||
channels : LongWord;
|
||||
bits_per_sample : LongWord;
|
||||
total_samples1 : LongWord;
|
||||
total_samples2 : LongWord;
|
||||
end;
|
||||
|
||||
PFLACInfo = ^FLACInfo;
|
||||
|
||||
PFLAC__StreamMetadata = Pointer;
|
||||
|
||||
PFLAC__FrameHeader = ^FLAC__FrameHeader;
|
||||
|
||||
FLACIntBuf = array[0..0] of FLAC__int32;
|
||||
PFLACIntBuf = ^FLACIntBuf;
|
||||
|
||||
FLACChannels = array[0..1] of PFLACIntBuf;
|
||||
PFLACChannels = ^FLACChannels;
|
||||
|
||||
FLAC__SeekableStreamEncoderWriteCallback = function(encoder : PFLAC__SeekableStreamEncoder;
|
||||
buffer : PFLAC__byte;
|
||||
bytes,
|
||||
samples,
|
||||
current_frame : LongWord;
|
||||
client_data : Pointer) : Integer; cdecl;
|
||||
|
||||
|
||||
FLAC__SeekableStreamEncoderSeekCallback = function(encoder : PFLAC__SeekableStreamEncoder;
|
||||
absolute_byte_offset : FLAC__uint64;
|
||||
client_data : Pointer) : Integer; cdecl;
|
||||
|
||||
FLAC__SeekableStreamDecoderReadCallback = function(decoder : PFLAC__SeekableStreamDecoder;
|
||||
buffer : PFLAC__byte;
|
||||
var bytes : LongWord;
|
||||
client_data : Pointer) : Integer; cdecl;
|
||||
|
||||
FLAC__SeekableStreamDecoderSeekCallback = function(decoder : PFLAC__SeekableStreamDecoder;
|
||||
absolute_byte_offset : FLAC__uint64;
|
||||
client_data : Pointer) : Integer; cdecl;
|
||||
|
||||
FLAC__SeekableStreamDecoderTellCallback = function(decoder : PFLAC__SeekableStreamDecoder;
|
||||
var absolute_byte_offset : FLAC__uint64;
|
||||
client_data : Pointer) : Integer; cdecl;
|
||||
|
||||
FLAC__SeekableStreamDecoderLengthCallback = function(decoder : PFLAC__SeekableStreamDecoder;
|
||||
var stream_length : FLAC__uint64;
|
||||
client_data : Pointer) : Integer; cdecl;
|
||||
|
||||
FLAC__SeekableStreamDecoderEofCallback = function(decoder : PFLAC__SeekableStreamDecoder;
|
||||
client_data : Pointer) : Boolean; cdecl;
|
||||
|
||||
FLAC__SeekableStreamDecoderWriteCallback = function(decoder : PFLAC__SeekableStreamDecoder;
|
||||
frame : PFLAC__Frame;
|
||||
buffer : PFLACChannels;
|
||||
client_data : Pointer) : Integer; cdecl;
|
||||
|
||||
FLAC__SeekableStreamDecoderMetadataCallback = procedure(decoder : PFLAC__SeekableStreamDecoder;
|
||||
metadata : PFLAC__StreamMetadata;
|
||||
client_data : Pointer); cdecl;
|
||||
|
||||
FLAC__SeekableStreamDecoderErrorCallback = procedure(decoder : PFLAC__SeekableStreamDecoder;
|
||||
status : Integer;
|
||||
client_data : Pointer); cdecl;
|
||||
|
||||
FLAC__seekable_stream_encoder_new_t = function : PFLAC__SeekableStreamEncoder; cdecl;
|
||||
FLAC__seekable_stream_encoder_delete_t = procedure(encoder : PFLAC__SeekableStreamEncoder); cdecl;
|
||||
FLAC__seekable_stream_encoder_set_verify_t = function( encoder : PFLAC__SeekableStreamEncoder; value : Boolean) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_set_streamable_subset_t = function( encoder : PFLAC__SeekableStreamEncoder; value : Boolean) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_set_do_mid_side_stereo_t = function( encoder : PFLAC__SeekableStreamEncoder; value : Boolean) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_set_loose_mid_side_stereo_t = function( encoder : PFLAC__SeekableStreamEncoder; value : Boolean) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_set_channels_t = function( encoder : PFLAC__SeekableStreamEncoder; value : LongWord) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_set_bits_per_sample_t = function( encoder : PFLAC__SeekableStreamEncoder; value : LongWord) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_set_sample_rate_t = function( encoder : PFLAC__SeekableStreamEncoder; value : LongWord) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_set_blocksize_t = function( encoder : PFLAC__SeekableStreamEncoder; value : LongWord) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_set_max_lpc_order_t = function( encoder : PFLAC__SeekableStreamEncoder; value : LongWord) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_set_qlp_coeff_precision_t = function( encoder : PFLAC__SeekableStreamEncoder; value : LongWord) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search_t = function( encoder : PFLAC__SeekableStreamEncoder; value : Boolean) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_set_do_escape_coding_t = function( encoder : PFLAC__SeekableStreamEncoder; value : Boolean) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_set_do_exhaustive_model_search_t = function( encoder : PFLAC__SeekableStreamEncoder; value : Boolean) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_set_min_residual_partition_order_t = function( encoder : PFLAC__SeekableStreamEncoder; value : LongWord) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_set_max_residual_partition_order_t = function( encoder : PFLAC__SeekableStreamEncoder; value : LongWord) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_set_rice_parameter_search_dist_t = function( encoder : PFLAC__SeekableStreamEncoder; value : LongWord) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_set_total_samples_estimate_t = function( encoder : PFLAC__SeekableStreamEncoder; value : FLAC__uint64) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_set_metadata_t = function( encoder : PFLAC__SeekableStreamEncoder; metadata : Pointer; num_blocks : LongWord) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_set_seek_callback_t = function( encoder : PFLAC__SeekableStreamEncoder; value : FLAC__SeekableStreamEncoderSeekCallback) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_set_write_callback_t = function( encoder : PFLAC__SeekableStreamEncoder; value : FLAC__SeekableStreamEncoderWriteCallback) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_set_client_data_t = function( encoder : PFLAC__SeekableStreamEncoder; value : Pointer) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_get_state_t = function( encoder : PFLAC__SeekableStreamEncoder) : Integer; cdecl;
|
||||
FLAC__seekable_stream_encoder_get_stream_encoder_state_t = function( encoder : PFLAC__SeekableStreamEncoder) : Integer; cdecl;
|
||||
FLAC__seekable_stream_encoder_get_verify_decoder_state_t = function( encoder : PFLAC__SeekableStreamEncoder) : Integer; cdecl;
|
||||
FLAC__seekable_stream_encoder_get_resolved_state_string_t = function( encoder : PFLAC__SeekableStreamEncoder) : PChar; cdecl;
|
||||
FLAC__seekable_stream_encoder_get_verify_decoder_error_stats_t = procedure(encoder : PFLAC__SeekableStreamEncoder; absolute_sample : PFLAC__uint64; frame_number, channel, sample : PLongWord; expected, got : FLAC__int32); cdecl;
|
||||
FLAC__seekable_stream_encoder_get_verify_t = function( encoder : PFLAC__SeekableStreamEncoder) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_get_streamable_subset_t = function( encoder : PFLAC__SeekableStreamEncoder) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_get_do_mid_side_stereo_t = function( encoder : PFLAC__SeekableStreamEncoder) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_get_loose_mid_side_stereo_t = function( encoder : PFLAC__SeekableStreamEncoder) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_get_channels_t = function( encoder : PFLAC__SeekableStreamEncoder) : LongWord; cdecl;
|
||||
FLAC__seekable_stream_encoder_get_bits_per_sample_t = function( encoder : PFLAC__SeekableStreamEncoder) : LongWord; cdecl;
|
||||
FLAC__seekable_stream_encoder_get_sample_rate_t = function( encoder : PFLAC__SeekableStreamEncoder) : LongWord; cdecl;
|
||||
FLAC__seekable_stream_encoder_get_blocksize_t = function( encoder : PFLAC__SeekableStreamEncoder) : LongWord; cdecl;
|
||||
FLAC__seekable_stream_encoder_get_max_lpc_order_t = function( encoder : PFLAC__SeekableStreamEncoder) : LongWord; cdecl;
|
||||
FLAC__seekable_stream_encoder_get_qlp_coeff_precision_t = function( encoder : PFLAC__SeekableStreamEncoder) : LongWord; cdecl;
|
||||
FLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search_t = function( encoder : PFLAC__SeekableStreamEncoder) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_get_do_escape_coding_t = function( encoder : PFLAC__SeekableStreamEncoder) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_get_do_exhaustive_model_search_t = function( encoder : PFLAC__SeekableStreamEncoder) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_get_min_residual_partition_order_t = function( encoder : PFLAC__SeekableStreamEncoder) : LongWord; cdecl;
|
||||
FLAC__seekable_stream_encoder_get_max_residual_partition_order_t = function( encoder : PFLAC__SeekableStreamEncoder) : LongWord; cdecl;
|
||||
FLAC__seekable_stream_encoder_get_rice_parameter_search_dist_t = function( encoder : PFLAC__SeekableStreamEncoder) : LongWord; cdecl;
|
||||
FLAC__seekable_stream_encoder_get_total_samples_estimate_t = function( encoder : PFLAC__SeekableStreamEncoder) : FLAC__uint64 cdecl;
|
||||
FLAC__seekable_stream_encoder_init_t = function( encoder : PFLAC__SeekableStreamEncoder) : Integer; cdecl;
|
||||
FLAC__seekable_stream_encoder_finish_t = procedure(encoder : PFLAC__SeekableStreamEncoder); cdecl;
|
||||
FLAC__seekable_stream_encoder_process_t = function(encoder : PFLAC__SeekableStreamEncoder; buffer : PFLAC__int32; samples : LongWord) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_encoder_process_interleaved_t = function(encoder : PFLAC__SeekableStreamEncoder; buffer : PFLAC__int32; samples : LongWord) : Boolean; cdecl;
|
||||
|
||||
FLAC__seekable_stream_decoder_new_t = function : PFLAC__SeekableStreamDecoder; cdecl;
|
||||
FLAC__seekable_stream_decoder_delete_t = procedure(decoder : PFLAC__SeekableStreamDecoder); cdecl;
|
||||
FLAC__seekable_stream_decoder_set_md5_checking_t = function( decoder : PFLAC__SeekableStreamDecoder; value : Boolean) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_set_read_callback_t = function( decoder : PFLAC__SeekableStreamDecoder; value : FLAC__SeekableStreamDecoderReadCallback) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_set_seek_callback_t = function( decoder : PFLAC__SeekableStreamDecoder; value : FLAC__SeekableStreamDecoderSeekCallback) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_set_tell_callback_t = function( decoder : PFLAC__SeekableStreamDecoder; value : FLAC__SeekableStreamDecoderTellCallback) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_set_length_callback_t = function( decoder : PFLAC__SeekableStreamDecoder; value : FLAC__SeekableStreamDecoderLengthCallback) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_set_eof_callback_t = function( decoder : PFLAC__SeekableStreamDecoder; value : FLAC__SeekableStreamDecoderEofCallback) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_set_write_callback_t = function( decoder : PFLAC__SeekableStreamDecoder; value : FLAC__SeekableStreamDecoderWriteCallback) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_set_metadata_callback_t = function( decoder : PFLAC__SeekableStreamDecoder; value : FLAC__SeekableStreamDecoderMetadataCallback) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_set_error_callback_t = function( decoder : PFLAC__SeekableStreamDecoder; value : FLAC__SeekableStreamDecoderErrorCallback) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_set_client_data_t = function( decoder : PFLAC__SeekableStreamDecoder; value : Pointer) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_set_metadata_respond_t = function( decoder : PFLAC__SeekableStreamDecoder; _type : FLAC__MetadataType) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_set_metadata_respond_application_t = function( decoder : PFLAC__SeekableStreamDecoder; id : PFLAC__byte) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_set_metadata_respond_all_t = function( decoder : PFLAC__SeekableStreamDecoder) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_set_metadata_ignore_t = function( decoder : PFLAC__SeekableStreamDecoder; _type : FLAC__MetadataType) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_set_metadata_ignore_application_t = function( decoder : PFLAC__SeekableStreamDecoder; id : PFLAC__byte) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_set_metadata_ignore_all_t = function( decoder : PFLAC__SeekableStreamDecoder) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_get_state_t = function( decoder : PFLAC__SeekableStreamDecoder) : Integer; cdecl;
|
||||
FLAC__seekable_stream_decoder_get_stream_decoder_state_t = function( decoder : PFLAC__SeekableStreamDecoder) : Integer; cdecl;
|
||||
FLAC__seekable_stream_decoder_get_resolved_state_string_t = function( decoder : PFLAC__SeekableStreamDecoder) : PChar; cdecl;
|
||||
FLAC__seekable_stream_decoder_get_md5_checking_t = function( decoder : PFLAC__SeekableStreamDecoder) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_get_channels_t = function( decoder : PFLAC__SeekableStreamDecoder) : Integer; cdecl;
|
||||
FLAC__seekable_stream_decoder_get_channel_assignment_t = function( decoder : PFLAC__SeekableStreamDecoder) : Integer; cdecl;
|
||||
FLAC__seekable_stream_decoder_get_bits_per_sample_t = function( decoder : PFLAC__SeekableStreamDecoder) : LongWord; cdecl;
|
||||
FLAC__seekable_stream_decoder_get_sample_rate_t = function( decoder : PFLAC__SeekableStreamDecoder) : LongWord; cdecl;
|
||||
FLAC__seekable_stream_decoder_get_blocksize_t = function( decoder : PFLAC__SeekableStreamDecoder) : LongWord; cdecl;
|
||||
FLAC__seekable_stream_decoder_get_decode_position_t = function( decoder : PFLAC__SeekableStreamDecoder; var position : FLAC__uint64) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_init_t = function( decoder : PFLAC__SeekableStreamDecoder) : Integer; cdecl;
|
||||
FLAC__seekable_stream_decoder_finish_t = function( decoder : PFLAC__SeekableStreamDecoder) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_flush_t = function( decoder : PFLAC__SeekableStreamDecoder) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_reset_t = function( decoder : PFLAC__SeekableStreamDecoder) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_process_single_t = function( decoder : PFLAC__SeekableStreamDecoder) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_process_until_end_of_metadata_t = function( decoder : PFLAC__SeekableStreamDecoder) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_process_until_end_of_stream_t = function( decoder : PFLAC__SeekableStreamDecoder) : Boolean; cdecl;
|
||||
FLAC__seekable_stream_decoder_seek_absolute_t = function( decoder : PFLAC__SeekableStreamDecoder; sample : FLAC__uint64) : Boolean; cdecl;
|
||||
|
||||
var
|
||||
|
||||
FLAC__seekable_stream_encoder_new : FLAC__seekable_stream_encoder_new_t;
|
||||
FLAC__seekable_stream_encoder_delete : FLAC__seekable_stream_encoder_delete_t;
|
||||
FLAC__seekable_stream_encoder_set_verify : FLAC__seekable_stream_encoder_set_verify_t;
|
||||
FLAC__seekable_stream_encoder_set_streamable_subset : FLAC__seekable_stream_encoder_set_streamable_subset_t;
|
||||
FLAC__seekable_stream_encoder_set_do_mid_side_stereo : FLAC__seekable_stream_encoder_set_do_mid_side_stereo_t;
|
||||
FLAC__seekable_stream_encoder_set_loose_mid_side_stereo : FLAC__seekable_stream_encoder_set_loose_mid_side_stereo_t;
|
||||
FLAC__seekable_stream_encoder_set_channels : FLAC__seekable_stream_encoder_set_channels_t;
|
||||
FLAC__seekable_stream_encoder_set_bits_per_sample : FLAC__seekable_stream_encoder_set_bits_per_sample_t;
|
||||
FLAC__seekable_stream_encoder_set_sample_rate : FLAC__seekable_stream_encoder_set_sample_rate_t;
|
||||
FLAC__seekable_stream_encoder_set_blocksize : FLAC__seekable_stream_encoder_set_blocksize_t;
|
||||
FLAC__seekable_stream_encoder_set_max_lpc_order : FLAC__seekable_stream_encoder_set_max_lpc_order_t;
|
||||
FLAC__seekable_stream_encoder_set_qlp_coeff_precision : FLAC__seekable_stream_encoder_set_qlp_coeff_precision_t;
|
||||
FLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search : FLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search_t;
|
||||
FLAC__seekable_stream_encoder_set_do_escape_coding : FLAC__seekable_stream_encoder_set_do_escape_coding_t;
|
||||
FLAC__seekable_stream_encoder_set_do_exhaustive_model_search : FLAC__seekable_stream_encoder_set_do_exhaustive_model_search_t;
|
||||
FLAC__seekable_stream_encoder_set_min_residual_partition_order : FLAC__seekable_stream_encoder_set_min_residual_partition_order_t;
|
||||
FLAC__seekable_stream_encoder_set_max_residual_partition_order : FLAC__seekable_stream_encoder_set_max_residual_partition_order_t;
|
||||
// FLAC__seekable_stream_encoder_set_rice_parameter_search_dist : FLAC__seekable_stream_encoder_set_rice_parameter_search_dist_t;
|
||||
FLAC__seekable_stream_encoder_set_total_samples_estimate : FLAC__seekable_stream_encoder_set_total_samples_estimate_t;
|
||||
FLAC__seekable_stream_encoder_set_metadata : FLAC__seekable_stream_encoder_set_metadata_t;
|
||||
FLAC__seekable_stream_encoder_set_seek_callback : FLAC__seekable_stream_encoder_set_seek_callback_t;
|
||||
FLAC__seekable_stream_encoder_set_write_callback : FLAC__seekable_stream_encoder_set_write_callback_t;
|
||||
FLAC__seekable_stream_encoder_set_client_data : FLAC__seekable_stream_encoder_set_client_data_t;
|
||||
FLAC__seekable_stream_encoder_get_state : FLAC__seekable_stream_encoder_get_state_t;
|
||||
FLAC__seekable_stream_encoder_get_stream_encoder_state : FLAC__seekable_stream_encoder_get_stream_encoder_state_t;
|
||||
FLAC__seekable_stream_encoder_get_verify_decoder_state : FLAC__seekable_stream_encoder_get_verify_decoder_state_t;
|
||||
FLAC__seekable_stream_encoder_get_resolved_state_string : FLAC__seekable_stream_encoder_get_resolved_state_string_t;
|
||||
FLAC__seekable_stream_encoder_get_verify_decoder_error_stats : FLAC__seekable_stream_encoder_get_verify_decoder_error_stats_t;
|
||||
FLAC__seekable_stream_encoder_get_verify : FLAC__seekable_stream_encoder_get_verify_t;
|
||||
FLAC__seekable_stream_encoder_get_streamable_subset : FLAC__seekable_stream_encoder_get_streamable_subset_t;
|
||||
FLAC__seekable_stream_encoder_get_do_mid_side_stereo : FLAC__seekable_stream_encoder_get_do_mid_side_stereo_t;
|
||||
FLAC__seekable_stream_encoder_get_loose_mid_side_stereo : FLAC__seekable_stream_encoder_get_loose_mid_side_stereo_t;
|
||||
FLAC__seekable_stream_encoder_get_channels : FLAC__seekable_stream_encoder_get_channels_t;
|
||||
FLAC__seekable_stream_encoder_get_bits_per_sample : FLAC__seekable_stream_encoder_get_bits_per_sample_t;
|
||||
FLAC__seekable_stream_encoder_get_sample_rate : FLAC__seekable_stream_encoder_get_sample_rate_t;
|
||||
FLAC__seekable_stream_encoder_get_blocksize : FLAC__seekable_stream_encoder_get_blocksize_t;
|
||||
FLAC__seekable_stream_encoder_get_max_lpc_order : FLAC__seekable_stream_encoder_get_max_lpc_order_t;
|
||||
FLAC__seekable_stream_encoder_get_qlp_coeff_precision : FLAC__seekable_stream_encoder_get_qlp_coeff_precision_t;
|
||||
FLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search : FLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search_t;
|
||||
FLAC__seekable_stream_encoder_get_do_escape_coding : FLAC__seekable_stream_encoder_get_do_escape_coding_t;
|
||||
FLAC__seekable_stream_encoder_get_do_exhaustive_model_search : FLAC__seekable_stream_encoder_get_do_exhaustive_model_search_t;
|
||||
FLAC__seekable_stream_encoder_get_min_residual_partition_order : FLAC__seekable_stream_encoder_get_min_residual_partition_order_t;
|
||||
FLAC__seekable_stream_encoder_get_max_residual_partition_order : FLAC__seekable_stream_encoder_get_max_residual_partition_order_t;
|
||||
// FLAC__seekable_stream_encoder_get_rice_parameter_search_dist : FLAC__seekable_stream_encoder_get_rice_parameter_search_dist_t;
|
||||
FLAC__seekable_stream_encoder_get_total_samples_estimate : FLAC__seekable_stream_encoder_get_total_samples_estimate_t;
|
||||
FLAC__seekable_stream_encoder_init : FLAC__seekable_stream_encoder_init_t;
|
||||
FLAC__seekable_stream_encoder_finish : FLAC__seekable_stream_encoder_finish_t;
|
||||
FLAC__seekable_stream_encoder_process : FLAC__seekable_stream_encoder_process_t;
|
||||
FLAC__seekable_stream_encoder_process_interleaved : FLAC__seekable_stream_encoder_process_interleaved_t;
|
||||
|
||||
FLAC__seekable_stream_decoder_new : FLAC__seekable_stream_decoder_new_t;
|
||||
FLAC__seekable_stream_decoder_delete : FLAC__seekable_stream_decoder_delete_t;
|
||||
FLAC__seekable_stream_decoder_set_md5_checking : FLAC__seekable_stream_decoder_set_md5_checking_t;
|
||||
FLAC__seekable_stream_decoder_set_read_callback : FLAC__seekable_stream_decoder_set_read_callback_t;
|
||||
FLAC__seekable_stream_decoder_set_seek_callback : FLAC__seekable_stream_decoder_set_seek_callback_t;
|
||||
FLAC__seekable_stream_decoder_set_tell_callback : FLAC__seekable_stream_decoder_set_tell_callback_t;
|
||||
FLAC__seekable_stream_decoder_set_length_callback : FLAC__seekable_stream_decoder_set_length_callback_t;
|
||||
FLAC__seekable_stream_decoder_set_eof_callback : FLAC__seekable_stream_decoder_set_eof_callback_t;
|
||||
FLAC__seekable_stream_decoder_set_write_callback : FLAC__seekable_stream_decoder_set_write_callback_t;
|
||||
FLAC__seekable_stream_decoder_set_metadata_callback : FLAC__seekable_stream_decoder_set_metadata_callback_t;
|
||||
FLAC__seekable_stream_decoder_set_error_callback : FLAC__seekable_stream_decoder_set_error_callback_t;
|
||||
FLAC__seekable_stream_decoder_set_client_data : FLAC__seekable_stream_decoder_set_client_data_t;
|
||||
FLAC__seekable_stream_decoder_set_metadata_respond : FLAC__seekable_stream_decoder_set_metadata_respond_t;
|
||||
FLAC__seekable_stream_decoder_set_metadata_respond_application : FLAC__seekable_stream_decoder_set_metadata_respond_application_t;
|
||||
FLAC__seekable_stream_decoder_set_metadata_respond_all : FLAC__seekable_stream_decoder_set_metadata_respond_all_t;
|
||||
FLAC__seekable_stream_decoder_set_metadata_ignore : FLAC__seekable_stream_decoder_set_metadata_ignore_t;
|
||||
FLAC__seekable_stream_decoder_set_metadata_ignore_application : FLAC__seekable_stream_decoder_set_metadata_ignore_application_t;
|
||||
FLAC__seekable_stream_decoder_set_metadata_ignore_all : FLAC__seekable_stream_decoder_set_metadata_ignore_all_t;
|
||||
FLAC__seekable_stream_decoder_get_state : FLAC__seekable_stream_decoder_get_state_t;
|
||||
FLAC__seekable_stream_decoder_get_stream_decoder_state : FLAC__seekable_stream_decoder_get_stream_decoder_state_t;
|
||||
FLAC__seekable_stream_decoder_get_resolved_state_string : FLAC__seekable_stream_decoder_get_resolved_state_string_t;
|
||||
FLAC__seekable_stream_decoder_get_md5_checking : FLAC__seekable_stream_decoder_get_md5_checking_t;
|
||||
FLAC__seekable_stream_decoder_get_channels : FLAC__seekable_stream_decoder_get_channels_t;
|
||||
FLAC__seekable_stream_decoder_get_channel_assignment : FLAC__seekable_stream_decoder_get_channel_assignment_t;
|
||||
FLAC__seekable_stream_decoder_get_bits_per_sample : FLAC__seekable_stream_decoder_get_bits_per_sample_t;
|
||||
FLAC__seekable_stream_decoder_get_sample_rate : FLAC__seekable_stream_decoder_get_sample_rate_t;
|
||||
FLAC__seekable_stream_decoder_get_blocksize : FLAC__seekable_stream_decoder_get_blocksize_t;
|
||||
FLAC__seekable_stream_decoder_get_decode_position : FLAC__seekable_stream_decoder_get_decode_position_t;
|
||||
FLAC__seekable_stream_decoder_init : FLAC__seekable_stream_decoder_init_t;
|
||||
FLAC__seekable_stream_decoder_finish : FLAC__seekable_stream_decoder_finish_t;
|
||||
FLAC__seekable_stream_decoder_flush : FLAC__seekable_stream_decoder_flush_t;
|
||||
FLAC__seekable_stream_decoder_reset : FLAC__seekable_stream_decoder_reset_t;
|
||||
FLAC__seekable_stream_decoder_process_single : FLAC__seekable_stream_decoder_process_single_t;
|
||||
FLAC__seekable_stream_decoder_process_until_end_of_metadata : FLAC__seekable_stream_decoder_process_until_end_of_metadata_t;
|
||||
FLAC__seekable_stream_decoder_process_until_end_of_stream : FLAC__seekable_stream_decoder_process_until_end_of_stream_t;
|
||||
FLAC__seekable_stream_decoder_seek_absolute : FLAC__seekable_stream_decoder_seek_absolute_t;
|
||||
|
||||
implementation
|
||||
|
||||
{$IFDEF WIN32}
|
||||
|
||||
var
|
||||
Libhandle : HMODULE;
|
||||
|
||||
initialization
|
||||
|
||||
Libhandle := LoadLibraryEx(LibFLACPath, 0, 0);
|
||||
|
||||
if Libhandle <> 0 then
|
||||
begin
|
||||
LibFLACLoaded := True;
|
||||
|
||||
FLAC__seekable_stream_encoder_new := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_new');
|
||||
FLAC__seekable_stream_encoder_delete := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_delete');
|
||||
FLAC__seekable_stream_encoder_set_verify := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_set_verify');
|
||||
FLAC__seekable_stream_encoder_set_streamable_subset := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_set_streamable_subset');
|
||||
FLAC__seekable_stream_encoder_set_do_mid_side_stereo := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_set_do_mid_side_stereo');
|
||||
FLAC__seekable_stream_encoder_set_loose_mid_side_stereo := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_set_loose_mid_side_stereo');
|
||||
FLAC__seekable_stream_encoder_set_channels := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_set_channels');
|
||||
FLAC__seekable_stream_encoder_set_bits_per_sample := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_set_bits_per_sample');
|
||||
FLAC__seekable_stream_encoder_set_sample_rate := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_set_sample_rate');
|
||||
FLAC__seekable_stream_encoder_set_blocksize := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_set_blocksize');
|
||||
FLAC__seekable_stream_encoder_set_max_lpc_order := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_set_max_lpc_order');
|
||||
FLAC__seekable_stream_encoder_set_qlp_coeff_precision := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_set_qlp_coeff_precision');
|
||||
FLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search');
|
||||
FLAC__seekable_stream_encoder_set_do_escape_coding := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_set_do_escape_coding');
|
||||
FLAC__seekable_stream_encoder_set_do_exhaustive_model_search := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_set_do_exhaustive_model_search');
|
||||
FLAC__seekable_stream_encoder_set_min_residual_partition_order := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_set_min_residual_partition_order');
|
||||
FLAC__seekable_stream_encoder_set_max_residual_partition_order := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_set_max_residual_partition_order');
|
||||
// FLAC__seekable_stream_encoder_set_rice_parameter_search_dist := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_set_rice_parameter_search_dist');
|
||||
FLAC__seekable_stream_encoder_set_total_samples_estimate := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_set_total_samples_estimate');
|
||||
FLAC__seekable_stream_encoder_set_metadata := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_set_metadata');
|
||||
FLAC__seekable_stream_encoder_set_seek_callback := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_set_seek_callback');
|
||||
FLAC__seekable_stream_encoder_set_write_callback := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_set_write_callback');
|
||||
FLAC__seekable_stream_encoder_set_client_data := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_set_client_data');
|
||||
FLAC__seekable_stream_encoder_get_state := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_state');
|
||||
FLAC__seekable_stream_encoder_get_stream_encoder_state := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_stream_encoder_state');
|
||||
FLAC__seekable_stream_encoder_get_verify_decoder_state := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_verify_decoder_state');
|
||||
FLAC__seekable_stream_encoder_get_resolved_state_string := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_resolved_state_string');
|
||||
FLAC__seekable_stream_encoder_get_verify_decoder_error_stats := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_verify_decoder_error_stats');
|
||||
FLAC__seekable_stream_encoder_get_verify := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_verify');
|
||||
FLAC__seekable_stream_encoder_get_streamable_subset := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_streamable_subset');
|
||||
FLAC__seekable_stream_encoder_get_do_mid_side_stereo := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_do_mid_side_stereo');
|
||||
FLAC__seekable_stream_encoder_get_loose_mid_side_stereo := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_loose_mid_side_stereo');
|
||||
FLAC__seekable_stream_encoder_get_channels := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_channels');
|
||||
FLAC__seekable_stream_encoder_get_bits_per_sample := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_bits_per_sample');
|
||||
FLAC__seekable_stream_encoder_get_sample_rate := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_sample_rate');
|
||||
FLAC__seekable_stream_encoder_get_blocksize := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_blocksize');
|
||||
FLAC__seekable_stream_encoder_get_max_lpc_order := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_max_lpc_order');
|
||||
FLAC__seekable_stream_encoder_get_qlp_coeff_precision := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_qlp_coeff_precision');
|
||||
FLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search');
|
||||
FLAC__seekable_stream_encoder_get_do_escape_coding := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_do_escape_coding');
|
||||
FLAC__seekable_stream_encoder_get_do_exhaustive_model_search := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_do_exhaustive_model_search');
|
||||
FLAC__seekable_stream_encoder_get_min_residual_partition_order := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_min_residual_partition_order');
|
||||
FLAC__seekable_stream_encoder_get_max_residual_partition_order := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_max_residual_partition_order');
|
||||
// FLAC__seekable_stream_encoder_get_rice_parameter_search_dist := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_rice_parameter_search_dist');
|
||||
FLAC__seekable_stream_encoder_get_total_samples_estimate := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_get_total_samples_estimate');
|
||||
FLAC__seekable_stream_encoder_init := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_init');
|
||||
FLAC__seekable_stream_encoder_finish := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_finish');
|
||||
FLAC__seekable_stream_encoder_process := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_process');
|
||||
FLAC__seekable_stream_encoder_process_interleaved := GetProcAddress(Libhandle, 'FLAC__seekable_stream_encoder_process_interleaved');
|
||||
|
||||
FLAC__seekable_stream_decoder_new := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_new');
|
||||
FLAC__seekable_stream_decoder_delete := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_delete');
|
||||
FLAC__seekable_stream_decoder_set_md5_checking := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_set_md5_checking');
|
||||
FLAC__seekable_stream_decoder_set_read_callback := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_set_read_callback');
|
||||
FLAC__seekable_stream_decoder_set_seek_callback := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_set_seek_callback');
|
||||
FLAC__seekable_stream_decoder_set_tell_callback := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_set_tell_callback');
|
||||
FLAC__seekable_stream_decoder_set_length_callback := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_set_length_callback');
|
||||
FLAC__seekable_stream_decoder_set_eof_callback := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_set_eof_callback');
|
||||
FLAC__seekable_stream_decoder_set_write_callback := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_set_write_callback');
|
||||
FLAC__seekable_stream_decoder_set_metadata_callback := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_set_metadata_callback');
|
||||
FLAC__seekable_stream_decoder_set_error_callback := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_set_error_callback');
|
||||
FLAC__seekable_stream_decoder_set_client_data := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_set_client_data');
|
||||
FLAC__seekable_stream_decoder_set_metadata_respond := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_set_metadata_respond');
|
||||
FLAC__seekable_stream_decoder_set_metadata_respond_application := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_set_metadata_respond_application');
|
||||
FLAC__seekable_stream_decoder_set_metadata_respond_all := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_set_metadata_respond_all');
|
||||
FLAC__seekable_stream_decoder_set_metadata_ignore := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_set_metadata_ignore');
|
||||
FLAC__seekable_stream_decoder_set_metadata_ignore_application := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_set_metadata_ignore_application');
|
||||
FLAC__seekable_stream_decoder_set_metadata_ignore_all := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_set_metadata_ignore_all');
|
||||
FLAC__seekable_stream_decoder_get_state := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_get_state');
|
||||
FLAC__seekable_stream_decoder_get_stream_decoder_state := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_get_stream_decoder_state');
|
||||
FLAC__seekable_stream_decoder_get_resolved_state_string := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_get_resolved_state_string');
|
||||
FLAC__seekable_stream_decoder_get_md5_checking := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_get_md5_checking');
|
||||
FLAC__seekable_stream_decoder_get_channels := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_get_channels');
|
||||
FLAC__seekable_stream_decoder_get_channel_assignment := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_get_channel_assignment');
|
||||
FLAC__seekable_stream_decoder_get_bits_per_sample := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_get_bits_per_sample');
|
||||
FLAC__seekable_stream_decoder_get_sample_rate := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_get_sample_rate');
|
||||
FLAC__seekable_stream_decoder_get_blocksize := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_get_blocksize');
|
||||
FLAC__seekable_stream_decoder_get_decode_position := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_get_decode_position');
|
||||
FLAC__seekable_stream_decoder_init := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_init');
|
||||
FLAC__seekable_stream_decoder_finish := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_finish');
|
||||
FLAC__seekable_stream_decoder_flush := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_flush');
|
||||
FLAC__seekable_stream_decoder_reset := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_reset');
|
||||
FLAC__seekable_stream_decoder_process_single := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_process_single');
|
||||
FLAC__seekable_stream_decoder_process_until_end_of_metadata := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_process_until_end_of_metadata');
|
||||
FLAC__seekable_stream_decoder_process_until_end_of_stream := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_process_until_end_of_stream');
|
||||
FLAC__seekable_stream_decoder_seek_absolute := GetProcAddress(Libhandle, 'FLAC__seekable_stream_decoder_seek_absolute');
|
||||
|
||||
end;
|
||||
|
||||
finalization
|
||||
|
||||
if Libhandle <> 0 then FreeLibrary(Libhandle);
|
||||
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF LINUX}
|
||||
|
||||
var
|
||||
Libhandle : Pointer;
|
||||
|
||||
{$IFDEF SEARCH_LIBS}
|
||||
Path : String;
|
||||
{$ENDIF}
|
||||
|
||||
initialization
|
||||
|
||||
{$IFDEF SEARCH_LIBS}
|
||||
|
||||
Libhandle := nil;
|
||||
Path := FindLibs(LibFLACPath);
|
||||
if Path <> '' then Libhandle := dlopen(@Path[1], RTLD_NOW or RTLD_GLOBAL);
|
||||
|
||||
{$ELSE}
|
||||
|
||||
Libhandle := dlopen(LibFLACPath, RTLD_NOW or RTLD_GLOBAL);
|
||||
|
||||
{$ENDIF}
|
||||
|
||||
if Libhandle <> nil then
|
||||
begin
|
||||
LibFLACLoaded := True;
|
||||
|
||||
FLAC__seekable_stream_encoder_new := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_new');
|
||||
FLAC__seekable_stream_encoder_delete := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_delete');
|
||||
FLAC__seekable_stream_encoder_set_verify := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_set_verify');
|
||||
FLAC__seekable_stream_encoder_set_streamable_subset := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_set_streamable_subset');
|
||||
FLAC__seekable_stream_encoder_set_do_mid_side_stereo := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_set_do_mid_side_stereo');
|
||||
FLAC__seekable_stream_encoder_set_loose_mid_side_stereo := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_set_loose_mid_side_stereo');
|
||||
FLAC__seekable_stream_encoder_set_channels := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_set_channels');
|
||||
FLAC__seekable_stream_encoder_set_bits_per_sample := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_set_bits_per_sample');
|
||||
FLAC__seekable_stream_encoder_set_sample_rate := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_set_sample_rate');
|
||||
FLAC__seekable_stream_encoder_set_blocksize := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_set_blocksize');
|
||||
FLAC__seekable_stream_encoder_set_max_lpc_order := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_set_max_lpc_order');
|
||||
FLAC__seekable_stream_encoder_set_qlp_coeff_precision := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_set_qlp_coeff_precision');
|
||||
FLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search');
|
||||
FLAC__seekable_stream_encoder_set_do_escape_coding := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_set_do_escape_coding');
|
||||
FLAC__seekable_stream_encoder_set_do_exhaustive_model_search := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_set_do_exhaustive_model_search');
|
||||
FLAC__seekable_stream_encoder_set_min_residual_partition_order := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_set_min_residual_partition_order');
|
||||
FLAC__seekable_stream_encoder_set_max_residual_partition_order := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_set_max_residual_partition_order');
|
||||
// FLAC__seekable_stream_encoder_set_rice_parameter_search_dist := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_set_rice_parameter_search_dist');
|
||||
FLAC__seekable_stream_encoder_set_total_samples_estimate := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_set_total_samples_estimate');
|
||||
FLAC__seekable_stream_encoder_set_metadata := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_set_metadata');
|
||||
FLAC__seekable_stream_encoder_set_seek_callback := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_set_seek_callback');
|
||||
FLAC__seekable_stream_encoder_set_write_callback := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_set_write_callback');
|
||||
FLAC__seekable_stream_encoder_set_client_data := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_set_client_data');
|
||||
FLAC__seekable_stream_encoder_get_state := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_state');
|
||||
FLAC__seekable_stream_encoder_get_stream_encoder_state := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_stream_encoder_state');
|
||||
FLAC__seekable_stream_encoder_get_verify_decoder_state := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_verify_decoder_state');
|
||||
FLAC__seekable_stream_encoder_get_resolved_state_string := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_resolved_state_string');
|
||||
FLAC__seekable_stream_encoder_get_verify_decoder_error_stats := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_verify_decoder_error_stats');
|
||||
FLAC__seekable_stream_encoder_get_verify := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_verify');
|
||||
FLAC__seekable_stream_encoder_get_streamable_subset := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_streamable_subset');
|
||||
FLAC__seekable_stream_encoder_get_do_mid_side_stereo := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_do_mid_side_stereo');
|
||||
FLAC__seekable_stream_encoder_get_loose_mid_side_stereo := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_loose_mid_side_stereo');
|
||||
FLAC__seekable_stream_encoder_get_channels := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_channels');
|
||||
FLAC__seekable_stream_encoder_get_bits_per_sample := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_bits_per_sample');
|
||||
FLAC__seekable_stream_encoder_get_sample_rate := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_sample_rate');
|
||||
FLAC__seekable_stream_encoder_get_blocksize := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_blocksize');
|
||||
FLAC__seekable_stream_encoder_get_max_lpc_order := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_max_lpc_order');
|
||||
FLAC__seekable_stream_encoder_get_qlp_coeff_precision := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_qlp_coeff_precision');
|
||||
FLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search');
|
||||
FLAC__seekable_stream_encoder_get_do_escape_coding := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_do_escape_coding');
|
||||
FLAC__seekable_stream_encoder_get_do_exhaustive_model_search := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_do_exhaustive_model_search');
|
||||
FLAC__seekable_stream_encoder_get_min_residual_partition_order := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_min_residual_partition_order');
|
||||
FLAC__seekable_stream_encoder_get_max_residual_partition_order := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_max_residual_partition_order');
|
||||
// FLAC__seekable_stream_encoder_get_rice_parameter_search_dist := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_rice_parameter_search_dist');
|
||||
FLAC__seekable_stream_encoder_get_total_samples_estimate := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_get_total_samples_estimate');
|
||||
FLAC__seekable_stream_encoder_init := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_init');
|
||||
FLAC__seekable_stream_encoder_finish := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_finish');
|
||||
FLAC__seekable_stream_encoder_process := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_process');
|
||||
FLAC__seekable_stream_encoder_process_interleaved := dlsym(Libhandle, 'FLAC__seekable_stream_encoder_process_interleaved');
|
||||
|
||||
FLAC__seekable_stream_decoder_new := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_new');
|
||||
FLAC__seekable_stream_decoder_delete := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_delete');
|
||||
FLAC__seekable_stream_decoder_set_md5_checking := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_set_md5_checking');
|
||||
FLAC__seekable_stream_decoder_set_read_callback := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_set_read_callback');
|
||||
FLAC__seekable_stream_decoder_set_seek_callback := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_set_seek_callback');
|
||||
FLAC__seekable_stream_decoder_set_tell_callback := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_set_tell_callback');
|
||||
FLAC__seekable_stream_decoder_set_length_callback := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_set_length_callback');
|
||||
FLAC__seekable_stream_decoder_set_eof_callback := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_set_eof_callback');
|
||||
FLAC__seekable_stream_decoder_set_write_callback := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_set_write_callback');
|
||||
FLAC__seekable_stream_decoder_set_metadata_callback := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_set_metadata_callback');
|
||||
FLAC__seekable_stream_decoder_set_error_callback := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_set_error_callback');
|
||||
FLAC__seekable_stream_decoder_set_client_data := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_set_client_data');
|
||||
FLAC__seekable_stream_decoder_set_metadata_respond := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_set_metadata_respond');
|
||||
FLAC__seekable_stream_decoder_set_metadata_respond_application := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_set_metadata_respond_application');
|
||||
FLAC__seekable_stream_decoder_set_metadata_respond_all := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_set_metadata_respond_all');
|
||||
FLAC__seekable_stream_decoder_set_metadata_ignore := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_set_metadata_ignore');
|
||||
FLAC__seekable_stream_decoder_set_metadata_ignore_application := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_set_metadata_ignore_application');
|
||||
FLAC__seekable_stream_decoder_set_metadata_ignore_all := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_set_metadata_ignore_all');
|
||||
FLAC__seekable_stream_decoder_get_state := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_get_state');
|
||||
FLAC__seekable_stream_decoder_get_stream_decoder_state := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_get_stream_decoder_state');
|
||||
FLAC__seekable_stream_decoder_get_resolved_state_string := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_get_resolved_state_string');
|
||||
FLAC__seekable_stream_decoder_get_md5_checking := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_get_md5_checking');
|
||||
FLAC__seekable_stream_decoder_get_channels := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_get_channels');
|
||||
FLAC__seekable_stream_decoder_get_channel_assignment := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_get_channel_assignment');
|
||||
FLAC__seekable_stream_decoder_get_bits_per_sample := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_get_bits_per_sample');
|
||||
FLAC__seekable_stream_decoder_get_sample_rate := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_get_sample_rate');
|
||||
FLAC__seekable_stream_decoder_get_blocksize := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_get_blocksize');
|
||||
FLAC__seekable_stream_decoder_get_decode_position := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_get_decode_position');
|
||||
FLAC__seekable_stream_decoder_init := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_init');
|
||||
FLAC__seekable_stream_decoder_finish := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_finish');
|
||||
FLAC__seekable_stream_decoder_flush := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_flush');
|
||||
FLAC__seekable_stream_decoder_reset := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_reset');
|
||||
FLAC__seekable_stream_decoder_process_single := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_process_single');
|
||||
FLAC__seekable_stream_decoder_process_until_end_of_metadata := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_process_until_end_of_metadata');
|
||||
FLAC__seekable_stream_decoder_process_until_end_of_stream := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_process_until_end_of_stream');
|
||||
FLAC__seekable_stream_decoder_seek_absolute := dlsym(Libhandle, 'FLAC__seekable_stream_decoder_seek_absolute');
|
||||
|
||||
end;
|
||||
|
||||
finalization
|
||||
|
||||
if Libhandle <> nil then dlclose(Libhandle);
|
||||
|
||||
{$ENDIF}
|
||||
|
||||
end.
|
||||
1058
acs/Src/fileformats/general/lame.pas
Normal file
1058
acs/Src/fileformats/general/lame.pas
Normal file
File diff suppressed because it is too large
Load Diff
297
acs/Src/fileformats/general/mad.pas
Normal file
297
acs/Src/fileformats/general/mad.pas
Normal file
@@ -0,0 +1,297 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.3.
|
||||
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: mad.pas,v $
|
||||
Revision 1.2 2006/08/03 17:31:09 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/12/19 18:36:56 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:53 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
unit mad;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
|
||||
{$IFDEF WIN32}
|
||||
Windows;
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF LINUX}
|
||||
baseunix,dl, ACS_Procs;
|
||||
{$ENDIF}
|
||||
|
||||
|
||||
const
|
||||
|
||||
{$IFDEF WIN32}
|
||||
MADLibPath = 'MADLib.dll';
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF LINUX}
|
||||
MADLibPath = 'libmad.so*'; // libmad.so
|
||||
{$DEFINE SEARCH_LIBS}
|
||||
{$ENDIF}
|
||||
|
||||
|
||||
var
|
||||
|
||||
MADLibLoaded : Boolean = False;
|
||||
|
||||
type
|
||||
|
||||
mad_bitptr = packed record
|
||||
b : PChar;
|
||||
Cache, Left : Word;
|
||||
end;
|
||||
|
||||
mad_stream = packed record
|
||||
buffer : Pointer;
|
||||
bufend : Pointer;
|
||||
skiplen : LongWord;
|
||||
sync : Integer;
|
||||
freerate : LongWord;
|
||||
this_frame : Pointer;
|
||||
next_frame : Pointer;
|
||||
ptr : mad_bitptr;
|
||||
anc_ptr : mad_bitptr;
|
||||
anc_bitlen : LongWord;
|
||||
main_data : Pointer;
|
||||
md_len : LongWord;
|
||||
options : Integer;
|
||||
error : Integer;
|
||||
end;
|
||||
|
||||
p_mad_stream = ^mad_stream;
|
||||
|
||||
mad_timer_t = packed record
|
||||
seconds : Integer;
|
||||
fraction : LongWord;
|
||||
end;
|
||||
|
||||
mad_header = packed record
|
||||
layer : Integer;
|
||||
mode : Integer;
|
||||
mode_extension : Integer;
|
||||
emphasis : Integer;
|
||||
bitrate : LongWord;
|
||||
samplerate : LongWord;
|
||||
crc_check : Word;
|
||||
crc_target : Word;
|
||||
flags : Integer;
|
||||
private_bits : Integer;
|
||||
duration : mad_timer_t;
|
||||
end;
|
||||
|
||||
p_mad_header = ^mad_header;
|
||||
|
||||
mad_frame = packed record
|
||||
header : mad_header;
|
||||
options : Integer;
|
||||
sbsample : packed array[0..1, 0..35, 0..31] of Integer;
|
||||
overlap : Pointer;
|
||||
end;
|
||||
|
||||
p_mad_frame = ^mad_frame;
|
||||
|
||||
mad_pcm = packed record
|
||||
samplerate : LongWord;
|
||||
channels : Word;
|
||||
length : Word;
|
||||
samples : packed array [0..1, 0..1151] of Integer;
|
||||
end;
|
||||
|
||||
p_mad_pcm = ^mad_pcm;
|
||||
|
||||
mad_synth = packed record
|
||||
filter : array[0..1, 0..1, 0..1, 0..15, 0..7] of Integer;
|
||||
phase : LongWord;
|
||||
pcm : mad_pcm;
|
||||
end;
|
||||
|
||||
async_struct = packed record
|
||||
pid : LongWord;
|
||||
_in : Integer;
|
||||
_out : Integer;
|
||||
end;
|
||||
|
||||
sync_struct = packed record
|
||||
stream : mad_stream;
|
||||
frame : mad_frame;
|
||||
synth : mad_synth;
|
||||
end;
|
||||
|
||||
p_sync_struct = ^sync_struct;
|
||||
|
||||
TInputFunc = function(CData : Pointer; Stream : p_mad_stream) : Integer; cdecl;
|
||||
THeaderFunc = function(CData : Pointer; Header : p_mad_header) : Integer; cdecl;
|
||||
TFilterFunc = function(CData : Pointer; Frame : p_mad_frame) : Integer; cdecl;
|
||||
TOutputFunc = function(CData : Pointer; Header : p_mad_header; pcm : p_mad_pcm) : Integer; cdecl;
|
||||
TErrorFunc = function(CData : Pointer; Stream : p_mad_stream; Frame : p_mad_frame) : Integer; cdecl;
|
||||
TMessageFunc = function(P1, P2 : Pointer; var l : LongWord) : Integer; cdecl;
|
||||
|
||||
mad_decoder = packed record
|
||||
mode : Integer;
|
||||
options : Integer;
|
||||
async : async_struct;
|
||||
sync : p_sync_struct;
|
||||
data : Pointer;
|
||||
InputFunc : TInputFunc;
|
||||
HeaderFunc : THeaderFunc;
|
||||
FilterFunc : TFilterFunc;
|
||||
OutputFunc : TOutputFunc;
|
||||
ErrorFunc : TErrorFunc;
|
||||
MessageFunc : TMessageFunc;
|
||||
end;
|
||||
|
||||
p_mad_decoder = ^mad_decoder;
|
||||
|
||||
const
|
||||
|
||||
MAD_F_FRACBITS = 28;
|
||||
MAD_F_ONE = $10000000;
|
||||
|
||||
MAD_FLOW_CONTINUE = $0;
|
||||
MAD_FLOW_STOP = $10;
|
||||
MAD_FLOW_BREAK = $11;
|
||||
MAD_FLOW_IGNORE = $20;
|
||||
|
||||
MAD_DECODER_MODE_SYNC = 0;
|
||||
MAD_DECODER_MODE_ASYNC = 1;
|
||||
|
||||
type
|
||||
|
||||
mad_decoder_init_t = procedure(mad_decoder : p_mad_decoder;
|
||||
CData : Pointer;
|
||||
InputFunc : TInputFunc;
|
||||
HeaderFunc : THeaderFunc;
|
||||
FilterFunc : TFilterFunc;
|
||||
OutputFunc : TOutputFunc;
|
||||
ErrorFunc : TErrorFunc;
|
||||
MessageFunc : TMessageFunc); cdecl;
|
||||
|
||||
mad_decoder_finish_t = function(mad_decoder : p_mad_decoder) : Integer; cdecl;
|
||||
|
||||
mad_decoder_run_t = function(mad_decoder : p_mad_decoder; mad_decoder_mode : Integer) : Integer; cdecl;
|
||||
|
||||
mad_decoder_message_t = function(mad_decoder : p_mad_decoder; P : Pointer; var l : LongWord) : Integer; cdecl;
|
||||
|
||||
mad_stream_buffer_t = procedure(MadStream : p_mad_stream; Data : Pointer; l : LongWord); cdecl;
|
||||
|
||||
mad_stream_skip_t = procedure(MadStream : p_mad_stream; Skip : LongWord); cdecl;
|
||||
|
||||
mad_stream_sync_t = function(MadStream : p_mad_stream) : Integer; cdecl;
|
||||
|
||||
var
|
||||
|
||||
mad_decoder_init: mad_decoder_init_t;
|
||||
mad_decoder_finish : mad_decoder_finish_t;
|
||||
mad_decoder_run : mad_decoder_run_t;
|
||||
mad_decoder_message : mad_decoder_message_t;
|
||||
mad_stream_buffer : mad_stream_buffer_t;
|
||||
mad_stream_skip : mad_stream_skip_t;
|
||||
mad_stream_sync : mad_stream_sync_t;
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
{$IFDEF WIN32}
|
||||
|
||||
var
|
||||
Libhandle : HMODULE;
|
||||
|
||||
initialization
|
||||
|
||||
Libhandle := LoadLibraryEx(MADLibPath, 0, 0);
|
||||
|
||||
if Libhandle <> 0 then
|
||||
begin
|
||||
MADLibLoaded := True;
|
||||
|
||||
mad_decoder_init := GetProcAddress(Libhandle, 'mad_decoder_init');
|
||||
mad_decoder_finish := GetProcAddress(Libhandle, 'mad_decoder_finish');
|
||||
mad_decoder_run := GetProcAddress(Libhandle, 'mad_decoder_run');
|
||||
mad_decoder_message := GetProcAddress(Libhandle, 'mad_decoder_message');
|
||||
mad_stream_buffer := GetProcAddress(Libhandle, 'mad_stream_buffer');
|
||||
mad_stream_skip := GetProcAddress(Libhandle, 'mad_stream_skip');
|
||||
mad_stream_sync := GetProcAddress(Libhandle, 'mad_stream_sync');
|
||||
|
||||
end;
|
||||
|
||||
finalization
|
||||
|
||||
if Libhandle <> 0 then FreeLibrary(Libhandle);
|
||||
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF LINUX}
|
||||
|
||||
var
|
||||
Libhandle : Pointer;
|
||||
|
||||
{$IFDEF SEARCH_LIBS}
|
||||
Path : String;
|
||||
{$ENDIF}
|
||||
|
||||
initialization
|
||||
|
||||
{$IFDEF SEARCH_LIBS}
|
||||
|
||||
Libhandle := nil;
|
||||
Path := FindLibs(MADLibPath);
|
||||
if Path <> '' then Libhandle := dlopen(@Path[1], RTLD_NOW or RTLD_GLOBAL);
|
||||
|
||||
{$ELSE}
|
||||
|
||||
Libhandle := dlopen(MADLibPath, RTLD_NOW or RTLD_GLOBAL);
|
||||
|
||||
{$ENDIF}
|
||||
|
||||
if Libhandle <> nil then
|
||||
begin
|
||||
|
||||
MADLibLoaded := True;
|
||||
|
||||
mad_decoder_init := dlsym(Libhandle, 'mad_decoder_init');
|
||||
mad_decoder_finish := dlsym(Libhandle, 'mad_decoder_finish');
|
||||
mad_decoder_run := dlsym(Libhandle, 'mad_decoder_run');
|
||||
mad_decoder_message := dlsym(Libhandle, 'mad_decoder_message');
|
||||
mad_stream_buffer := dlsym(Libhandle, 'mad_stream_buffer');
|
||||
mad_stream_skip := dlsym(Libhandle, 'mad_stream_skip');
|
||||
mad_stream_sync := dlsym(Libhandle, 'mad_stream_sync');
|
||||
|
||||
end;
|
||||
|
||||
finalization
|
||||
|
||||
if Libhandle <> nil then dlclose(Libhandle);
|
||||
|
||||
{$ENDIF}
|
||||
|
||||
|
||||
end.
|
||||
535
acs/Src/fileformats/general/ogg.pas
Normal file
535
acs/Src/fileformats/general/ogg.pas
Normal file
@@ -0,0 +1,535 @@
|
||||
(*
|
||||
delphi/kylix headers for oggvorbis software codec.
|
||||
translated from ogg.h and os_types.h headers
|
||||
by andrei borovsky, acs@compiler4.net
|
||||
the original c/c++ headers and libraries (c) copyright 1994-2001
|
||||
by the xiphophorus company http://www.xiph.org/
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: ogg.pas,v $
|
||||
Revision 1.4 2005/12/29 20:46:00 z0m3ie
|
||||
fixed some problems with vorbis in lazarus
|
||||
|
||||
Revision 1.3 2005/12/19 18:36:56 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:53 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
unit ogg;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
|
||||
ACS_Procs,
|
||||
|
||||
{$IFDEF LINUX}
|
||||
baseunix,dl;
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF WINDOWS}
|
||||
Windows;
|
||||
{$ENDIF}
|
||||
|
||||
type
|
||||
|
||||
(* Type declarations from os_types.h header with
|
||||
some Delphi-specific types added *)
|
||||
|
||||
OGG_INT64_T = int64;
|
||||
|
||||
POGG_INT64_T = ^OGG_INT64_T;
|
||||
|
||||
OGG_INT32_T = Integer;
|
||||
|
||||
OGG_UINT32_T = LongWord;
|
||||
|
||||
OGG_INT16_T = SmallInt; // Word ?
|
||||
|
||||
(* Note by AB: The following three type declarations,
|
||||
strange as they seem, are required to make C
|
||||
pointer/array stuff work in Delphi/Kylix.
|
||||
See TVorbisOut class for details. *)
|
||||
|
||||
FLOAT_T = array[0..0] of Single;
|
||||
|
||||
PFLOAT = ^FLOAT_T;
|
||||
|
||||
PPFLOAT = ^PFLOAT;
|
||||
|
||||
// Type declarations from ogg.h header
|
||||
|
||||
POGGPACK_BUFFER = ^OGGPACK_BUFFER;
|
||||
|
||||
OGGPACK_BUFFER = record
|
||||
endbyte: LongInt;
|
||||
endbit: Integer;
|
||||
buffer: PByte;
|
||||
ptr: PByte;
|
||||
storage: LongInt;
|
||||
end;
|
||||
|
||||
// ogg_page is used to encapsulate the data in one Ogg bitstream page
|
||||
|
||||
OGG_PAGE = record
|
||||
header: PByte;
|
||||
header_len: LongInt;
|
||||
body: PByte;
|
||||
body_len: LongInt;
|
||||
end;
|
||||
|
||||
(* ogg_stream_state contains the current encode/decode state of a logical
|
||||
Ogg bitstream *)
|
||||
|
||||
OGG_STREAM_STATE = record
|
||||
body_data: PByte; // bytes from packet bodies
|
||||
body_storage: LongInt; // storage elements allocated
|
||||
body_fill: LongInt; // elements stored; fill mark
|
||||
body_returned: LongInt; // elements of fill returned
|
||||
lacing_vals: PInteger; // The values that will go to the segment table
|
||||
granule_vals: POGG_INT64_T; (* granulepos values for headers. Not compact
|
||||
this way, but it is simple coupled to the
|
||||
lacing fifo *)
|
||||
lacing_storage: LongInt;
|
||||
lacing_fill: LongInt;
|
||||
lacing_packet: LongInt;
|
||||
lacing_returned: LongInt;
|
||||
header: array[0..281] of Byte; // working space for header encode
|
||||
header_fill: Integer;
|
||||
e_o_s: Integer; (* set when we have buffered the last packet in the
|
||||
logical bitstream *)
|
||||
b_o_s: Integer; (* set after we've written the initial page
|
||||
of a logical bitstream *)
|
||||
serialno: LongInt;
|
||||
pageno: LongInt;
|
||||
packetno: OGG_INT64_T;
|
||||
(* sequence number for decode; the framing
|
||||
knows where there's a hole in the data,
|
||||
but we need coupling so that the codec
|
||||
(which is in a seperate abstraction
|
||||
layer) also knows about the gap *)
|
||||
granulepos: OGG_INT64_T;
|
||||
end;
|
||||
|
||||
(* ogg_packet is used to encapsulate the data and metadata belonging
|
||||
to a single raw Ogg/Vorbis packet *)
|
||||
|
||||
POGG_PACKET = ^OGG_PACKET;
|
||||
|
||||
OGG_PACKET = record
|
||||
packet: PByte;
|
||||
bytes: LongInt;
|
||||
b_o_s: LongInt;
|
||||
e_o_s: LongInt;
|
||||
granulepos: OGG_INT64_T;
|
||||
packetno: OGG_INT64_T;
|
||||
(* sequence number for decode; the framing
|
||||
knows where there's a hole in the data,
|
||||
but we need coupling so that the codec
|
||||
(which is in a seperate abstraction
|
||||
layer) also knows about the gap *)
|
||||
end;
|
||||
|
||||
OGG_SYNC_STATE = record
|
||||
data: PByte;
|
||||
storage: Integer;
|
||||
fill: Integer;
|
||||
returned: Integer;
|
||||
unsynced: Integer;
|
||||
headerbytes: Integer;
|
||||
bodybytes: Integer;
|
||||
end;
|
||||
|
||||
|
||||
const
|
||||
|
||||
{$IFDEF LINUX}
|
||||
LiboggPath = 'libogg.so*'; // '/usr/lib/libogg.so';
|
||||
{$DEFINE SEARCH_LIBS}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF WINDOWS}
|
||||
LiboggPath = 'ogg.dll';
|
||||
{$ENDIF}
|
||||
|
||||
|
||||
var
|
||||
LiboggLoaded : Boolean = False;
|
||||
|
||||
type
|
||||
|
||||
// Ogg BITSTREAM PRIMITIVES: bitstream
|
||||
|
||||
oggpack_writeinit_t = procedure(var b: OGGPACK_BUFFER); cdecl;
|
||||
|
||||
oggpack_reset_t = procedure(var b: OGGPACK_BUFFER); cdecl;
|
||||
|
||||
oggpack_writeclear_t = procedure(var b: OGGPACK_BUFFER); cdecl;
|
||||
|
||||
oggpack_readinit_t = procedure(var b: OGGPACK_BUFFER;
|
||||
buf: PByte;
|
||||
bytes: Integer); cdecl;
|
||||
|
||||
oggpack_write_t = procedure(var b: OGGPACK_BUFFER;
|
||||
value: LongInt;
|
||||
bits: Integer); cdecl;
|
||||
|
||||
oggpack_look_t = function(var b: OGGPACK_BUFFER;
|
||||
bits: Integer): LongInt; cdecl;
|
||||
|
||||
oggpack_look_huff_t = function(var b: OGGPACK_BUFFER;
|
||||
bits: Integer): LongInt; cdecl;
|
||||
|
||||
oggpack_look1_t = function(var b: OGGPACK_BUFFER): LongInt; cdecl;
|
||||
|
||||
oggpack_adv_t = procedure(var b: OGGPACK_BUFFER;
|
||||
bits: Integer); cdecl;
|
||||
|
||||
oggpack_adv_huff_t = function(var b: OGGPACK_BUFFER;
|
||||
bits: Integer): Integer; cdecl;
|
||||
|
||||
oggpack_adv1_t = procedure(var b: OGGPACK_BUFFER); cdecl;
|
||||
|
||||
oggpack_read_t = function(var b: OGGPACK_BUFFER;
|
||||
bits: Integer): LongInt; cdecl;
|
||||
|
||||
oggpack_read1_t = function(var b: OGGPACK_BUFFER): LongInt; cdecl;
|
||||
|
||||
oggpack_bytes_t = function(var b: OGGPACK_BUFFER): LongInt; cdecl;
|
||||
|
||||
oggpack_bits_t = function(var b: OGGPACK_BUFFER): LongInt; cdecl;
|
||||
|
||||
oggpack_get_buffer_t = function(var b: OGGPACK_BUFFER): PByte; cdecl;
|
||||
|
||||
// Ogg BITSTREAM PRIMITIVES: encoding
|
||||
|
||||
ogg_stream_packetin_t = function(var os: OGG_STREAM_STATE;
|
||||
var op: OGG_PACKET): Integer; cdecl;
|
||||
|
||||
ogg_stream_pageout_t = function(var os: OGG_STREAM_STATE;
|
||||
var og: OGG_PAGE): Integer; cdecl;
|
||||
|
||||
ogg_stream_flush_t = function(var os: OGG_STREAM_STATE;
|
||||
var og: OGG_PAGE): Integer; cdecl;
|
||||
|
||||
// Ogg BITSTREAM PRIMITIVES: decoding
|
||||
|
||||
ogg_sync_init_t = function(var oy: OGG_SYNC_STATE): Integer; cdecl;
|
||||
|
||||
ogg_sync_clear_t = function(var oy: OGG_SYNC_STATE): Integer; cdecl;
|
||||
|
||||
ogg_sync_reset_t = function(var oy: OGG_SYNC_STATE): Integer; cdecl;
|
||||
|
||||
ogg_sync_destroy_t = function(var oy: OGG_SYNC_STATE): Integer; cdecl;
|
||||
|
||||
ogg_sync_buffer_t = function(var oy: OGG_SYNC_STATE;
|
||||
size: LongInt): PChar; cdecl;
|
||||
|
||||
ogg_sync_wrote_t = function(var oy: OGG_SYNC_STATE;
|
||||
bytes: LongInt): Integer; cdecl;
|
||||
|
||||
ogg_sync_pageseek_t = function(var oy: OGG_SYNC_STATE;
|
||||
var og: OGG_PAGE): LongInt; cdecl;
|
||||
|
||||
ogg_sync_pageout_t = function(var oy: OGG_SYNC_STATE;
|
||||
var og: OGG_PAGE): Integer; cdecl;
|
||||
|
||||
ogg_stream_pagein_t = function(var os: OGG_STREAM_STATE;
|
||||
var og: OGG_PAGE): Integer; cdecl;
|
||||
|
||||
ogg_stream_packetout_t = function(var os: OGG_STREAM_STATE;
|
||||
var op: OGG_PACKET): Integer; cdecl;
|
||||
|
||||
ogg_stream_packetpeek_t = function(var os: OGG_STREAM_STATE;
|
||||
var op: OGG_PACKET): Integer; cdecl;
|
||||
|
||||
|
||||
// Ogg BITSTREAM PRIMITIVES: general
|
||||
|
||||
ogg_stream_init_t = function(var os: OGG_STREAM_STATE;
|
||||
serialno: Integer): Integer; cdecl;
|
||||
|
||||
ogg_stream_clear_t = function(var os: OGG_STREAM_STATE): Integer; cdecl;
|
||||
|
||||
ogg_stream_reset_t = function(var os: OGG_STREAM_STATE): Integer; cdecl;
|
||||
|
||||
ogg_stream_destroy_t = function(var os: OGG_STREAM_STATE): Integer; cdecl;
|
||||
|
||||
ogg_stream_eos_t = function(var os: OGG_STREAM_STATE): Integer; cdecl;
|
||||
|
||||
ogg_page_checksum_set_t = procedure(var og: OGG_PAGE); cdecl;
|
||||
|
||||
ogg_page_version_t = function(var og: OGG_PAGE): Integer; cdecl;
|
||||
|
||||
ogg_page_continued_t = function(var og: OGG_PAGE): Integer; cdecl;
|
||||
|
||||
ogg_page_bos_t = function(var og: OGG_PAGE): Integer; cdecl;
|
||||
|
||||
ogg_page_eos_t = function(var og: OGG_PAGE): Integer; cdecl;
|
||||
|
||||
ogg_page_granulepos_t = function(var og: OGG_PAGE): OGG_INT64_T; cdecl;
|
||||
|
||||
ogg_page_serialno_t = function(var og: OGG_PAGE): Integer; cdecl;
|
||||
|
||||
ogg_page_pageno_t = function(var og: OGG_PAGE): LongInt; cdecl;
|
||||
|
||||
ogg_page_packets_t = function(var og: OGG_PAGE): Integer; cdecl;
|
||||
|
||||
ogg_packet_clear_t = procedure(var op: OGG_PACKET); cdecl;
|
||||
|
||||
var
|
||||
|
||||
ogg_stream_init : ogg_stream_init_t;
|
||||
|
||||
ogg_stream_clear : ogg_stream_clear_t;
|
||||
|
||||
ogg_stream_reset : ogg_stream_reset_t;
|
||||
|
||||
ogg_stream_destroy : ogg_stream_destroy_t;
|
||||
|
||||
ogg_stream_eos : ogg_stream_eos_t;
|
||||
|
||||
ogg_page_checksum_set : ogg_page_checksum_set_t;
|
||||
|
||||
ogg_page_version : ogg_page_version_t;
|
||||
|
||||
ogg_page_continued : ogg_page_continued_t;
|
||||
|
||||
ogg_page_bos : ogg_page_bos_t;
|
||||
|
||||
ogg_page_eos : ogg_page_eos_t;
|
||||
|
||||
ogg_page_granulepos : ogg_page_granulepos_t;
|
||||
|
||||
ogg_page_serialno : ogg_page_serialno_t;
|
||||
|
||||
ogg_page_pageno : ogg_page_pageno_t;
|
||||
|
||||
ogg_page_packets : ogg_page_packets_t;
|
||||
|
||||
ogg_packet_clear : ogg_packet_clear_t;
|
||||
|
||||
oggpack_writeinit : oggpack_writeinit_t;
|
||||
|
||||
oggpack_reset : oggpack_reset_t;
|
||||
|
||||
oggpack_writeclear : oggpack_writeclear_t;
|
||||
|
||||
oggpack_readinit : oggpack_readinit_t;
|
||||
|
||||
oggpack_write : oggpack_write_t;
|
||||
|
||||
oggpack_look : oggpack_look_t;
|
||||
|
||||
oggpack_look_huff : oggpack_look_huff_t;
|
||||
|
||||
oggpack_look1 : oggpack_look1_t;
|
||||
|
||||
oggpack_adv : oggpack_adv_t;
|
||||
|
||||
oggpack_adv_huff : oggpack_adv_huff_t;
|
||||
|
||||
oggpack_adv1 : oggpack_adv1_t;
|
||||
|
||||
oggpack_read : oggpack_read_t;
|
||||
|
||||
oggpack_read1 : oggpack_read1_t;
|
||||
|
||||
oggpack_bytes : oggpack_bytes_t;
|
||||
|
||||
oggpack_bits : oggpack_bits_t;
|
||||
|
||||
oggpack_get_buffer : oggpack_get_buffer_t;
|
||||
|
||||
ogg_stream_packetin : ogg_stream_packetin_t;
|
||||
|
||||
ogg_stream_pageout : ogg_stream_pageout_t;
|
||||
|
||||
ogg_stream_flush : ogg_stream_flush_t;
|
||||
|
||||
ogg_sync_init : ogg_sync_init_t;
|
||||
|
||||
ogg_sync_clear : ogg_sync_clear_t;
|
||||
|
||||
ogg_sync_reset : ogg_sync_reset_t;
|
||||
|
||||
ogg_sync_destroy : ogg_sync_destroy_t;
|
||||
|
||||
ogg_sync_buffer : ogg_sync_buffer_t;
|
||||
|
||||
ogg_sync_wrote : ogg_sync_wrote_t;
|
||||
|
||||
ogg_sync_pageseek : ogg_sync_pageseek_t;
|
||||
|
||||
ogg_sync_pageout : ogg_sync_pageout_t;
|
||||
|
||||
ogg_stream_pagein : ogg_stream_pagein_t;
|
||||
|
||||
ogg_stream_packetout : ogg_stream_packetout_t;
|
||||
|
||||
ogg_stream_packetpeek : ogg_stream_packetpeek_t;
|
||||
|
||||
implementation
|
||||
|
||||
{$IFDEF LINUX}
|
||||
|
||||
var
|
||||
Libhandle : Pointer;
|
||||
|
||||
{$IFDEF SEARCH_LIBS}
|
||||
Path : String;
|
||||
{$ENDIF}
|
||||
|
||||
initialization
|
||||
|
||||
{$IFDEF SEARCH_LIBS}
|
||||
|
||||
Libhandle := nil;
|
||||
Path := FindLibs(LiboggPath);
|
||||
if Path <> '' then Libhandle := dlopen(@Path[1], RTLD_NOW or RTLD_GLOBAL);
|
||||
|
||||
{$ELSE}
|
||||
|
||||
Libhandle := dlopen(LiboggPath, RTLD_NOW or RTLD_GLOBAL);
|
||||
|
||||
{$ENDIF}
|
||||
|
||||
if Libhandle <> nil then
|
||||
begin
|
||||
LiboggLoaded := True;
|
||||
ogg_stream_init := dlsym(Libhandle, 'ogg_stream_init');
|
||||
ogg_stream_clear := dlsym(Libhandle, 'ogg_stream_clear');
|
||||
ogg_stream_reset := dlsym(Libhandle, 'ogg_stream_reset');
|
||||
ogg_stream_destroy := dlsym(Libhandle, 'ogg_stream_destroy');
|
||||
ogg_stream_eos := dlsym(Libhandle, 'ogg_stream_eos');
|
||||
ogg_page_checksum_set := dlsym(Libhandle, 'ogg_page_checksum_set');
|
||||
ogg_page_version := dlsym(Libhandle, 'ogg_page_version');
|
||||
ogg_page_continued := dlsym(Libhandle, 'ogg_page_continued');
|
||||
ogg_page_bos := dlsym(Libhandle, 'ogg_page_bos');
|
||||
ogg_page_eos := dlsym(Libhandle, 'ogg_page_eos');
|
||||
ogg_page_granulepos := dlsym(Libhandle, 'ogg_page_granulepos');
|
||||
ogg_page_serialno := dlsym(Libhandle, 'ogg_page_serialno');
|
||||
ogg_page_pageno := dlsym(Libhandle, 'ogg_page_pageno');
|
||||
ogg_page_packets := dlsym(Libhandle, 'ogg_page_packets');
|
||||
ogg_packet_clear := dlsym(Libhandle, 'ogg_packet_clear');
|
||||
oggpack_writeinit := dlsym(Libhandle, 'oggpack_writeinit');
|
||||
oggpack_reset := dlsym(Libhandle, 'oggpack_reset');
|
||||
oggpack_writeclear := dlsym(Libhandle, 'oggpack_writeclear');
|
||||
oggpack_readinit := dlsym(Libhandle, 'oggpack_readinit');
|
||||
oggpack_write := dlsym(Libhandle, 'oggpack_write');
|
||||
oggpack_look := dlsym(Libhandle, 'oggpack_look');
|
||||
oggpack_look_huff := dlsym(Libhandle, 'oggpack_look_huff');
|
||||
oggpack_look1 := dlsym(Libhandle, 'oggpack_look1');
|
||||
oggpack_adv := dlsym(Libhandle, 'oggpack_adv');
|
||||
oggpack_adv_huff := dlsym(Libhandle, 'oggpack_adv_huff');
|
||||
oggpack_adv1 := dlsym(Libhandle, 'oggpack_adv1');
|
||||
oggpack_read := dlsym(Libhandle, 'oggpack_read');
|
||||
oggpack_read1 := dlsym(Libhandle, 'oggpack_read1');
|
||||
oggpack_bytes := dlsym(Libhandle, 'oggpack_bytes');
|
||||
oggpack_bits := dlsym(Libhandle, 'oggpack_bits');
|
||||
oggpack_get_buffer := dlsym(Libhandle, 'oggpack_get_buffer');
|
||||
ogg_stream_packetin := dlsym(Libhandle, 'ogg_stream_packetin');
|
||||
ogg_stream_pageout := dlsym(Libhandle, 'ogg_stream_pageout');
|
||||
ogg_stream_flush := dlsym(Libhandle, 'ogg_stream_flush');
|
||||
ogg_sync_init := dlsym(Libhandle, 'ogg_sync_init');
|
||||
ogg_sync_clear := dlsym(Libhandle, 'ogg_sync_clear');
|
||||
ogg_sync_reset := dlsym(Libhandle, 'ogg_sync_reset');
|
||||
ogg_sync_destroy := dlsym(Libhandle, 'ogg_sync_destroy');
|
||||
ogg_sync_buffer := dlsym(Libhandle, 'ogg_sync_buffer');
|
||||
ogg_sync_wrote := dlsym(Libhandle, 'ogg_sync_wrote');
|
||||
ogg_sync_pageseek := dlsym(Libhandle, 'ogg_sync_pageseek');
|
||||
ogg_sync_pageout := dlsym(Libhandle, 'ogg_sync_pageout');
|
||||
ogg_stream_pagein := dlsym(Libhandle, 'ogg_stream_pagein');
|
||||
ogg_stream_packetout := dlsym(Libhandle, 'ogg_stream_packetout');
|
||||
ogg_stream_packetpeek := dlsym(Libhandle, 'ogg_stream_packetpeek');
|
||||
end;
|
||||
|
||||
finalization
|
||||
|
||||
if Libhandle <> nil then dlclose(Libhandle);
|
||||
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF WIN32}
|
||||
|
||||
var
|
||||
Libhandle : HMODULE;
|
||||
|
||||
initialization
|
||||
Libhandle := LoadLibraryEx(LiboggPath, 0, 0);
|
||||
|
||||
if Libhandle <> 0 then
|
||||
begin
|
||||
LiboggLoaded := True;
|
||||
ogg_stream_init := GetProcAddress(Libhandle, 'ogg_stream_init');
|
||||
ogg_stream_clear := GetProcAddress(Libhandle, 'ogg_stream_clear');
|
||||
ogg_stream_reset := GetProcAddress(Libhandle, 'ogg_stream_reset');
|
||||
ogg_stream_destroy := GetProcAddress(Libhandle, 'ogg_stream_destroy');
|
||||
ogg_stream_eos := GetProcAddress(Libhandle, 'ogg_stream_eos');
|
||||
ogg_page_checksum_set := GetProcAddress(Libhandle, 'ogg_page_checksum_set');
|
||||
ogg_page_version := GetProcAddress(Libhandle, 'ogg_page_version');
|
||||
ogg_page_continued := GetProcAddress(Libhandle, 'ogg_page_continued');
|
||||
ogg_page_bos := GetProcAddress(Libhandle, 'ogg_page_bos');
|
||||
ogg_page_eos := GetProcAddress(Libhandle, 'ogg_page_eos');
|
||||
ogg_page_granulepos := GetProcAddress(Libhandle, 'ogg_page_granulepos');
|
||||
ogg_page_serialno := GetProcAddress(Libhandle, 'ogg_page_serialno');
|
||||
ogg_page_pageno := GetProcAddress(Libhandle, 'ogg_page_pageno');
|
||||
ogg_page_packets := GetProcAddress(Libhandle, 'ogg_page_packets');
|
||||
ogg_packet_clear := GetProcAddress(Libhandle, 'ogg_packet_clear');
|
||||
oggpack_writeinit := GetProcAddress(Libhandle, 'oggpack_writeinit');
|
||||
oggpack_reset := GetProcAddress(Libhandle, 'oggpack_reset');
|
||||
oggpack_writeclear := GetProcAddress(Libhandle, 'oggpack_writeclear');
|
||||
oggpack_readinit := GetProcAddress(Libhandle, 'oggpack_readinit');
|
||||
oggpack_write := GetProcAddress(Libhandle, 'oggpack_write');
|
||||
oggpack_look := GetProcAddress(Libhandle, 'oggpack_look');
|
||||
oggpack_look_huff := GetProcAddress(Libhandle, 'oggpack_look_huff');
|
||||
oggpack_look1 := GetProcAddress(Libhandle, 'oggpack_look1');
|
||||
oggpack_adv := GetProcAddress(Libhandle, 'oggpack_adv');
|
||||
oggpack_adv_huff := GetProcAddress(Libhandle, 'oggpack_adv_huff');
|
||||
oggpack_adv1 := GetProcAddress(Libhandle, 'oggpack_adv1');
|
||||
oggpack_read := GetProcAddress(Libhandle, 'oggpack_read');
|
||||
oggpack_read1 := GetProcAddress(Libhandle, 'oggpack_read1');
|
||||
oggpack_bytes := GetProcAddress(Libhandle, 'oggpack_bytes');
|
||||
oggpack_bits := GetProcAddress(Libhandle, 'oggpack_bits');
|
||||
oggpack_get_buffer := GetProcAddress(Libhandle, 'oggpack_get_buffer');
|
||||
ogg_stream_packetin := GetProcAddress(Libhandle, 'ogg_stream_packetin');
|
||||
ogg_stream_pageout := GetProcAddress(Libhandle, 'ogg_stream_pageout');
|
||||
ogg_stream_flush := GetProcAddress(Libhandle, 'ogg_stream_flush');
|
||||
ogg_sync_init := GetProcAddress(Libhandle, 'ogg_sync_init');
|
||||
ogg_sync_clear := GetProcAddress(Libhandle, 'ogg_sync_clear');
|
||||
ogg_sync_reset := GetProcAddress(Libhandle, 'ogg_sync_reset');
|
||||
ogg_sync_destroy := GetProcAddress(Libhandle, 'ogg_sync_destroy');
|
||||
ogg_sync_buffer := GetProcAddress(Libhandle, 'ogg_sync_buffer');
|
||||
ogg_sync_wrote := GetProcAddress(Libhandle, 'ogg_sync_wrote');
|
||||
ogg_sync_pageseek := GetProcAddress(Libhandle, 'ogg_sync_pageseek');
|
||||
ogg_sync_pageout := GetProcAddress(Libhandle, 'ogg_sync_pageout');
|
||||
ogg_stream_pagein := GetProcAddress(Libhandle, 'ogg_stream_pagein');
|
||||
ogg_stream_packetout := GetProcAddress(Libhandle, 'ogg_stream_packetout');
|
||||
ogg_stream_packetpeek := GetProcAddress(Libhandle, 'ogg_stream_packetpeek');
|
||||
end;
|
||||
|
||||
finalization
|
||||
|
||||
if Libhandle <> 0 then FreeLibrary(Libhandle);
|
||||
|
||||
{$ENDIF}
|
||||
|
||||
end.
|
||||
480
acs/Src/fileformats/general/vorbiscodec.pas
Normal file
480
acs/Src/fileformats/general/vorbiscodec.pas
Normal file
@@ -0,0 +1,480 @@
|
||||
(*
|
||||
delphi/kylix headers for oggvorbis software codec.
|
||||
translated from codec.h header
|
||||
by andrei borovsky, acs@compiler4.net
|
||||
the original c/c++ headers and libraries (c) copyright 1994-2001
|
||||
by the xiphophorus company http://www.xiph.org/
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: vorbiscodec.pas,v $
|
||||
Revision 1.1 2005/12/29 20:46:00 z0m3ie
|
||||
fixed some problems with vorbis in lazarus
|
||||
|
||||
Revision 1.1 2005/12/19 18:36:56 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:53 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
{$IFDEF FPC}
|
||||
{$IFDEF WIN32}
|
||||
{$PACKRECORDS C}
|
||||
{$ENDIF WIN32}
|
||||
{$ENDIF WIN32}
|
||||
|
||||
unit vorbiscodec;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
|
||||
ACS_Procs,
|
||||
|
||||
{$IFDEF LINUX}
|
||||
baseunix,dl,
|
||||
{$ENDIF}
|
||||
{$IFDEF WIN32}
|
||||
Windows,
|
||||
{$ENDIF}
|
||||
ogg;
|
||||
|
||||
type
|
||||
|
||||
PVORBIS_INFO = ^VORBIS_INFO;
|
||||
|
||||
VORBIS_INFO = record
|
||||
version: Integer;
|
||||
channels: Integer;
|
||||
rate: LongInt;
|
||||
|
||||
(* The below bitrate declarations are *hints*.
|
||||
Combinations of the three values carry the following implications:
|
||||
all three set to the same value:
|
||||
implies a fixed rate bitstream
|
||||
only nominal set:
|
||||
implies a VBR stream that averages the nominal bitrate. No hard
|
||||
upper/lower limit
|
||||
upper and or lower set:
|
||||
implies a VBR bitstream that obeys the bitrate limits. nominal
|
||||
may also be set to give a nominal rate.
|
||||
none set:
|
||||
the coder does not care to speculate. *)
|
||||
|
||||
bitrate_upper: LongInt;
|
||||
bitrate_nominal: LongInt;
|
||||
bitrate_lower: LongInt;
|
||||
bitrate_window: LongInt;
|
||||
codec_setup: Pointer;
|
||||
end;
|
||||
|
||||
(* vorbis_dsp_state buffers the current vorbis audio
|
||||
analysis/synthesis state. The DSP state belongs to a specific
|
||||
logical bitstream *)
|
||||
|
||||
PVORBIS_DSP_STATE = ^VORBIS_DSP_STATE;
|
||||
|
||||
VORBIS_DSP_STATE = record
|
||||
analysisp: Integer;
|
||||
vi: PVORBIS_INFO;
|
||||
pcm: PPFLOAT;
|
||||
pcmret: PPFLOAT;
|
||||
pcm_storage: Integer;
|
||||
pcm_current: Integer;
|
||||
pcm_returned: Integer;
|
||||
preextrapolate: Integer;
|
||||
eofflag: Integer;
|
||||
lW: LongInt;
|
||||
W: LongInt;
|
||||
nW: LongInt;
|
||||
centerW: LongInt;
|
||||
granulepos: OGG_INT64_T;
|
||||
sequence: OGG_INT64_T;
|
||||
glue_bits: OGG_INT64_T;
|
||||
time_bits: OGG_INT64_T;
|
||||
floor_bits: OGG_INT64_T;
|
||||
res_bits: OGG_INT64_T;
|
||||
backend_state: Pointer;
|
||||
end;
|
||||
|
||||
PALLOC_CHAIN = ^ALLOC_CHAIN;
|
||||
|
||||
ALLOC_CHAIN = record
|
||||
ptr: Pointer;
|
||||
next: PALLOC_CHAIN;
|
||||
end;
|
||||
|
||||
|
||||
VORBIS_BLOCK = record
|
||||
// necessary stream state for linking to the framing abstraction
|
||||
pcm: PPFLOAT;
|
||||
// this is a pointer into local storage
|
||||
opb: OGGPACK_BUFFER;
|
||||
lW: LongInt;
|
||||
W: LongInt;
|
||||
nW: LongInt;
|
||||
pcmend: Integer;
|
||||
mode: Integer;
|
||||
eofflag: Integer;
|
||||
granulepos: OGG_INT64_T;
|
||||
sequence: OGG_INT64_T;
|
||||
vd: PVORBIS_DSP_STATE; // For read-only access of configuration
|
||||
(* local storage to avoid remallocing; it's up to the mapping to
|
||||
structure it *)
|
||||
localstore: Pointer;
|
||||
localtop: LongInt;
|
||||
localalloc: LongInt;
|
||||
totaluse: LongInt;
|
||||
reap: PALLOC_CHAIN;
|
||||
// bitmetrics for the frame
|
||||
glue_bits: LongInt;
|
||||
time_bits: LongInt;
|
||||
floor_bits: LongInt;
|
||||
res_bits: LongInt;
|
||||
internal: Pointer;
|
||||
end;
|
||||
|
||||
(* vorbis_block is a single block of data to be processed as part of
|
||||
the analysis/synthesis stream; it belongs to a specific logical
|
||||
bitstream, but is independant from other vorbis_blocks belonging to
|
||||
that logical bitstream. *)
|
||||
|
||||
(* vorbis_info contains all the setup information specific to the
|
||||
specific compression/decompression mode in progress (eg,
|
||||
psychoacoustic settings, channel setup, options, codebook
|
||||
etc). vorbis_info and substructures are in backends.h. *)
|
||||
|
||||
(* the comments are not part of vorbis_info so that vorbis_info can be
|
||||
static storage *)
|
||||
|
||||
PVORBIS_COMMENT = ^VORBIS_COMMENT;
|
||||
|
||||
VORBIS_COMMENT = record
|
||||
(* unlimited user comment fields. libvorbis writes 'libvorbis'
|
||||
whatever vendor is set to in encode *)
|
||||
user_comments: PPChar;
|
||||
comment_lengths: PInteger;
|
||||
comments: Integer;
|
||||
vendor: PChar;
|
||||
end;
|
||||
|
||||
(* libvorbis encodes in two abstraction layers; first we perform DSP
|
||||
and produce a packet (see docs/analysis.txt). The packet is then
|
||||
coded into a framed OggSquish bitstream by the second layer (see
|
||||
docs/framing.txt). Decode is the reverse process; we sync/frame
|
||||
the bitstream and extract individual packets, then decode the
|
||||
packet back into PCM audio. *)
|
||||
|
||||
(* The extra framing/packetizing is used in streaming formats, such as
|
||||
files. Over the net (such as with UDP), the framing and
|
||||
packetization aren't necessary as they're provided by the transport
|
||||
and the streaming layer is not used *)
|
||||
|
||||
// Vorbis PRIMITIVES: general
|
||||
|
||||
|
||||
const
|
||||
|
||||
{$IFDEF LINUX}
|
||||
LibvorbisPath = 'libvorbis.so*'; //'/usr/lib/libvorbis.so';
|
||||
{$DEFINE SEARCH_LIBS}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF WINDOWS}
|
||||
LibvorbisPath = 'vorbis.dll';
|
||||
{$ENDIF}
|
||||
|
||||
var
|
||||
LibvorbisLoaded : Boolean = False;
|
||||
|
||||
type
|
||||
|
||||
vorbis_info_init_t = procedure(var vi: VORBIS_INFO); cdecl;
|
||||
|
||||
vorbis_info_clear_t = procedure(var vi: VORBIS_INFO); cdecl;
|
||||
|
||||
vorbis_info_blocksize_t = function(var vi: VORBIS_INFO;
|
||||
zo: Integer): Integer; cdecl;
|
||||
|
||||
vorbis_comment_init_t = procedure(var vc: VORBIS_COMMENT); cdecl;
|
||||
|
||||
vorbis_comment_add_t = procedure(var vc: VORBIS_COMMENT;
|
||||
comment: PChar); cdecl;
|
||||
|
||||
vorbis_comment_add_tag_t = procedure(var vc: VORBIS_COMMENT;
|
||||
tag: PChar;
|
||||
contents: PChar); cdecl;
|
||||
|
||||
vorbis_comment_query_t = function(var vc: VORBIS_COMMENT;
|
||||
tag: PChar;
|
||||
count: Integer): PChar; cdecl;
|
||||
|
||||
vorbis_comment_query_count_t = function(var vc: VORBIS_COMMENT;
|
||||
tag: PChar): Integer; cdecl;
|
||||
|
||||
vorbis_comment_clear_t = procedure(var vc: VORBIS_COMMENT) cdecl;
|
||||
|
||||
vorbis_block_init_t = function(var v: VORBIS_DSP_STATE;
|
||||
var vb: VORBIS_BLOCK): Integer; cdecl;
|
||||
|
||||
vorbis_block_clear_t = function(var vb: VORBIS_BLOCK): Integer; cdecl;
|
||||
|
||||
vorbis_dsp_clear_t = procedure(var v: VORBIS_DSP_STATE); cdecl;
|
||||
|
||||
// Vorbis PRIMITIVES: analysis/DSP layer
|
||||
|
||||
vorbis_analysis_init_t = function(var v: VORBIS_DSP_STATE;
|
||||
var vi: VORBIS_INFO): Integer; cdecl;
|
||||
|
||||
vorbis_commentheader_out_t = function(var vc: VORBIS_COMMENT;
|
||||
var op: OGG_PACKET): Integer; cdecl;
|
||||
|
||||
vorbis_analysis_headerout_t = function(var v: VORBIS_DSP_STATE;
|
||||
var vc: VORBIS_COMMENT;
|
||||
var op: OGG_PACKET;
|
||||
var op_comm: OGG_PACKET;
|
||||
var op_code: OGG_PACKET): Integer; cdecl;
|
||||
|
||||
vorbis_analysis_buffer_t = function(var v: VORBIS_DSP_STATE;
|
||||
vals: Integer): PPFLOAT; cdecl;
|
||||
|
||||
vorbis_analysis_wrote_t = function(var v: VORBIS_DSP_STATE;
|
||||
vals: Integer): Integer; cdecl;
|
||||
|
||||
vorbis_analysis_blockout_t = function(var v: VORBIS_DSP_STATE;
|
||||
var vb: VORBIS_BLOCK): Integer; cdecl;
|
||||
|
||||
vorbis_analysis_t = function(var vb: VORBIS_BLOCK;
|
||||
op: POGG_PACKET): Integer; cdecl;
|
||||
|
||||
vorbis_bitrate_addblock_t = function(var vb: VORBIS_BLOCK): Integer; cdecl;
|
||||
|
||||
vorbis_bitrate_flushpacket_t = function(var vd: VORBIS_DSP_STATE;
|
||||
var op: OGG_PACKET): Integer; cdecl;
|
||||
|
||||
// Vorbis PRIMITIVES: synthesis layer
|
||||
|
||||
vorbis_synthesis_headerin_t = function(var vi: VORBIS_INFO;
|
||||
var vc: VORBIS_COMMENT;
|
||||
var op: OGG_PACKET): Integer; cdecl;
|
||||
|
||||
vorbis_synthesis_init_t = function(var v: VORBIS_DSP_STATE;
|
||||
var vi: VORBIS_INFO): Integer; cdecl;
|
||||
|
||||
vorbis_synthesis_t = function(var vb: VORBIS_BLOCK;
|
||||
var op: OGG_PACKET): Integer; cdecl;
|
||||
|
||||
vorbis_synthesis_blockin_t = function(var v: VORBIS_DSP_STATE;
|
||||
var vb: VORBIS_BLOCK): Integer; cdecl;
|
||||
|
||||
vorbis_synthesis_pcmout_t = function(var v: VORBIS_DSP_STATE;
|
||||
var pcm: PPFLOAT): Integer; cdecl;
|
||||
|
||||
vorbis_synthesis_read_t = function(var v: VORBIS_DSP_STATE;
|
||||
samples: Integer): Integer; cdecl;
|
||||
|
||||
vorbis_packet_blocksize_t = function(var vi: VORBIS_INFO;
|
||||
var op: OGG_PACKET): LongInt; cdecl;
|
||||
var
|
||||
|
||||
vorbis_info_init : vorbis_info_init_t;
|
||||
|
||||
vorbis_info_clear : vorbis_info_clear_t;
|
||||
|
||||
vorbis_info_blocksize : vorbis_info_blocksize_t;
|
||||
|
||||
vorbis_comment_init : vorbis_comment_init_t;
|
||||
|
||||
vorbis_comment_add : vorbis_comment_add_t;
|
||||
|
||||
vorbis_comment_add_tag : vorbis_comment_add_tag_t;
|
||||
|
||||
vorbis_comment_query : vorbis_comment_query_t;
|
||||
|
||||
vorbis_comment_query_count : vorbis_comment_query_count_t;
|
||||
|
||||
vorbis_comment_clear : vorbis_comment_clear_t;
|
||||
|
||||
vorbis_block_init : vorbis_block_init_t;
|
||||
|
||||
vorbis_block_clear : vorbis_block_clear_t;
|
||||
|
||||
vorbis_dsp_clear : vorbis_dsp_clear_t;
|
||||
|
||||
vorbis_analysis_init : vorbis_analysis_init_t;
|
||||
|
||||
vorbis_commentheader_out : vorbis_commentheader_out_t;
|
||||
|
||||
vorbis_analysis_headerout : vorbis_analysis_headerout_t;
|
||||
|
||||
vorbis_analysis_buffer : vorbis_analysis_buffer_t;
|
||||
|
||||
vorbis_analysis_wrote : vorbis_analysis_wrote_t;
|
||||
|
||||
vorbis_analysis_blockout : vorbis_analysis_blockout_t;
|
||||
|
||||
vorbis_analysis : vorbis_analysis_t;
|
||||
|
||||
vorbis_bitrate_addblock : vorbis_bitrate_addblock_t;
|
||||
|
||||
vorbis_bitrate_flushpacket : vorbis_bitrate_flushpacket_t;
|
||||
|
||||
vorbis_synthesis_headerin : vorbis_synthesis_headerin_t;
|
||||
|
||||
vorbis_synthesis_init : vorbis_synthesis_init_t;
|
||||
|
||||
vorbis_synthesis : vorbis_synthesis_t;
|
||||
|
||||
vorbis_synthesis_blockin : vorbis_synthesis_blockin_t;
|
||||
|
||||
vorbis_synthesis_pcmout : vorbis_synthesis_pcmout_t;
|
||||
|
||||
vorbis_synthesis_read : vorbis_synthesis_read_t;
|
||||
|
||||
vorbis_packet_blocksize : vorbis_packet_blocksize_t;
|
||||
|
||||
// Vorbis ERRORS and return codes
|
||||
|
||||
const
|
||||
|
||||
OV_FALSE = -1;
|
||||
OV_EOF = -2;
|
||||
OV_HOLE = -3;
|
||||
OV_EREAD = -128;
|
||||
OV_EFAULT = -129;
|
||||
OV_EIMPL = -130;
|
||||
OV_EINVAL = -131;
|
||||
OV_ENOTVORBIS = -132;
|
||||
OV_EBADHEADER = -133;
|
||||
OV_EVERSION = -134;
|
||||
OV_ENOTAUDIO = -135;
|
||||
OV_EBADPACKET = -136;
|
||||
OV_EBADLINK = -137;
|
||||
OV_ENOSEEK = -138;
|
||||
|
||||
implementation
|
||||
|
||||
{$IFDEF LINUX}
|
||||
|
||||
var
|
||||
Libhandle : Pointer;
|
||||
|
||||
{$IFDEF SEARCH_LIBS}
|
||||
Path : String;
|
||||
{$ENDIF}
|
||||
|
||||
initialization
|
||||
|
||||
{$IFDEF SEARCH_LIBS}
|
||||
|
||||
Libhandle := nil;
|
||||
Path := FindLibs(LibvorbisPath);
|
||||
if Path <> '' then Libhandle := dlopen(@Path[1], RTLD_NOW or RTLD_GLOBAL);
|
||||
|
||||
{$ELSE}
|
||||
|
||||
Libhandle := dlopen(LibvorbisPath, RTLD_NOW or RTLD_GLOBAL);
|
||||
|
||||
{$ENDIF}
|
||||
|
||||
if Libhandle <> nil then
|
||||
begin
|
||||
LibvorbisLoaded := True;
|
||||
vorbis_info_init := dlsym(Libhandle, 'vorbis_info_init');
|
||||
vorbis_info_clear := dlsym(Libhandle, 'vorbis_info_clear');
|
||||
vorbis_info_blocksize := dlsym(Libhandle, 'vorbis_info_blocksize');
|
||||
vorbis_comment_init := dlsym(Libhandle, 'vorbis_comment_init');
|
||||
vorbis_comment_add := dlsym(Libhandle, 'vorbis_comment_add');
|
||||
vorbis_comment_add_tag := dlsym(Libhandle, 'vorbis_comment_add_tag');
|
||||
vorbis_comment_query := dlsym(Libhandle, 'vorbis_comment_query');
|
||||
vorbis_comment_query_count := dlsym(Libhandle, 'vorbis_comment_query_count');
|
||||
vorbis_comment_clear := dlsym(Libhandle, 'vorbis_comment_clear');
|
||||
vorbis_block_init := dlsym(Libhandle, 'vorbis_block_init');
|
||||
vorbis_block_clear := dlsym(Libhandle, 'vorbis_block_clear');
|
||||
vorbis_dsp_clear := dlsym(Libhandle, 'vorbis_dsp_clear');
|
||||
vorbis_analysis_init := dlsym(Libhandle, 'vorbis_analysis_init');
|
||||
vorbis_commentheader_out := dlsym(Libhandle, 'vorbis_commentheader_out');
|
||||
vorbis_analysis_headerout := dlsym(Libhandle, 'vorbis_analysis_headerout');
|
||||
vorbis_analysis_buffer := dlsym(Libhandle, 'vorbis_analysis_buffer');
|
||||
vorbis_analysis_wrote := dlsym(Libhandle, 'vorbis_analysis_wrote');
|
||||
vorbis_analysis_blockout := dlsym(Libhandle, 'vorbis_analysis_blockout');
|
||||
vorbis_analysis := dlsym(Libhandle, 'vorbis_analysis');
|
||||
vorbis_bitrate_addblock := dlsym(Libhandle, 'vorbis_bitrate_addblock');
|
||||
vorbis_bitrate_flushpacket := dlsym(Libhandle, 'vorbis_bitrate_flushpacket');
|
||||
vorbis_synthesis_headerin := dlsym(Libhandle, 'vorbis_synthesis_headerin');
|
||||
vorbis_synthesis_init := dlsym(Libhandle, 'vorbis_synthesis_init');
|
||||
vorbis_synthesis := dlsym(Libhandle, 'vorbis_synthesis');
|
||||
vorbis_synthesis_blockin := dlsym(Libhandle, 'vorbis_synthesis_blockin');
|
||||
vorbis_synthesis_pcmout := dlsym(Libhandle, 'vorbis_synthesis_pcmout');
|
||||
vorbis_synthesis_read := dlsym(Libhandle, 'vorbis_synthesis_read');
|
||||
vorbis_packet_blocksize := dlsym(Libhandle, 'vorbis_packet_blocksize');
|
||||
end;
|
||||
|
||||
finalization
|
||||
if libhandle <> nil then dlclose(libhandle);
|
||||
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF WIN32}
|
||||
|
||||
var
|
||||
Libhandle : HMODULE;
|
||||
|
||||
initialization
|
||||
|
||||
Libhandle := LoadLibraryEx(LibvorbisPath, 0, 0);
|
||||
if Libhandle <> 0 then
|
||||
begin
|
||||
LibvorbisLoaded := True;
|
||||
vorbis_info_init := GetProcAddress(Libhandle, 'vorbis_info_init');
|
||||
vorbis_info_clear := GetProcAddress(Libhandle, 'vorbis_info_clear');
|
||||
vorbis_info_blocksize := GetProcAddress(Libhandle, 'vorbis_info_blocksize');
|
||||
vorbis_comment_init := GetProcAddress(Libhandle, 'vorbis_comment_init');
|
||||
vorbis_comment_add := GetProcAddress(Libhandle, 'vorbis_comment_add');
|
||||
vorbis_comment_add_tag := GetProcAddress(Libhandle, 'vorbis_comment_add_tag');
|
||||
vorbis_comment_query := GetProcAddress(Libhandle, 'vorbis_comment_query');
|
||||
vorbis_comment_query_count := GetProcAddress(Libhandle, 'vorbis_comment_query_count');
|
||||
vorbis_comment_clear := GetProcAddress(Libhandle, 'vorbis_comment_clear');
|
||||
vorbis_block_init := GetProcAddress(Libhandle, 'vorbis_block_init');
|
||||
vorbis_block_clear := GetProcAddress(Libhandle, 'vorbis_block_clear');
|
||||
vorbis_dsp_clear := GetProcAddress(Libhandle, 'vorbis_dsp_clear');
|
||||
vorbis_analysis_init := GetProcAddress(Libhandle, 'vorbis_analysis_init');
|
||||
vorbis_commentheader_out := GetProcAddress(Libhandle, 'vorbis_commentheader_out');
|
||||
vorbis_analysis_headerout := GetProcAddress(Libhandle, 'vorbis_analysis_headerout');
|
||||
vorbis_analysis_buffer := GetProcAddress(Libhandle, 'vorbis_analysis_buffer');
|
||||
vorbis_analysis_wrote := GetProcAddress(Libhandle, 'vorbis_analysis_wrote');
|
||||
vorbis_analysis_blockout := GetProcAddress(Libhandle, 'vorbis_analysis_blockout');
|
||||
vorbis_analysis := GetProcAddress(Libhandle, 'vorbis_analysis');
|
||||
vorbis_bitrate_addblock := GetProcAddress(Libhandle, 'vorbis_bitrate_addblock');
|
||||
vorbis_bitrate_flushpacket := GetProcAddress(Libhandle, 'vorbis_bitrate_flushpacket');
|
||||
vorbis_synthesis_headerin := GetProcAddress(Libhandle, 'vorbis_synthesis_headerin');
|
||||
vorbis_synthesis_init := GetProcAddress(Libhandle, 'vorbis_synthesis_init');
|
||||
vorbis_synthesis := GetProcAddress(Libhandle, 'vorbis_synthesis');
|
||||
vorbis_synthesis_blockin := GetProcAddress(Libhandle, 'vorbis_synthesis_blockin');
|
||||
vorbis_synthesis_pcmout := GetProcAddress(Libhandle, 'vorbis_synthesis_pcmout');
|
||||
vorbis_synthesis_read := GetProcAddress(Libhandle, 'vorbis_synthesis_read');
|
||||
vorbis_packet_blocksize := GetProcAddress(Libhandle, 'vorbis_packet_blocksize');
|
||||
end;
|
||||
|
||||
finalization
|
||||
if Libhandle <> 0 then FreeLibrary(Libhandle);
|
||||
|
||||
{$ENDIF}
|
||||
|
||||
|
||||
end.
|
||||
199
acs/Src/fileformats/general/vorbisenc.pas
Normal file
199
acs/Src/fileformats/general/vorbisenc.pas
Normal file
@@ -0,0 +1,199 @@
|
||||
(*
|
||||
delphi/kylix headers for oggvorbis software codec.
|
||||
translated from vorbisenc.h header
|
||||
by andrei borovsky, acs@compiler4.net
|
||||
the original c/c++ headers and libraries (c) copyright 1994-2001
|
||||
by the xiphophorus company http://www.xiph.org/
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: vorbisenc.pas,v $
|
||||
Revision 1.2 2005/12/29 20:46:00 z0m3ie
|
||||
fixed some problems with vorbis in lazarus
|
||||
|
||||
Revision 1.1 2005/12/19 18:36:56 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:53 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
|
||||
unit vorbisenc;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
|
||||
ACS_Procs,
|
||||
|
||||
{$IFDEF LINUX}
|
||||
baseunix,dl,
|
||||
{$ENDIF}
|
||||
{$IFDEF WIN32}
|
||||
Windows,
|
||||
{$ENDIF}
|
||||
|
||||
vorbiscodec;
|
||||
|
||||
|
||||
const
|
||||
|
||||
{$IFDEF LINUX}
|
||||
LibvorbisencPath = 'libvorbisenc.so*'; //'/usr/lib/libvorbisenc.so';
|
||||
{$DEFINE SEARCH_LIBS}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF WIN32}
|
||||
LibvorbisencPath = 'vorbisenc.dll';
|
||||
{$ENDIF}
|
||||
|
||||
|
||||
OV_ECTL_RATEMANAGE2_GET = $14;
|
||||
OV_ECTL_RATEMANAGE2_SET = $15;
|
||||
|
||||
|
||||
var
|
||||
LibvorbisencLoaded : Boolean = False;
|
||||
|
||||
type
|
||||
|
||||
vorbis_encode_init_t = function(var vi: VORBIS_INFO;
|
||||
channels: LongInt;
|
||||
rate: LongInt;
|
||||
max_bitrate: LongInt;
|
||||
nominal_bitrate: LongInt;
|
||||
min_bitrate: LongInt): Integer cdecl;
|
||||
|
||||
vorbis_encode_setup_managed_t = function(var vi: VORBIS_INFO;
|
||||
channels: LongInt;
|
||||
rate: LongInt;
|
||||
max_bitrate: LongInt;
|
||||
nominal_bitrate: LongInt;
|
||||
min_bitrate: LongInt): Integer; cdecl;
|
||||
|
||||
vorbis_encode_setup_vbr_t = function(var vi: VORBIS_INFO;
|
||||
channels: LongInt;
|
||||
rate: LongInt;
|
||||
fl: Single): Integer; cdecl;
|
||||
|
||||
vorbis_encode_init_vbr_t = function(var vi: VORBIS_INFO;
|
||||
channels: LongInt;
|
||||
rate: LongInt;
|
||||
base_quality: Single): Integer; cdecl;
|
||||
|
||||
vorbis_encode_setup_init_t = function(var vi: VORBIS_INFO): Integer; cdecl;
|
||||
|
||||
vorbis_encode_ctl_t = function(var vi: VORBIS_INFO;
|
||||
number: Integer;
|
||||
arg: Pointer): Integer; cdecl;
|
||||
|
||||
ovectl_ratemanage2_arg = record
|
||||
management_active : Integer;
|
||||
bitrate_limit_min_kbps : LongWord;
|
||||
bitrate_limit_max_kbps : LongWord;
|
||||
bitrate_limit_reservoir_bits : LongWord;
|
||||
bitrate_limit_reservoir_bias : Double;
|
||||
bitrate_average_kbps : LongWord;
|
||||
bitrate_average_damping : Double;
|
||||
end;
|
||||
|
||||
|
||||
var
|
||||
|
||||
vorbis_encode_init : vorbis_encode_init_t;
|
||||
|
||||
vorbis_encode_setup_managed : vorbis_encode_setup_managed_t;
|
||||
|
||||
vorbis_encode_setup_vbr : vorbis_encode_setup_vbr_t;
|
||||
|
||||
vorbis_encode_init_vbr : vorbis_encode_init_vbr_t;
|
||||
|
||||
vorbis_encode_setup_init : vorbis_encode_setup_init_t;
|
||||
|
||||
vorbis_encode_ctl : vorbis_encode_ctl_t;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
{$IFDEF LINUX}
|
||||
|
||||
var
|
||||
Libhandle : Pointer;
|
||||
|
||||
{$IFDEF SEARCH_LIBS}
|
||||
Path : String;
|
||||
{$ENDIF}
|
||||
|
||||
initialization
|
||||
|
||||
{$IFDEF SEARCH_LIBS}
|
||||
|
||||
Libhandle := nil;
|
||||
Path := FindLibs(LibvorbisencPath);
|
||||
if Path <> '' then Libhandle := dlopen(@Path[1], RTLD_NOW or RTLD_GLOBAL);
|
||||
|
||||
{$ELSE}
|
||||
|
||||
Libhandle := dlopen(LibvorbisencPath, RTLD_NOW or RTLD_GLOBAL);
|
||||
|
||||
{$ENDIF}
|
||||
|
||||
if Libhandle <> nil then
|
||||
begin
|
||||
LibvorbisencLoaded := True;
|
||||
vorbis_encode_init := dlsym(Libhandle, 'vorbis_encode_init');
|
||||
vorbis_encode_setup_managed := dlsym(Libhandle, 'vorbis_encode_setup_managed');
|
||||
vorbis_encode_setup_vbr := dlsym(Libhandle, 'vorbis_encode_setup_vbr');
|
||||
vorbis_encode_init_vbr := dlsym(Libhandle, 'vorbis_encode_init_vbr');
|
||||
vorbis_encode_setup_init := dlsym(Libhandle, 'vorbis_encode_setup_init');
|
||||
vorbis_encode_ctl := dlsym(Libhandle, 'vorbis_encode_ctl');
|
||||
end;
|
||||
|
||||
finalization
|
||||
|
||||
if libhandle <> nil then dlclose(Libhandle);
|
||||
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF WIN32}
|
||||
|
||||
var
|
||||
Libhandle : HMODULE;
|
||||
|
||||
initialization
|
||||
|
||||
Libhandle := LoadLibraryEx(LibvorbisencPath, 0, 0);
|
||||
if Libhandle <> 0 then
|
||||
begin
|
||||
LibvorbisencLoaded := True;
|
||||
vorbis_encode_init := GetProcAddress(Libhandle, 'vorbis_encode_init');
|
||||
vorbis_encode_setup_managed := GetProcAddress(Libhandle, 'vorbis_encode_setup_managed');
|
||||
vorbis_encode_setup_vbr := GetProcAddress(Libhandle, 'vorbis_encode_setup_vbr');
|
||||
vorbis_encode_init_vbr := GetProcAddress(Libhandle, 'vorbis_encode_init_vbr');
|
||||
vorbis_encode_setup_init := GetProcAddress(Libhandle, 'vorbis_encode_setup_init');
|
||||
vorbis_encode_ctl := GetProcAddress(Libhandle, 'vorbis_encode_ctl');
|
||||
end;
|
||||
|
||||
finalization
|
||||
|
||||
if libhandle <> 0 then FreeLibrary(Libhandle);
|
||||
|
||||
{$ENDIF}
|
||||
|
||||
end.
|
||||
316
acs/Src/fileformats/general/vorbisfile.pas
Normal file
316
acs/Src/fileformats/general/vorbisfile.pas
Normal file
@@ -0,0 +1,316 @@
|
||||
(*
|
||||
delphi/kylix headers for oggvorbis software codec.
|
||||
translated from vorbisfile.h header
|
||||
by andrei borovsky, acs@compiler4.net
|
||||
the original c/c++ headers and libraries (c) copyright 1994-2001
|
||||
by the xiphophorus company http://www.xiph.org/
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: vorbisfile.pas,v $
|
||||
Revision 1.2 2005/12/29 20:46:00 z0m3ie
|
||||
fixed some problems with vorbis in lazarus
|
||||
|
||||
Revision 1.1 2005/12/19 18:36:56 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2005/10/09 19:01:03 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:53 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.2 2005/09/10 08:25:40 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
{$IFDEF FPC}
|
||||
{$IFDEF WIN32}
|
||||
{$PACKRECORDS C}
|
||||
{$ENDIF WIN32}
|
||||
{$ENDIF WIN32}
|
||||
|
||||
unit vorbisfile;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
|
||||
ACS_Procs,
|
||||
|
||||
{$IFDEF LINUX}
|
||||
baseunix,dl,
|
||||
{$ENDIF}
|
||||
{$IFDEF WIN32}
|
||||
Windows,
|
||||
{$ENDIF}
|
||||
ogg,
|
||||
vorbiscodec,
|
||||
dynlibs;
|
||||
|
||||
(* The function prototypes for the callbacks are basically the same as for
|
||||
the stdio functions fread, fseek, fclose, ftell.
|
||||
The one difference is that the FILE* arguments have been replaced with
|
||||
a void* - this is to be used as a pointer to whatever internal data these
|
||||
functions might need. In the stdio case, it's just a FILE* cast to a void*
|
||||
|
||||
If you use other functions, check the docs for these functions and return
|
||||
the right values. For seek_func(), you*MUST* return -1 if the stream is
|
||||
unseekable *)
|
||||
|
||||
type
|
||||
|
||||
read_func_t = function(ptr : Pointer; size, nmemb : Cardinal;const datasource : Pointer) : Cardinal; cdecl;
|
||||
seek_func_t = function(const datasource : Pointer; offset : ogg_int64_t; whence : Integer) : Integer; cdecl;
|
||||
close_func_t = function(const datasource : Pointer) : Integer; cdecl;
|
||||
tell_func_t = function(const datasource : Pointer) : Integer; cdecl;
|
||||
|
||||
OV_CALLBACKS = record
|
||||
read_func : read_func_t;
|
||||
seek_func : seek_func_t;
|
||||
close_func : close_func_t;
|
||||
tell_func : tell_func_t;
|
||||
end;
|
||||
|
||||
const
|
||||
|
||||
NOTOPEN = 0;
|
||||
PARTOPEN = 1;
|
||||
OPENED = 2;
|
||||
STREAMSET = 3;
|
||||
INITSET = 4;
|
||||
|
||||
type
|
||||
|
||||
OGGVORBIS_FILE = record
|
||||
datasource: Pointer; // Pointer to a FILE*, etc.
|
||||
seekable: Integer;
|
||||
offset: OGG_INT64_T;
|
||||
_end: OGG_INT64_T;
|
||||
oy: OGG_SYNC_STATE;
|
||||
(* If the FILE handle isn't seekable (eg, a pipe),
|
||||
only the current stream appears *)
|
||||
links: Integer;
|
||||
offsets: POGG_INT64_T;
|
||||
dataoffsets: POGG_INT64_T;
|
||||
serialnos: PLongInt;
|
||||
pcmlengths: POGG_INT64_T;
|
||||
vi: PVORBIS_INFO;
|
||||
vc: PVORBIS_COMMENT;
|
||||
// Decoding working state local storage
|
||||
pcm_offset: OGG_INT64_T;
|
||||
ready_state: Integer;
|
||||
current_serialno: LongInt;
|
||||
current_link: Integer;
|
||||
bittrack: Double;
|
||||
samptrack: Double;
|
||||
os: OGG_STREAM_STATE;
|
||||
(* take physical pages, weld into a logical
|
||||
stream of packets *)
|
||||
vd: VORBIS_DSP_STATE;
|
||||
// central working state for the packet->PCM decoder
|
||||
vb: VORBIS_BLOCK;
|
||||
// local working space for packet->PCM decode
|
||||
callbacks: OV_CALLBACKS;
|
||||
end;
|
||||
|
||||
const
|
||||
|
||||
{$IFDEF LINUX}
|
||||
LibvorbisfilePath = 'libvorbisfile.so*'; //'/usr/lib/libvorbisfile.so';
|
||||
{$DEFINE SEARCH_LIBS}
|
||||
{$ENDIF}
|
||||
{$IFDEF WINDOWS}
|
||||
LibvorbisfilePath = 'vorbisfile.dll';
|
||||
{$ENDIF}
|
||||
|
||||
// stdio.h constants
|
||||
SEEK_CUR = 1;
|
||||
SEEK_END = 2;
|
||||
SEEK_SET = 0;
|
||||
|
||||
var
|
||||
LibvorbisfileLoaded : Boolean = False;
|
||||
|
||||
type
|
||||
|
||||
{$IFDEF LINUX}
|
||||
ov_open_t = function(f: Pointer;var vf: OGGVORBIS_FILE;initial: PChar;ibytes: LongInt): Integer; cdecl;
|
||||
ov_test_t = function(f: Pointer;var vf: OGGVORBIS_FILE;initial: PChar;ibytes: LongInt): Integer; cdecl;
|
||||
{$ENDIF}
|
||||
ov_clear_t = function(var vf: OGGVORBIS_FILE): Integer; cdecl;
|
||||
ov_open_callbacks_t = function(datasource: Pointer;var vf: OGGVORBIS_FILE;initial: PChar;ibytes: LongInt; callbacks: OV_CALLBACKS): Integer; cdecl;
|
||||
ov_test_callbacks_t = function(datasource: Pointer;var vf: OGGVORBIS_FILE;initial: PChar;ibytes: LongInt; callbacks: OV_CALLBACKS): Integer; cdecl;
|
||||
ov_test_open_t = function(var vf: OGGVORBIS_FILE): Integer; cdecl;
|
||||
ov_bitrate_t = function(var vf: OGGVORBIS_FILE;i: Integer): LongInt cdecl;
|
||||
ov_bitrate_instant_t = function(var vf: OGGVORBIS_FILE): LongInt cdecl;
|
||||
ov_streams_t = function(var vf: OGGVORBIS_FILE): LongInt cdecl;
|
||||
ov_seekable_t = function(var vf: OGGVORBIS_FILE): LongInt cdecl;
|
||||
ov_serialnumber_t = function(var vf: OGGVORBIS_FILE;i: Integer): LongInt cdecl;
|
||||
ov_raw_total_t = function(var vf: OGGVORBIS_FILE;i: Integer): OGG_INT64_T cdecl;
|
||||
ov_pcm_total_t = function(var vf: OGGVORBIS_FILE;i: Integer): OGG_INT64_T cdecl;
|
||||
ov_time_total_t = function(var vf: OGGVORBIS_FILE;i: Integer): Double cdecl;
|
||||
ov_raw_seek_t = function(var vf: OGGVORBIS_FILE;pos: LongInt): Integer cdecl;
|
||||
ov_pcm_seek_t = function(var vf: OGGVORBIS_FILE;pos: OGG_INT64_T): Integer cdecl;
|
||||
ov_pcm_seek_page_t = function(var vf: OGGVORBIS_FILE;pos: OGG_INT64_T): Integer cdecl;
|
||||
ov_time_seek_t = function(var vf: OGGVORBIS_FILE;pos: Double): Integer cdecl;
|
||||
ov_time_seek_page_t = function(var vf: OGGVORBIS_FILE;pos: Double): Integer cdecl;
|
||||
ov_raw_tell_t = function(var vf: OGGVORBIS_FILE): OGG_INT64_T cdecl;
|
||||
ov_pcm_tell_t = function(var vf: OGGVORBIS_FILE): OGG_INT64_T cdecl;
|
||||
ov_time_tell_t = function(var vf: OGGVORBIS_FILE): Double cdecl;
|
||||
ov_info_t = function(var vf: OGGVORBIS_FILE;link : Integer): PVORBIS_INFO cdecl;
|
||||
ov_comment_t = function(var vf: OGGVORBIS_FILE;link : Integer): PVORBIS_COMMENT cdecl;
|
||||
ov_read_float_t = function(var vf: OGGVORBIS_FILE;var pcm_channels: PPFLOAT;bitstream: PInteger): LongInt cdecl;
|
||||
ov_read_t = function(var vf: OGGVORBIS_FILE;buffer: PChar;length: Integer;bigendianp: Integer;word: Integer;sgned: Integer;bitstream: PInteger): LongInt cdecl;
|
||||
var
|
||||
{$IFDEF LINUX}
|
||||
ov_open : ov_open_t;
|
||||
ov_test : ov_test_t;
|
||||
{$ENDIF}
|
||||
ov_clear : ov_clear_t;
|
||||
ov_open_callbacks : ov_open_callbacks_t;
|
||||
ov_test_callbacks : ov_test_callbacks_t;
|
||||
ov_test_open : ov_test_open_t;
|
||||
ov_bitrate : ov_bitrate_t;
|
||||
ov_bitrate_instant : ov_bitrate_instant_t;
|
||||
ov_streams : ov_streams_t;
|
||||
ov_seekable : ov_seekable_t;
|
||||
ov_serialnumber : ov_serialnumber_t;
|
||||
ov_raw_total : ov_raw_total_t;
|
||||
ov_pcm_total : ov_pcm_total_t;
|
||||
ov_time_total : ov_time_total_t;
|
||||
ov_raw_seek : ov_raw_seek_t;
|
||||
ov_pcm_seek : ov_pcm_seek_t;
|
||||
ov_pcm_seek_page : ov_pcm_seek_page_t;
|
||||
ov_time_seek : ov_time_seek_t;
|
||||
ov_time_seek_page : ov_time_seek_page_t;
|
||||
ov_raw_tell : ov_raw_tell_t;
|
||||
ov_pcm_tell : ov_pcm_tell_t;
|
||||
ov_time_tell : ov_time_tell_t;
|
||||
ov_info : ov_info_t;
|
||||
ov_comment : ov_comment_t;
|
||||
ov_read_float : ov_read_float_t;
|
||||
ov_read : ov_read_t;
|
||||
|
||||
|
||||
{$IFDEF WINDOWS}
|
||||
Libhandle : HMODULE;
|
||||
{$ELSE}
|
||||
Libhandle : Pointer;
|
||||
{$ENDIF}
|
||||
|
||||
procedure VORBISLoadLibrary;
|
||||
|
||||
implementation
|
||||
|
||||
{$IFDEF SEARCH_LIBS}
|
||||
var
|
||||
Path : String;
|
||||
{$ENDIF}
|
||||
|
||||
procedure VORBISLoadLibrary;
|
||||
begin
|
||||
if LibvorbisfileLoaded then
|
||||
exit;
|
||||
{$IFDEF MSWINDOWS}
|
||||
Libhandle := LoadLibrary(PChar(LibvorbisfilePath));
|
||||
if Libhandle <> 0 then
|
||||
begin
|
||||
LibvorbisfileLoaded := True;
|
||||
ov_clear := GetProcAddress(Libhandle, 'ov_clear');
|
||||
ov_open_callbacks := GetProcAddress(Libhandle, 'ov_open_callbacks');
|
||||
ov_test_callbacks := GetProcAddress(Libhandle, 'ov_test_callbacks');
|
||||
ov_test_open := GetProcAddress(Libhandle, 'ov_test_open');
|
||||
ov_bitrate := GetProcAddress(Libhandle, 'ov_bitrate');
|
||||
ov_bitrate_instant := GetProcAddress(Libhandle, 'ov_bitrate_instant');
|
||||
ov_streams := GetProcAddress(Libhandle, 'ov_streams');
|
||||
ov_seekable := GetProcAddress(Libhandle, 'ov_seekable');
|
||||
ov_serialnumber := GetProcAddress(Libhandle, 'ov_serialnumber');
|
||||
ov_raw_total := GetProcAddress(Libhandle, 'ov_raw_total');
|
||||
ov_pcm_total := GetProcAddress(Libhandle, 'ov_pcm_total');
|
||||
ov_time_total := GetProcAddress(Libhandle, 'ov_time_total');
|
||||
ov_raw_seek := GetProcAddress(Libhandle, 'ov_raw_seek');
|
||||
ov_pcm_seek := GetProcAddress(Libhandle, 'ov_pcm_seek');
|
||||
ov_pcm_seek_page := GetProcAddress(Libhandle, 'ov_pcm_seek_page');
|
||||
ov_time_seek := GetProcAddress(Libhandle, 'ov_time_seek');
|
||||
ov_time_seek_page := GetProcAddress(Libhandle, 'ov_time_seek_page');
|
||||
ov_raw_tell := GetProcAddress(Libhandle, 'ov_raw_tell');
|
||||
ov_pcm_tell := GetProcAddress(Libhandle, 'ov_pcm_tell');
|
||||
ov_time_tell := GetProcAddress(Libhandle, 'ov_time_tell');
|
||||
ov_info := GetProcAddress(Libhandle, 'ov_info');
|
||||
ov_comment := GetProcAddress(Libhandle, 'ov_comment');
|
||||
ov_read_float := GetProcAddress(Libhandle, 'ov_read_float');
|
||||
ov_read := GetProcAddress(Libhandle, 'ov_read');
|
||||
end;
|
||||
{$ELSE}
|
||||
{$IFDEF SEARCH_LIBS}
|
||||
Libhandle := nil;
|
||||
Path := FindLibs(LibvorbisfilePath);
|
||||
if Path <> '' then Libhandle := dlopen(@Path[1], RTLD_NOW or RTLD_GLOBAL);
|
||||
{$ELSE}
|
||||
Libhandle := dlopen(LibvorbisfilePath, RTLD_NOW or RTLD_GLOBAL);
|
||||
{$ENDIF}
|
||||
if Libhandle <> nil then
|
||||
begin {$IFDEF FPC}
|
||||
{$IFDEF WIN32}
|
||||
{$PACKRECORDS C}
|
||||
{$ENDIF WIN32}
|
||||
{$ENDIF WIN32}
|
||||
|
||||
LibvorbisfileLoaded := True;
|
||||
ov_open := dlsym(Libhandle, 'ov_open');
|
||||
ov_test := dlsym(Libhandle, 'ov_test');
|
||||
ov_clear := dlsym(Libhandle, 'ov_clear');
|
||||
ov_open_callbacks := dlsym(Libhandle, 'ov_open_callbacks');
|
||||
ov_test_callbacks := dlsym(Libhandle, 'ov_test_callbacks');
|
||||
ov_test_open := dlsym(Libhandle, 'ov_test_open');
|
||||
ov_bitrate := dlsym(Libhandle, 'ov_bitrate');
|
||||
ov_bitrate_instant := dlsym(Libhandle, 'ov_bitrate_instant');
|
||||
ov_streams := dlsym(Libhandle, 'ov_streams');
|
||||
ov_seekable := dlsym(Libhandle, 'ov_seekable');
|
||||
ov_serialnumber := dlsym(Libhandle, 'ov_serialnumber');
|
||||
ov_raw_total := dlsym(Libhandle, 'ov_raw_total');
|
||||
ov_pcm_total := dlsym(Libhandle, 'ov_pcm_total');
|
||||
ov_time_total := dlsym(Libhandle, 'ov_time_total');
|
||||
ov_raw_seek := dlsym(Libhandle, 'ov_raw_seek');
|
||||
ov_pcm_seek := dlsym(Libhandle, 'ov_pcm_seek');
|
||||
ov_pcm_seek_page := dlsym(Libhandle, 'ov_pcm_seek_page');
|
||||
ov_time_seek := dlsym(Libhandle, 'ov_time_seek');
|
||||
ov_time_seek_page := dlsym(Libhandle, 'ov_time_seek_page');
|
||||
ov_raw_tell := dlsym(Libhandle, 'ov_raw_tell');
|
||||
ov_pcm_tell := dlsym(Libhandle, 'ov_pcm_tell');
|
||||
ov_time_tell := dlsym(Libhandle, 'ov_time_tell');
|
||||
ov_info := dlsym(Libhandle, 'ov_info');
|
||||
ov_comment := dlsym(Libhandle, 'ov_comment');
|
||||
ov_read_float := dlsym(Libhandle, 'ov_read_float');
|
||||
ov_read := dlsym(Libhandle, 'ov_read');
|
||||
end;
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
||||
finalization
|
||||
|
||||
{$IFDEF MSWINDOWS}
|
||||
if Libhandle <> 0 then FreeLibrary(Libhandle);
|
||||
{$ELSE}
|
||||
if libhandle <> nil then dlclose(Libhandle);
|
||||
{$ENDIF}
|
||||
|
||||
end.
|
||||
253
acs/Src/fileformats/linux/smpeg.pas
Normal file
253
acs/Src/fileformats/linux/smpeg.pas
Normal file
@@ -0,0 +1,253 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.3.
|
||||
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: smpeg.pas,v $
|
||||
Revision 1.5 2006/09/04 14:40:16 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.4 2006/08/30 18:59:51 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.3 2005/12/19 18:37:03 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:53 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
Revision 1.4 2005/08/22 20:17:01 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
|
||||
{$weakpackageunit on}
|
||||
|
||||
// Linux and Windows C-Compilers use different byte-allignment
|
||||
{$IFDEF Linux}
|
||||
{$align 4} // linux uses dword alignment
|
||||
{$endif}
|
||||
{$ifdef win32}
|
||||
{$ifdef ver140}
|
||||
{$align 8} // windows uses quad-word alignment
|
||||
{$endif}
|
||||
{$endif}
|
||||
|
||||
{$IFDEF FPC}
|
||||
{$PACKRECORDS 4}
|
||||
{$ENDIF FPC}
|
||||
|
||||
unit smpeg;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
SysUtils,ACS_Procs,Dialogs
|
||||
{$ifdef LINUX}
|
||||
, baseunix,dl
|
||||
{$else}
|
||||
, Windows
|
||||
{$endif}
|
||||
;
|
||||
|
||||
const
|
||||
|
||||
SMPEG_ERROR = -1;
|
||||
SMPEG_STOPPED = 0;
|
||||
SMPEG_PLAYING = 1;
|
||||
|
||||
type
|
||||
|
||||
_SMPEG = record
|
||||
//obj: PMPEG;
|
||||
end;
|
||||
TSMPEG = _SMPEG;
|
||||
PSMPEG = ^_SMPEG;
|
||||
|
||||
SDL_AudioSpec = record
|
||||
freq: Integer;
|
||||
format: Word;
|
||||
channels: Byte;
|
||||
silence: Byte;
|
||||
samples: Word;
|
||||
padding: Word;
|
||||
size: LongWord;
|
||||
callback: Pointer;
|
||||
userdata: Pointer;
|
||||
end;
|
||||
|
||||
SMPEG_Info ={ packed} record
|
||||
has_audio : Integer;
|
||||
has_video : Integer;
|
||||
width : Integer;
|
||||
height: Integer;
|
||||
current_frame: Integer;
|
||||
current_fps: Double;
|
||||
audio_string : array[0..79] of Char;
|
||||
audio_current_frame : Integer;
|
||||
current_offset: LongWord;
|
||||
total_size: LongWord;
|
||||
current_time: Double;
|
||||
total_time: Double;
|
||||
end;
|
||||
|
||||
const
|
||||
|
||||
{$ifdef LINUX}
|
||||
LibsmpegPath = 'libsmpeg*.so*';
|
||||
LibSDLPath = 'libSDL*.so*';
|
||||
{$ELSE}
|
||||
LibsmpegPath = 'smpeg.dll';
|
||||
LibSDLPath = 'SDL.dll';
|
||||
{$ENDIF}
|
||||
|
||||
var
|
||||
LibsmpegLoaded : Boolean = False;
|
||||
|
||||
type
|
||||
|
||||
SMPEG_new_t = function(const filename : PChar; var info : SMPEG_Info; sdl_audio : Integer): PSMPEG; cdecl;
|
||||
|
||||
SMPEG_delete_t = procedure(mpeg: Pointer); cdecl;
|
||||
|
||||
SMPEG_wantedSpec_t = function(mpeg: Pointer; var spec: SDL_AudioSpec): Integer; cdecl;
|
||||
|
||||
SMPEG_play_t = procedure(mpeg: Pointer); cdecl;
|
||||
|
||||
SMPEG_status_t = function(mpeg: Pointer) : Integer; cdecl;
|
||||
|
||||
SMPEG_stop_t = procedure(mpeg: Pointer); cdecl;
|
||||
|
||||
SMPEG_playAudio_t = function(mpeg: Pointer; stream: Pointer; len: Integer): Integer; cdecl;
|
||||
|
||||
SMPEG_skip_t = procedure(mpeg : Pointer; Pos : Single); cdecl;
|
||||
|
||||
SMPEG_rewind_t = procedure(mpeg : Pointer); cdecl;
|
||||
|
||||
var
|
||||
|
||||
SMPEG_new : SMPEG_new_t;
|
||||
|
||||
SMPEG_delete : SMPEG_delete_t;
|
||||
|
||||
SMPEG_wantedSpec : SMPEG_wantedSpec_t;
|
||||
|
||||
SMPEG_play : SMPEG_play_t;
|
||||
|
||||
SMPEG_status : SMPEG_status_t;
|
||||
|
||||
SMPEG_stop : SMPEG_stop_t;
|
||||
|
||||
SMPEG_playAudio : SMPEG_playAudio_t;
|
||||
|
||||
SMPEG_skip : SMPEG_skip_t;
|
||||
|
||||
SMPEG_rewind : SMPEG_rewind_t;
|
||||
|
||||
procedure LoadMPEGLibrary;
|
||||
procedure UnloadMPEGLibrary;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
type
|
||||
SDL_Init_t = function(Flags : LongWord) : Integer; cdecl;
|
||||
SDL_Quit_t = procedure; cdecl;
|
||||
|
||||
const
|
||||
SDL_INIT_AUDIO = $00000010;
|
||||
|
||||
var
|
||||
{$ifdef LINUX}
|
||||
Libhandle : Pointer;
|
||||
SDLhandle : Pointer;
|
||||
{$else}
|
||||
Libhandle : Cardinal;
|
||||
SDLhandle : Cardinal;
|
||||
{$endif}
|
||||
SDL_Init : SDL_Init_t;
|
||||
SDL_Quit : SDL_Quit_t;
|
||||
|
||||
procedure LoadMPEGLibrary;
|
||||
var
|
||||
Path : string;
|
||||
begin
|
||||
{$ifdef LINUX}
|
||||
Path := FindLibs(LibSDLPath);
|
||||
if Path <> '' then SDLhandle := dlopen(@Path[1], RTLD_NOW or RTLD_GLOBAL);
|
||||
// SDLhandle := dlopen(LibSDLPath, RTLD_NOW{$IFDEF LINUX} or RTLD_GLOBAL{$ENDIF});
|
||||
if SDLhandle = nil then exit;
|
||||
SDL_Init := dlsym(SDLhandle, 'SDL_Init');
|
||||
SDL_Quit := dlsym(SDLhandle, 'SDL_Quit');
|
||||
SDL_Init(SDL_INIT_AUDIO);
|
||||
|
||||
Path := FindLibs(LibsmpegPath);
|
||||
if Path <> '' then Libhandle := dlopen(@Path[1], RTLD_NOW or RTLD_GLOBAL);
|
||||
// Libhandle := dlopen(LibsmpegPath, RTLD_NOW{$IFDEF LINUX} or RTLD_GLOBAL{$ENDIF});
|
||||
if Libhandle = nil then exit;
|
||||
if Libhandle <> nil then
|
||||
begin
|
||||
LibsmpegLoaded := True;
|
||||
SMPEG_new := dlsym(Libhandle, 'SMPEG_new');
|
||||
SMPEG_delete := dlsym(Libhandle, 'SMPEG_delete');
|
||||
SMPEG_wantedSpec := dlsym(Libhandle, 'SMPEG_wantedSpec');
|
||||
SMPEG_play := dlsym(Libhandle, 'SMPEG_play');
|
||||
SMPEG_status := dlsym(Libhandle, 'SMPEG_status');
|
||||
SMPEG_stop := dlsym(Libhandle, 'SMPEG_stop');
|
||||
SMPEG_playAudio := dlsym(Libhandle, 'SMPEG_playAudio');
|
||||
SMPEG_skip := dlsym(Libhandle, 'SMPEG_skip');
|
||||
SMPEG_rewind := dlsym(Libhandle, 'SMPEG_rewind');
|
||||
end;
|
||||
{$ELSE}
|
||||
SDLhandle := LoadLibrary(LibSDLPath);
|
||||
if SDLhandle = 0 then exit;
|
||||
SDL_Init := GetProcAddress(SDLhandle, 'SDL_Init');
|
||||
SDL_Quit := GetProcAddress(SDLhandle, 'SDL_Quit');
|
||||
SDL_Init(SDL_INIT_AUDIO);
|
||||
Libhandle := LoadLibrary(LibsmpegPath);
|
||||
if Libhandle = 0 then exit;
|
||||
if Libhandle <> 0 then
|
||||
begin
|
||||
LibsmpegLoaded := True;
|
||||
SMPEG_new := GetProcAddress(Libhandle, 'SMPEG_new');
|
||||
SMPEG_delete := GetProcAddress(Libhandle, 'SMPEG_delete');
|
||||
SMPEG_wantedSpec := GetProcAddress(Libhandle, 'SMPEG_wantedSpec');
|
||||
SMPEG_play := GetProcAddress(Libhandle, 'SMPEG_play');
|
||||
SMPEG_status := GetProcAddress(Libhandle, 'SMPEG_status');
|
||||
SMPEG_stop := GetProcAddress(Libhandle, 'SMPEG_stop');
|
||||
SMPEG_playAudio := GetProcAddress(Libhandle, 'SMPEG_playAudio');
|
||||
SMPEG_skip := GetProcAddress(Libhandle, 'SMPEG_skip');
|
||||
SMPEG_rewind := GetProcAddress(Libhandle, 'SMPEG_rewind');
|
||||
end;
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
procedure UnloadMPEGLibrary;
|
||||
|
||||
begin
|
||||
SDL_Quit;
|
||||
{$ifdef LINUX}
|
||||
if Libhandle <> nil then dlclose(Libhandle);
|
||||
if SDLhandle <> nil then dlclose(SDLhandle);
|
||||
{$else}
|
||||
if Libhandle <> 0 then FreeLibrary(Libhandle);
|
||||
if SDLhandle <> 0 then FreeLibrary(SDLhandle);
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
end.
|
||||
3619
acs/Src/fileformats/windows/direct3d9.pas
Normal file
3619
acs/Src/fileformats/windows/direct3d9.pas
Normal file
File diff suppressed because it is too large
Load Diff
6340
acs/Src/fileformats/windows/directdraw.pas
Normal file
6340
acs/Src/fileformats/windows/directdraw.pas
Normal file
File diff suppressed because it is too large
Load Diff
32049
acs/Src/fileformats/windows/directshow9.pas
Normal file
32049
acs/Src/fileformats/windows/directshow9.pas
Normal file
File diff suppressed because it is too large
Load Diff
1821
acs/Src/fileformats/windows/directsound.pas
Normal file
1821
acs/Src/fileformats/windows/directsound.pas
Normal file
File diff suppressed because it is too large
Load Diff
29
acs/Src/fileformats/windows/directx.inc
Normal file
29
acs/Src/fileformats/windows/directx.inc
Normal file
@@ -0,0 +1,29 @@
|
||||
{******************************************************************************}
|
||||
{ }
|
||||
{ The contents of this file are subject to the Mozilla Public License Version }
|
||||
{ 1.1 (the "License"); you may not use this file except in compliance with the }
|
||||
{ License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ }
|
||||
{ }
|
||||
{ Software distributed under the License is distributed on an "AS IS" basis, }
|
||||
{ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for }
|
||||
{ the specific language governing rights and limitations under the License. }
|
||||
{ }
|
||||
{ The Original Code is DirectX.inc. }
|
||||
{ }
|
||||
{******************************************************************************}
|
||||
|
||||
// Borland compilers support
|
||||
{$INCLUDE Jedi.inc}
|
||||
|
||||
{$DEFINE TYPE_IDENTITY}
|
||||
{$DEFINE SUPPORTS_EXCEPTIONS}
|
||||
|
||||
// Additional settings
|
||||
{$MINENUMSIZE 4}
|
||||
{$ALIGN ON}
|
||||
|
||||
{$IFDEF COMPILER7_UP}
|
||||
{$WARN UNSAFE_CODE OFF}
|
||||
{$WARN UNSAFE_TYPE OFF}
|
||||
{$WARN UNSAFE_CAST OFF}
|
||||
{$ENDIF}
|
||||
133
acs/Src/fileformats/windows/dxtypes.pas
Normal file
133
acs/Src/fileformats/windows/dxtypes.pas
Normal file
@@ -0,0 +1,133 @@
|
||||
{******************************************************************************}
|
||||
{* *}
|
||||
{* copyright (c) microsoft corporation. all rights reserved. *}
|
||||
{* *}
|
||||
{* files: dxsdkver.h, extracts from various directx sdk include files *}
|
||||
{* content: directx 9.0 headers common types *}
|
||||
{* *}
|
||||
{* directx 9.0 delphi / freepascal adaptation by alexey barkovoy *}
|
||||
{* e-mail: directx@clootie.ru *}
|
||||
{* *}
|
||||
{* latest version can be downloaded from: *}
|
||||
{* http://www.clootie.ru *}
|
||||
{* http://sourceforge.net/projects/delphi-dx9sdk *}
|
||||
{* *}
|
||||
{*----------------------------------------------------------------------------*}
|
||||
{* $id: dxtypes.pas,v 1.1 2005/09/12 22:04:53 z0m3ie exp $ }
|
||||
{******************************************************************************}
|
||||
{ }
|
||||
{ the contents of this file are used with permission, subject to the mozilla }
|
||||
{ public license version 1.1 (the "license"); you may not use this file except }
|
||||
{ in compliance with the license. you may obtain a copy of the license at }
|
||||
{ http://www.mozilla.org/mpl/mpl-1.1.html }
|
||||
{ }
|
||||
{ software distributed under the license is distributed on an "as is" basis, }
|
||||
{ without warranty of any kind, either express or implied. see the license for }
|
||||
{ the specific language governing rights and limitations under the license. }
|
||||
{ }
|
||||
{ alternatively, the contents of this file may be used under the terms of the }
|
||||
{ gnu lesser general public license (the "lgpl license"), in which case the }
|
||||
{ provisions of the lgpl license are applicable instead of those above. }
|
||||
{ if you wish to allow use of your version of this file only under the terms }
|
||||
{ of the lgpl license and not to allow others to use your version of this file }
|
||||
{ under the mpl, indicate your decision by deleting the provisions above and }
|
||||
{ replace them with the notice and other provisions required by the lgpl }
|
||||
{ license. if you do not delete the provisions above, a recipient may use }
|
||||
{ your version of this file under either the mpl or the lgpl license. }
|
||||
{ }
|
||||
{ for more information about the lgpl: http://www.gnu.org/copyleft/lesser.html }
|
||||
{ }
|
||||
{******************************************************************************}
|
||||
|
||||
{.$I DirectX.inc}
|
||||
|
||||
unit dxtypes;
|
||||
|
||||
interface
|
||||
|
||||
|
||||
uses windows;
|
||||
|
||||
(*==========================================================================;
|
||||
*
|
||||
* File: dxsdkver.h
|
||||
* Content: DirectX SDK Version Include File
|
||||
*
|
||||
****************************************************************************)
|
||||
const
|
||||
_DXSDK_PRODUCT_MAJOR = 9;
|
||||
_DXSDK_PRODUCT_MINOR = 08;
|
||||
_DXSDK_BUILD_MAJOR = 299;
|
||||
_DXSDK_BUILD_MINOR = 0000;
|
||||
|
||||
|
||||
|
||||
(****************************************************************************
|
||||
* Other files
|
||||
****************************************************************************)
|
||||
type
|
||||
// TD3DValue is the fundamental Direct3D fractional data type
|
||||
D3DVALUE = Single;
|
||||
TD3DValue = D3DVALUE;
|
||||
PD3DValue = ^TD3DValue;
|
||||
|
||||
D3DCOLOR = DWord;
|
||||
TD3DColor = D3DCOLOR;
|
||||
PD3DColor = ^TD3DColor;
|
||||
|
||||
_D3DVECTOR = packed record
|
||||
x: Single;
|
||||
y: Single;
|
||||
z: Single;
|
||||
end {_D3DVECTOR};
|
||||
D3DVECTOR = _D3DVECTOR;
|
||||
TD3DVector = _D3DVECTOR;
|
||||
PD3DVector = ^TD3DVector;
|
||||
|
||||
REFERENCE_TIME = LONGLONG;
|
||||
TReferenceTime = REFERENCE_TIME;
|
||||
PReferenceTime = ^TReferenceTime;
|
||||
|
||||
|
||||
// ==================================================================
|
||||
// Here comes generic Windows types for Win32 / Win64 compatibility
|
||||
//
|
||||
|
||||
//
|
||||
// The INT_PTR is guaranteed to be the same size as a pointer. Its
|
||||
// size with change with pointer size (32/64). It should be used
|
||||
// anywhere that a pointer is cast to an integer type. UINT_PTR is
|
||||
// the unsigned variation.
|
||||
//
|
||||
{$IFDEF WIN64}
|
||||
INT_PTR = Int64;
|
||||
UINT_PTR = Int64; // not yet: UInt64;
|
||||
LONG_PTR = Int64;
|
||||
ULONG_PTR = Int64; // not yet: UInt64;
|
||||
DWORD_PTR = Int64; // not yet: UInt64;
|
||||
{$ELSE}
|
||||
INT_PTR = Longint;
|
||||
UINT_PTR = Longword;
|
||||
LONG_PTR = Longint;
|
||||
ULONG_PTR = Longword;
|
||||
DWORD_PTR = Longword;
|
||||
{$ENDIF}
|
||||
PINT_PTR = ^INT_PTR;
|
||||
PUINT_PTR = ^UINT_PTR;
|
||||
PLONG_PTR = ^LONG_PTR;
|
||||
PULONG_PTR = ^ULONG_PTR;
|
||||
|
||||
|
||||
//
|
||||
// SIZE_T used for counts or ranges which need to span the range of
|
||||
// of a pointer. SSIZE_T is the signed variation.
|
||||
//
|
||||
SIZE_T = ULONG_PTR;
|
||||
SSIZE_T = LONG_PTR;
|
||||
PSIZE_T = ^SIZE_T;
|
||||
PSSIZE_T = ^SSIZE_T;
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
||||
|
||||
578
acs/Src/fileformats/windows/jedi.inc
Normal file
578
acs/Src/fileformats/windows/jedi.inc
Normal file
@@ -0,0 +1,578 @@
|
||||
{******************************************************************************}
|
||||
{ }
|
||||
{ The contents of this file are subject to the Mozilla Public License Version }
|
||||
{ 1.1 (the "License"); you may not use this file except in compliance with the }
|
||||
{ License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ }
|
||||
{ }
|
||||
{ Software distributed under the License is distributed on an "AS IS" basis, }
|
||||
{ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for }
|
||||
{ the specific language governing rights and limitations under the License. }
|
||||
{ }
|
||||
{ The Original Code is JEDI.INC. }
|
||||
{ }
|
||||
{ The Initial Developer of the Original Code is Project JEDI }
|
||||
{ http://www.delphi-jedi.org }
|
||||
{ }
|
||||
{******************************************************************************}
|
||||
{ }
|
||||
{ This file defines various generic compiler directives used in the JEDI Code }
|
||||
{ Library (JCL) and JEDI Visual Component Library Library (J-VCL). The }
|
||||
{ directives in this file are of generic nature and consist mostly of mappings }
|
||||
{ from the VERXXX directives defined by Delphi and C++ Builder to friendly }
|
||||
{ names such as DELPHI5 and SUPPORTS_WIDESTRING. These friendly names are }
|
||||
{ subsequently used in both libraries to test for compiler versions and/or }
|
||||
{ whether the compiler supports certain features (such as widestring's or 64 }
|
||||
{ bit integers. Both libraries provide an additional, library specific, }
|
||||
{ include file. For the JCL this is JCL.INC. These files should be included in }
|
||||
{ source files instead of this file (which is pulled in automatically). }
|
||||
{ }
|
||||
{ Maintainer: Marcel van Brakel }
|
||||
{ Last modified: May 25, 2002 }
|
||||
{ }
|
||||
{******************************************************************************}
|
||||
|
||||
(*
|
||||
|
||||
- Development environment directives
|
||||
|
||||
This file defines two driectives to indicate which development environment the
|
||||
library is being compiled with. Currently this can either be Delphi or
|
||||
C++ Builder (in the near future "Kylix" will be added).
|
||||
|
||||
Directive Description
|
||||
------------------------------------------------------------------------------
|
||||
DELPHI Defined if compiled with Delphi
|
||||
CBUILDER Defined if compiled with C++ Builder
|
||||
|
||||
- Platform Directives
|
||||
|
||||
Platform directives are not explicitly defined in this file but are defined
|
||||
by the compiler itself. They are listed here only for completeness.
|
||||
|
||||
Directive Description
|
||||
------------------------------------------------------------------------------
|
||||
WIN32 Defined when target platform is 32 bit Windows
|
||||
LINUX Defined when target platform is Linux
|
||||
|
||||
- Delphi Versions
|
||||
|
||||
The following directives are direct mappings from the VERXXX directives to a
|
||||
friendly name of the associated compiler. These directives are only defined if
|
||||
the compiler is Delphi (ie DELPHI is defined).
|
||||
|
||||
Directive Description
|
||||
------------------------------------------------------------------------------
|
||||
DELPHI1 Defined when compiling with Delphi 1
|
||||
DELPHI2 Defined when compiling with Delphi 2
|
||||
DELPHI3 Defined when compiling with Delphi 3
|
||||
DELPHI4 Defined when compiling with Delphi 4
|
||||
DELPHI5 Defined when compiling with Delphi 5
|
||||
DELPHI6 Defined when compiling with Delphi 6
|
||||
DELPHI7 Defined when compiling with Delphi 7
|
||||
DELPHI8 Defined when compiling with Delphi 8
|
||||
DELPHI9 Defined when compiling with Delphi 9
|
||||
DELPHI1_UP Defined when compiling with Delphi 1 or higher
|
||||
DELPHI2_UP Defined when compiling with Delphi 2 or higher
|
||||
DELPHI3_UP Defined when compiling with Delphi 3 or higher
|
||||
DELPHI4_UP Defined when compiling with Delphi 4 or higher
|
||||
DELPHI5_UP Defined when compiling with Delphi 5 or higher
|
||||
DELPHI6_UP Defined when compiling with Delphi 6 or higher
|
||||
DELPHI7_UP Defined when compiling with Delphi 7 or higher
|
||||
DELPHI8_UP Defined when compiling with Delphi 8 or higher
|
||||
DELPHI9_UP Defined when compiling with Delphi 9 or higher
|
||||
|
||||
- C++ Builder Versions
|
||||
|
||||
The following directives are direct mappings from the VERXXX directives to a
|
||||
friendly name of the associated compiler. These directives are only defined if
|
||||
the compiler is C++ Builder (ie BCB is defined).
|
||||
|
||||
Directive Description
|
||||
------------------------------------------------------------------------------
|
||||
BCB1 Defined when compiling with C++ Builder 1
|
||||
BCB3 Defined when compiling with C++ Builder 3
|
||||
BCB4 Defined when compiling with C++ Builder 4
|
||||
BCB5 Defined when compiling with C++ Builder 5
|
||||
BCB6 Defined when compiling with C++ Builder 6
|
||||
BCB7 Defined when compiling with C++ Builder 7
|
||||
BCB1_UP Defined when compiling with C++ Builder 1 or higher
|
||||
BCB3_UP Defined when compiling with C++ Builder 3 or higher
|
||||
BCB4_UP Defined when compiling with C++ Builder 4 or higher
|
||||
BCB5_UP Defined when compiling with C++ Builder 5 or higher
|
||||
BCB6_UP Defined when compiling with C++ Builder 6 or higher
|
||||
BCB7_UP Defined when compiling with C++ Builder 7 or higher
|
||||
|
||||
- Compiler Versions
|
||||
|
||||
The following directives are direct mappings from the VERXXX directives to a
|
||||
friendly name of the associated compiler. Unlike the DELPHI_X and BCB_X
|
||||
directives, these directives are indepedent of the development environment.
|
||||
That is, they are defined regardless of whether compilation takes place using
|
||||
Delphi or C++ Builder.
|
||||
|
||||
Directive Description
|
||||
------------------------------------------------------------------------------
|
||||
COMPILER1 Defined when compiling with Delphi 1
|
||||
COMPILER2 Defined when compiling with Delphi 2 or C++ Builder 1
|
||||
COMPILER3 Defined when compiling with Delphi 3
|
||||
COMPILER35 Defined when compiling with C++ Builder 3
|
||||
COMPILER4 Defined when compiling with Delphi 4 or C++ Builder 4
|
||||
COMPILER5 Defined when compiling with Delphi 5 or C++ Builder 5
|
||||
COMPILER6 Defined when compiling with Delphi 6 or C++ Builder 6
|
||||
COMPILER1_UP Defined when compiling with Delphi 1 or higher
|
||||
COMPILER2_UP Defined when compiling with Delphi 2 or C++ Builder 1 or higher
|
||||
COMPILER3_UP Defined when compiling with Delphi 3 or higher
|
||||
COMPILER35_UP Defined when compiling with C++ Builder 3 or higher
|
||||
COMPILER4_UP Defined when compiling with Delphi 4 or C++ Builder 4 or higher
|
||||
COMPILER5_UP Defined when compiling with Delphi 5 or C++ Builder 5 or higher
|
||||
COMPILER6_UP Defined when compiling with Delphi 6 or C++ Builder 6 or higher
|
||||
COMPILER7_UP Defined when compiling with Delphi 6 or C++ Builder 6 or higher
|
||||
|
||||
- Feature Directives
|
||||
|
||||
The features directives are used to test if the compiler supports specific
|
||||
features, such as method overloading, and adjust the sources accordingly. Use
|
||||
of these directives is preferred over the use of the DELPHI and COMPILER
|
||||
directives.
|
||||
|
||||
Directive Description
|
||||
------------------------------------------------------------------------------
|
||||
SUPPORTS_WIDESTRING Compiler supports the WideString type (D3/BCB3 up)
|
||||
SUPPORTS_INTERFACE Compiler supports interfaces (D3/BCB3)
|
||||
SUPPORTS_EXTSYM Compiler supports the $EXTERNALSYM directive (D4/BCB3)
|
||||
SUPPORTS_NODEFINE Compiler supports the $NODEFINE directive (D4/BCB3)
|
||||
SUPPORTS_INT64 Compiler supports the Int64 type (D4/BCB4)
|
||||
SUPPORTS_DYNAMICARRAYS Compiler supports dynamic arrays (D4/BCB4)
|
||||
SUPPORTS_DEFAULTPARAMS Compiler supports default parameters (D4/BCB4)
|
||||
SUPPORTS_OVERLOAD Compiler supports overloading (D4/BCB4)
|
||||
SUPPORTS_INLINE Compiler supports inline directive (D9)
|
||||
|
||||
- Compiler Settings
|
||||
|
||||
The compiler settings directives indicate whether a specific compiler setting
|
||||
is in effect. This facilitates changing compiler settings locally in a more
|
||||
compact and readible manner.
|
||||
|
||||
Directive Description
|
||||
------------------------------------------------------------------------------
|
||||
ALIGN_ON Compiling in the A+ state (no alignment)
|
||||
BOOLEVAL_ON Compiling in the B+ state (complete boolean evaluation)
|
||||
ASSERTIONS_ON Compiling in the C+ state (assertions on)
|
||||
DEBUGINFO_ON Compiling in the D+ state (debug info generation on)
|
||||
IMPORTEDDATA_ON Compiling in the G+ state (creation of imported data references)
|
||||
LONGSTRINGS_ON Compiling in the H+ state (string defined as AnsiString)
|
||||
IOCHECKS_ON Compiling in the I+ state (I/O checking enabled)
|
||||
WRITEABLECONST_ON Compiling in the J+ state (typed constants can be modified)
|
||||
LOCALSYMBOLS Compiling in the L+ state (local symbol generation)
|
||||
TYPEINFO_ON Compiling in the M+ state (RTTI generation on)
|
||||
OPTIMIZATION_ON Compiling in the O+ state (code optimization on)
|
||||
OPENSTRINGS_ON Compiling in the P+ state (variable string parameters are openstrings)
|
||||
OVERFLOWCHECKS_ON Compiling in the Q+ state (overflow checing on)
|
||||
RANGECHECKS_ON Compiling in the R+ state (range checking on)
|
||||
TYPEDADDRESS_ON Compiling in the T+ state (pointers obtained using the @ operator are typed)
|
||||
SAFEDIVIDE_ON Compiling in the U+ state (save FDIV instruction through RTL emulation)
|
||||
VARSTRINGCHECKS_ON Compiling in the V+ state (type checking of shortstrings)
|
||||
STACKFRAMES_ON Compiling in the W+ state (generation of stack frames)
|
||||
EXTENDEDSYNTAX_ON Compiling in the X+ state (Delphi extended syntax enabled)
|
||||
|
||||
*)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Compiler settings
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
{$IFOPT A+} {$DEFINE ALIGN_ON} {$ENDIF}
|
||||
{$IFOPT B+} {$DEFINE BOOLEVAL_ON} {$ENDIF}
|
||||
{$IFOPT C+} {$DEFINE ASSERTIONS_ON} {$ENDIF}
|
||||
{$IFOPT D+} {$DEFINE DEBUGINFO_ON} {$ENDIF}
|
||||
{$IFOPT G+} {$DEFINE IMPORTEDDATA_ON} {$ENDIF}
|
||||
{$IFOPT H+} {$DEFINE LONGSTRINGS_ON} {$ENDIF}
|
||||
//HINTS
|
||||
{$IFOPT I+} {$DEFINE IOCHECKS_ON} {$ENDIF}
|
||||
{$IFOPT J+} {$DEFINE WRITEABLECONST_ON} {$ENDIF}
|
||||
{$IFOPT L+} {$DEFINE LOCALSYMBOLS} {$ENDIF}
|
||||
{$IFOPT M+} {$DEFINE TYPEINFO_ON} {$ENDIF}
|
||||
{$IFOPT O+} {$DEFINE OPTIMIZATION_ON} {$ENDIF}
|
||||
{$IFOPT P+} {$DEFINE OPENSTRINGS_ON} {$ENDIF}
|
||||
{$IFOPT Q+} {$DEFINE OVERFLOWCHECKS_ON} {$ENDIF}
|
||||
{$IFOPT R+} {$DEFINE RANGECHECKS_ON} {$ENDIF}
|
||||
//REALCOMPATIBILITY
|
||||
{$IFOPT T+} {$DEFINE TYPEDADDRESS_ON} {$ENDIF}
|
||||
{$IFOPT U+} {$DEFINE SAFEDIVIDE_ON} {$ENDIF}
|
||||
{$IFOPT V+} {$DEFINE VARSTRINGCHECKS_ON} {$ENDIF}
|
||||
{$IFOPT W+} {$DEFINE STACKFRAMES_ON} {$ENDIF}
|
||||
//WARNINGS
|
||||
{$IFOPT X+} {$DEFINE EXTENDEDSYNTAX_ON} {$ENDIF}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// VERXXX to COMPILERX, DELPHIX and BCBX mappings
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
{$IFDEF VER170}
|
||||
{$DEFINE COMPILER9}
|
||||
{$IFDEF BCB}
|
||||
{$DEFINE BCB9}
|
||||
{$DEFINE CBUILDER}
|
||||
{$ELSE}
|
||||
{$DEFINE DELPHI9}
|
||||
{$DEFINE DELPHI}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER160}
|
||||
{$DEFINE COMPILER8}
|
||||
{$IFDEF BCB}
|
||||
{$DEFINE BCB8}
|
||||
{$DEFINE CBUILDER}
|
||||
{$ELSE}
|
||||
{$DEFINE DELPHI8}
|
||||
{$DEFINE DELPHI}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER150}
|
||||
{$DEFINE COMPILER7}
|
||||
{$IFDEF BCB}
|
||||
{$DEFINE BCB7}
|
||||
{$DEFINE CBUILDER}
|
||||
{$ELSE}
|
||||
{$DEFINE DELPHI7}
|
||||
{$DEFINE DELPHI}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER140}
|
||||
{$DEFINE COMPILER6}
|
||||
{$IFDEF BCB}
|
||||
{$DEFINE BCB6}
|
||||
{$DEFINE CBUILDER}
|
||||
{$ELSE}
|
||||
{$DEFINE DELPHI6}
|
||||
{$DEFINE DELPHI}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER130}
|
||||
{$DEFINE COMPILER5}
|
||||
{$IFDEF BCB}
|
||||
{$DEFINE BCB5}
|
||||
{$DEFINE CBUILDER}
|
||||
{$ELSE}
|
||||
{$DEFINE DELPHI5}
|
||||
{$DEFINE DELPHI}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER125}
|
||||
{$DEFINE COMPILER4}
|
||||
{$DEFINE BCB4}
|
||||
{$DEFINE CBUILDER}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER120}
|
||||
{$DEFINE COMPILER4}
|
||||
{$DEFINE DELPHI4}
|
||||
{$DEFINE DELPHI}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER110}
|
||||
{$DEFINE COMPILER35}
|
||||
{$DEFINE BCB3}
|
||||
{$DEFINE CBUILDER}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER100}
|
||||
{$DEFINE COMPILER3}
|
||||
{$DEFINE DELPHI3}
|
||||
{$DEFINE DELPHI}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER93}
|
||||
{$DEFINE COMPILER2}
|
||||
{$DEFINE BCB1}
|
||||
{$DEFINE CBUILDER}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER90}
|
||||
{$DEFINE COMPILER2}
|
||||
{$DEFINE DELPHI2}
|
||||
{$DEFINE DELPHI}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER80}
|
||||
{$DEFINE COMPILER1}
|
||||
{$DEFINE DELPHI1}
|
||||
{$DEFINE DELPHI}
|
||||
{$ENDIF}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// DELPHIX_UP from DELPHIX mappings
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
{$IFDEF DELPHI9}
|
||||
{$DEFINE DELPHI9_UP}
|
||||
{$DEFINE DELPHI8_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI4_UP}
|
||||
{$DEFINE DELPHI3_UP}
|
||||
{$DEFINE DELPHI2_UP}
|
||||
{$DEFINE DELPHI1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF DELPHI8}
|
||||
{$DEFINE DELPHI8_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI4_UP}
|
||||
{$DEFINE DELPHI3_UP}
|
||||
{$DEFINE DELPHI2_UP}
|
||||
{$DEFINE DELPHI1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF DELPHI7}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI4_UP}
|
||||
{$DEFINE DELPHI3_UP}
|
||||
{$DEFINE DELPHI2_UP}
|
||||
{$DEFINE DELPHI1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF DELPHI6}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI4_UP}
|
||||
{$DEFINE DELPHI3_UP}
|
||||
{$DEFINE DELPHI2_UP}
|
||||
{$DEFINE DELPHI1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF DELPHI5}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI4_UP}
|
||||
{$DEFINE DELPHI3_UP}
|
||||
{$DEFINE DELPHI2_UP}
|
||||
{$DEFINE DELPHI1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF DELPHI4}
|
||||
{$DEFINE DELPHI4_UP}
|
||||
{$DEFINE DELPHI3_UP}
|
||||
{$DEFINE DELPHI2_UP}
|
||||
{$DEFINE DELPHI1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF DELPHI3}
|
||||
{$DEFINE DELPHI3_UP}
|
||||
{$DEFINE DELPHI2_UP}
|
||||
{$DEFINE DELPHI1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF DELPHI2}
|
||||
{$DEFINE DELPHI2_UP}
|
||||
{$DEFINE DELPHI1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF DELPHI1}
|
||||
{$DEFINE DELPHI1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// BCBX_UP from BCBX mappings
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
{$IFDEF BCB9}
|
||||
{$DEFINE BCB9_UP}
|
||||
{$DEFINE BCB8_UP}
|
||||
{$DEFINE BCB7_UP}
|
||||
{$DEFINE BCB6_UP}
|
||||
{$DEFINE BCB5_UP}
|
||||
{$DEFINE BCB4_UP}
|
||||
{$DEFINE BCB3_UP}
|
||||
{$DEFINE BCB1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF BCB8}
|
||||
{$DEFINE BCB8_UP}
|
||||
{$DEFINE BCB7_UP}
|
||||
{$DEFINE BCB6_UP}
|
||||
{$DEFINE BCB5_UP}
|
||||
{$DEFINE BCB4_UP}
|
||||
{$DEFINE BCB3_UP}
|
||||
{$DEFINE BCB1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF BCB7}
|
||||
{$DEFINE BCB7_UP}
|
||||
{$DEFINE BCB6_UP}
|
||||
{$DEFINE BCB5_UP}
|
||||
{$DEFINE BCB4_UP}
|
||||
{$DEFINE BCB3_UP}
|
||||
{$DEFINE BCB1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF BCB6}
|
||||
{$DEFINE BCB6_UP}
|
||||
{$DEFINE BCB5_UP}
|
||||
{$DEFINE BCB4_UP}
|
||||
{$DEFINE BCB3_UP}
|
||||
{$DEFINE BCB1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF BCB5}
|
||||
{$DEFINE BCB5_UP}
|
||||
{$DEFINE BCB4_UP}
|
||||
{$DEFINE BCB3_UP}
|
||||
{$DEFINE BCB1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF BCB4}
|
||||
{$DEFINE BCB4_UP}
|
||||
{$DEFINE BCB3_UP}
|
||||
{$DEFINE BCB1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF BCB3}
|
||||
{$DEFINE BCB3_UP}
|
||||
{$DEFINE BCB1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF BCB1}
|
||||
{$DEFINE BCB1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// COMPILERX_UP from COMPILERX mappings
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
{$IFDEF COMPILER9}
|
||||
{$DEFINE COMPILER9_UP}
|
||||
{$DEFINE COMPILER8_UP}
|
||||
{$DEFINE COMPILER7_UP}
|
||||
{$DEFINE COMPILER6_UP}
|
||||
{$DEFINE COMPILER5_UP}
|
||||
{$DEFINE COMPILER4_UP}
|
||||
{$DEFINE COMPILER35_UP}
|
||||
{$DEFINE COMPILER3_UP}
|
||||
{$DEFINE COMPILER2_UP}
|
||||
{$DEFINE COMPILER1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF COMPILER8}
|
||||
{$DEFINE COMPILER8_UP}
|
||||
{$DEFINE COMPILER7_UP}
|
||||
{$DEFINE COMPILER6_UP}
|
||||
{$DEFINE COMPILER5_UP}
|
||||
{$DEFINE COMPILER4_UP}
|
||||
{$DEFINE COMPILER35_UP}
|
||||
{$DEFINE COMPILER3_UP}
|
||||
{$DEFINE COMPILER2_UP}
|
||||
{$DEFINE COMPILER1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF COMPILER7}
|
||||
{$DEFINE COMPILER7_UP}
|
||||
{$DEFINE COMPILER6_UP}
|
||||
{$DEFINE COMPILER5_UP}
|
||||
{$DEFINE COMPILER4_UP}
|
||||
{$DEFINE COMPILER35_UP}
|
||||
{$DEFINE COMPILER3_UP}
|
||||
{$DEFINE COMPILER2_UP}
|
||||
{$DEFINE COMPILER1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF COMPILER6}
|
||||
{$DEFINE COMPILER6_UP}
|
||||
{$DEFINE COMPILER5_UP}
|
||||
{$DEFINE COMPILER4_UP}
|
||||
{$DEFINE COMPILER35_UP}
|
||||
{$DEFINE COMPILER3_UP}
|
||||
{$DEFINE COMPILER2_UP}
|
||||
{$DEFINE COMPILER1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF COMPILER5}
|
||||
{$DEFINE COMPILER5_UP}
|
||||
{$DEFINE COMPILER4_UP}
|
||||
{$DEFINE COMPILER35_UP}
|
||||
{$DEFINE COMPILER3_UP}
|
||||
{$DEFINE COMPILER2_UP}
|
||||
{$DEFINE COMPILER1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF COMPILER4}
|
||||
{$DEFINE COMPILER4_UP}
|
||||
{$DEFINE COMPILER35_UP}
|
||||
{$DEFINE COMPILER3_UP}
|
||||
{$DEFINE COMPILER2_UP}
|
||||
{$DEFINE COMPILER1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF COMPILER35}
|
||||
{$DEFINE COMPILER35_UP}
|
||||
{$DEFINE COMPILER3_UP}
|
||||
{$DEFINE COMPILER2_UP}
|
||||
{$DEFINE COMPILER1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF COMPILER3}
|
||||
{$DEFINE COMPILER3_UP}
|
||||
{$DEFINE COMPILER2_UP}
|
||||
{$DEFINE COMPILER1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF COMPILER2}
|
||||
{$DEFINE COMPILER2_UP}
|
||||
{$DEFINE COMPILER1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF COMPILER1}
|
||||
{$DEFINE COMPILER1_UP}
|
||||
{$ENDIF}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Map COMPILERX_UP to friendly feature names
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
{$IFDEF COMPILER3_UP}
|
||||
{$DEFINE SUPPORTS_WIDESTRING}
|
||||
{$DEFINE SUPPORTS_INTERFACE}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF COMPILER35_UP}
|
||||
{$DEFINE SUPPORTS_EXTSYM}
|
||||
{$DEFINE SUPPORTS_NODEFINE}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF COMPILER4_UP}
|
||||
{$DEFINE SUPPORTS_INT64}
|
||||
{$DEFINE SUPPORTS_DYNAMICARRAYS}
|
||||
{$DEFINE SUPPORTS_DEFAULTPARAMS}
|
||||
{$DEFINE SUPPORTS_OVERLOAD}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF COMPILER9_UP}
|
||||
{$DEFINE SUPPORTS_INLINE}
|
||||
{$ENDIF}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Cross-platform related defines
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
{$IFDEF WIN32}
|
||||
{$DEFINE MSWINDOWS}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF LINUX}
|
||||
{$DEFINE UNIX}
|
||||
{$DEFINE COMPLIB_CLX}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFNDEF COMPLIB_CLX}
|
||||
{$DEFINE COMPLIB_VCL}
|
||||
{$ENDIF}
|
||||
1200
acs/Src/fileformats/windows/macdll.pas
Normal file
1200
acs/Src/fileformats/windows/macdll.pas
Normal file
File diff suppressed because it is too large
Load Diff
290
acs/Src/fileformats/windows/mad.pas
Normal file
290
acs/Src/fileformats/windows/mad.pas
Normal file
@@ -0,0 +1,290 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.3 (delphi version).
|
||||
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
||||
see the license file for more details.
|
||||
you can contact me at acs@compiler4.net
|
||||
this is the acs for delphi (windows) version of the unit.
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: mad.pas,v $
|
||||
Revision 1.1 2005/12/19 18:36:49 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:53 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:02 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
unit mad;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
|
||||
{$IFDEF WIN32}
|
||||
Windows;
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF LINUX}
|
||||
baseunix, ACS_Procs;
|
||||
{$ENDIF}
|
||||
|
||||
|
||||
const
|
||||
|
||||
{$IFDEF WIN32}
|
||||
MADLibPath = 'MADLib.dll';
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF LINUX}
|
||||
MADLibPath = 'libmad.so*'; // libmad.so
|
||||
{$DEFINE SEARCH_LIBS}
|
||||
{$ENDIF}
|
||||
|
||||
|
||||
var
|
||||
|
||||
MADLibLoaded : Boolean = False;
|
||||
|
||||
type
|
||||
|
||||
mad_bitptr = packed record
|
||||
b : PChar;
|
||||
Cache, Left : Word;
|
||||
end;
|
||||
|
||||
mad_stream = packed record
|
||||
buffer : Pointer;
|
||||
bufend : Pointer;
|
||||
skiplen : LongWord;
|
||||
sync : Integer;
|
||||
freerate : LongWord;
|
||||
this_frame : Pointer;
|
||||
next_frame : Pointer;
|
||||
ptr : mad_bitptr;
|
||||
anc_ptr : mad_bitptr;
|
||||
anc_bitlen : LongWord;
|
||||
main_data : Pointer;
|
||||
md_len : LongWord;
|
||||
options : Integer;
|
||||
error : Integer;
|
||||
end;
|
||||
|
||||
p_mad_stream = ^mad_stream;
|
||||
|
||||
mad_timer_t = packed record
|
||||
seconds : Integer;
|
||||
fraction : LongWord;
|
||||
end;
|
||||
|
||||
mad_header = packed record
|
||||
layer : Integer;
|
||||
mode : Integer;
|
||||
mode_extension : Integer;
|
||||
emphasis : Integer;
|
||||
bitrate : LongWord;
|
||||
samplerate : LongWord;
|
||||
crc_check : Word;
|
||||
crc_target : Word;
|
||||
flags : Integer;
|
||||
private_bits : Integer;
|
||||
duration : mad_timer_t;
|
||||
end;
|
||||
|
||||
p_mad_header = ^mad_header;
|
||||
|
||||
mad_frame = packed record
|
||||
header : mad_header;
|
||||
options : Integer;
|
||||
sbsample : packed array[0..1, 0..35, 0..31] of Integer;
|
||||
overlap : Pointer;
|
||||
end;
|
||||
|
||||
p_mad_frame = ^mad_frame;
|
||||
|
||||
mad_pcm = packed record
|
||||
samplerate : LongWord;
|
||||
channels : Word;
|
||||
length : Word;
|
||||
samples : packed array [0..1, 0..1151] of Integer;
|
||||
end;
|
||||
|
||||
p_mad_pcm = ^mad_pcm;
|
||||
|
||||
mad_synth = packed record
|
||||
filter : array[0..1, 0..1, 0..1, 0..15, 0..7] of Integer;
|
||||
phase : LongWord;
|
||||
pcm : mad_pcm;
|
||||
end;
|
||||
|
||||
async_struct = packed record
|
||||
pid : LongWord;
|
||||
_in : Integer;
|
||||
_out : Integer;
|
||||
end;
|
||||
|
||||
sync_struct = packed record
|
||||
stream : mad_stream;
|
||||
frame : mad_frame;
|
||||
synth : mad_synth;
|
||||
end;
|
||||
|
||||
p_sync_struct = ^sync_struct;
|
||||
|
||||
TInputFunc = function(CData : Pointer; Stream : p_mad_stream) : Integer; cdecl;
|
||||
THeaderFunc = function(CData : Pointer; Header : p_mad_header) : Integer; cdecl;
|
||||
TFilterFunc = function(CData : Pointer; Frame : p_mad_frame) : Integer; cdecl;
|
||||
TOutputFunc = function(CData : Pointer; Header : p_mad_header; pcm : p_mad_pcm) : Integer; cdecl;
|
||||
TErrorFunc = function(CData : Pointer; Stream : p_mad_stream; Frame : p_mad_frame) : Integer; cdecl;
|
||||
TMessageFunc = function(P1, P2 : Pointer; var l : LongWord) : Integer; cdecl;
|
||||
|
||||
mad_decoder = packed record
|
||||
mode : Integer;
|
||||
options : Integer;
|
||||
async : async_struct;
|
||||
sync : p_sync_struct;
|
||||
data : Pointer;
|
||||
InputFunc : TInputFunc;
|
||||
HeaderFunc : THeaderFunc;
|
||||
FilterFunc : TFilterFunc;
|
||||
OutputFunc : TOutputFunc;
|
||||
ErrorFunc : TErrorFunc;
|
||||
MessageFunc : TMessageFunc;
|
||||
end;
|
||||
|
||||
p_mad_decoder = ^mad_decoder;
|
||||
|
||||
const
|
||||
|
||||
MAD_F_FRACBITS = 28;
|
||||
MAD_F_ONE = $10000000;
|
||||
|
||||
MAD_FLOW_CONTINUE = $0;
|
||||
MAD_FLOW_STOP = $10;
|
||||
MAD_FLOW_BREAK = $11;
|
||||
MAD_FLOW_IGNORE = $20;
|
||||
|
||||
MAD_DECODER_MODE_SYNC = 0;
|
||||
MAD_DECODER_MODE_ASYNC = 1;
|
||||
|
||||
type
|
||||
|
||||
mad_decoder_init_t = procedure(mad_decoder : p_mad_decoder; CData : Pointer;
|
||||
InputFunc : TInputFunc;
|
||||
HeaderFunc : THeaderFunc;
|
||||
FilterFunc : TFilterFunc;
|
||||
OutputFunc : TOutputFunc;
|
||||
ErrorFunc : TErrorFunc;
|
||||
MessageFunc : TMessageFunc); cdecl;
|
||||
|
||||
mad_decoder_finish_t = function(mad_decoder : p_mad_decoder) : Integer; cdecl;
|
||||
|
||||
mad_decoder_run_t = function(mad_decoder : p_mad_decoder; mad_decoder_mode : Integer) : Integer; cdecl;
|
||||
|
||||
mad_decoder_message_t = function(mad_decoder : p_mad_decoder; P : Pointer; var l : LongWord) : Integer; cdecl;
|
||||
|
||||
mad_stream_buffer_t = procedure(MadStream : p_mad_stream; Data : Pointer; l : LongWord); cdecl;
|
||||
|
||||
mad_stream_skip_t = procedure(MadStream : p_mad_stream; Skip : LongWord); cdecl;
|
||||
|
||||
mad_stream_sync_t = function(MadStream : p_mad_stream) : Integer; cdecl;
|
||||
|
||||
var
|
||||
|
||||
mad_decoder_init: mad_decoder_init_t;
|
||||
mad_decoder_finish : mad_decoder_finish_t;
|
||||
mad_decoder_run : mad_decoder_run_t;
|
||||
mad_decoder_message : mad_decoder_message_t;
|
||||
mad_stream_buffer : mad_stream_buffer_t;
|
||||
mad_stream_skip : mad_stream_skip_t;
|
||||
mad_stream_sync : mad_stream_sync_t;
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
{$IFDEF WIN32}
|
||||
|
||||
var
|
||||
Libhandle : HMODULE;
|
||||
|
||||
initialization
|
||||
|
||||
Libhandle := LoadLibraryEx(MADLibPath, 0, 0);
|
||||
|
||||
if Libhandle <> 0 then
|
||||
begin
|
||||
MADLibLoaded := True;
|
||||
|
||||
mad_decoder_init := GetProcAddress(Libhandle, 'mad_decoder_init');
|
||||
mad_decoder_finish := GetProcAddress(Libhandle, 'mad_decoder_finish');
|
||||
mad_decoder_run := GetProcAddress(Libhandle, 'mad_decoder_run');
|
||||
mad_decoder_message := GetProcAddress(Libhandle, 'mad_decoder_message');
|
||||
mad_stream_buffer := GetProcAddress(Libhandle, 'mad_stream_buffer');
|
||||
mad_stream_skip := GetProcAddress(Libhandle, 'mad_stream_skip');
|
||||
mad_stream_sync := GetProcAddress(Libhandle, 'mad_stream_sync');
|
||||
|
||||
end;
|
||||
|
||||
finalization
|
||||
|
||||
if Libhandle <> 0 then FreeLibrary(Libhandle);
|
||||
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF LINUX}
|
||||
|
||||
var
|
||||
Libhandle : Pointer;
|
||||
|
||||
{$IFDEF SEARCH_LIBS}
|
||||
Path : String;
|
||||
{$ENDIF}
|
||||
|
||||
initialization
|
||||
|
||||
{$IFDEF SEARCH_LIBS}
|
||||
|
||||
Libhandle := nil;
|
||||
Path := FindLibs(MADLibPath);
|
||||
if Path <> '' then Libhandle := dlopen(@Path[1], RTLD_NOW or RTLD_GLOBAL);
|
||||
|
||||
{$ELSE}
|
||||
|
||||
Libhandle := dlopen(MADLibPath, RTLD_NOW or RTLD_GLOBAL);
|
||||
|
||||
{$ENDIF}
|
||||
|
||||
if Libhandle <> nil then
|
||||
begin
|
||||
|
||||
MADLibLoaded := True;
|
||||
|
||||
mad_decoder_init := dlsym(Libhandle, 'mad_decoder_init');
|
||||
mad_decoder_finish := dlsym(Libhandle, 'mad_decoder_finish');
|
||||
mad_decoder_run := dlsym(Libhandle, 'mad_decoder_run');
|
||||
mad_decoder_message := dlsym(Libhandle, 'mad_decoder_message');
|
||||
mad_stream_buffer := dlsym(Libhandle, 'mad_stream_buffer');
|
||||
mad_stream_skip := dlsym(Libhandle, 'mad_stream_skip');
|
||||
mad_stream_sync := dlsym(Libhandle, 'mad_stream_sync');
|
||||
|
||||
end;
|
||||
|
||||
finalization
|
||||
|
||||
if Libhandle <> nil then dlclose(Libhandle);
|
||||
|
||||
{$ENDIF}
|
||||
|
||||
|
||||
end.
|
||||
1411
acs/Src/fileformats/windows/msacm.pas
Normal file
1411
acs/Src/fileformats/windows/msacm.pas
Normal file
File diff suppressed because it is too large
Load Diff
334
acs/Src/fileformats/windows/waveconverter.pas
Normal file
334
acs/Src/fileformats/windows/waveconverter.pas
Normal file
@@ -0,0 +1,334 @@
|
||||
(*
|
||||
this file is a part of audio components suite v 2.3 (delphi version).
|
||||
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
||||
see the license file for more details.
|
||||
you can contact me at acs@compiler4.net
|
||||
this is the acs for delphi (windows) version of the unit.
|
||||
*)
|
||||
|
||||
{
|
||||
$Log: waveconverter.pas,v $
|
||||
Revision 1.1 2005/12/19 18:36:49 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2005/09/12 22:04:53 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.1 2005/08/25 20:18:00 z0m3ie
|
||||
Version 2.4 restructure
|
||||
TCDPlayer removed (fits not in component structure)
|
||||
TMP3ToWavConverter removed (fits not in component structure)
|
||||
|
||||
Revision 1.2 2005/08/22 20:17:02 z0m3ie
|
||||
changed Headers to log
|
||||
changed mail adress
|
||||
|
||||
}
|
||||
|
||||
unit waveconverter;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
SysUtils,
|
||||
Windows, Classes, MMSystem, MSAcm;
|
||||
|
||||
type
|
||||
{$IFDEF FPC}
|
||||
TWaveFormat = WAVEFORMAT;
|
||||
{$ENDIF}
|
||||
|
||||
TRiffID = array[0..3] of char;
|
||||
TRiffHeader = packed record
|
||||
ID: TRiffID;
|
||||
BytesFollowing: DWord;
|
||||
end;
|
||||
|
||||
|
||||
TACMWaveFormat = packed record
|
||||
case integer of
|
||||
0 : (Format : TWaveFormatEx);
|
||||
1 : (RawData : Array[0..128] of byte);
|
||||
end;
|
||||
|
||||
TWaveConverter = class(TMemoryStream)
|
||||
private
|
||||
FMaxFmtSize: DWord;
|
||||
public
|
||||
CurrentFormat: TACMWaveFormat;
|
||||
NewFormat: TACMWaveFormat;
|
||||
function LoadStream(Stream : TStream): integer;
|
||||
function Convert: integer;
|
||||
function SaveWavToStream(MS: TStream): Integer;
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{ TWaveConverter }
|
||||
|
||||
function TWaveConverter.Convert: integer;
|
||||
var
|
||||
FStreamHandle: HACMStream;
|
||||
OutputBufferSize: DWord;
|
||||
FStreamHeader: TACMStreamHeader;
|
||||
OutPut: Pointer;
|
||||
begin
|
||||
FStreamHandle := nil;
|
||||
|
||||
//
|
||||
// Open the stream we're going to use to convert from the current to the
|
||||
// new format
|
||||
//
|
||||
Result := acmStreamOpen(FStreamhandle, nil, CurrentFormat.Format,
|
||||
NewFormat.Format, nil, 0, 0, ACM_STREAMOPENF_NONREALTIME);
|
||||
if Result <> 0 then
|
||||
begin
|
||||
//SetError('acmStreamOpen', Result);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
//
|
||||
// Calculate the size of the converted data
|
||||
//
|
||||
Result := acmStreamSize(FStreamHandle, self. Size, OutputBufferSize,
|
||||
ACM_STREAMSIZEF_SOURCE);
|
||||
|
||||
if Result <> 0 then
|
||||
begin
|
||||
// SetError('acmStreamSize', Result);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
//
|
||||
// Allocate memory for the converted data
|
||||
//
|
||||
GetMem(OutPut, OutputBufferSize);
|
||||
FillChar(OutPut^,OutputBufferSize,#0);
|
||||
|
||||
Self.Seek(0,0);
|
||||
|
||||
//
|
||||
// Initialize and prepare a header
|
||||
//
|
||||
with FStreamHeader do
|
||||
begin
|
||||
cbStruct := SizeOf(TACMStreamHeader);
|
||||
fdwStatus := 0;
|
||||
dwUser := 0;
|
||||
pbSrc := self.Memory;
|
||||
cbSrcLength := self.Size;
|
||||
cbSrcLengthUsed := 0;
|
||||
dwSrcUser := 0;
|
||||
pbDst := OutPut;
|
||||
cbDstLength := OutputBufferSize;
|
||||
cbDstLengthUsed := 0;
|
||||
dwDstUser := 0;
|
||||
end;
|
||||
Result := acmStreamPrepareHeader(FStreamHandle,FStreamHeader, 0);
|
||||
if Result <> 0 then
|
||||
begin
|
||||
// SetError('acmStreamPrepareHeader', Result);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
//
|
||||
// Tell acm to convert the stream
|
||||
//
|
||||
Result := acmStreamConvert(FStreamHandle,FStreamHeader,
|
||||
ACM_STREAMCONVERTF_BLOCKALIGN);
|
||||
if Result <> 0 then
|
||||
begin
|
||||
// SetError('acmStreamConvert', Result);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
//
|
||||
// Set the format eqaul to the newformat and copy the
|
||||
// data over to the streams memory
|
||||
//
|
||||
Move(NewFormat.RawData, CurrentFormat.RawData, FMaxFmtSize);
|
||||
Self.SetSize(OutputBufferSize);
|
||||
Self.Seek(0,0);
|
||||
Self.Write(Output^, OutputBufferSize);
|
||||
|
||||
//
|
||||
// Unprepeare the header
|
||||
//
|
||||
Result := acmStreamUnprepareHeader(FStreamHandle,FStreamHeader, 0);
|
||||
if Result <> 0 then
|
||||
begin
|
||||
// SetError('acmStreamUnprepareHeader', Result);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
//
|
||||
// Close the stream
|
||||
//
|
||||
Result := acmStreamClose(FStreamHandle, 0);
|
||||
if Result <> 0 then
|
||||
begin
|
||||
// SetError('acmStreamClose', Result);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
FreeMem(OutPut);
|
||||
end;
|
||||
|
||||
constructor TWaveConverter.Create;
|
||||
begin
|
||||
inherited;
|
||||
|
||||
acmMetrics(nil, ACM_METRIC_MAX_SIZE_FORMAT, FMaxFmtSize);
|
||||
|
||||
FillChar(CurrentFormat.Format, FMaxFmtSize, 0);
|
||||
FillChar(NewFormat.Format, FMaxFmtSize, 0);
|
||||
end;
|
||||
|
||||
destructor TWaveConverter.Destroy;
|
||||
begin
|
||||
inherited;
|
||||
end;
|
||||
|
||||
function TWaveConverter.LoadStream(Stream : TStream): integer;
|
||||
var
|
||||
Header: TRiffHeader;
|
||||
ID: TRiffID;
|
||||
Mem: Pointer;
|
||||
Data: PByteArray;
|
||||
|
||||
|
||||
NumRead: Integer;
|
||||
Pos: Integer;
|
||||
|
||||
begin
|
||||
Result := 0;
|
||||
try
|
||||
//read the header
|
||||
NumRead := Stream.Read(Header, SizeOf(Header));
|
||||
Pos := NumRead;
|
||||
|
||||
NumRead := Stream.Read(ID, SizeOf(ID));
|
||||
Pos := Pos + NumRead;
|
||||
|
||||
if (Header.ID <> 'RIFF') or (ID <> 'WAVE') then
|
||||
begin
|
||||
Exit;
|
||||
end;
|
||||
|
||||
while Pos < Stream.Size -1 do
|
||||
begin
|
||||
Dec(Pos,7);
|
||||
Stream.Seek(Pos, soFromBeginning);
|
||||
|
||||
NumRead := Stream.Read(Header, SizeOf(Header));
|
||||
Pos := Pos + NumRead;
|
||||
|
||||
|
||||
if Header.ID = 'fmt ' then
|
||||
begin
|
||||
GetMem(Mem, Header.BytesFollowing);
|
||||
try
|
||||
NumRead := Stream.Read(Mem^, Header.BytesFollowing);
|
||||
Pos := Pos + NumRead;
|
||||
|
||||
if Header.BytesFollowing < SizeOf(TWaveFormatEx) then
|
||||
Move(Mem^, CurrentFormat.Format , SizeOf(TWaveFormatEx))
|
||||
else
|
||||
Move(Mem^, CurrentFormat.Format, Header.BytesFollowing);
|
||||
finally
|
||||
FreeMem(Mem);
|
||||
end;
|
||||
end
|
||||
else
|
||||
if Header.ID = 'fact' then
|
||||
begin
|
||||
GetMem(Data, Header.BytesFollowing);
|
||||
try
|
||||
NumRead := Stream.Read(Data^, Header.BytesFollowing);
|
||||
Pos := Pos + NumRead;
|
||||
finally
|
||||
FreeMem(Data);
|
||||
end;
|
||||
end
|
||||
else
|
||||
if Header.ID = 'data' then
|
||||
begin
|
||||
if Header.BytesFollowing > 0 then
|
||||
begin
|
||||
GetMem(Data, Header.BytesFollowing);
|
||||
try
|
||||
NumRead := Stream.Read(Data^, Header.BytesFollowing);
|
||||
Pos := Pos + NumRead;
|
||||
|
||||
Self.SetSize(Header.BytesFollowing);
|
||||
Self.Seek(0,0);
|
||||
Self.Write(Data^, (*Header.BytesFollowing*)self.Size);
|
||||
finally
|
||||
FreeMem(Data);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
Seek(0,0);
|
||||
finally
|
||||
// FileStream.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function TWaveConverter.SaveWavToStream(MS: TStream): Integer;
|
||||
var
|
||||
CurrentPos : Integer;
|
||||
H : TRiffHeader;
|
||||
ID : TRiffID;
|
||||
begin
|
||||
Result := 0;
|
||||
try
|
||||
CurrentPos := Position;
|
||||
|
||||
H.ID := 'RIFF';
|
||||
H.BytesFollowing := 0;
|
||||
MS.Write(H, SizeOf(H));
|
||||
|
||||
ID := 'WAVE';
|
||||
MS.Write(ID, SizeOf(ID));
|
||||
|
||||
H.ID := 'fmt ';
|
||||
H.BytesFollowing := SizeOf(TWaveFormat) + 2;
|
||||
MS.Write(H, SizeOf(H));
|
||||
MS.Write(CurrentFormat.Format, SizeOf(TWaveFormat) + 2);
|
||||
|
||||
H.ID := 'data';
|
||||
H.BytesFollowing := Size;
|
||||
MS.Write(H, SizeOf(H));
|
||||
Seek(0,0);
|
||||
// MS.CopyFrom(Self, Size);
|
||||
// ms.Write( Self, Size);
|
||||
self.SaveToStream(MS);
|
||||
|
||||
|
||||
MS.Seek(0,0);
|
||||
H.ID := 'RIFF';
|
||||
H.BytesFollowing := MS.Size - SizeOf(H) +1;
|
||||
MS.Write(H,SizeOf(H));
|
||||
|
||||
Position := CurrentPos;
|
||||
// MS.Free;
|
||||
except
|
||||
on E: Exception do
|
||||
begin
|
||||
Result := MCIERR_FILE_NOT_SAVED;
|
||||
// SetError('SaveFile', MCIERR_FILE_NOT_SAVED);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
||||
|
||||
|
||||
33
acs/Src/linux/ACS.conf
Normal file
33
acs/Src/linux/ACS.conf
Normal file
@@ -0,0 +1,33 @@
|
||||
-$A8
|
||||
-$B-
|
||||
-$C+
|
||||
-$D-
|
||||
-$E-
|
||||
-$F-
|
||||
-$G+
|
||||
-$H+
|
||||
-$I+
|
||||
-$J-
|
||||
-$K-
|
||||
-$L-
|
||||
-$M-
|
||||
-$N+
|
||||
-$O+
|
||||
-$P+
|
||||
-$Q-
|
||||
-$R-
|
||||
-$S-
|
||||
-$T-
|
||||
-$U-
|
||||
-$V+
|
||||
-$W-
|
||||
-$X+
|
||||
-$Y-
|
||||
-$Z1
|
||||
-cg
|
||||
-H+
|
||||
-W+
|
||||
-M
|
||||
-$M1048576
|
||||
-K$00400000
|
||||
-Z
|
||||
112
acs/Src/linux/ACS.dof
Normal file
112
acs/Src/linux/ACS.dof
Normal file
@@ -0,0 +1,112 @@
|
||||
[FileVersion]
|
||||
Version=6.0
|
||||
[Compiler]
|
||||
A=8
|
||||
B=0
|
||||
C=1
|
||||
D=1
|
||||
E=0
|
||||
F=0
|
||||
G=1
|
||||
H=1
|
||||
I=1
|
||||
J=0
|
||||
K=0
|
||||
L=1
|
||||
M=0
|
||||
N=1
|
||||
O=0
|
||||
P=1
|
||||
Q=0
|
||||
R=0
|
||||
S=0
|
||||
T=0
|
||||
U=0
|
||||
V=1
|
||||
W=0
|
||||
X=1
|
||||
Y=1
|
||||
Z=1
|
||||
ShowHints=1
|
||||
ShowWarnings=1
|
||||
UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
|
||||
[Linker]
|
||||
MapFile=0
|
||||
OutputObjs=0
|
||||
ConsoleApp=1
|
||||
DebugInfo=0
|
||||
RemoteSymbols=0
|
||||
MinStackSize=16384
|
||||
MaxStackSize=1048576
|
||||
ImageBase=4194304
|
||||
ExeDescription=Audio Components Suite v 2.4
|
||||
[Directories]
|
||||
OutputDir=
|
||||
UnitOutputDir=lib
|
||||
PackageDLLOutputDir=
|
||||
PackageDCPOutputDir=
|
||||
SearchPath=..\classes;..\classes\linux;..\drivers;..\drivers\linux;..\fileformats;..\fileformats\general;..\fileformats\linux
|
||||
Packages=vcl;rtl;dbrtl;adortl;vcldb;vclx;bdertl;vcldbx;ibxpress;dsnap;cds;bdecds;qrpt;teeui;teedb;tee;dss;teeqr;visualclx;visualdbclx;dsnapcrba;dsnapcon;VclSmp;vclshlctrls;vclie;xmlrtl;inet;inetdbbde;inetdbxpress;inetdb;nmfast;webdsnap;websnap;dbexpress;dbxcds
|
||||
Conditionals=
|
||||
DebugSourceDirs=
|
||||
UsePackages=0
|
||||
[Parameters]
|
||||
RunParams=
|
||||
HostApplication=
|
||||
Launcher=
|
||||
UseLauncher=0
|
||||
DebugCWD=
|
||||
[Language]
|
||||
ActiveLang=
|
||||
ProjectLang=
|
||||
RootDir=
|
||||
[Version Info]
|
||||
IncludeVerInfo=1
|
||||
AutoIncBuild=1
|
||||
MajorVer=2
|
||||
MinorVer=4
|
||||
Release=0
|
||||
Build=2
|
||||
Debug=0
|
||||
PreRelease=0
|
||||
Special=0
|
||||
Private=0
|
||||
DLL=0
|
||||
Locale=1033
|
||||
CodePage=1252
|
||||
[Version Info Keys]
|
||||
CompanyName=
|
||||
FileDescription=Audio Components Suite (Delphi Edition)
|
||||
FileVersion=2.4.0.2
|
||||
InternalName=ACS
|
||||
LegalCopyright=Copyright (c) 2002, 2003 by Andrei Borovsky
|
||||
LegalTrademarks=
|
||||
OriginalFilename=
|
||||
ProductName=
|
||||
ProductVersion=2.4.0.0
|
||||
[HistoryLists\hlDebugSourcePath]
|
||||
Count=1
|
||||
Item0=D:\Program Files\Borland\Delphi6\Lib
|
||||
[HistoryLists\hlUnitAliases]
|
||||
Count=1
|
||||
Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
|
||||
[HistoryLists\hlSearchPath]
|
||||
Count=8
|
||||
Item0=..\classes;..\classes\linux;..\drivers;..\drivers\linux;..\fileformats;..\fileformats\general;..\fileformats\linux
|
||||
Item1=..\classes;..\classes\windows;..\drivers;..\drivers\windows;..\fileformats;..\fileformats\general;..\fileformats\windows
|
||||
Item2=..\classes;..\classes\windows;D:\LKomponenten\acs\Src\classes;D:\LKomponenten\acs\Src\classes\windows
|
||||
Item3=..\classes;..\classes\include\general;..\classes\windows
|
||||
Item4=..\classes;..\classes\include\general;..\classes\include\windows
|
||||
Item5=..\Common;..\Common\include\general;..\Common\include\windows
|
||||
Item6=..\Common
|
||||
Item7=D:\Program Files\Borland\Delphi6\Lib
|
||||
[HistoryLists\hlUnitOutputDirectory]
|
||||
Count=2
|
||||
Item0=lib
|
||||
Item1=D:\Program Files\Borland\Delphi6\Lib
|
||||
[HistoryLists\hlBPLOutput]
|
||||
Count=1
|
||||
Item0=D:\Program Files\Borland\Delphi6\Lib
|
||||
[HistoryLists\hlDCPOutput]
|
||||
Count=1
|
||||
Item0=D:\Program Files\Borland\Delphi6\Lib
|
||||
50
acs/Src/linux/ACS.dpk
Normal file
50
acs/Src/linux/ACS.dpk
Normal file
@@ -0,0 +1,50 @@
|
||||
package ACS;
|
||||
|
||||
{$R *.res}
|
||||
{$ALIGN 8}
|
||||
{$ASSERTIONS ON}
|
||||
{$BOOLEVAL OFF}
|
||||
{$DEBUGINFO ON}
|
||||
{$EXTENDEDSYNTAX ON}
|
||||
{$IMPORTEDDATA ON}
|
||||
{$IOCHECKS ON}
|
||||
{$LOCALSYMBOLS ON}
|
||||
{$LONGSTRINGS ON}
|
||||
{$OPENSTRINGS ON}
|
||||
{$OPTIMIZATION OFF}
|
||||
{$OVERFLOWCHECKS OFF}
|
||||
{$RANGECHECKS OFF}
|
||||
{$REFERENCEINFO ON}
|
||||
{$SAFEDIVIDE OFF}
|
||||
{$STACKFRAMES OFF}
|
||||
{$TYPEDADDRESS OFF}
|
||||
{$VARSTRINGCHECKS ON}
|
||||
{$WRITEABLECONST OFF}
|
||||
{$MINENUMSIZE 1}
|
||||
{$IMAGEBASE $400000}
|
||||
{$DESCRIPTION 'Audio Components Suite v 2.4'}
|
||||
{$IMPLICITBUILD OFF}
|
||||
|
||||
contains
|
||||
ACS_Types in '..\classes\ACS_Types.pas',
|
||||
ACS_Audio in '..\classes\ACS_Audio.pas',
|
||||
ACS_AudioMix in '..\classes\ACS_AudioMix.pas',
|
||||
ACS_CDROM in '..\classes\ACS_CDROM.pas',
|
||||
ACS_Classes in '..\classes\ACS_Classes.pas',
|
||||
ACS_Converters in '..\classes\ACS_Converters.pas',
|
||||
ACS_File in '..\classes\ACS_File.pas',
|
||||
ACS_Filters in '..\classes\ACS_Filters.pas',
|
||||
ACS_Indicator in '..\classes\ACS_Indicator.pas',
|
||||
ACS_Misc in '..\classes\ACS_Misc.pas',
|
||||
ACS_Mixer in '..\classes\ACS_Mixer.pas',
|
||||
ACS_MultiMix in '..\classes\ACS_MultiMix.pas',
|
||||
ACS_Procs in '..\classes\ACS_Procs.pas',
|
||||
ACS_Streams in '..\classes\ACS_Streams.pas',
|
||||
ACS_Strings in '..\classes\ACS_Strings.pas',
|
||||
akrip32 in '..\classes\windows\akrip32.pas',
|
||||
acs_reg in 'acs_reg.pas',
|
||||
ACS_AllFormats in '..\fileformats\ACS_Allformats.pas',
|
||||
ACS_StdAudio in '..\drivers\ACS_StdAudio.pas',
|
||||
ACS_DXAudio in '..\drivers\ACS_DXAudio.pas';
|
||||
|
||||
end.
|
||||
56
acs/Src/linux/acs_reg.pas
Normal file
56
acs/Src/linux/acs_reg.pas
Normal file
@@ -0,0 +1,56 @@
|
||||
(*
|
||||
This file is a part of Audio Components Suite v 2.2 (Kylix Edition).
|
||||
Copyright (c) 2002, 2003 Andrei Borovsky. All rights reserved.
|
||||
See the LICENSE file for more details.
|
||||
You can contact me at aborovsky@mtu-net.ru
|
||||
|
||||
$Log: acs_reg.pas,v $
|
||||
Revision 1.9 2006/07/04 17:12:44 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.7 2005/12/19 18:37:21 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.5 2005/12/04 16:54:33 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.4 2005/11/27 16:50:33 z0m3ie
|
||||
add ACS VolumeQuerry
|
||||
make ACS_VolumeQuerry localizeable
|
||||
some little errorfixes (buffersize for linuxdrivers was initially 0)
|
||||
make TAudioIn workable
|
||||
|
||||
*)
|
||||
|
||||
unit acs_reg;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, ACS_Audio,
|
||||
ACS_CDROM, ACS_AudioMix, ACS_Converters, ACS_Misc, ACS_File, ACS_Filters,
|
||||
ACS_Streams, ACS_Indicator, ACS_Mixer,ACS_MultiMix,ACS_VolumeQuery
|
||||
{$IFDEF FPC}
|
||||
,LResources
|
||||
{$ENDIF};
|
||||
|
||||
procedure Register;
|
||||
|
||||
implementation
|
||||
|
||||
procedure Register();
|
||||
begin
|
||||
RegisterComponents('Audio I/O', [TACSAudioIn, TACSAudioOut,TACSMixer,
|
||||
TACSCDIn,TACSInputList, TACSMemoryIn, TACSFileIn, TACSFileOut, TACSStreamIn, TACSStreamOut, TACSNULLOut]);
|
||||
RegisterComponents('Audio Processing', [TACSAudioMixer,TACSMultiMixer, TACSSampleConverter, TACSRateConverter,
|
||||
TACSMSConverter, TACSAudioProcessor, TACSBWFilter, TACSSincFilter, TACSSoundIndicator, TACSStereoBalance, TACSConvolver,TACSVolumeQuery]);
|
||||
end;
|
||||
|
||||
initialization
|
||||
{$IFDEF FPC}
|
||||
{$i ..\resources\acs_reg.lrs}
|
||||
{$ELSE}
|
||||
{$r ..\resources\resource.dcr}
|
||||
{$ENDIF}
|
||||
|
||||
end.
|
||||
122
acs/Src/linux/laz_acs.lpk
Normal file
122
acs/Src/linux/laz_acs.lpk
Normal file
@@ -0,0 +1,122 @@
|
||||
<?xml version="1.0"?>
|
||||
<CONFIG>
|
||||
<Package Version="3">
|
||||
<Name Value="laz_acs"/>
|
||||
<CompilerOptions>
|
||||
<Version Value="9"/>
|
||||
<SearchPaths>
|
||||
<IncludeFiles Value="../classes/linux/;../fileformats/linux/;../drivers/linux/"/>
|
||||
<OtherUnitFiles Value="../classes/;../classes/linux/;../fileformats/;../fileformats/linux/;../fileformats/general/;../drivers/;../drivers/linux/"/>
|
||||
<UnitOutputDirectory Value="lib"/>
|
||||
</SearchPaths>
|
||||
<Parsing>
|
||||
<SyntaxOptions>
|
||||
<SyntaxMode Value="Delphi"/>
|
||||
<CStyleOperator Value="False"/>
|
||||
<UseAnsiStrings Value="False"/>
|
||||
</SyntaxOptions>
|
||||
</Parsing>
|
||||
<Other>
|
||||
<CompilerPath Value="$(CompPath)"/>
|
||||
</Other>
|
||||
</CompilerOptions>
|
||||
<Description Value="Audio Component Suite
|
||||
"/>
|
||||
<Version Major="2" Minor="4" Release="3" Build="21"/>
|
||||
<Files Count="18">
|
||||
<Item1>
|
||||
<Filename Value="../classes/acs_audio.pas"/>
|
||||
<UnitName Value="acs_audio"/>
|
||||
</Item1>
|
||||
<Item2>
|
||||
<Filename Value="../classes/acs_audiomix.pas"/>
|
||||
<UnitName Value="acs_audiomix"/>
|
||||
</Item2>
|
||||
<Item3>
|
||||
<Filename Value="../classes/acs_cdrom.pas"/>
|
||||
<UnitName Value="acs_cdrom"/>
|
||||
</Item3>
|
||||
<Item4>
|
||||
<Filename Value="../classes/acs_classes.pas"/>
|
||||
<UnitName Value="acs_classes"/>
|
||||
</Item4>
|
||||
<Item5>
|
||||
<Filename Value="../classes/acs_converters.pas"/>
|
||||
<UnitName Value="acs_converters"/>
|
||||
</Item5>
|
||||
<Item6>
|
||||
<Filename Value="../classes/acs_file.pas"/>
|
||||
<UnitName Value="acs_file"/>
|
||||
</Item6>
|
||||
<Item7>
|
||||
<Filename Value="../classes/acs_filters.pas"/>
|
||||
<UnitName Value="acs_filters"/>
|
||||
</Item7>
|
||||
<Item8>
|
||||
<Filename Value="../classes/acs_indicator.pas"/>
|
||||
<UnitName Value="acs_indicator"/>
|
||||
</Item8>
|
||||
<Item9>
|
||||
<Filename Value="../classes/acs_misc.pas"/>
|
||||
<UnitName Value="acs_misc"/>
|
||||
</Item9>
|
||||
<Item10>
|
||||
<Filename Value="../classes/acs_mixer.pas"/>
|
||||
<UnitName Value="acs_mixer"/>
|
||||
</Item10>
|
||||
<Item11>
|
||||
<Filename Value="../classes/acs_multimix.pas"/>
|
||||
<UnitName Value="acs_multimix"/>
|
||||
</Item11>
|
||||
<Item12>
|
||||
<Filename Value="../classes/acs_procs.pas"/>
|
||||
<AddToUsesPkgSection Value="False"/>
|
||||
<UnitName Value="acs_procs"/>
|
||||
</Item12>
|
||||
<Item13>
|
||||
<Filename Value="../classes/acs_streams.pas"/>
|
||||
<UnitName Value="acs_streams"/>
|
||||
</Item13>
|
||||
<Item14>
|
||||
<Filename Value="../classes/acs_strings.pas"/>
|
||||
<UnitName Value="acs_strings"/>
|
||||
</Item14>
|
||||
<Item15>
|
||||
<Filename Value="../classes/acs_types.pas"/>
|
||||
<UnitName Value="acs_types"/>
|
||||
</Item15>
|
||||
<Item16>
|
||||
<Filename Value="../drivers/acs_stdaudio.pas"/>
|
||||
<UnitName Value="acs_stdaudio"/>
|
||||
</Item16>
|
||||
<Item17>
|
||||
<Filename Value="acs_reg.pas"/>
|
||||
<HasRegisterProc Value="True"/>
|
||||
<UnitName Value="acs_reg"/>
|
||||
</Item17>
|
||||
<Item18>
|
||||
<Filename Value="../fileformats/acs_allformats.pas"/>
|
||||
<UnitName Value="acs_allformats"/>
|
||||
</Item18>
|
||||
</Files>
|
||||
<Type Value="RunAndDesignTime"/>
|
||||
<RequiredPkgs Count="2">
|
||||
<Item1>
|
||||
<PackageName Value="LCL"/>
|
||||
</Item1>
|
||||
<Item2>
|
||||
<PackageName Value="FCL"/>
|
||||
<MinVersion Major="1" Valid="True"/>
|
||||
</Item2>
|
||||
</RequiredPkgs>
|
||||
<UsageOptions>
|
||||
<CustomOptions Value="
|
||||
"/>
|
||||
<UnitPath Value="$(PkgOutDir)/"/>
|
||||
</UsageOptions>
|
||||
<PublishOptions>
|
||||
<Version Value="2"/>
|
||||
<IgnoreBinaries Value="False"/>
|
||||
</PublishOptions>
|
||||
</Package>
|
||||
</CONFIG>
|
||||
24
acs/Src/linux/laz_acs.pas
Normal file
24
acs/Src/linux/laz_acs.pas
Normal file
@@ -0,0 +1,24 @@
|
||||
{ This file was automatically created by Lazarus. do not edit!
|
||||
This source is only used to compile and install the package.
|
||||
}
|
||||
|
||||
unit laz_acs;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
acs_audio, acs_audiomix, acs_cdrom, acs_classes, acs_converters, acs_file,
|
||||
acs_filters, acs_indicator, acs_misc, acs_mixer, acs_multimix, acs_streams,
|
||||
acs_strings, acs_types, acs_stdaudio, acs_reg, acs_allformats,
|
||||
LazarusPackageIntf;
|
||||
|
||||
implementation
|
||||
|
||||
procedure Register;
|
||||
begin
|
||||
RegisterUnit('acs_reg', @acs_reg.Register);
|
||||
end;
|
||||
|
||||
initialization
|
||||
RegisterPackage('laz_acs', @Register);
|
||||
end.
|
||||
33
acs/Src/resources/TACSAudioIn.xpm
Normal file
33
acs/Src/resources/TACSAudioIn.xpm
Normal file
@@ -0,0 +1,33 @@
|
||||
/* XPM */
|
||||
static char * TAudioIn_xpm[] = {
|
||||
"24 24 6 1",
|
||||
" c None",
|
||||
". c #0000FF",
|
||||
"+ c #00FFFF",
|
||||
"@ c #000080",
|
||||
"# c #000000",
|
||||
"$ c #808000",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" .+.+.@ ",
|
||||
" +.+...@.@ ",
|
||||
" ....@..@.@ ",
|
||||
" +.....@@.@@ ",
|
||||
" .....@..@.@ ",
|
||||
" +....@.@@.@@ ",
|
||||
" ....@.@..@.@ ",
|
||||
" +@.@.@.@@.@@ ",
|
||||
" . @.@.@.@@@ ",
|
||||
" # $@@.@@@@@ ",
|
||||
" # $$$@@@@@ ",
|
||||
" # $$$@@@@ ",
|
||||
" # $$$# ",
|
||||
" # $$## ",
|
||||
" # $$$# ",
|
||||
" # $### ",
|
||||
" # $$### ",
|
||||
" #$$$#### ",
|
||||
" $## ### ",
|
||||
" ### "};
|
||||
32
acs/Src/resources/TACSAudioMixer.xpm
Normal file
32
acs/Src/resources/TACSAudioMixer.xpm
Normal file
@@ -0,0 +1,32 @@
|
||||
/* XPM */
|
||||
static char * TAudioMixer_xpm[] = {
|
||||
"24 24 5 1",
|
||||
" c None",
|
||||
". c #0000FF",
|
||||
"+ c #000080",
|
||||
"@ c #800000",
|
||||
"# c #00FFFF",
|
||||
" ",
|
||||
" .+ ",
|
||||
" @@@@@.+@@@@@ ",
|
||||
" @@@ .+ @@@ ",
|
||||
" @ .+ #@ ",
|
||||
" @ .+ # #@ ",
|
||||
" @ .+ # @ ",
|
||||
" @@ .+ # @@ ",
|
||||
" @#@@@ .+ @@@ @ ",
|
||||
" @ # @@@@@@@@@@@@ . @ ",
|
||||
" @# .+ @ ",
|
||||
" @ # .+ @ ",
|
||||
" @# .+ @ ",
|
||||
" @ # +++++ .+ +++++ @ ",
|
||||
" @ +.....+.++++++++ @ ",
|
||||
" @ +.......+++......+ @ ",
|
||||
" @ +......+++.......+ @ ",
|
||||
" @@ +++++++.++.....+ @@ ",
|
||||
" @ +++++ .+ +++++ @ ",
|
||||
" @ @ ",
|
||||
" @ @ ",
|
||||
" @@@ @@@ ",
|
||||
" @@@@@@@@@@@@ ",
|
||||
" "};
|
||||
33
acs/Src/resources/TACSAudioOut.xpm
Normal file
33
acs/Src/resources/TACSAudioOut.xpm
Normal file
@@ -0,0 +1,33 @@
|
||||
/* XPM */
|
||||
static char * TAudioOut_xpm[] = {
|
||||
"24 24 6 1",
|
||||
" c None",
|
||||
". c #000000",
|
||||
"+ c #000080",
|
||||
"@ c #800000",
|
||||
"# c #00FFFF",
|
||||
"$ c #0000FF",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" .. ",
|
||||
" ++.. @ @ @ ",
|
||||
" +#. . @ @ ",
|
||||
" +#.. . ",
|
||||
" +# . . @ @ @ ",
|
||||
" .++# #.+ . @ @ ",
|
||||
" .+ $ # ..+ . ",
|
||||
" . #$# #. . . @ @ @ ",
|
||||
" .##$ # ... . @ @ ",
|
||||
" .$$.# #..+ . ",
|
||||
" ...$# .+ . @ @ @ ",
|
||||
" .$#. . @ @ ",
|
||||
" .$.. . ",
|
||||
" .$. . @ @ @ ",
|
||||
" .$.. @ @ ",
|
||||
" .. ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" "};
|
||||
36
acs/Src/resources/TACSAudioProcessor.xpm
Normal file
36
acs/Src/resources/TACSAudioProcessor.xpm
Normal file
@@ -0,0 +1,36 @@
|
||||
/* XPM */
|
||||
static char * TAudioProcessor_xpm[] = {
|
||||
"24 24 9 1",
|
||||
" c None",
|
||||
". c #800000",
|
||||
"+ c #FF0000",
|
||||
"@ c #808000",
|
||||
"# c #800080",
|
||||
"$ c #FFFF00",
|
||||
"% c #000000",
|
||||
"& c #000080",
|
||||
"* c #0000FF",
|
||||
" ",
|
||||
" . ",
|
||||
" .. ",
|
||||
" ..++. ",
|
||||
" .+++++. ",
|
||||
" @# @$ .++++++.",
|
||||
" @%%% .+++++. ",
|
||||
" @%%%%% @$ ..++. ",
|
||||
" @%%%%%%% .. ",
|
||||
" @%%%%%%%%% @$ . ",
|
||||
" %%%%%% %%%% ",
|
||||
" $%%%%%% %%%% @$ ",
|
||||
" @ %%%%%%%%%%% ",
|
||||
" $%%%%%%%%%%% @$ ",
|
||||
" & %%%%%% %%% ",
|
||||
" && $%%%%% %%%% ",
|
||||
" &&**& @ %%%%%%%%% ",
|
||||
"&*****& $%%%%%%% ",
|
||||
"&******& @ %%%%% ",
|
||||
"&*****& $%%% ",
|
||||
" &&**& @ ",
|
||||
" && ",
|
||||
" & ",
|
||||
" "};
|
||||
32
acs/Src/resources/TACSBWFilter.xpm
Normal file
32
acs/Src/resources/TACSBWFilter.xpm
Normal file
@@ -0,0 +1,32 @@
|
||||
/* XPM */
|
||||
static char * TBWFilter_xpm[] = {
|
||||
"24 24 5 1",
|
||||
" c None",
|
||||
". c #FFFF00",
|
||||
"+ c #0000FF",
|
||||
"@ c #FF0000",
|
||||
"# c #000000",
|
||||
" . ",
|
||||
" . . ",
|
||||
" ++ ++ ++ ",
|
||||
" + + + + + + ",
|
||||
" ++++ + + ++++ ",
|
||||
" @ @ ",
|
||||
" @ ### @ ",
|
||||
" @ # # + @ ",
|
||||
" @ # # + @ ",
|
||||
" @ ### ++ @ ",
|
||||
" @ # # @ ",
|
||||
" @@@@@ # # @@@@@ ",
|
||||
" ### ",
|
||||
" @@@@@ # # @@@@@ ",
|
||||
" @ # # @ ",
|
||||
" @ # # # @ ",
|
||||
" @ @@ # # # @ ",
|
||||
" @ @ # # # @ ",
|
||||
" @ @@ # # @ ",
|
||||
" @ @ ",
|
||||
" @ @ ",
|
||||
" ++++++++++++++++++++++ ",
|
||||
" ",
|
||||
" "};
|
||||
34
acs/Src/resources/TACSCDIn.xpm
Normal file
34
acs/Src/resources/TACSCDIn.xpm
Normal file
@@ -0,0 +1,34 @@
|
||||
/* XPM */
|
||||
static char * TCDIn_xpm[] = {
|
||||
"24 24 7 1",
|
||||
" c None",
|
||||
". c #800000",
|
||||
"+ c #000000",
|
||||
"@ c #00FFFF",
|
||||
"# c #00FF00",
|
||||
"$ c #FF0000",
|
||||
"% c #FFFF00",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" . ",
|
||||
" +++++ .. ",
|
||||
" ++@@###+ .$. ",
|
||||
" + @@#### ....$$. ",
|
||||
" + @@####.$$$$$$$. ",
|
||||
" + @@##%.$$$$$$$$. ",
|
||||
" + @@#%%.$$$$$$$$$. ",
|
||||
"+ +++%%.$$$$$$$$. ",
|
||||
"+ + + .$$$$$$$. ",
|
||||
"+ + + ....$$. ",
|
||||
"+ + + .$. ",
|
||||
"+ %%+++ .. ",
|
||||
" + %%%#@@ +. ",
|
||||
" + %%%##@@ + ",
|
||||
" +%%###@@@ + ",
|
||||
" +%####@@ + ",
|
||||
" ++###@@++ ",
|
||||
" +++++ ",
|
||||
" ",
|
||||
" ",
|
||||
" "};
|
||||
34
acs/Src/resources/TACSCDPlayer.xpm
Normal file
34
acs/Src/resources/TACSCDPlayer.xpm
Normal file
@@ -0,0 +1,34 @@
|
||||
/* XPM */
|
||||
static char * TCDPlayer_xpm[] = {
|
||||
"24 24 7 1",
|
||||
" c None",
|
||||
". c #000000",
|
||||
"+ c #000080",
|
||||
"@ c #00FFFF",
|
||||
"# c #0000FF",
|
||||
"$ c #00FF00",
|
||||
"% c #FFFF00",
|
||||
" ",
|
||||
" .. ",
|
||||
" ++.. ",
|
||||
" +@. . ",
|
||||
" +@.. . ",
|
||||
" +@ . . ",
|
||||
" .++@ @.+ .",
|
||||
" ......+ # @ ..+ .",
|
||||
" ..@@$$$. @#@ @. . .",
|
||||
" . @@$$$.@@# @ ... .",
|
||||
" . @@$$$.##.@ @..+ .",
|
||||
" . @@$$%...#@ .+ .",
|
||||
" . @@$%%% .#@. . ",
|
||||
". ...%% .#.. . ",
|
||||
". . . ..#. . ",
|
||||
". . . . .#.. ",
|
||||
". . . . .. ",
|
||||
". %%... . ",
|
||||
" . %%%$@@ . ",
|
||||
" . %%%$$@@ . ",
|
||||
" .%%$$$@@@ . ",
|
||||
" .%$$$$@@ . ",
|
||||
" ..$$$@@.. ",
|
||||
" ..... "};
|
||||
31
acs/Src/resources/TACSConvolver.xpm
Normal file
31
acs/Src/resources/TACSConvolver.xpm
Normal file
@@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * TConvolver_xpm[] = {
|
||||
"24 24 4 1",
|
||||
" c None",
|
||||
". c #FF0000",
|
||||
"+ c #0000FF",
|
||||
"@ c #000000",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" .. ",
|
||||
" . ",
|
||||
" . ",
|
||||
" ++ + @ . .. ",
|
||||
" ++ @ @ @ . . . ",
|
||||
" + @@@ .. . ",
|
||||
" + @ @ @ . . ",
|
||||
" + + @ . . ",
|
||||
" + + . .. ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" "};
|
||||
31
acs/Src/resources/TACSFileIn.xpm
Normal file
31
acs/Src/resources/TACSFileIn.xpm
Normal file
@@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * TFileIn_xpm[] = {
|
||||
"24 24 4 1",
|
||||
" c None",
|
||||
". c #FFFFFF",
|
||||
"+ c #FF0000",
|
||||
"@ c #FFFF00",
|
||||
" ",
|
||||
" ",
|
||||
" ........... ",
|
||||
" ............. ",
|
||||
" .............. ",
|
||||
" ............... ",
|
||||
" ................ ",
|
||||
" ................+ ",
|
||||
" ................++ ",
|
||||
" ................+++ ",
|
||||
" .............+++++++ ",
|
||||
" ............+++++++++ ",
|
||||
" ............++++++++++ ",
|
||||
" ............+++++++++++",
|
||||
" ............++++++++++ ",
|
||||
" ............+++++++++ ",
|
||||
" .............+++++++ ",
|
||||
" ..............@.+++ ",
|
||||
" ...........@.@.@++ ",
|
||||
" ....@.@..@@.@.@.+ ",
|
||||
" ..@.@.@.@@.@.@.@. ",
|
||||
" ............... ",
|
||||
" ",
|
||||
" "};
|
||||
31
acs/Src/resources/TACSFileOut.xpm
Normal file
31
acs/Src/resources/TACSFileOut.xpm
Normal file
@@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * TFileOut_xpm[] = {
|
||||
"24 24 4 1",
|
||||
" c None",
|
||||
". c #FFFFFF",
|
||||
"+ c #0000FF",
|
||||
"@ c #FFFF00",
|
||||
" ",
|
||||
" ",
|
||||
" ........... ",
|
||||
" ............. ",
|
||||
" .............. ",
|
||||
" ............... ",
|
||||
" ................ ",
|
||||
" + ................. ",
|
||||
" ++................. ",
|
||||
" +++................ ",
|
||||
" +++++++............... ",
|
||||
"+++++++++.............. ",
|
||||
"++++++++++...........@. ",
|
||||
"+++++++++++............ ",
|
||||
"++++++++++...........@. ",
|
||||
"+++++++++...........@.. ",
|
||||
" +++++++.............@. ",
|
||||
" +++............@@.. ",
|
||||
" ++............@@.@. ",
|
||||
" + .....@.@..@...@.. ",
|
||||
" ..@.@.@.@@.@.@.@. ",
|
||||
" ............... ",
|
||||
" ",
|
||||
" "};
|
||||
31
acs/Src/resources/TACSFixedResampler.xpm
Normal file
31
acs/Src/resources/TACSFixedResampler.xpm
Normal file
@@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * TFixedResampler_xpm[] = {
|
||||
"24 24 4 1",
|
||||
" c None",
|
||||
". c #0000FF",
|
||||
"+ c #FF0000",
|
||||
"@ c #000000",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" . . ",
|
||||
" .. . ",
|
||||
" . . ",
|
||||
" . . ",
|
||||
" ..... +++ ",
|
||||
" .. ++ ++ ",
|
||||
" .. ++ ++ ",
|
||||
" ....... ++ ++ ",
|
||||
" .. ++ ",
|
||||
" .. @@@ ++ ",
|
||||
" .. @@@ ++ ",
|
||||
" .. @@@ ++ ",
|
||||
" .. ++ ",
|
||||
" ....... +++++++ ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" "};
|
||||
32
acs/Src/resources/TACSInputList.xpm
Normal file
32
acs/Src/resources/TACSInputList.xpm
Normal file
@@ -0,0 +1,32 @@
|
||||
/* XPM */
|
||||
static char * TInputList_xpm[] = {
|
||||
"24 24 5 1",
|
||||
" c None",
|
||||
". c #800000",
|
||||
"+ c #FFFF00",
|
||||
"@ c #000000",
|
||||
"# c #FF0000",
|
||||
" ",
|
||||
" ... ",
|
||||
" . . ",
|
||||
" . . ",
|
||||
" . +.@ ",
|
||||
" . ++.@ ",
|
||||
" .....@ . ",
|
||||
" @@@@@ .. ",
|
||||
" .#. ",
|
||||
" ... ....##. ",
|
||||
" . . .#######. ",
|
||||
" . . .########. ",
|
||||
" . +.@ .#########. ",
|
||||
" . ++.@ .########. ",
|
||||
" .....@ .#######. ",
|
||||
" @@@@@ ....##. ",
|
||||
" .#. ",
|
||||
" ... .. ",
|
||||
" . . . ",
|
||||
" . . ",
|
||||
" . +.@ ",
|
||||
" . ++.@ ",
|
||||
" .....@ ",
|
||||
" @@@@@ "};
|
||||
30
acs/Src/resources/TACSMSConverter.xpm
Normal file
30
acs/Src/resources/TACSMSConverter.xpm
Normal file
@@ -0,0 +1,30 @@
|
||||
/* XPM */
|
||||
static char * TMSConverter_xpm[] = {
|
||||
"24 24 3 1",
|
||||
" c None",
|
||||
". c #808000",
|
||||
"+ c #FF0000",
|
||||
" ....... ",
|
||||
" . . ",
|
||||
" . ... . ",
|
||||
" . ..... . ",
|
||||
" . ..... . ",
|
||||
" . ..... . ",
|
||||
" . ... . ",
|
||||
" . . ",
|
||||
" . . ",
|
||||
" ....... ",
|
||||
" + + ",
|
||||
" ++ + ",
|
||||
" + + + + ",
|
||||
" + ++ ",
|
||||
" ....... + + ....... ",
|
||||
" . . . . ",
|
||||
" . ... . . ... . ",
|
||||
" . ..... . . ..... . ",
|
||||
" . ..... . . ..... . ",
|
||||
" . ..... . . ..... . ",
|
||||
" . ... . . ... . ",
|
||||
" . . . . ",
|
||||
" . . . . ",
|
||||
" ....... ....... "};
|
||||
34
acs/Src/resources/TACSMemoryIn.xpm
Normal file
34
acs/Src/resources/TACSMemoryIn.xpm
Normal file
@@ -0,0 +1,34 @@
|
||||
/* XPM */
|
||||
static char * TMemoryIn_xpm[] = {
|
||||
"24 24 7 1",
|
||||
" c None",
|
||||
". c #800000",
|
||||
"+ c #FF0000",
|
||||
"@ c #808000",
|
||||
"# c #800080",
|
||||
"$ c #FFFF00",
|
||||
"% c #000000",
|
||||
" . ",
|
||||
" .. ",
|
||||
" .+. ",
|
||||
" ....++. ",
|
||||
" .+++++++. ",
|
||||
" .++++++++. ",
|
||||
" .+++++++++. ",
|
||||
" @# @$ .++++++++. ",
|
||||
" @%%% .+++++++. ",
|
||||
" @%%%%% @$ ....++. ",
|
||||
" @%%%%%%% .+. ",
|
||||
" @%%%%%%%%% @$ .. ",
|
||||
" %%%%%% %%%% . ",
|
||||
" $%%%%%% %%%% @$ ",
|
||||
" @ %%%%%%%%%%% ",
|
||||
" $%%%%%%%%%%% @$ ",
|
||||
" @ %%%%%% %%% ",
|
||||
" $%%%%% %%%% ",
|
||||
" @ %%%%%%%%% ",
|
||||
" $%%%%%%% ",
|
||||
" @ %%%%% ",
|
||||
" $%%% ",
|
||||
" @ ",
|
||||
" "};
|
||||
29
acs/Src/resources/TACSMixer.xpm
Normal file
29
acs/Src/resources/TACSMixer.xpm
Normal file
@@ -0,0 +1,29 @@
|
||||
/* XPM */
|
||||
static char * TMixer_xpm[] = {
|
||||
"24 24 2 1",
|
||||
" c None",
|
||||
". c #000000",
|
||||
" ",
|
||||
" ",
|
||||
" . ",
|
||||
" . . . . ",
|
||||
" . . . . ",
|
||||
" . . . . ",
|
||||
" . . .. . ",
|
||||
" . . ...... . ",
|
||||
" . . .. . ",
|
||||
" .. . . . ",
|
||||
" ...... . . . ",
|
||||
" .. . . . ",
|
||||
" . . . . ",
|
||||
" . . . . ",
|
||||
" . .. . . ",
|
||||
" . ...... . . ",
|
||||
" . .. . . ",
|
||||
" . . . . ",
|
||||
" . . . . ",
|
||||
" . . . . ",
|
||||
" . . . . ",
|
||||
" . ",
|
||||
" ...................... ",
|
||||
" "};
|
||||
32
acs/Src/resources/TACSNULLOut.xpm
Normal file
32
acs/Src/resources/TACSNULLOut.xpm
Normal file
@@ -0,0 +1,32 @@
|
||||
/* XPM */
|
||||
static char * TNULLOut_xpm[] = {
|
||||
"24 24 5 1",
|
||||
" c None",
|
||||
". c #000080",
|
||||
"+ c #0000FF",
|
||||
"@ c #00FFFF",
|
||||
"# c #000000",
|
||||
" ",
|
||||
" . ",
|
||||
" .. ",
|
||||
" .+. ",
|
||||
" ....++. ",
|
||||
" .+++++++. ",
|
||||
" .++++++++. ",
|
||||
" .+++++++++. ..... ",
|
||||
" .++++++++. +.+++++.+ ",
|
||||
" .+++++++. ..+++++@. ",
|
||||
" ....++. ...+++++@.. ",
|
||||
" .+. ...+++++@.# ",
|
||||
" .. ....+++.... ",
|
||||
" . .@+.....++. ",
|
||||
" .@++++++++. ",
|
||||
" .@++++++++# ",
|
||||
" ...+++++... ",
|
||||
" .@+.....++. ",
|
||||
" .@++++++++. ",
|
||||
" ...+++++... ",
|
||||
" .@+.....++. ",
|
||||
" +.@++++++.+ ",
|
||||
" +.+++++.+ ",
|
||||
" ..... "};
|
||||
31
acs/Src/resources/TACSRateConverter.xpm
Normal file
31
acs/Src/resources/TACSRateConverter.xpm
Normal file
@@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * TRateConverter_xpm[] = {
|
||||
"24 24 4 1",
|
||||
" c None",
|
||||
". c #FF0000",
|
||||
"+ c #000000",
|
||||
"@ c #0000FF",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
".. .. .. ",
|
||||
" . . . . . .",
|
||||
" . . . . . .",
|
||||
" . . . . . . ",
|
||||
" . . . . . . ",
|
||||
" .. .. .. ",
|
||||
" ",
|
||||
" + + ",
|
||||
" + + +++ ",
|
||||
" +++ + + ",
|
||||
" + + ",
|
||||
" ",
|
||||
" @ @ @ @ @ ",
|
||||
" @ @ @ @ @ ",
|
||||
"@ @ @ @ @ @ @ @ @ @ @ @ ",
|
||||
"@ @ @ @ @ @ @ @ @ @ @ @ ",
|
||||
" @ @ @ @ @ @ ",
|
||||
" @ @ @ @ @ @ ",
|
||||
" ",
|
||||
" ",
|
||||
" "};
|
||||
34
acs/Src/resources/TACSSINCFilter.xpm
Normal file
34
acs/Src/resources/TACSSINCFilter.xpm
Normal file
@@ -0,0 +1,34 @@
|
||||
/* XPM */
|
||||
static char * TSINCFilter_xpm[] = {
|
||||
"24 24 7 1",
|
||||
" c None",
|
||||
". c #800000",
|
||||
"+ c #000000",
|
||||
"@ c #0000FF",
|
||||
"# c #008080",
|
||||
"$ c #00FFFF",
|
||||
"% c #000080",
|
||||
" ",
|
||||
" ... . . . ... ",
|
||||
" . . .. . . ",
|
||||
" .. . . . . ",
|
||||
" . . . . . ",
|
||||
" ... . . . ... ",
|
||||
" ",
|
||||
" +++++++ ",
|
||||
" +++@#@#@#@+++ ",
|
||||
" +@#@#@#@#@#@#$+ ",
|
||||
" +%#@#@#@#@#@#@$%+ ",
|
||||
" +%%#@#@#@#@#@$$%+ ",
|
||||
" ++++@#@#@#@++++ ",
|
||||
" +$@+++++++@@+ ",
|
||||
" %$@@@@@@@@+ ",
|
||||
" %$@@@@@@+ ",
|
||||
" %$@@@@+ ",
|
||||
" %@+++ ",
|
||||
" %$@@+ ",
|
||||
" %$@@+ ",
|
||||
" %$@@+ ",
|
||||
" %$@@+ ",
|
||||
" %%% ",
|
||||
" "};
|
||||
31
acs/Src/resources/TACSSampleConverter.xpm
Normal file
31
acs/Src/resources/TACSSampleConverter.xpm
Normal file
@@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * TSampleConverter_xpm[] = {
|
||||
"24 24 4 1",
|
||||
" c None",
|
||||
". c #0000FF",
|
||||
"+ c #000080",
|
||||
"@ c #000000",
|
||||
" ",
|
||||
"........................",
|
||||
" . . ",
|
||||
" . + + + + . + + +",
|
||||
" . + + + + . + + ",
|
||||
" . + + . + ",
|
||||
" . + + + + . + + ",
|
||||
" . + + + + . + + +",
|
||||
" . . ",
|
||||
"........................",
|
||||
" @ @ ",
|
||||
" @ @ @@@ ",
|
||||
" @@@ @ @ ",
|
||||
" @ @ ",
|
||||
"........................",
|
||||
" . . . ",
|
||||
" . + + . + + . + +",
|
||||
" . + + . + + . + + ",
|
||||
" . + . + . + ",
|
||||
" . + + . + + . + + ",
|
||||
" . + + . + + . + +",
|
||||
" . . . ",
|
||||
"........................",
|
||||
" "};
|
||||
30
acs/Src/resources/TACSSoundIndicator.xpm
Normal file
30
acs/Src/resources/TACSSoundIndicator.xpm
Normal file
@@ -0,0 +1,30 @@
|
||||
/* XPM */
|
||||
static char * TSoundIndicator_xpm[] = {
|
||||
"24 24 3 1",
|
||||
" c None",
|
||||
". c #000000",
|
||||
"+ c #00FF00",
|
||||
" ",
|
||||
" ",
|
||||
" .................... ",
|
||||
" .................... ",
|
||||
" .................... ",
|
||||
" .................... ",
|
||||
" .................... ",
|
||||
" ....++.............. ",
|
||||
" ....++.............. ",
|
||||
" .................... ",
|
||||
" .++.++.++........... ",
|
||||
" .++.++.++........... ",
|
||||
" .................... ",
|
||||
" .++.++.++.......++.. ",
|
||||
" .++.++.++.......++.. ",
|
||||
" .................... ",
|
||||
" .++.++.++.++....++.. ",
|
||||
" .++.++.++.++....++.. ",
|
||||
" .................... ",
|
||||
" .++.++.++.++.++.++.. ",
|
||||
" .++.++.++.++.++.++.. ",
|
||||
" .................... ",
|
||||
" ",
|
||||
" "};
|
||||
30
acs/Src/resources/TACSStereoBalance.xpm
Normal file
30
acs/Src/resources/TACSStereoBalance.xpm
Normal file
@@ -0,0 +1,30 @@
|
||||
/* XPM */
|
||||
static char * TStereoBalance_xpm[] = {
|
||||
"24 24 3 1",
|
||||
" c None",
|
||||
". c #800000",
|
||||
"+ c #000000",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" . . ",
|
||||
" .. .. ",
|
||||
" ... ... ",
|
||||
" ...... ...... ",
|
||||
" ...... ...... ",
|
||||
" ...... ...... ",
|
||||
" ...... ...... ",
|
||||
" ... ... ",
|
||||
" .. .. ",
|
||||
" . . ",
|
||||
" ++ ",
|
||||
" ++ ",
|
||||
" ++ ",
|
||||
" +++++++ +++++++++ ",
|
||||
" +++++++ +++++++++ ",
|
||||
" +++ ",
|
||||
" ",
|
||||
" ",
|
||||
" "};
|
||||
35
acs/Src/resources/TACSStreamIn.xpm
Normal file
35
acs/Src/resources/TACSStreamIn.xpm
Normal file
@@ -0,0 +1,35 @@
|
||||
/* XPM */
|
||||
static char * TStreamIn_xpm[] = {
|
||||
"24 24 8 1",
|
||||
" c None",
|
||||
". c #800000",
|
||||
"+ c #FF0000",
|
||||
"@ c #0000FF",
|
||||
"# c #000080",
|
||||
"$ c #00FFFF",
|
||||
"% c #008080",
|
||||
"& c #000000",
|
||||
" . ",
|
||||
" .. ",
|
||||
" .+. ",
|
||||
" ....++. ",
|
||||
" .+++++++. ",
|
||||
" .++++++++. ",
|
||||
" .+++++++++. ",
|
||||
" @# @$ .++++++++. ",
|
||||
" @### .+++++++. ",
|
||||
" @##### @$ ....++. ",
|
||||
" @####### .+. ",
|
||||
" @####%#### @$ .. ",
|
||||
" &@####$#### . ",
|
||||
" $&@####$#### @$ ",
|
||||
" & &@######### ",
|
||||
" $&@####%#### @$ ",
|
||||
" & &@####$$### ",
|
||||
" $&####$$#### ",
|
||||
" & &#######& ",
|
||||
" $&#####& ",
|
||||
" & &###& ",
|
||||
" $&#& ",
|
||||
" & ",
|
||||
" "};
|
||||
33
acs/Src/resources/TACSStreamOut.xpm
Normal file
33
acs/Src/resources/TACSStreamOut.xpm
Normal file
@@ -0,0 +1,33 @@
|
||||
/* XPM */
|
||||
static char * TStreamOut_xpm[] = {
|
||||
"24 24 6 1",
|
||||
" c None",
|
||||
". c #0000FF",
|
||||
"+ c #000080",
|
||||
"@ c #00FFFF",
|
||||
"# c #008080",
|
||||
"$ c #000000",
|
||||
" .+ .@ ",
|
||||
" .+++ ",
|
||||
" .+++++ .@ ",
|
||||
" .+++++++ ",
|
||||
" .++++#++++ .@ ",
|
||||
" $.++++@++++ ",
|
||||
" @$.++++@++++ .@ ",
|
||||
" $ $.+++++++++ ",
|
||||
" @$.++++#++++ .@",
|
||||
" $ $.++++@@+++ ",
|
||||
" + @$++++@@++++ ",
|
||||
" ++ $ $+++++++$ ",
|
||||
" +.+ @$+++++$ ",
|
||||
" ++++..+ $ $+++$ ",
|
||||
"+.......+ @$+$ ",
|
||||
"+........+ $ ",
|
||||
"+.........+ ",
|
||||
"+........+ ",
|
||||
"+.......+ ",
|
||||
" ++++..+ ",
|
||||
" +.+ ",
|
||||
" ++ ",
|
||||
" + ",
|
||||
" "};
|
||||
1
acs/Src/resources/makeres.bat
Normal file
1
acs/Src/resources/makeres.bat
Normal file
@@ -0,0 +1 @@
|
||||
lazres.exe acs_reg.lrs TACSAudioIn.xpm TACSAudioOut.xpm TACSCDIn.xpm TACSAudioMixer.xpm TACSRateConverter.xpm TACSMSConverter.xpm TACSSampleConverter.xpm TACSFixedResampler.xpm TACSStereoBalance.xpm TACSBWFilter.xpm TACSSINCFilter.xpm TACSConvolver.xpm TACSSoundIndicator.xpm TACSMemoryIn.xpm TACSAudioProcessor.xpm TACSNULLOut.xpm TACSInputList.xpm TACSStreamIn.xpm TACSStreamOut.xpm TACSFileIn.xpm TACSFileOut.xpm TACSMixer.xpm
|
||||
2
acs/Src/resources/makeres.sh
Normal file
2
acs/Src/resources/makeres.sh
Normal file
@@ -0,0 +1,2 @@
|
||||
lazres acs_reg.lrs TACSAudioIn.xpm TACSAudioOut.xpm TACSCDIn.xpm TACSAudioMixer.xpm TACSRateConverter.xpm TACSMSConverter.xpm TACSSampleConverter.xpm TACSFixedResampler.xpm TACSStereoBalance.xpm TACSBWFilter.xpm TACSSINCFilter.xpm TACSConvolver.xpm TACSSoundIndicator.xpm TACSMemoryIn.xpm TACSAudioProcessor.xpm TACSNULLOut.xpm TACSInputList.xpm TACSStreamIn.xpm TACSStreamOut.xpm TACSFileIn.xpm TACSFileOut.xpm TACSMixer.xpm
|
||||
|
||||
BIN
acs/Src/resources/resource.dcr
Normal file
BIN
acs/Src/resources/resource.dcr
Normal file
Binary file not shown.
124
acs/Src/samples/converter.pas
Normal file
124
acs/Src/samples/converter.pas
Normal file
@@ -0,0 +1,124 @@
|
||||
(*
|
||||
this file is a part of audio components suite.
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
|
||||
This is an sample unit for an converter
|
||||
*)
|
||||
unit converter;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils;
|
||||
|
||||
type
|
||||
|
||||
{ TACSNewConverter }
|
||||
|
||||
TACSNewConverter = class(TACSCustomConverter)
|
||||
private
|
||||
protected
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
published
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{ TACSNewConverter }
|
||||
|
||||
function TACSNewConverter.GetBPS: Integer;
|
||||
begin
|
||||
Result:=FInput.GetBPS;
|
||||
end;
|
||||
|
||||
function TACSNewConverter.GetCh: Integer;
|
||||
begin
|
||||
Result:=FInput.GetCh;
|
||||
end;
|
||||
|
||||
function TACSNewConverter.GetSR: Integer;
|
||||
begin
|
||||
Result:=FInput.GetSR;
|
||||
end;
|
||||
|
||||
constructor TACSNewConverter.Create(AOwner: TComponent);
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
end;
|
||||
|
||||
destructor TACSNewConverter.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TACSNewConverter.GetData(Buffer: Pointer; BufferSize: Integer): Integer;
|
||||
var
|
||||
l : Integer;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create(strStreamnotopen);
|
||||
if BufStart > BufEnd then
|
||||
begin
|
||||
if EndOfInput then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
BufStart := 1;
|
||||
|
||||
|
||||
while InputLock do;
|
||||
InputLock := True;
|
||||
|
||||
l := Finput.GetData(@Yourbuffer[0], WantedSize);
|
||||
|
||||
InputLock := False;
|
||||
if l = 0 then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
InSize := l;
|
||||
while (l<>0) and (InSize < WantedSize) do
|
||||
begin
|
||||
while InputLock do;
|
||||
InputLock := True;
|
||||
l := Finput.GetData(@YourBuffer[InSize], WantedSize - InSize);
|
||||
InputLock := False;
|
||||
Inc(InSize, l);
|
||||
end;
|
||||
if l = 0 then EndOfInput := True;
|
||||
|
||||
//Do Your DSP Stuff here
|
||||
|
||||
end;
|
||||
if BufferSize < (BufEnd - BufStart + 1)
|
||||
then Result := BufferSize
|
||||
else Result := BufEnd - BufStart + 1;
|
||||
|
||||
Move(YourOutBuffer[BufStart-1], Buffer^, Result);
|
||||
|
||||
Inc(BufStart, Result);
|
||||
Inc(FPosition, Result);
|
||||
end;
|
||||
|
||||
procedure TACSNewConverter.Init;
|
||||
begin
|
||||
inherited Init;
|
||||
end;
|
||||
|
||||
procedure TACSNewConverter.Flush;
|
||||
begin
|
||||
inherited Flush;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
303
acs/Src/samples/driver.pas
Normal file
303
acs/Src/samples/driver.pas
Normal file
@@ -0,0 +1,303 @@
|
||||
(*
|
||||
this file is a part of audio components suite
|
||||
see the license file for more details.
|
||||
you can contact me at mail@z0m3ie.de
|
||||
|
||||
this is an sample unit for an driver
|
||||
*)
|
||||
|
||||
unit driver;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
ACS_Audio,SysUtils, Classes, ACS_Types, ACS_Classes, ACS_Strings;
|
||||
|
||||
const
|
||||
LATENCY = 25;
|
||||
|
||||
type
|
||||
TOwnAudioOut = class(TACSBaseAudioOut)
|
||||
private
|
||||
EndOfInput, StartInput : Boolean;
|
||||
FDeviceNumber : Integer;
|
||||
FDeviceCount : Integer;
|
||||
procedure SetDevice(Ch : Integer);override;
|
||||
function GetDeviceInfo : TACSDeviceInfo;override;
|
||||
function GetDeviceCount : Integer;override;
|
||||
protected
|
||||
procedure Done; override;
|
||||
function DoOutput(Abort : Boolean):Boolean; override;
|
||||
procedure Prepare; override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
procedure Pause;override;
|
||||
procedure Resume;override;
|
||||
end;
|
||||
|
||||
TOwnAudioIn = class(TACSBaseAudioIn)
|
||||
private
|
||||
FDeviceNumber : Integer;
|
||||
FDeviceCount : Integer;
|
||||
FBPS, FChan, FFreq : Integer;
|
||||
FOpened : Integer;
|
||||
FRecTime : Integer;
|
||||
procedure SetDevice(i : Integer);override;
|
||||
procedure OpenAudio;
|
||||
procedure CloseAudio;
|
||||
function GetBPS : Integer; override;
|
||||
function GetCh : Integer; override;
|
||||
function GetSR : Integer; override;
|
||||
function GetTotalTime : real; override;
|
||||
procedure SetRecTime(aRecTime : Integer);
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override;
|
||||
procedure Init; override;
|
||||
procedure Flush; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TOwnAudioOut.Prepare;
|
||||
begin
|
||||
FInput.Init;
|
||||
FBuffer := AllocMem(FBufferSize);
|
||||
StartInput := True;
|
||||
EndOfInput := False;
|
||||
|
||||
//Init your output device here
|
||||
end;
|
||||
|
||||
procedure TOwnAudioOut.Done;
|
||||
begin
|
||||
//Flush your output device here
|
||||
|
||||
Finput.Flush;
|
||||
FreeMem(FBuffer);
|
||||
end;
|
||||
|
||||
function TOwnAudioOut.DoOutput(Abort : Boolean):Boolean;
|
||||
var
|
||||
Len, offs, lb : Integer;
|
||||
Stat : LongWord;
|
||||
Res : HRESULT;
|
||||
PlayTime, CTime : LongWord;
|
||||
begin
|
||||
Result := True;
|
||||
if not Busy then Exit;
|
||||
if not CanOutput then
|
||||
begin
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
if StartInput then
|
||||
begin
|
||||
Len := 0;
|
||||
while Len < FBufferSize do
|
||||
begin
|
||||
offs := FInput.GetData(@FBuffer^[Len], FBufferSize-Len);
|
||||
if offs = 0 then
|
||||
begin
|
||||
EndOfInput := True;
|
||||
Break;
|
||||
end;
|
||||
Inc(Len, offs);
|
||||
end;
|
||||
//Do Output Len bytes from FBuffer^
|
||||
|
||||
StartInput := False;
|
||||
end;
|
||||
if Abort then
|
||||
begin
|
||||
//Stop your output device
|
||||
|
||||
CanOutput := False;
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
if EndOfInput then
|
||||
begin
|
||||
CanOutput := False;
|
||||
|
||||
//Stop your output device
|
||||
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TOwnAudioOut.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FBufferSize := $40000;
|
||||
|
||||
//enumerate devices and set Devicecount
|
||||
FDeviceCount := 0;
|
||||
end;
|
||||
|
||||
destructor TOwnAudioOut.Destroy;
|
||||
begin
|
||||
//Wahtever
|
||||
end;
|
||||
|
||||
procedure TOwnAudioOut.Pause;
|
||||
begin
|
||||
if EndOfInput then Exit;
|
||||
//Pause
|
||||
end;
|
||||
|
||||
procedure TOwnAudioOut.Resume;
|
||||
begin
|
||||
if EndOfInput then Exit;
|
||||
//waht schoud i say ?
|
||||
end;
|
||||
|
||||
procedure TOwnAudioOut.SetDevice(Ch: Integer);
|
||||
begin
|
||||
FBaseChannel := Ch;
|
||||
end;
|
||||
|
||||
function TOwnAudioOut.GetDeviceInfo: TACSDeviceInfo;
|
||||
begin
|
||||
if (FBaseChannel >= FDeviceCount) then
|
||||
exit;
|
||||
//return an Deviceinfo
|
||||
end;
|
||||
|
||||
function TOwnAudioOut.GetDeviceCount: Integer;
|
||||
begin
|
||||
Result := FDeviceCount;
|
||||
end;
|
||||
|
||||
constructor TOwnAudioIn.Create;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FBPS := 8;
|
||||
FChan := 1;
|
||||
FFreq := 8000;
|
||||
FSize := -1;
|
||||
BufferSize := $2000;
|
||||
//enumerate devices and set Devicecount
|
||||
FDeviceCount := 0;
|
||||
end;
|
||||
|
||||
destructor TOwnAudioIn.Destroy;
|
||||
begin
|
||||
//whatever
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TOwnAudioIn.OpenAudio;
|
||||
var
|
||||
Res : HResult;
|
||||
BufSize : Integer;
|
||||
begin
|
||||
BufSize := BufferSize;
|
||||
if FOpened = 0 then
|
||||
begin
|
||||
//Init your In put device
|
||||
end;
|
||||
Inc(FOpened);
|
||||
end;
|
||||
|
||||
procedure TOwnAudioIn.CloseAudio;
|
||||
begin
|
||||
if FOpened = 1 then
|
||||
begin
|
||||
//Flush your Input device
|
||||
end;
|
||||
if FOpened > 0 then Dec(FOpened);
|
||||
end;
|
||||
|
||||
function TOwnAudioIn.GetBPS : Integer;
|
||||
begin
|
||||
Result := FBPS;
|
||||
end;
|
||||
|
||||
function TOwnAudioIn.GetCh : Integer;
|
||||
begin
|
||||
Result := FChan;
|
||||
end;
|
||||
|
||||
function TOwnAudioIn.GetSR : Integer;
|
||||
begin
|
||||
Result := FFreq;
|
||||
end;
|
||||
|
||||
procedure TOwnAudioIn.Init;
|
||||
begin
|
||||
if Busy then raise EACSException.Create(strBusy);
|
||||
if (FDeviceNumber >= FDeviceCount) then raise EACSException.Create(Format(strChannelnotavailable,[FDeviceNumber]));
|
||||
if FRecTime > 0 then FBytesToRead := FRecTime*FFreq*FChan*(FBPS div 8);
|
||||
BufEnd := 0;
|
||||
BufStart := 1;
|
||||
FPosition := 0;
|
||||
Busy := True;
|
||||
FSize := FBytesToRead;
|
||||
OpenAudio;
|
||||
end;
|
||||
|
||||
procedure TOwnAudioIn.Flush;
|
||||
begin
|
||||
CloseAudio;
|
||||
Busy := False;
|
||||
end;
|
||||
|
||||
function TOwnAudioIn.GetData(Buffer : Pointer; BufferSize : Integer): Integer;
|
||||
var
|
||||
l : Integer;
|
||||
begin
|
||||
if not Busy then raise EACSException.Create(strStreamnotopen);
|
||||
if (FBytesToRead >=0) and (FPosition >= FBytesToRead) then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
if BufStart >= BufEnd then
|
||||
begin
|
||||
BufStart := 0;
|
||||
|
||||
//Read Buffersize bytes from your input device and convert to PCM
|
||||
//l is the real readed size maybe you cant ead the full buffer jet
|
||||
BufEnd := l;
|
||||
end;
|
||||
if BufferSize < (BufEnd - BufStart)
|
||||
then Result := BufferSize
|
||||
else Result := BufEnd - BufStart;
|
||||
Move(FBuffer[BufStart], Buffer^, Result);
|
||||
Inc(BufStart, Result);
|
||||
Inc(FPosition, Result);
|
||||
end;
|
||||
|
||||
procedure TOwnAudioIn.SetRecTime;
|
||||
begin
|
||||
FRecTime := aRecTime;
|
||||
if FRecTime > 0 then
|
||||
FBytesToRead := FRecTime*FFreq*FChan*(FBPS div 8)
|
||||
else
|
||||
FBytesToRead := -1;
|
||||
end;
|
||||
|
||||
procedure TOwnAudioIn.SetDevice(i : Integer);
|
||||
begin
|
||||
FDeviceNumber := i
|
||||
end;
|
||||
|
||||
function TOwnAudioIn.GetTotalTime : real;
|
||||
var
|
||||
BytesPerSec : Integer;
|
||||
begin
|
||||
BytesPerSec := FFreq*FChan*(FBPS div 8);
|
||||
Result := FBytesToRead/BytesPerSec;
|
||||
end;
|
||||
|
||||
initialization
|
||||
RegisterAudioOut('My Drivers Name',TOwnAudioOut,LATENCY);
|
||||
RegisterAudioIn('My Drivers Name',TOwnAudioIn,LATENCY);
|
||||
|
||||
finalization
|
||||
|
||||
end.
|
||||
73
acs/Src/win32/ACS.dpk
Normal file
73
acs/Src/win32/ACS.dpk
Normal file
@@ -0,0 +1,73 @@
|
||||
package ACS;
|
||||
|
||||
{$R *.res}
|
||||
{$ALIGN 8}
|
||||
{$ASSERTIONS ON}
|
||||
{$BOOLEVAL OFF}
|
||||
{$DEBUGINFO ON}
|
||||
{$EXTENDEDSYNTAX ON}
|
||||
{$IMPORTEDDATA ON}
|
||||
{$IOCHECKS ON}
|
||||
{$LOCALSYMBOLS ON}
|
||||
{$LONGSTRINGS ON}
|
||||
{$OPENSTRINGS ON}
|
||||
{$OPTIMIZATION OFF}
|
||||
{$OVERFLOWCHECKS OFF}
|
||||
{$RANGECHECKS OFF}
|
||||
{$REFERENCEINFO ON}
|
||||
{$SAFEDIVIDE OFF}
|
||||
{$STACKFRAMES OFF}
|
||||
{$TYPEDADDRESS OFF}
|
||||
{$VARSTRINGCHECKS ON}
|
||||
{$WRITEABLECONST ON}
|
||||
{$MINENUMSIZE 1}
|
||||
{$IMAGEBASE $400000}
|
||||
{$DESCRIPTION 'Audio Components Suite v 2.4'}
|
||||
{$IMPLICITBUILD OFF}
|
||||
|
||||
requires
|
||||
vcl,
|
||||
rtl;
|
||||
|
||||
contains
|
||||
ACS_Types in '..\classes\ACS_Types.pas',
|
||||
ACS_Audio in '..\classes\ACS_Audio.pas',
|
||||
ACS_AudioMix in '..\classes\ACS_AudioMix.pas',
|
||||
ACS_CDROM in '..\classes\acs_cdrom.pas',
|
||||
ACS_Classes in '..\classes\ACS_Classes.pas',
|
||||
ACS_Converters in '..\classes\ACS_Converters.pas',
|
||||
ACS_File in '..\classes\ACS_File.pas',
|
||||
ACS_Filters in '..\classes\ACS_Filters.pas',
|
||||
ACS_Indicator in '..\classes\ACS_Indicator.pas',
|
||||
ACS_Misc in '..\classes\ACS_Misc.pas',
|
||||
ACS_Mixer in '..\classes\ACS_Mixer.pas',
|
||||
ACS_MultiMix in '..\classes\ACS_MultiMix.pas',
|
||||
ACS_Procs in '..\classes\ACS_Procs.pas',
|
||||
ACS_Streams in '..\classes\ACS_Streams.pas',
|
||||
ACS_Strings in '..\classes\ACS_Strings.pas',
|
||||
akrip32 in '..\classes\windows\akrip32.pas',
|
||||
acs_reg in 'acs_reg.pas',
|
||||
ACS_AllFormats in '..\fileformats\ACS_Allformats.pas',
|
||||
ACS_StdAudio in '..\drivers\ACS_StdAudio.pas',
|
||||
ACS_DXAudio in '..\drivers\ACS_DXAudio.pas',
|
||||
ogg in '..\fileformats\general\ogg.pas',
|
||||
DirectShow9 in '..\fileformats\windows\DirectShow9.pas',
|
||||
vorbisfile in '..\fileformats\general\vorbisfile.pas',
|
||||
vorbisenc in '..\fileformats\general\vorbisenc.pas',
|
||||
acs_dsfiles in '..\fileformats\ACS_DSFiles.pas',
|
||||
directdraw in '..\fileformats\windows\directdraw.pas',
|
||||
directsound in '..\fileformats\windows\directsound.pas',
|
||||
direct3d9 in '..\fileformats\windows\direct3d9.pas',
|
||||
acs_vorbis in '..\fileformats\ACS_Vorbis.pas',
|
||||
dxtypes in '..\fileformats\windows\dxtypes.pas',
|
||||
acs_mac in '..\fileformats\acs_mac.pas',
|
||||
acs_flac in '..\fileformats\acs_flac.pas',
|
||||
macdll in '..\fileformats\windows\macdll.pas',
|
||||
lame in '..\fileformats\general\lame.pas',
|
||||
acs_lame in '..\fileformats\acs_lame.pas',
|
||||
flac in '..\fileformats\general\flac.pas',
|
||||
acs_wave in '..\fileformats\acs_wave.pas',
|
||||
waveconverter in '..\fileformats\windows\waveconverter.pas',
|
||||
acs_volumequery in '..\classes\acs_volumequery.pas';
|
||||
|
||||
end.
|
||||
75
acs/Src/win32/acs_reg.pas
Normal file
75
acs/Src/win32/acs_reg.pas
Normal file
@@ -0,0 +1,75 @@
|
||||
(*
|
||||
$Log: acs_reg.pas,v $
|
||||
Revision 1.16 2006/07/04 17:12:45 z0m3ie
|
||||
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
||||
|
||||
Revision 1.13 2005/12/19 18:37:41 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.11 2005/12/18 17:01:53 z0m3ie
|
||||
delphi compatibility
|
||||
|
||||
Revision 1.10 2005/12/04 16:54:33 z0m3ie
|
||||
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
||||
|
||||
Revision 1.9 2005/11/27 16:50:33 z0m3ie
|
||||
add ACS VolumeQuerry
|
||||
make ACS_VolumeQuerry localizeable
|
||||
some little errorfixes (buffersize for linuxdrivers was initially 0)
|
||||
make TAudioIn workable
|
||||
|
||||
Revision 1.8 2005/10/02 16:51:58 z0m3ie
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.7 2005/09/13 21:54:11 z0m3ie
|
||||
acs is localizeable now (ACS_Strings)
|
||||
|
||||
Revision 1.6 2005/09/12 22:04:52 z0m3ie
|
||||
modified structure again, fileformats are now in an sperat folder.
|
||||
all File In/Out classes are capsulated from TFileIn and TFileOut
|
||||
|
||||
Revision 1.5 2005/08/26 17:03:20 z0m3ie
|
||||
begon to make acs resourcestring aware
|
||||
more advanced tmixer for windows
|
||||
restructured tmixer its better handleable now
|
||||
|
||||
Revision 1.4 2005/08/25 21:06:29 z0m3ie
|
||||
Added TMultiMixer
|
||||
|
||||
Revision 1.3 2005/08/25 20:15:37 z0m3ie
|
||||
Version 2.4 restructure
|
||||
*)
|
||||
|
||||
unit acs_reg;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, ACS_Audio,
|
||||
ACS_CDROM, ACS_AudioMix, ACS_Converters, ACS_Misc, ACS_File, ACS_Filters,
|
||||
ACS_Streams, ACS_Indicator, ACS_Mixer,ACS_MultiMix,ACS_VolumeQuery
|
||||
{$IFDEF FPC}
|
||||
,LResources
|
||||
{$ENDIF};
|
||||
|
||||
procedure Register();
|
||||
|
||||
implementation
|
||||
|
||||
procedure Register();
|
||||
begin
|
||||
RegisterComponents('Audio I/O', [TACSAudioIn, TACSAudioOut,TACSMixer,
|
||||
TACSCDIn,TACSInputList, TACSMemoryIn, TACSFileIn, TACSFileOut, TACSStreamIn, TACSStreamOut, TACSNULLOut]);
|
||||
RegisterComponents('Audio Processing', [TACSAudioMixer,TACSMultiMixer, TACSSampleConverter, TACSRateConverter,
|
||||
TACSMSConverter, TACSAudioProcessor, TACSBWFilter, TACSSincFilter, TACSSoundIndicator, TACSStereoBalance, TACSConvolver,TACSVolumeQuery]);
|
||||
end;
|
||||
|
||||
initialization
|
||||
{$IFDEF FPC}
|
||||
{$i ..\resources\acs_reg.lrs}
|
||||
{$ELSE}
|
||||
{$R ..\resources\resource.dcr}
|
||||
{$ENDIF}
|
||||
|
||||
|
||||
end.
|
||||
158
acs/Src/win32/laz_acs.lpk
Normal file
158
acs/Src/win32/laz_acs.lpk
Normal file
@@ -0,0 +1,158 @@
|
||||
<?xml version="1.0"?>
|
||||
<CONFIG>
|
||||
<Package Version="3">
|
||||
<PathDelim Value="\"/>
|
||||
<Name Value="LAZ_ACS"/>
|
||||
<CompilerOptions>
|
||||
<Version Value="8"/>
|
||||
<PathDelim Value="\"/>
|
||||
<SearchPaths>
|
||||
<IncludeFiles Value="..\classes\windows\;..\fileformats\windows\;..\drivers\windows\;..\dsp\"/>
|
||||
<OtherUnitFiles Value="..\classes\;..\classes\windows\;..\fileformats\;..\fileformats\windows\;..\fileformats\general\;..\drivers\;..\drivers\windows\;..\dsp\"/>
|
||||
<UnitOutputDirectory Value="lib"/>
|
||||
</SearchPaths>
|
||||
<Parsing>
|
||||
<SyntaxOptions>
|
||||
<SyntaxMode Value="Delphi"/>
|
||||
<CStyleOperator Value="False"/>
|
||||
</SyntaxOptions>
|
||||
</Parsing>
|
||||
<CodeGeneration>
|
||||
<Optimizations>
|
||||
<OptimizationLevel Value="2"/>
|
||||
</Optimizations>
|
||||
</CodeGeneration>
|
||||
<Other>
|
||||
<CompilerPath Value="$(CompPath)"/>
|
||||
</Other>
|
||||
</CompilerOptions>
|
||||
<Description Value="Audio Component Suite
|
||||
"/>
|
||||
<Version Major="2" Minor="4" Release="3" Build="23"/>
|
||||
<Files Count="26">
|
||||
<Item1>
|
||||
<Filename Value="acs_reg.pas"/>
|
||||
<HasRegisterProc Value="True"/>
|
||||
<UnitName Value="acs_reg"/>
|
||||
</Item1>
|
||||
<Item2>
|
||||
<Filename Value="..\classes\acs_audio.pas"/>
|
||||
<UnitName Value="acs_audio"/>
|
||||
</Item2>
|
||||
<Item3>
|
||||
<Filename Value="..\classes\acs_audiomix.pas"/>
|
||||
<UnitName Value="acs_audiomix"/>
|
||||
</Item3>
|
||||
<Item4>
|
||||
<Filename Value="..\classes\acs_cdrom.pas"/>
|
||||
<UnitName Value="acs_cdrom"/>
|
||||
</Item4>
|
||||
<Item5>
|
||||
<Filename Value="..\classes\acs_classes.pas"/>
|
||||
<UnitName Value="acs_classes"/>
|
||||
</Item5>
|
||||
<Item6>
|
||||
<Filename Value="..\classes\acs_converters.pas"/>
|
||||
<UnitName Value="acs_converters"/>
|
||||
</Item6>
|
||||
<Item7>
|
||||
<Filename Value="..\classes\acs_file.pas"/>
|
||||
<UnitName Value="acs_file"/>
|
||||
</Item7>
|
||||
<Item8>
|
||||
<Filename Value="..\classes\acs_filters.pas"/>
|
||||
<UnitName Value="acs_filters"/>
|
||||
</Item8>
|
||||
<Item9>
|
||||
<Filename Value="..\classes\acs_indicator.pas"/>
|
||||
<UnitName Value="acs_indicator"/>
|
||||
</Item9>
|
||||
<Item10>
|
||||
<Filename Value="..\classes\acs_misc.pas"/>
|
||||
<UnitName Value="acs_misc"/>
|
||||
</Item10>
|
||||
<Item11>
|
||||
<Filename Value="..\classes\acs_mixer.pas"/>
|
||||
<UnitName Value="acs_mixer"/>
|
||||
</Item11>
|
||||
<Item12>
|
||||
<Filename Value="..\classes\acs_multimix.pas"/>
|
||||
<UnitName Value="acs_multimix"/>
|
||||
</Item12>
|
||||
<Item13>
|
||||
<Filename Value="..\classes\acs_procs.pas"/>
|
||||
<UnitName Value="acs_procs"/>
|
||||
</Item13>
|
||||
<Item14>
|
||||
<Filename Value="..\classes\acs_streams.pas"/>
|
||||
<UnitName Value="acs_streams"/>
|
||||
</Item14>
|
||||
<Item15>
|
||||
<Filename Value="..\classes\acs_strings.pas"/>
|
||||
<UnitName Value="acs_strings"/>
|
||||
</Item15>
|
||||
<Item16>
|
||||
<Filename Value="..\classes\acs_types.pas"/>
|
||||
<UnitName Value="acs_types"/>
|
||||
</Item16>
|
||||
<Item17>
|
||||
<Filename Value="..\fileformats\acs_dsfiles.pas"/>
|
||||
<UnitName Value="acs_dsfiles"/>
|
||||
</Item17>
|
||||
<Item18>
|
||||
<Filename Value="..\fileformats\acs_flac.pas"/>
|
||||
<UnitName Value="acs_flac"/>
|
||||
</Item18>
|
||||
<Item19>
|
||||
<Filename Value="..\fileformats\acs_lame.pas"/>
|
||||
<UnitName Value="acs_lame"/>
|
||||
</Item19>
|
||||
<Item20>
|
||||
<Filename Value="..\fileformats\acs_mac.pas"/>
|
||||
<UnitName Value="acs_mac"/>
|
||||
</Item20>
|
||||
<Item21>
|
||||
<Filename Value="..\fileformats\acs_vorbis.pas"/>
|
||||
<UnitName Value="acs_vorbis"/>
|
||||
</Item21>
|
||||
<Item22>
|
||||
<Filename Value="..\fileformats\acs_wave.pas"/>
|
||||
<UnitName Value="acs_wave"/>
|
||||
</Item22>
|
||||
<Item23>
|
||||
<Filename Value="..\fileformats\acs_allformats.pas"/>
|
||||
<UnitName Value="acs_allformats"/>
|
||||
</Item23>
|
||||
<Item24>
|
||||
<Filename Value="..\drivers\acs_dxaudio.pas"/>
|
||||
<UnitName Value="acs_dxaudio"/>
|
||||
</Item24>
|
||||
<Item25>
|
||||
<Filename Value="..\drivers\acs_stdaudio.pas"/>
|
||||
<UnitName Value="acs_stdaudio"/>
|
||||
</Item25>
|
||||
<Item26>
|
||||
<Filename Value="acs_reg.lrs"/>
|
||||
<Type Value="LRS"/>
|
||||
</Item26>
|
||||
</Files>
|
||||
<Type Value="DesignTime"/>
|
||||
<RequiredPkgs Count="2">
|
||||
<Item1>
|
||||
<PackageName Value="LCL"/>
|
||||
</Item1>
|
||||
<Item2>
|
||||
<PackageName Value="FCL"/>
|
||||
<MinVersion Major="1" Valid="True"/>
|
||||
</Item2>
|
||||
</RequiredPkgs>
|
||||
<UsageOptions>
|
||||
<UnitPath Value="$(PkgOutDir)\"/>
|
||||
</UsageOptions>
|
||||
<PublishOptions>
|
||||
<Version Value="2"/>
|
||||
<DestinationDirectory Value="$(TestDir)\publishedpackage\"/>
|
||||
<IgnoreBinaries Value="False"/>
|
||||
</PublishOptions>
|
||||
</Package>
|
||||
</CONFIG>
|
||||
25
acs/Src/win32/laz_acs.pas
Normal file
25
acs/Src/win32/laz_acs.pas
Normal file
@@ -0,0 +1,25 @@
|
||||
{ This file was automatically created by Lazarus. Do not edit!
|
||||
This source is only used to compile and install the package.
|
||||
}
|
||||
|
||||
unit LAZ_ACS;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
acs_reg, acs_audio, acs_audiomix, acs_cdrom, acs_classes, acs_converters,
|
||||
acs_file, acs_filters, acs_indicator, acs_misc, acs_mixer, acs_multimix,
|
||||
acs_procs, acs_streams, acs_strings, acs_types, acs_dsfiles, acs_flac,
|
||||
acs_lame, acs_mac, acs_vorbis, acs_wave, acs_allformats, acs_dxaudio,
|
||||
acs_stdaudio, LazarusPackageIntf;
|
||||
|
||||
implementation
|
||||
|
||||
procedure Register;
|
||||
begin
|
||||
RegisterUnit('acs_reg', @acs_reg.Register);
|
||||
end;
|
||||
|
||||
initialization
|
||||
RegisterPackage('LAZ_ACS', @Register);
|
||||
end.
|
||||
Reference in New Issue
Block a user