delphiwaveout

Delphi - Get Wave amplitude


I need to make Delphi library / component that takes the currently playing sound ( it does not play my apps , just the general sound of what goes on loud-speakers ) returns me the data ( the amplitude of the left and right channels ) . Currently I have it processed by scanning from the microphone. He was looking for and I tried different VU meters that are on the net ( Torry ... ) , but they are not compatible with Win7 and higher. Anyone know of a solution? Thanks


Solution

  • 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.