2

現在再生中のサウンドを取得する Delphi ライブラリ/コンポーネントを作成する必要があります (アプリは再生されず、ラウドスピーカーで発生する一般的なサウンドのみ) がデータ (左右のチャンネルの振幅) を返します。現在、マイクからスキャンして処理しています。彼は探していて、ネット上にあるさまざまな VU メーターを試してみました (Torry ...) が、Win7 以降とは互換性がありません。解決策を知っている人はいますか?ありがとう

4

2 に答える 2

4

私が正しく理解しているかどうかわかりませんが、デフォルトの再生デバイスのピークメーターを取得する方法を意味している場合は、これを試してみてください:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Winapi.ActiveX, System.Win.ComObj, MMSystem,
  Vcl.ComCtrls, Vcl.ExtCtrls;

type
  EDATAFLOW = TOleEnum;
  EROLE = TOleEnum;

  IMMDevice = interface(IUnknown)
    ['{D666063F-1587-4E43-81F1-B948E807363F}']
    function Activate(const iid: TGUID; const dwClsCtx: UINT; const pActivationParams: PPropVariant; out ppInterface: IUnknown)
      : HRESULT; stdcall;
  end;

  IMMDeviceCollection = interface(IUnknown)
    ['{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}']
  end;

  IMMDeviceEnumerator = interface(IUnknown)
    ['{A95664D2-9614-4F35-A746-DE8DB63617E6}']
    function EnumAudioEndpoints(const dataFlow: EDATAFLOW; const dwStateMask: DWORD; out ppDevices: IMMDeviceCollection): HRESULT; stdcall;
    function GetDefaultAudioEndpoint(const dataFlow: EDATAFLOW; const role: EROLE; out ppEndpoint: IMMDevice): HRESULT; stdcall;
  end;

  IAudioMeterInformation = interface(IUnknown)
    ['{C02216F6-8C67-4B5B-9D00-D008E73E0064}']
    function GetPeakValue(out pfPeak: Single): HRESULT; stdcall;
    function GetMeteringChannelCount(out pnChannelCount: UINT): HRESULT; stdcall;
    function GetChannelsPeakValues(u32ChannelCount: UINT; out afPeakValues: pSingle): HRESULT; stdcall;
    function QueryHardwareSupport(out pdwHardwareSupportMask: UINT): HRESULT; stdcall;
  end;

  TForm1 = class(TForm)
    ProgressBar1: TProgressBar;
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

const
  IID_IMMDeviceEnumerator: TGUID = '{A95664D2-9614-4F35-A746-DE8DB63617E6}';
  CLASS_IMMDeviceEnumerator: TGUID = '{BCDE0395-E52F-467C-8E3D-C4579291692E}';
  IID_IAudioMeterInformation: TGUID = '{C02216F6-8C67-4B5B-9D00-D008E73E0064}';
  eRender = $00000000;
  eConsole = $00000000;

var
  Form1: TForm1;
  peak: IAudioMeterInformation = nil;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);

var
  device: IMMDevice;
  deviceEnumerator: IMMDeviceEnumerator;
begin
  Timer1.Enabled := False;
  ProgressBar1.Max := 65535; 
  CoCreateInstance(CLASS_IMMDeviceEnumerator, nil, CLSCTX_ALL, IID_IMMDeviceEnumerator, deviceEnumerator);
  deviceEnumerator.GetDefaultAudioEndpoint(eRender, eConsole, device);
  device.Activate(IID_IAudioMeterInformation, CLSCTX_ALL, nil, IUnknown(peak));
  Timer1.Enabled := true;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  Temp: Single;
begin
  peak.GetPeakValue(Temp);
  ProgressBar1.position := Round(Temp * 65535);
end;

end.
于 2014-09-22T22:48:04.220 に答える
3

私の知る限り、あなたが探しているものは直接不可能です。


Windows は、他のプログラムのサウンド出力に関する情報を提供しません。直接入力として、ボイス ミキサーへのアクセスとしても使用できません。この動作の原因は、そのようなアクセスによって著作権保護を迂回できるようになることです。(メディア プレーヤーまたはメディア ストリーミング プログラムの wave 出力を記録することができます。) Windows は通常、著作権侵害のためのAPIを提供しません。今回は、法律に準拠した何か(ボリューム正規化アプリケーションなど)を実行したいと想定し、この著作権ロジックをバイパスするソリューション共有しますが、このソリューションは簡単ではなく、広範なプログラミング スキルが必要です。

したがって、このようなタスクを実行する唯一の方法は、独自の仮想オーディオ デバイスを作成し、それをデフォルトのウェーブ出力デバイスとして扱うことです。受信したオーディオ データを録音しながら、通常ウェーブ出力に使用するオーディオ デバイスに転送することもできます。このソリューションの欠点は、サウンド カード ドライバを作成する必要があることです。の知る限り、 Delphiはカーネル モード ドライバーを作成する方法を提供していないため、 C/C++を使用する必要があります。WDK コンパイラも使用する必要があります。

ドライバーを書くのは簡単ではありません。そうすることを選択した場合、MS Visual Studio (express)をインストールする のが賢明な選択です (必須ではありません)。WDKには、これを実行する方法を示す多数のサンプル コードとナレッジ ベース記事があります。サンプル コードを使用して、約 10 ~ 12 工数で目的のサウンド カード ドライバーを一緒にハッキングできます。

ps:エラーが発生しやすいコードを書くことを忘れないでください! カーネル モードのソフトウェアは正常に動作しなくなる可能性があることを忘れないでください。カーネル モードでは、未処理の例外またはバッファ オーバーランによりBSODが発生する可能性がありました。

于 2014-09-22T09:18:00.640 に答える