(* 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.