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.