using NAudio.Wave;
using System;
using System.Collections.Generic;
namespace WinFromBaidu
{
class NAudioRecorder
{
#region var
/// <summary>
/// 录音机对象
/// </summary>
public WaveIn waveSource = null;
/// <summary>
/// 录音写入磁盘记录者 用于截取声音测试
/// </summary>
public WaveFileWriter waveFile = null;
/// <summary>
/// 录音保存格式
/// </summary>
private string fileName = string.Empty;
/// <summary>
/// 委托声音触发时间
/// </summary>
public Action<byte[]> ReciveMaxData;
/// <summary>
/// 缓存截取声音片段
/// </summary>
private List<byte> CacheBuffer = new List<byte>();
/// <summary>
/// 记录有人说话时间
/// </summary>
private DateTime BeginTime = DateTime.Now;
/// <summary>
/// 是否有人说话标志
/// </summary>
private bool IsSpeeak = false;
/// <summary>
/// 声音响度标准
/// </summary>
public float LoudnessStant = 0.08F;
#endregion
/// <summary>
/// 开始录音方法
/// </summary>
public void StartRec()
{
waveSource = new WaveIn();
waveSource.WaveFormat = new WaveFormat(16000, 16, 1); // 16bit,16KHz,Mono的录音格式
waveSource.DataAvailable += new EventHandler<WaveInEventArgs>(waveSource_DataAvailable);
waveSource.RecordingStopped += new EventHandler<StoppedEventArgs>(waveSource_RecordingStopped);
waveFile = new WaveFileWriter(fileName, waveSource.WaveFormat);
waveSource.StartRecording();
}
/// <summary>
/// 停止录音
/// </summary>
public void StopRec()
{
waveSource.StopRecording();
// Close Wave(Not needed under synchronous situation)
if (waveSource != null)
{
waveSource.Dispose();
waveSource = null;
}
if (waveFile != null)
{
waveFile.Dispose();
waveFile = null;
}
}
/// <summary>
/// 录音结束后保存的文件路径
/// </summary>
/// <param name="fileName">保存wav文件的路径名</param>
public void SetFileName(string fileName)
{
this.fileName = fileName;
}
/// <summary>
/// 开始录音回调函数
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void waveSource_DataAvailable(object sender, WaveInEventArgs e)
{
if (waveFile != null)
{
//waveFile.Write(e.Buffer, 0, e.BytesRecorded);
//waveFile.Flush();
}
AnalyzeVoice(e.Buffer);
}
/// <summary>
/// 录音结束回调函数
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void waveSource_RecordingStopped(object sender, StoppedEventArgs e)
{
if (waveSource != null)
{
waveSource.Dispose();
waveSource = null;
}
if (waveFile != null)
{
waveFile.Dispose();
waveFile = null;
}
}
/// <summary>
/// 语音分析
/// </summary>
/// <param name="buf"></param>
private void AnalyzeVoice(byte[] buf)
{
float max = LoudnessStant;
int maxNumber = 0;
// interpret as 16 bit audio
for (int index = 0; index < buf.Length; index += 2)
{
short sample = (short)((buf[index + 1] << 8) |
buf[index + 0]);
// to floating point
var sample32 = sample / 32768f;
// absolute value
if (sample32 < 0) sample32 = -sample32;
// is this the max value?
if (sample32 > max)
{
max = sample32;
maxNumber++;
}
}
if (max != LoudnessStant)
{
CacheBuffer.AddRange(buf);
IsSpeeak = true;
BeginTime = DateTime.Now;
}
else
{
if (IsSpeeak)
{
if ((DateTime.Now - BeginTime).TotalSeconds < 2)
{
CacheBuffer.AddRange(buf);
}
else
{
CacheBuffer.AddRange(buf);
//waveFile.Write(CacheBuffer.ToArray(), 0, CacheBuffer.Count);
//waveFile.Flush();
//回调声音触发方法
ReciveMaxData(CacheBuffer.ToArray());
CacheBuffer.Clear();
IsSpeeak = false;
}
}
else
{
if (CacheBuffer.Count > 3200 * 6)
{
CacheBuffer.RemoveRange(0, 3200);
}
CacheBuffer.AddRange(buf);
}
}
}
}
}