⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 balancer.pas

📁 TBalncer 音频声道均衡控件 基于 DSPack 的音频均衡控件,可以设置左右声道. 因为原版 DSPack 里是没有对左右声道作选择的,要选择左右声道只能通过一边的喇叭出声,另一边没声.
💻 PAS
📖 第 1 页 / 共 2 页
字号:
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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -