228 lines
5.6 KiB
ObjectPascal
228 lines
5.6 KiB
ObjectPascal
(*
|
|
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.
|