?? balancer.pas
字號(hào):
unit Balancer;
interface
uses Classes, BaseClass, ActiveX, DirectShow9, MMSystem, Windows, DSUTil,
DSPack;
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)
FThisInstance: integer;
FPreferred: TAMMediaType;
FBalancerLock: TBCCritSec;
FCurrentChannel: TAudioChannel;
FParent: TBalancer;
private
function AudioChannelMix(PBuffer: PByte; Size: Integer;
AudioChannel:
TAudioChannel; AudioBits: Integer): HRESULT;
public
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);
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;
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 - 1 do
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 - 1 do
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 - 1 do
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 - 1 do
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 - 1 do
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 - 1 do
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 - 1 do
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 - 1 do
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.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_OK do
begin
ppFilter.QueryInterface(IMpegAudioDecoder, MpegAudioDecoder);
if MpegAudioDecoder <> nil then
begin
MpegAudioDecoder.get_DualMode(IntDecode);
MpegAudioDecoder.put_DualMode(0);
end;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -