//下面是我通过DC-DSP Filter里面的动态放大音量改的
//TBalancer for DSPACK(声道均衡控件,加入了动态放大音量)
//下面是源代码
unit Balancer;
interface
uses Classes, BaseClass, ActiveX, DirectShow9, MMSystem, Windows, DSUTil,
DSPack, BalConst, Math, SysUtils, Trace, Forms;
const
Name_Balancer = 'Audio Balancer by Style.Chen';
CLSID_Balancer: TGUID = '{BD8A846D-95A3-4916-AFEC-951C6A469363}';
IID_BalancerChannel: TGUID = '{01F2EFF9-722A-4D84-A93D-53CF6CD47384}';
type
TAudioChannel = (acStereo, acLeft, acRight);
type
TBalancerFilterGraph = class(TFilterGraph)
public
procedure InsertFilter(AFilter: IFilter);
procedure RemoveFilter(AFilter: IFilter);
end;
IBalancerChannel = interface(IunKnown)
['{BF88E3D0-573E-4D9B-9794-FC18B93E346B}']
function put_MediaType(mt: PAMMediaType): HRESULT;
stdcall;
function get_MediaType(out mt: TAMMediaType): HRESULT;
stdcall;
function get_IPin(out Pin: IPin): HRESULT;
stdcall;
function get_State(out State: TFilterState): HRESULT;
stdcall;
function SetAudioChannel(AudioChannel: TAudioChannel): HRESULT;
stdcall;
end;
const
MEDIATYPE_Audio: TGUID = (D1: $73647561;
D2: $0000;
D3: $0010;
D4: ($80, $00,
$00, $AA, $00, $38, $9B, $71));
MEDIASUBTYPE_PCM: TGUID = (D1: $00000001;
D2: $0000;
D3: $0010;
D4: ($80, $00,
$00, $AA, $00, $38, $9B, $71));
var
InstanceCount: integer = 0;
type
TBalancer = class;
TBalancerFilter = class(TBCTransInPlaceFilter, IBalancerChannel, IPersist)
//动态放大
fMaxAmplification : Cardinal;
fAmpWait : integer;
fReleaseTime : Cardinal;
fLastAmp : Single;
fAmpWaitPos : integer;
fAttackTime : Cardinal;
fSampleSize : Cardinal;
fSamplerate :integer;
FThisInstance: integer;
FPreferred: TAMMediaType;
FBalancerLock: TBCCritSec;
FCurrentChannel: TAudioChannel;
FParent: TBalancer;
private
function AudioChannelMix(PBuffer: Pointer;
Size: Integer;
AudioChannel:
TAudioChannel;
AudioBits: Integer;
Channels: WORD;
Float: boolean): HRESULT;
public
property Samplerate : integer read fSamplerate write fSamplerate;
{ Sets the SampleSize so that the Buffer will be splitted to Process an amount
of Data only on every Process. Set SampleSize to 0 to disable it. Prevent
using small size Values. Use at least 1024 or more. }
property SampleSize : Cardinal read fSampleSize write fSampleSize;
{ Specifys the Amplification Value than will be used when Amplifying. }
property AttackTime : Cardinal read fAttackTime write fAttackTime;
{ Specifys the Time in MilliSeconds that the DSP will wait to continue
Amplification, after the Maximum has been reached. }
property ReleaseTime : Cardinal read fReleaseTime write fReleaseTime;
{ Sets the Amplification for a Channel. Default Value is 10000, which means
that no Amplification occours. A Value of 20000 raises the Amplification
by 2. }
property MaxAmplification : Cardinal read fMaxAmplification write fMaxAmplification;
{ Retrieves the Current Amplification Factor. }
property CurrentAmplification : Single read fLastAmp;
function StartStreaming: HRESULT;
override;
function CheckInputType(mtIn: PAMMediaType): HRESULT;
override;
function put_MediaType(mt: PAMMediaType): HRESULT;
stdcall;
function get_MediaType(out mt: TAMMediaType): HRESULT;
stdcall;
function get_IPin(out Pin: IPin): HRESULT;
stdcall;
function get_State(out State: TFilterState): HRESULT;
stdcall;
function GetPages(out pages: TCAGUID): HResult;
stdcall;
constructor Create(ObjName: string;
unk: IUnKnown;
out hr: HRESULT);
constructor CreateFromFactory(Factory: TBCClassFactory;
const Controller:
IUnknown);
override;
destructor Destroy;
override;
function Transform(Sample: IMediaSample): HRESULT;
override;
function SetAudioChannel(AudioChannel: TAudioChannel): HRESULT;
stdcall;
property Parent: TBalancer read FParent write FParent;
end;
TBalancer = class(TComponent, IFilter)
private
FFilter: TBalancerFilter;
FFilterGraph: TFilterGraph;
FBaseFilter: IBaseFilter;
FAudioChannel: TAudioChannel;
function GetFilter: IBaseFilter;
function GetName: string;
procedure NotifyFilter(operation: TFilterOperation;
Param: integer = 0);
procedure SetFilterGraph(AFilterGraph: TFilterGraph);
procedure SetAudioChannel(AAudioChannel: TAudioChannel);
function CreateFilter: HResult;
function GetCurrentAmplification: Single;
function GetAttackTime: Cardinal;
function GetReleaseTime: Cardinal;
function GetMaxAmplification: Cardinal;
procedure SetAttackTime(Value: Cardinal);
procedure SetReleaseTime(Value: Cardinal);
procedure SetMaxAmplification(Value: Cardinal);
protected
procedure Notification(AComponent: TComponent;
Operation: TOperation);
override;
public
constructor Create(AOwner: TComponent);
override;
destructor Destroy;
override;
function QueryInterface(const IID: TGUID;
out Obj): HResult;
override;
stdcall;
published
property FilterGraph: TFilterGraph read FFilterGraph write SetFilterGraph;
property AudioChannel: TAudioChannel read FAudioChannel write
SetAudioChannel;
{ Specifys the Amplification Value than will be used when Amplifying. }
property AttackTime : Cardinal read GetAttackTime write SetAttackTime;
{ Specifys the Time in MilliSeconds that the DSP will wait to continue
Amplification, after the Maximum has been reached. }
property ReleaseTime : Cardinal read GetReleaseTime write SetReleaseTime;
{ Sets the Amplification for a Channel. Default Value is 10000, which means
that no Amplification occours. A Value of 20000 raises the Amplification
by 2. }
property MaxAmplification : Cardinal read GetMaxAmplification write SetMaxAmplification;
public
//这里是即时放大的值
property CurrentAmplification : Single read GetCurrentAmplification;
end;
procedure Register;
implementation
procedure TBalancerFilterGraph.InsertFilter(AFilter: IFilter);
begin
inherited InsertFilter(AFilter);
end;
procedure TBalancerFilterGraph.RemoveFilter(AFilter: IFilter);
begin
inherited RemoveFilter(AFilter);
end;
{
这个是以前的东西
function TBalancerFilter.AudioChannelMix(PBuffer: PByte;
Size: Integer;
AudioChannel:
TAudioChannel;
AudioBits: Integer): HRESULT;
var
i: Integer;
begin
Result := S_OK;
try
if AudioBits = 8 then
begin
case AudioChannel of
acRight:
begin
for i := 0 to Size - 1do
begin
if (i mod 2) = 0 then
begin
PByte(Integer(PBuffer) + i + 1)^ :=
PByte(Integer(PBuffer) +
i)^;
end;
end;
end;
acLeft:
begin
for i := 0 to Size - 1do
begin
if (i mod 2) = 0 then
begin
PByte(Integer(PBuffer) + i)^ :=
PByte(Integer(PBuffer) + i +
1)^;
end;
end;
end;
end;
Exit;
end;
if AudioBits = 16 then
begin
case AudioChannel of
acRight:
begin
for i := 0 to Size - 1do
begin
if (i mod 4) = 0 then
begin
PByte(Integer(PBuffer) + i + 2)^ :=
PByte(Integer(PBuffer) +
i)^;
PByte(Integer(PBuffer) + i + 3)^ :=
PByte(Integer(PBuffer) + i +
1)^;
end;
end;
end;
acLeft:
begin
for i := 0 to Size - 1do
begin
if (i mod 4) = 0 then
begin
PByte(Integer(PBuffer) + i)^ := PByte(Integer(PBuffer) + i +
2)^;
PByte(Integer(PBuffer) + i + 1)^ := PByte(Integer(PBuffer) + i +
3)^;
end;
end;
end;
end;
Exit;
end;
if AudioBits = 24 then
begin
case AudioChannel of
acRight:
begin
for i := 0 to Size - 1do
begin
if (i mod 6) = 0 then
begin
PByte(Integer(PBuffer) + i + 3)^ :=
PByte(Integer(PBuffer) +
i)^;
PByte(Integer(PBuffer) + i + 4)^ :=
PByte(Integer(PBuffer) + i +
1)^;
PByte(Integer(PBuffer) + i + 5)^ :=
PByte(Integer(PBuffer) + i +
2)^;
end;
end;
end;
acLeft:
begin
for i := 0 to Size - 1do
begin
if (i mod 6) = 0 then
begin
PByte(Integer(PBuffer) + i)^ :=
PByte(Integer(PBuffer) +
i + 3)^;
PByte(Integer(PBuffer) + i + 1)^ :=
PByte(Integer(PBuffer) + i +
4)^;
PByte(Integer(PBuffer) + i + 2)^ :=
PByte(Integer(PBuffer) + i +
5)^;
end;
end;
end;
end;
Exit;
end;
if AudioBits = 32 then
begin
case AudioChannel of
acRight:
begin
for i := 0 to Size - 1do
begin
if (i mod 8) = 0 then
begin
PByte(Integer(PBuffer) + i + 4)^ :=
PByte(Integer(PBuffer) +
i)^;
PByte(Integer(PBuffer) + i + 5)^ :=
PByte(Integer(PBuffer) + i +
1)^;
PByte(Integer(PBuffer) + i + 6)^ :=
PByte(Integer(PBuffer) +
2)^;
PByte(Integer(PBuffer) + i + 7)^ :=
PByte(Integer(PBuffer) + i +
3)^;
end;
end;
end;
acLeft:
begin
for i := 0 to Size - 1do
begin
if (i mod 4) = 0 then
begin
PByte(Integer(PBuffer) + i)^ := PByte(Integer(PBuffer) + i +
4)^;
PByte(Integer(PBuffer) + i + 1)^ := PByte(Integer(PBuffer) + i +
5)^;
PByte(Integer(PBuffer) + i + 2)^ := PByte(Integer(PBuffer) + i +
6)^;
PByte(Integer(PBuffer) + i + 3)^ := PByte(Integer(PBuffer) + i +
7)^;
end;
end;
end;
end;
Exit;
end;
Result := S_OK;
except
Result := S_FALSE;
end;
end;
}
//这个是加入了动态放大的声音
function TBalancerFilter.AudioChannelMix(PBuffer: Pointer;
Size: Integer;
AudioChannel:
TAudioChannel;
AudioBits: Integer;
Channels: WORD;
Float: boolean): HRESULT;
var
Buf8 : PByteArray;
Buf16 : PSmallIntArray;
Buf24 : PInteger24Array;
Buf32 : PFloatArray;
Buf32i : PIntegerArray;
NumSamples : integer;
i,c : integer;
LoudestSample : integer;
LoudestSample64 : Int64;
AmpFactor,
AmpFactorS : Single;
tmp : integer;
sLastAmp : Single;
SmoothAmp : Single;
begin
LoudestSample := 0;
LoudestSample64 := 0;
NumSamples := Size div (AudioBits div 8);
AmpFactorS := fMaxAmplification / 1000;
AmpFactor := 1.0;
fAmpWait := Round((Samplerate * Channels * (AudioBits div 8) * Int64(fReleaseTime)) / 1000);
Buf32 := nil;
Buf16 := nil;
Buf24 := nil;
Buf32i := nil;
Buf8 := nil;
case AudioBits of
8:
begin
Buf8 := PByteArray(PBuffer);
for i := 0 to (NumSamples) -1do
// Check for the Loudest Sample in this Chunk
if abs(Buf8^ - 128) > LoudestSample then
LoudestSample := abs(Buf8^ - 128);
AmpFactor := 128 / LoudestSample;
end;
16:
begin
Buf16 := PSmallIntArray(PBuffer);
for i := 0 to (NumSamples) -1do
// Check for the Loudest Sample in this Chunk
if abs(Buf16^) > LoudestSample then
LoudestSample := abs(Buf16^);
AmpFactor := 32768 / LoudestSample;
end;
24:
begin
Buf24 := PInteger24Array(PBuffer);
for i := 0 to (NumSamples) -1do
// Check for the Loudest Sample in this Chunk
if abs(Cvt24BitTo32(Buf24^)) > LoudestSample then
LoudestSample := abs(Cvt24BitTo32(Buf24^));
AmpFactor := 8388608 / LoudestSample;
end;
32:
begin
if Float then
begin
Buf32 := PFloatArray(PBuffer);
for i := 0 to (NumSamples) -1do
begin
// Check for the Loudest Sample in this Chunk
tmp := Round(abs(Buf32^) * 32767);
if tmp > LoudestSample then
LoudestSample := tmp;
end;
AmpFactor := 32768 / LoudestSample;
end else
begin
Buf32i := PIntegerArray(PBuffer);
for i := 0 to (NumSamples) -1do
// Check for the Loudest Sample in this Chunk
if abs(Buf32i^) > LoudestSample64 then
LoudestSample64 := abs(Buf32i^);
AmpFactor := 2147483648 / LoudestSample64;
end;
end;
end;
sLastAmp := fLastAmp;
if AmpFactor > AmpFactorS then
AmpFactor := AmpFactorS;
if AmpFactor < fLastAmp then
begin
fAmpWaitPos := 0;
fLastAmp := AmpFactor;
end else
begin
if fAmpWaitPos <= fAmpWait then
begin
inc(fAmpWaitPos,Size);
AmpFactor := fLastAmp;
end else
begin
fLastAmp := fLastAmp + ((Size * (fAttackTime / 1000) / Samplerate / Channels / (AudioBits div 8)));
AmpFactor := fLastAmp;
if AmpFactor > AmpFactorS then
begin
AmpFactor := AmpFactorS;
fLastAmp := AmpFactor;
end;
end;
end;
NumSamples := NumSamples div Channels;
case AudioBits of
8:
begin
case AudioChannel of
acRight:
begin
c := 0;
SmoothAmp := (sLastAmp - AmpFactor) / NumSamples;
for i := 0 to (NumSamples -1)do
Buf8^[i * Channels + (1-c)] := Clip_8(Trunc((Buf8^[i * Channels + c] - 128) * (sLastAmp - (SmoothAmp * i)))) + 128;
end;
acLeft:
begin
c := 0;
SmoothAmp := (sLastAmp - AmpFactor) / NumSamples;
for i := 0 to (NumSamples -1)do
Buf8^[i * Channels + c] := Clip_8(Trunc((Buf8^[i * Channels + (1 - c)] - 128) * (sLastAmp - (SmoothAmp * i)))) + 128;
end;
acStereo:
for c := 0 to Channels -1do
begin
SmoothAmp := (sLastAmp - AmpFactor) / NumSamples;
for i := 0 to (NumSamples -1)do
Buf8^[i * Channels + c] := Clip_8(Trunc((Buf8^[i * Channels + c] - 128) * (sLastAmp - (SmoothAmp * i)))) + 128;
end;
end;
end;
16:
begin
case AudioChannel of
acRight:
begin
c := 0;
SmoothAmp := (sLastAmp - AmpFactor) / NumSamples;
for i := 0 to (NumSamples -1)do
Buf16^[i * Channels + (1-c)] := Clip_16(Trunc(Buf16^[i * Channels + c] * (sLastAmp - (SmoothAmp * i))));
end;
acLeft:
begin
c := 0;
SmoothAmp := (sLastAmp - AmpFactor) / NumSamples;
for i := 0 to (NumSamples -1)do
Buf16^[i * Channels + c] := Clip_16(Trunc(Buf16^[i * Channels + (1-c)] * (sLastAmp - (SmoothAmp * i))));
end;
acStereo:
for c := 0 to Channels -1do
begin
SmoothAmp := (sLastAmp - AmpFactor) / NumSamples;
for i := 0 to (NumSamples -1)do
Buf16^[i * Channels + c] := Clip_16(Trunc(Buf16^[i * Channels + c] * (sLastAmp - (SmoothAmp * i))));
end;
end;
end;
24:
begin
case AudioChannel of
acRight:
begin
c := 0;
SmoothAmp := (sLastAmp - AmpFactor) / NumSamples;
for i := 0 to (NumSamples -1)do
Buf24^[i * Channels + (1-c)] := Cvt32BitTo24(Clip_24(Trunc(Cvt24BitTo32(Buf24^[i * Channels + c]) * (sLastAmp - (SmoothAmp * i)))));
end;
acLeft:
begin
c := 0;
SmoothAmp := (sLastAmp - AmpFactor) / NumSamples;
for i := 0 to (NumSamples -1)do
Buf24^[i * Channels + c] := Cvt32BitTo24(Clip_24(Trunc(Cvt24BitTo32(Buf24^[i * Channels + (1-c)]) * (sLastAmp - (SmoothAmp * i)))));
end;
acStereo:
for c := 0 to Channels -1do
begin
SmoothAmp := (sLastAmp - AmpFactor) / NumSamples;
for i := 0 to (NumSamples -1)do
Buf24^[i * Channels + c] := Cvt32BitTo24(Clip_24(Trunc(Cvt24BitTo32(Buf24^[i * Channels + c]) * (sLastAmp - (SmoothAmp * i)))));
end;
end;
end;
32:
begin
if Float then
begin
case AudioChannel of
acRight:
begin
c := 0;
SmoothAmp := (sLastAmp - AmpFactor) / NumSamples;
for i := 0 to (NumSamples -1)do
Buf32^[i * Channels + (1-c)] := Buf32^[i * Channels + c] * (sLastAmp - (SmoothAmp * i));
end;
acLeft:
begin
c := 0;
SmoothAmp := (sLastAmp - AmpFactor) / NumSamples;
for i := 0 to (NumSamples -1)do
Buf32^[i * Channels + c] := Buf32^[i * Channels + (1-c)] * (sLastAmp - (SmoothAmp * i));
end;
acStereo:
for c := 0 to Channels -1do
begin
SmoothAmp := (sLastAmp - AmpFactor) / NumSamples;
for i := 0 to (NumSamples -1)do
Buf32^[i * Channels + c] := Buf32^[i * Channels + c] * (sLastAmp - (SmoothAmp * i));
end;
end;
end else
begin
case AudioChannel of
acRight:
begin
c := 0;
SmoothAmp := (sLastAmp - AmpFactor) / NumSamples;
for i := 0 to (NumSamples -1)do
Buf32i^[i * Channels + (1-c)] := Clip_32(Trunc(Int64(Buf32i^[i * Channels + c]) * (sLastAmp - (SmoothAmp * i))));
end;
acLeft:
begin
c := 0;
SmoothAmp := (sLastAmp - AmpFactor) / NumSamples;
for i := 0 to (NumSamples -1)do
Buf32i^[i * Channels + c] := Clip_32(Trunc(Int64(Buf32i^[i * Channels + (1-c)]) * (sLastAmp - (SmoothAmp * i))));
end;
acStereo:
for c := 0 to Channels -1do
begin
SmoothAmp := (sLastAmp - AmpFactor) / NumSamples;
for i := 0 to (NumSamples -1)do
Buf32i^[i * Channels + c] := Clip_32(Trunc(Int64(Buf32i^[i * Channels + c]) * (sLastAmp - (SmoothAmp * i))));
end;
end;
end;
end;
end;
end;
function TBalancerFilter.StartStreaming: HRESULT;
var
MpegAudioDecoder: IMpegAudioDecoder;
IntDecode: LongWord;
ppEnum: IEnumFilters;
ppFilter: IBaseFilter;
begin
if FParent.FFilterGraph <> nil then
begin
(FParent.FFilterGraph as IFilterGraph).EnumFilters(ppEnum);
while ppEnum.Next(1, ppFilter, nil) = S_OKdo
begin
ppFilter.QueryInterface(IMpegAudioDecoder, MpegAudioDecoder);
if MpegAudioDecoder <> nil then
begin
MpegAudioDecoder.get_DualMode(IntDecode);
MpegAudioDecoder.put_DualMode(0);
end;
end;
end;
MpegAudioDecoder := nil;
ppEnum := nil;
ppFilter := nil;
Result := S_OK;
end;
function TBalancerFilter.CheckInputType(mtIn: PAMMediaType):
HRESULT;
begin
if not IsEqualGUID(mtIn^.majortype, MEDIATYPE_Audio) then
begin
Result := VFW_E_INVALIDMEDIATYPE;
Exit;
end;
if (not IsEqualGUID(mtIn^.subtype, MEDIASUBTYPE_PCM)) and
(not IsEqualGUID(mtIn^.subtype, MEDIASUBTYPE_IEEE_FLOAT)) then
begin
Result := VFW_E_INVALIDSUBTYPE;
Exit;
end;
if not IsEqualGUID(mtIn^.formattype, FORMAT_WaveFormatEx) then
begin
Result := VFW_E_TYPE_NOT_ACCEPTED;
Exit;
end;
Result := S_OK;
end;
constructor TBalancerFilter.Create(ObjName: string;
unk:
IInterface;
out hr: HRESULT);
var
pmt: PAMMediaType;
begin
inherited Create(ObjName, unk, CLSID_Balancer, hr);
FThisInstance := InterlockedIncrement(InstanceCount);
pmt := @FPreferred;
TBCMediaType(pmt).InitMediaType;
FBalancerLock := TBCCritSec.Create;
FCurrentChannel := acStereo;
fLastAmp := 1.0;
fAttackTime := 1000;
fReleaseTime := 3000;
fMaxAmplification := 10000;
fSamplerate := 44100;
fSampleSize := DefaultSampleSize;
end;
constructor TBalancerFilter.CreateFromFactory(Factory:
TBCClassFactory;
const Controller: IInterface);
var
hr: HRESULT;
begin
Create(Factory.Name, Controller, hr);
end;
destructor TBalancerFilter.Destroy;
begin
FBalancerLock.Free;
inherited;
end;
function TBalancerFilter.get_IPin(out Pin: IPin): HRESULT;
begin
Result := S_OK;
FBalancerLock.Lock;
try
if (Input = nil) then
begin
Pin := nil;
Exit;
end;
if not Input.IsConnected then
Pin := nil
else
Pin := Input.GetConnected;
finally
FBalancerLock.UnLock;
end;
end;
function TBalancerFilter.get_MediaType(out mt: TAMMediaType):
HRESULT;
begin
FBalancerLock.Lock;
try
mt := FPreferred;
Result := NOERROR;
finally
FBalancerLock.UnLock;
end;
end;
function TBalancerFilter.get_State(out State: TFilterState):
HRESULT;
begin
FBalancerLock.Lock;
try
State := self.State;
Result := NOERROR;
finally
FBalancerLock.UnLock;
end;
end;
function TBalancerFilter.GetPages(out pages: TCAGUID): HResult;
begin
Pages.cElems := 1;
Result := NOERROR;
end;
function TBalancerFilter.put_MediaType(mt: PAMMediaType):
HRESULT;
var
Pin: IPin;
pmt: PAMMediaType;
begin
FBalancerLock.Lock;
try
if (State = State_Running) then
begin
Result := E_UNEXPECTED;
Exit;
end;
pmt := @FPreferred;
if (mt = nil) then
TBCMediaType(pmt).InitMediaType
else
begin
Pin := Input.GetConnected;
if (Pin <> nil) then
begin
if (Pin.QueryAccept(mt^) <> NOERROR) then
begin
MessageBox(0,
PChar('Upstream filter cannot provide this type'),
PChar('Format Selection'),
MB_OK or MB_ICONEXCLAMATION);
Result := VFW_E_TYPE_NOT_ACCEPTED;
Exit;
end;
end;
Pin := Output.GetConnected;
if (Pin <> nil) then
begin
if (Pin.QueryAccept(mt^) <> NOERROR) then
begin
MessageBox(0,
PChar('Downstream filter cannot accept this type'),
PChar('Format Selection'),
MB_OK or MB_ICONEXCLAMATION);
Result := VFW_E_TYPE_NOT_ACCEPTED;
Exit;
end;
end;
FPreferred := mt^;
end;
if (Input.IsConnected) then
begin
pmt := Input.CurrentMediaType.MediaType;
if not TBCMediaType(pmt).Equal(@FPreferred) then
Graph.Reconnect(Input);
end;
Result := NOERROR;
finally
FBalancerLock.Unlock;
end;
end;
function TBalancerFilter.Transform(Sample: IMediaSample):
HRESULT;
var
PWaveFormat: PWaveFormatEx;
AudioChannel: TAudioChannel;
Size: Integer;
PBuffer: PByte;
SplitBuffer : PChar;
SizeLeft : integer;
SplitSize : integer;
CurrentSize : integer;
Msg: TMsg;
begin
try
PWaveFormat := FInput.CurrentMediaType.MediaType.pbFormat;
// 输出通道数
// TraceString(IntToStr(pWaveFormat.nChannels));
AudioChannel := FCurrentChannel;
Sample.GetPointer(PBuffer);
Size := Sample.GetActualDataLength;
// AudioChannelMix2(Pbuffer, Size, AudioChannel, PWaveFormat.wBitsPerSample, pWaveFormat.nChannels, true);
if fSampleSize = 0 then
AudioChannelMix(Pbuffer, Size, AudioChannel, PWaveFormat.wBitsPerSample, pWaveFormat.nChannels, true)
else
begin
SplitBuffer := Pointer(PBuffer);
SplitSize := fSampleSize * (PWaveFormat.wBitsPerSample div 8) * pWaveFormat.nChannels;
SizeLeft := Size;
while SizeLeft > 0do
begin
if SizeLeft > SplitSize then
CurrentSize := SplitSize
else
CurrentSize := SizeLeft;
AudioChannelMix(@SplitBuffer[Size - SizeLeft], CurrentSize, AudioChannel, PWaveFormat.wBitsPerSample, pWaveFormat.nChannels, true);
if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
dec(SizeLeft,SplitSize);
end;
end;
finally
Result := S_OK;
end;
end;
{
var
SplitBuffer : PChar;
SizeLeft : integer;
SplitSize : integer;
CurrentSize : integer;
if not fEnabled then
Exit;
if fSampleSize = 0 then
begin
do
DSP(Buffer,Size,Samplerate,Bits,Channels,Float);
end else
begin
SplitBuffer := Buffer;
SplitSize := fSampleSize * (Bits div 8) * Channels;
SizeLeft := Size;
while SizeLeft > 0do
begin
if SizeLeft > SplitSize then
CurrentSize := SplitSize
else
CurrentSize := SizeLeft;
do
DSP(@SplitBuffer[Size - SizeLeft],CurrentSize,Samplerate,Bits,Channels,Float);
if fProcessMessages then
Application.ProcessMessages;
dec(SizeLeft,SplitSize);
end;
end;
}
function TBalancerFilter.SetAudioChannel(AudioChannel:
TAudioChannel): HRESULT;
stdcall;
begin
try
FCurrentChannel := AudioChannel;
finally
Result := S_OK;
end;
end;
function TBalancer.GetFilter: IBaseFilter;
begin
Result := FBaseFilter;
end;
function TBalancer.GetName: string;
begin
Result := Name_Balancer;
end;
procedure TBalancer.NotifyFilter(operation: TFilterOperation;
Param: integer =
0);
begin
case operation of
foAdding:
begin
CreateFilter;
end;
foRemoving: if FFilter <> nil then
FFilter.Stop;
foRemoved:
begin
FFilter := nil;
FBaseFilter := nil;
end;
foRefresh: if Assigned(FFilterGraph) then
begin
TBalancerFilterGraph(FFilterGraph).RemoveFilter(self);
TBalancerFilterGraph(FFilterGraph).InsertFilter(self);
end;
end;
end;
procedure TBalancer.SetFilterGraph(AFilterGraph: TFilterGraph);
begin
if AFilterGraph = FFilterGraph then
exit;
if FFilterGraph <> nil then
TBalancerFilterGraph(FFilterGraph).RemoveFilter(self);
if AFilterGraph <> nil then
TBalancerFilterGraph(AFilterGraph).InsertFilter(self);
FFilterGraph := AFilterGraph;
end;
procedure TBalancer.Notification(AComponent: TComponent;
Operation:
TOperation);
begin
inherited Notification(AComponent, Operation);
if ((AComponent = FFilterGraph) and (Operation = opRemove)) then
FFilterGraph := nil;
end;
constructor TBalancer.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FAudioChannel := acStereo;
CreateFilter;
end;
destructor TBalancer.Destroy;
begin
FilterGraph := nil;
inherited Destroy;
end;
function TBalancer.QueryInterface(const IID: TGUID;
out Obj):
HResult;
begin
Result := inherited QueryInterface(IID, Obj);
if not Succeeded(Result) then
if Assigned(FFilter) then
begin
Result := FFilter.QueryInterface(IID, Obj);
end;
end;
procedure TBalancer.SetAudioChannel(AAudioChannel: TAudioChannel);
begin
FAudioChannel := AAudioChannel;
FFilter.SetAudioChannel(FAudioChannel);
end;
function TBalancer.CreateFilter: HResult;
var
hr: HRESULT;
begin
if FFilter = nil then
begin
FFilter := TBalancerFilter.Create(Name, nil, hr);
FFilter.Parent := Self;
FBaseFilter := FFilter as IBaseFilter;
end;
Result := hr;
end;
function TBalancer.GetCurrentAmplification: Single;
begin
Result := FFilter.CurrentAmplification;
end;
function TBalancer.GetAttackTime: Cardinal;
begin
Result := FFilter.AttackTime;
end;
function TBalancer.GetReleaseTime: Cardinal;
begin
Result := FFilter.ReleaseTime;
end;
function TBalancer.GetMaxAmplification: Cardinal;
begin
Result := FFilter.MaxAmplification;
end;
procedure TBalancer.SetAttackTime(Value: Cardinal);
begin
FFilter.AttackTime := Value;
end;
procedure TBalancer.SetReleaseTime(Value: Cardinal);
begin
FFilter.ReleaseTime := Value;
end;
procedure TBalancer.SetMaxAmplification(Value: Cardinal);
begin
FFilter.MaxAmplification := Value;
end;
procedure Register;
begin
RegisterComponents('DSPack', [TBalancer]);
end;
end.