语音采集

语音采集

2023年7月29日发(作者:)

语音采集

由于所实现的方法与录音方法一致,因此不会着墨过多,如果你不能很好的理解,请先参考:C# 中利用 DirectSound 录音

与录音不同的是,录音我们需要建立一个WAVE文件来存储这些采集到的数据,而在语音聊天中,则不需要存储,当采集到一些数据后,就立刻发送出去,因此也不需要开辟很大的空间来存放PCM数据。

我们先来回顾下采集的基本步骤:

1. 设置PCM格式,设置相关的参数,如:采样频率、量化位数等。

2. 建立采集用的设备对象,建立采集用的缓冲区对象。

3. 设置缓冲区通知,设置通知被触发后的事件。通知是用于当缓冲区的读指针达到某预设位置时触发通知事件,提醒我们可以对某部分的数据进行传送了。

4. 开始采集声音。

5. 当通知被触发后,建立一个新的线程来处理数据传送的事件。(建立一个新的线程,就是为了防止采集过程被中断)。

///

/// 设置音频格式,如采样率等

///

/// 设置完成后的格式

private WaveFormat SetWaveFormat()

{

WaveFormat format = new WaveFormat();

Tag = ;//设置音频类型

sPerSecond = 11025;//采样率(单位:赫兹)典型值:11025、22050、44100Hz

rSample = 16;//采样位数

ls = 1;//声道

lign = (short)(ls * (rSample / 8));//单位采样点的字节数

eBytesPerSecond = lign * sPerSecond;

return format;

//按照以上采样规格,可知采样1秒钟的字节数为22050*2=44100B 约为 43K

}

///

/// 创建捕捉设备对象

///

/// 如果创建成功返回true

private bool CreateCaputerDevice()

{ //首先要玫举可用的捕捉设备

CaptureDevicesCollection capturedev = new CaptureDevicesCollection();

Guid devguid;

if ( > 0)

{

devguid = capturedev[0].DriverGuid;

}

else

{

("当前没有可用于音频捕捉的设备", "系统提示");

return false;

}

//利用设备GUID来建立一个捕捉设备对象

capture = new Capture(devguid);

return true;

}

///

/// 创建捕捉缓冲区对象

///

private void CreateCaptureBuffer()

{

//想要创建一个捕捉缓冲区必须要两个参数:缓冲区信息(描述这个缓冲区中的格式等),缓冲设备。

WaveFormat mWavFormat = SetWaveFormat();

CaptureBufferDescription bufferdescription = new CaptureBufferDescription();

= mWavFormat;//设置缓冲区要捕捉的数据格式

iNotifySize = eBytesPerSecond / iNotifyNum;//1秒的数据量/设置的通知数得到的每个通知大小小于0.2s的数据量,话音延迟小于200ms为优质话音

iBufferSize = iNotifyNum * iNotifySize;

Bytes = iBufferSize;

lEffects = true;

pped = true;

capturebuffer = new CaptureBuffer(bufferdescription, capture);//建立设备缓冲区对象

}

//设置通知

private void CreateNotification()

{ BufferPositionNotify[] bpn = new BufferPositionNotify[iNotifyNum];//设置缓冲区通知个数

//设置通知事件

notifyEvent = new AutoResetEvent(false);

notifyThread = new Thread(RecoData);//通知触发事件

ground = true;

();

for (int i = 0; i < iNotifyNum; i++)

{

bpn[i].Offset = iNotifySize + i * iNotifySize - 1;//设置具体每个的位置

bpn[i].EventNotifyHandle = ;

}

myNotify = new Notify(capturebuffer);

ificationPositions(bpn);

}

//线程中的事件

private void RecoData()

{

while (true)

{

// 等待缓冲区的通知消息

e(te, true);

// 录制数据

RecordCapturedData(Client,epServer);

}

}

//真正转移数据的事件,其实就是把数据传送到网络上去。

private void RecordCapturedData(Socket Client,EndPoint epServer )

{

byte[] capturedata = null;

int readpos = 0, capturepos = 0, locksize = 0;

rentPosition(out capturepos, out readpos);

locksize = readpos - iBufferOffset;//这个大小就是我们可以安全读取的大小

if (locksize == 0)

{

return;

}

if (locksize < 0)

{//因为我们是循环的使用缓冲区,所以有一种情况下为负:当文以载读指针回到第一个通知点,而Ibuffeoffset还在最后一个通知处

locksize += iBufferSize;

}

capturedata = (byte[])(iBufferOffset, typeof(byte), iteCursor, locksize);

//capturedata = (capturedata);//语音编码

try

{

(capturedata, epServer);//传送语音

}

catch

{

throw new Exception();

}

iBufferOffset += ;

iBufferOffset %= iBufferSize;//取模是因为缓冲区是循环的。

}

上述代码可以很好的采集到声音数据,几乎与原始声音一致。如果你已经可以实现录音,那么以上对你来说应该并不陌生。

发布者:admin,转转请注明出处:http://www.yc00.com/news/1690643542a384537.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信