該控制項是在Jacob Klint的作品之上精簡而來。特此鳴謝。
現在在開發一個語音錄製軟體。需要實際監控麥克風的輸入音量並顯示。類似QQ的語音功能。
可用的技術很多,Windows media encoder、microsoft expression encoder、microsoft SAPI以及microsoft directx均可以實現上述功能。考慮到XP、Vista和win7的相容,最終採用directx作為技術方案。
先讓我們來看一下成品的效果:
思路是這樣的:
捕捉聲音,然後啟動線程,每隔一段時間從緩衝中讀資料,求出該組資料的電平值,更新ProgressBar控制項。
首先我們需要從音效卡中捕捉聲音(audio capture)。使用directx捕捉聲音的具體步驟如下: C#代碼 // 建立 capture 對象 Capture cap = new Capture(audioDevices[deviceIndex].DriverGuid); // 建立對 capture buffer對象的描述 CaptureBufferDescription desc = new CaptureBufferDescription(); WaveFormat wf = new WaveFormat(); wf.BitsPerSample = 16; wf.SamplesPerSecond = 16000; // 單聲道 wf.Channels = 1; // 資料的最小的原子單元 wf.BlockAlign = (short)(wf.Channels * wf.BitsPerSample / 8); wf.AverageBytesPerSecond = wf.BlockAlign * wf.SamplesPerSecond; // 未經壓縮的PCM wf.FormatTag = WaveFormatTag.Pcm; desc.Format = wf; desc.BufferBytes = SAMPLES * wf.BlockAlign; // 建立 capturebuffer對象 buffer = new Microsoft.DirectX.DirectSound.CaptureBuffer(desc, cap); // 捕捉資料至緩衝 buffer.Start(true);
然後,我們需要啟動一個線程,來監控音量並修改UI控制項。 C#代碼 liveVolumeThread = new Thread(new ThreadStart(updateProgress)); liveVolumeThread.Priority = ThreadPriority.Lowest; liveVolumeThread.Start();
下面讓我們來實現updateProgress這個方法。第一步,讀入聲音資料,寫入一個數組。 C#代碼 Array samples = buffer.Read(0, typeof(Int16), LockFlag.FromWriteCursor, SAMPLE_FORMAT_ARRAY);
第二步,求出此組資料的電平值 C#代碼 int goal = 0; for (int i = 0; i < SAMPLES; i++) { goal += (Int16)samples.GetValue(i, 0, 0); } goal = (int)Math.Abs(goal / SAMPLES); 最後一步,設定progressbar的值,讓線程睡眠一個固定的值。 C#代碼 progressBar.Value = goal; Thread.Sleep(tempFrameDelay);
該控制項實現了usercontrol介面,故可以在介面設計器中直接拖放。
調用Start()方法開啟捕捉;
調用Stop()方法關閉捕捉;
更多屬性請查看屬性面板。
運行範例程式碼的時候,如果提示“檢測到loaderlocker”這樣的異常,處理方法為:
調試-異常-managed debugging assistants-將loaderlocker的勾反選。(如圖)
VolumeMeter.zip (189 KB) 下載次數: 711 查看圖片附件
from:http://fantasticinblur.iteye.com/blog/678527