Delphi - Get Wave amplitude

白昼怎懂夜的黑 提交于 2019-12-06 14:58:24

dont know if i understood corectly, if you mean how to get peak meter for default playback device you may try this:

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.

As far as I know what you are looking for is not possible directly.


Windows does not provide you information of the sound output of other programs. Neither as a direct input, nor as access to their voice mixer. The cause of this behavior is that such access would enable bypassing copyright protection. (You could record the wave output of the media player or media streaming programs.) Windows does not normally provide API s for copyright infringement. This time I will assume you want to perform something law-obedient (like a volume normalizing application) and I will share a solution to bypass this copyright logic, but this solution is not easy and requires extensive programming skills.

So the only way I'm aware of to perform such tasks is to create your own virtual audio device, then treat it as the default wave output device. It could record the received audio data while also channelling it to the audio device you normally use for wave-out. The drawback of this solution is that you have to write a sound card driver. AFAIK Delphi does not provide a way to write kernel mode drivers, so you will have to use C/C++. You also will have to use the WDK compiler.

Writing a driver is not easy. If you choose to do so, installing MS Visual Studio (express) would be a wise (but not necessary) choice. The WDK has plenty of example codes and knowledge base articles that will show you the way to perform this. A sound card driver for your purposes can be hacked together using the example codes in about 10-12 man-hours.

p.s.: Please don't forget to write error-prone code! Don't forget that kernel-mode software could not fail gracefully. In kernel mode an unhandled exception or buffer overrun could cause BSOD.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!