如何在任务管理器上可视化声音

具体效果可以先观看一下视频 av37598946

源码:https://github.com/ibukisaar/Taskmgr_x_Spectrum
注意事项:只在Win10 x64下运行过,Visual Studio版本至少2017。程序本身需要管理员权限启动,如需调试Visual Studio也要管理员权限启动。任务管理器上的CPU监视窗口数量如果不是4,可能要对代码作出修改。

原理
先用C++写个dll用于注入拦截WM_PAINT消息,不然CPU监视窗口会有间歇性闪烁。注入不是必须的,这步可以省略,如果可以容忍闪烁发生的话。
用GetWindowLongPtr拿到旧的WndProc,放到map里,再用SetWindowLongPtr为每个子窗口设定新的WndProc。

接下来全都是C#代码。
使用查找窗体相关的WinAPI拿到目标窗体句柄,并获得子窗体以及它们的层级关系,然后搜索CPU使用率监视窗口。如果你的情况不太一样,那么需要用spy++重新进行分析。



拿到各个子窗口后,把句柄传进WindowGraphics构造函数并实例化,这是一个可以跨进程窗体绘制的类,绘图方式使用WPF中的DrawingContext。调用WindowGraphics中的OpenDraw()方法,并返回一个IGraphics接口对象,通过该对象开始绘制,最后调用Dispose()方法将绘制内容提交到目标窗体。其WinAPI原理是:创建内存DC,用SetDIBits将绘制内容拷贝到内存DC,再用BitBlt将内存DC内容拷贝到目标DC。

捕获声音用的是第三方库NAudio中的WasapiLoopbackCapture,这种录制方式不会受到系统音量的影响(即使系统音量是0依然可以录制)。如果你想显示麦克风的频谱,可以将这个类改成WasapiCapture。
FFT运算使用了FFTW库,据说是世界上最快的FFT库。但是FFT后的数据并不能直接拿来绘制,还要自己处理一下。整个处理过程:复数结果取模 → 提取感兴趣频率区域 → 频率以对数刻度方式显示(依照人耳听觉)→ 振幅以分贝刻度显示(依照人耳听觉)。在进行FFT之前,最好进行加窗处理,减少频谱能量泄漏,所谓的加窗处理就是声波和窗口直接对应相乘。




暂时说到这,如果有什么问题我会在评论区补充。