217 lines
4.9 KiB
ObjectPascal
217 lines
4.9 KiB
ObjectPascal
(*
|
|
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.
|
|
|