我需要让Delphi库/组件接收当前播放的声音(它不播放我的应用程序,只播放扬声器上的一般声音),并向我返回数据(左右声道的振幅)。目前,我通过麦克风扫描来处理它。他一直在寻找,我尝试了网上不同的VU仪表(Torry…),但它们与Win7及更高版本不兼容。有人知道解决方案吗?感谢
不知道我是否理解得很清楚,如果你是说如何为默认播放设备获取峰值测量仪,你可以试试这个:
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.
据我所知,您不可能直接查找
Windows不会为您提供其他程序的声音输出信息既不是作为直接输入,也不是作为对其混音器的访问。这种行为的原因是这样的访问将绕过版权保护。(您可以记录媒体播放器或媒体流程序的波形输出。)Windows通常不为版权侵权提供APIs。这一次我假设你想执行一些遵守法律的(比如卷规范化应用程序),我将共享一个绕过版权逻辑的解决方案,但这个解决方案并不容易,需要广泛的编程技能。
因此,我所知道的执行此类任务的唯一方法是创建自己的虚拟音频设备,然后将其视为默认的波形输出设备。它可以记录接收到的音频数据,同时也可以将其引导到您通常用于输出的音频设备。此解决方案的缺点是必须编写声卡驱动程序AFAIKDelphi不提供编写内核模式驱动程序的方法,因此您必须使用C/C++。您还必须使用WDK编译器。
编写驱动程序并不容易如果您选择这样做,安装MS Visual Studio(express)将是明智的(但不是必要的)选择。WDK有大量的示例代码和知识库文章,将向您展示执行此操作的方法。一个用于您目的的声卡驱动程序可以在大约10-12个工时内使用示例代码进行黑客攻击。
p.s.:请不要忘记编写易出错的代码!别忘了,内核模式的软件不可能优雅地失败。在内核模式下,未处理的异常或缓冲区溢出可能导致BSOD。