怎样同时输出左声道或右声道(有或无原唱) ( 积分: 30 )

  • 主题发起人 主题发起人 py6530
  • 开始时间 开始时间
P

py6530

Unregistered / Unconfirmed
GUEST, unregistred user!
如果播放的是VCD或WMV等左右声道 的文件,怎样实现原唱的有或无?即:
怎样同时输出左声道或右声道
 
如果播放的是VCD或WMV等左右声道 的文件,怎样实现原唱的有或无?即:
怎样同时输出左声道或右声道
 
用DSPACK和TBalncer控件可以实现
 
我下载并安装了DSPACK,
我看了它提供的例子,但没发现有设置声道的,
你能举个例子给我吗?QQ:328980163
 
还TBalncer控件,把TBalncer控件绑定到DSPACK中的,filtergraph上就可以了
 
我在GOOGLE上搜索"TBalncer",只有三个结果,但均打一开页面,所以找不到这控件,请将你手上的TBalncer,传一份给我,好吗?
 
将 filtergraph.balance:=-10000;

filtergraph.balance:=0;
立体
filtergraph.balance:=10000;
 
两位还没明白我的意思:
我想的不是停掉某一声道,而是让左右声道都有声音,并且是相同的,或都是左声道,或都是右声道.(即放原唱或消原唱)
 
我终于找到了TBalancer控件,只有一个文件:Balancer.pas;也安装成功了,但是,它的属性:
FilterGraph,无法绑定到FilterGraph1,它一下拉框是空的。所以声道的设置也不成功。
不知道是何原因,(我用的是D6,它提供的DPK安装包,是D7的,)
 
Tbalancer在哪里造到的?
 
把以下保存为Balancer.pas

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);
function CreateFilter: HResult;
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 - 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.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;
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;
begin

try
PWaveFormat := FInput.CurrentMediaType.MediaType.pbFormat;

AudioChannel := FCurrentChannel;

Sample.GetPointer(PBuffer);
Size := Sample.GetActualDataLength;

AudioChannelMix(Pbuffer, Size, AudioChannel,
PWaveFormat.wBitsPerSample);
finally
Result := S_OK;
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;


procedure Register;
begin

RegisterComponents('DSPack', [TBalancer]);
end;


end.
 
把以下保存为Balance_D7.dpk,并执行这个文件,编译安装即在DSPACK面板上了

package Balance_D7;

{$R *.res}
{$R 'Balancer.dcr'}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO ON}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION ON}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES OFF}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$DESCRIPTION 'Audio Balancer 2.1 for Delphi 7'}
{$IMPLICITBUILD OFF}

contains
Balancer in 'Balancer.pas';

end.
 
此控件可控制DAT,MPG,RM,RMVB,WMV,ASF的声道,就像VCD机的声道切换
不足之外无法控制VOB的声道,我正为这问题烦着

也可到源码空间找此控件
 
终于行了,因为用了这Balancer.pas,经对照,确实我找到的跟这有区别,也放在这,供你们研究,看是何原因用不得(指在D6):

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

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));

SudPinTypes: TRegPinTypes =
(clsMajorType: @MEDIATYPE_Audio;
clsMinorType: @MEDIASUBTYPE_PCM);

SudPins: array[0..1] of TRegFilterPins =
((strName: 'Input';
bRendered: FALSE;
bOutput: FALSE;
bZero: FALSE;
bMany:
FALSE;
oFilter: nil;
strConnectsToPin: 'Output';
nMediaTypes: 1;
lpMediaType:
@SudPinTypes),
(strName: 'Output';
bRendered: FALSE;
bOutput: TRUE;
bZero: FALSE;
bMany:
FALSE;
oFilter: nil;
strConnectsToPin: 'Input';
nMediaTypes: 1;
lpMediaType:
@SudPinTypes));

type

TBalancerInputPin = class(TBCTransInPlaceInputPin)
public
constructor Create(ObjectName: string;
TransInPlaceFilter:
TBCTransInPlaceFilter;
out hr: HRESULT;
Name: WideString);
function CheckMediaType(mt: PAMMediaType): HRESULT;
override;
end;


TBalancerOutputPin = class(TBCTransInPlaceOutputPin)
public
constructor Create(ObjectName: string;
TransInPlaceFilter:
TBCTransInPlaceFilter;
out hr: HRESULT;
Name: WideString);
function CheckMediaType(mt: PAMMediaType): HRESULT;
override;
end;


var
InstanceCount: integer = 0;

type

TBalancerFilter = class(TBCTransInPlaceFilter, IBalancerChannel)
FThisInstance: integer;
FPreferred: TAMMediaType;
FBalancerLock: TBCCritSec;
FCurrentChannel: TAudioChannel;
public
function GetPin(n: integer): TBCBasePin;
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;
end;


TFilterGraph1 = class(TFilterGraph)
end;


TBalancer = class(TComponent, IFilter)
private
FFilterGraph: TFilterGraph1;
FBaseFilter: TBalancerFilter;
FFilter: IBaseFilter;
FAudioChannel: TAudioChannel;
function GetFilter: IBaseFilter;
function GetName: string;
procedure NotifyFilter(operation: TFilterOperation;
Param: integer = 0);
procedure SetFilterGraph(AFilterGraph: TFilterGraph1);
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: TFilterGraph1 read FFilterGraph write SetFilterGraph;
property AudioChannel: TAudioChannel read FAudioChannel write
SetAudioChannel;
end;


procedure Register;

implementation

function AudioChannelMix(PBuffer: PByte;
Size: Integer;
AudioChannel:
TAudioChannel;
AudioBits: Integer): HRESULT;
var
i: Integer;
begin

try
if AudioBits = 8 then

begin

case AudioChannel of
acLeft:
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;

acRight:
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;

end;

if AudioBits = 16 then

begin

case AudioChannel of
acLeft:
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;

acRight:
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;

end;

Result := S_OK;
except
Result := S_FALSE;
end;

end;


function TBalancerInputPin.CheckMediaType(mt: PAMMediaType):
HRESULT;
var
pmt: PAMMediaType;
begin

pmt := @TBalancerFilter(FTIPFilter).FPreferred;
if not TBCMediaType(pmt).IsValid then

begin

if TBalancerFilter(FTIPFilter).Output.IsConnected then

begin

Result :=
TBalancerFilter(FTIPFilter).Output.GetConnected.QueryAccept(mt^);
Exit;
end;

Result := S_OK;
Exit;
end
else
if TBCMediaType(pmt).Equal(mt) then

begin

Result := S_OK;
Exit;
end
else

Result := VFW_E_TYPE_NOT_ACCEPTED;
end;


constructor TBalancerInputPin.Create(ObjectName: string;
TransInPlaceFilter: TBCTransInPlaceFilter;
out hr: HRESULT;
Name: WideString);
begin

inherited Create(ObjectName, TransInPlaceFilter, hr, Name);
end;


function TBalancerOutputPin.CheckMediaType(mt: PAMMediaType):
HRESULT;
var
pmt: PAMMediaType;
begin

pmt := @TBalancerFilter(FTIPFilter).FPreferred;
if not TBCMediaType(pmt).IsValid then

begin

Result := inherited CheckMediaType(mt);
Exit;
end
else
if TBCMediaType(pmt).Equal(mt) then

begin

Result := S_OK;
Exit;
end
else

Result := VFW_E_TYPE_NOT_ACCEPTED;
end;


constructor TBalancerOutputPin.Create(ObjectName: string;
TransInPlaceFilter: TBCTransInPlaceFilter;
out hr: HRESULT;
Name: WideString);
begin

inherited Create(ObjectName, TransInPlaceFilter, hr, Name);
end;


function TBalancerFilter.CheckInputType(mtIn: PAMMediaType):
HRESULT;
begin

if not IsEqualGUID(mtIn^.formattype, FORMAT_WaveFormatEx) then

begin

Result := E_INVALIDARG;
Exit;
end;


if not IsEqualGUID(mtIn^.majortype, MEDIATYPE_Audio) then

begin

Result := E_INVALIDARG;
Exit;
end;


if not IsEqualGUID(mtIn^.subtype, MEDIASUBTYPE_PCM) then

begin

Result := E_INVALIDARG;
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;
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.GetPin(n: integer): TBCBasePin;
var
hr: HRESULT;
begin

if (Input = nil) or (Output = nil) then

begin

hr := S_OK;
Input := TBalancerInputPin.Create('Balancer input pin',
self, hr, 'Input');

if FAILED(hr) or (Input = nil) then

begin

if (Input <> nil) then

input.Free;
input := nil;
Result := nil;
Exit;
end;


Output := TBalancerOutputPin.Create('Balancer output pin',
self, hr,
'Output');

if FAILED(hr) or (Output = nil) then

begin

if (Input <> nil) then

input.Free;
if (Output <> nil) then

Output.Free;
Input := nil;
Output := nil;
Result := nil;
Exit;
end;

end;


case n of
0: Result := Input;
1: Result := Output;
else

Result := nil;
end;

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;
begin

try
PWaveFormat := FInput.CurrentMediaType.MediaType.pbFormat;

AudioChannel := FCurrentChannel;

Sample.GetPointer(PBuffer);
Size := Sample.GetActualDataLength;

AudioChannelMix(Pbuffer, Size, AudioChannel,
PWaveFormat.wBitsPerSample);
finally
Result := S_OK;
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: FFilter := FBaseFilter;
foRemoving: if FFilter <> nil then

FFilter.Stop;
foRemoved: FFilter := nil;
foRefresh: if assigned(FFilterGraph) then

begin

FFilterGraph.RemoveFilter(self);
FFilterGraph.InsertFilter(self);
end;

end;

end;


procedure TBalancer.SetFilterGraph(AFilterGraph: TFilterGraph1);
begin

if AFilterGraph = FFilterGraph then

exit;
if FFilterGraph <> nil then

FFilterGraph.RemoveFilter(self);
if AFilterGraph <> nil then

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);
var
hr: HRESULT;
begin

inherited Create(AOwner);
FBaseFilter := TBalancerFilter.Create(Name_Balancer, AOwner,
hr);
FAudioChannel := acStereo;
end;


destructor TBalancer.Destroy;
begin

FBaseFilter.Free;
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

result := FFilter.QueryInterface(IID, Obj);
end;


procedure TBalancer.SetAudioChannel(AAudioChannel: TAudioChannel);
begin

FAudioChannel := AAudioChannel;
FBaseFilter.SetAudioChannel(FAudioChannel);
end;


procedure Register;
begin

RegisterComponents('DSPack', [TBalancer]);
end;


end.
 
播放MPG文件时,不能切换声音
 
后退
顶部