如何在任務(wù)管理器上可視化聲音

具體效果可以先觀看一下視頻?av37598946

源碼:https://github.com/ibukisaar/Taskmgr_x_Spectrum
注意事項(xiàng):只在Win10 x64下運(yùn)行過(guò),Visual?Studio版本至少2017。程序本身需要管理員權(quán)限啟動(dòng),如需調(diào)試Visual?Studio也要管理員權(quán)限啟動(dòng)。任務(wù)管理器上的CPU監(jiān)視窗口數(shù)量如果不是4,可能要對(duì)代碼作出修改。

原理
先用C++寫(xiě)個(gè)dll用于注入攔截WM_PAINT消息,不然CPU監(jiān)視窗口會(huì)有間歇性閃爍。注入不是必須的,這步可以省略,如果可以容忍閃爍發(fā)生的話(huà)。
用GetWindowLongPtr拿到舊的WndProc,放到map里,再用SetWindowLongPtr為每個(gè)子窗口設(shè)定新的WndProc。

接下來(lái)全都是C#代碼。
使用查找窗體相關(guān)的WinAPI拿到目標(biāo)窗體句柄,并獲得子窗體以及它們的層級(jí)關(guān)系,然后搜索CPU使用率監(jiān)視窗口。如果你的情況不太一樣,那么需要用spy++重新進(jìn)行分析。



拿到各個(gè)子窗口后,把句柄傳進(jìn)WindowGraphics構(gòu)造函數(shù)并實(shí)例化,這是一個(gè)可以跨進(jìn)程窗體繪制的類(lèi),繪圖方式使用WPF中的DrawingContext。調(diào)用WindowGraphics中的OpenDraw()方法,并返回一個(gè)IGraphics接口對(duì)象,通過(guò)該對(duì)象開(kāi)始繪制,最后調(diào)用Dispose()方法將繪制內(nèi)容提交到目標(biāo)窗體。其WinAPI原理是:創(chuàng)建內(nèi)存DC,用SetDIBits將繪制內(nèi)容拷貝到內(nèi)存DC,再用BitBlt將內(nèi)存DC內(nèi)容拷貝到目標(biāo)DC。

捕獲聲音用的是第三方庫(kù)NAudio中的WasapiLoopbackCapture,這種錄制方式不會(huì)受到系統(tǒng)音量的影響(即使系統(tǒng)音量是0依然可以錄制)。如果你想顯示麥克風(fēng)的頻譜,可以將這個(gè)類(lèi)改成WasapiCapture。
FFT運(yùn)算使用了FFTW庫(kù),據(jù)說(shuō)是世界上最快的FFT庫(kù)。但是FFT后的數(shù)據(jù)并不能直接拿來(lái)繪制,還要自己處理一下。整個(gè)處理過(guò)程:復(fù)數(shù)結(jié)果取模?→?提取感興趣頻率區(qū)域 → 頻率以對(duì)數(shù)刻度方式顯示(依照人耳聽(tīng)覺(jué))→ 振幅以分貝刻度顯示(依照人耳聽(tīng)覺(jué))。在進(jìn)行FFT之前,最好進(jìn)行加窗處理,減少頻譜能量泄漏,所謂的加窗處理就是聲波和窗口直接對(duì)應(yīng)相乘。




暫時(shí)說(shuō)到這,如果有什么問(wèn)題我會(huì)在評(píng)論區(qū)補(bǔ)充。