C#基于NAudio的声音识别(一)——录制与切割
準備做個非特定的聲音識別程序,卡在錄音和切割一小段時間,C#下基于DirectX的聲音處理真的超級麻煩,后來找到了NAudio,非常好用,安利給大家,順帶把幾個小坑稍微描述下,希望幫到類似需求的人。
項目下載:
NAudio官方地址:http://naudio.codeplex.com/
GitHub地址:https://github.com/naudio/NAudio
下載后是完整的工程文件,直接運行應該沒問題,官方的demo都寫成自定義控件的形式,界面寫的不錯,我也就懶得慢慢摘出來了,照貓畫虎的去掉了demo里面選擇控件的部分,直接顯示在tabControl里,效果如下圖。
demos是項目下所有自定控件的集合,我這里刪的大部分,只留下了一個錄音和一個播放,所以只有last和first。
至此,錄音和播放功能完全實現了,而后我的工作是希望將聲音切割,判斷依據是dB(分貝),
就是上圖中垂直的綠色條條和黃色圖中的波形,達到某個值就切割出來,靜音部分不要(做監聽咯,懂的,沒聲音就pass掉)
void OnPostVolumeMeter(object sender, StreamVolumeEventArgs e){// we know it is stereovolumeMeter1.Amplitude = e.MaxSampleValues[0];volumeMeter2.Amplitude = e.MaxSampleValues[1];if (e.MaxSampleValues[0] > 0.01 && StartOREnd == false){StartOREnd = true;DateTime starttime = DateTime.ParseExact(this.labelCurrentTime.Text,"mm:ss:fff",null);int StartPoint = starttime.Minute * 60 * 1000 + starttime.Second * 1000 + starttime.Millisecond;this.richTextBox1.Text += "\r\n開始:" + StartPoint.ToString();CutInfo.Add(StartPoint);}if (e.MaxSampleValues[0] < 0.01 && StartOREnd == true){StartOREnd = false;DateTime endtime = DateTime.ParseExact(this.labelCurrentTime.Text, "mm:ss:fff", null);int EndPoint = endtime.Minute * 60 * 1000 + endtime.Second * 1000 + endtime.Millisecond;this.richTextBox1.Text += "\r\n結束:" + EndPoint.ToString();CutInfo.Add(EndPoint);}}我定義了一個CutInfo的list,坦白說這里的e.MaxSampleValuesde的值代表什么意思我沒搞明白,但是有聲音數值就大,沒聲音數值就小,所以我這就當時dB來用了,按照閾值定義起點和終點,用于后期的切割。
切割分兩部分,mp3和wav,其中mp3直接就能按照時間進行切割,wav得換算為字節長度稍微麻煩一點點。
public static void TrimMp3File(string inputPath, string outputPath, TimeSpan? begin, TimeSpan? end){if (begin.HasValue && end.HasValue && begin > end)throw new ArgumentOutOfRangeException("end", "end should be greater than begin");using (var reader = new Mp3FileReader(inputPath))using (var writer = File.Create(outputPath)){Mp3Frame frame;while ((frame = reader.ReadNextFrame()) != null)if (reader.CurrentTime >= begin || !begin.HasValue){if (reader.CurrentTime <= end || !end.HasValue)writer.Write(frame.RawData, 0, frame.RawData.Length);else break;}}}public static void TrimWavFile(string inPath, string outPath, TimeSpan cutFromStart, TimeSpan cutFromEnd){using (WaveFileReader reader = new WaveFileReader(inPath)){using (WaveFileWriter writer = new WaveFileWriter(outPath, reader.WaveFormat)){int bytesPerMillisecond = reader.WaveFormat.AverageBytesPerSecond/1000;int startPos = (int)cutFromStart.TotalMilliseconds * bytesPerMillisecond;startPos = startPos - startPos % reader.WaveFormat.BlockAlign;int endPos = (int)cutFromEnd.TotalMilliseconds * bytesPerMillisecond;endPos = endPos - endPos % reader.WaveFormat.BlockAlign;TrimWavFile(reader, writer, startPos, endPos);}}}private static void TrimWavFile(WaveFileReader reader, WaveFileWriter writer, int startPos, int endPos){reader.Position = startPos;byte[] buffer = new byte[1024];while (reader.Position < endPos){int bytesRequired = (int)(endPos - reader.Position);if (bytesRequired > 0){int bytesToRead = Math.Min(bytesRequired, buffer.Length);int bytesRead = reader.Read(buffer, 0, bytesToRead);if (bytesRead > 0){writer.WriteData(buffer, 0, bytesRead);}}}}我每段測試音頻都念了五個音,測試MP3和WAV都成功,效果如下圖:
黃色波形圖前5個波是一段,后面的是切割后單獨放的5個。切割的目的是識別,下一篇寫識別。
新開博客,目的為學習交流,本人QQ:273651820。
總結
以上是生活随笔為你收集整理的C#基于NAudio的声音识别(一)——录制与切割的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 北理工计算机学院沈建斌,沈建冰_北京理工
- 下一篇: C#基于NAudio的声音识别(二)——