您的位置:首页 > 编程语言 > C#

Kinect for windows 开发入门 十:语音数据的获取和使用

2013-09-22 17:40 232 查看
背景知识

KinectAudioSource:KinectAudioSource类的主要作用是从麦克风阵列中提取原始的或者经过处理的音频流。音频流可能会经过一系列的算法来处理以提高音频质量,这些处理包括:降噪、自动增益控制和回声消除。KinectAudioSource能够进行一些配置使得Kinect麦克风阵列可以以不同的模式进行工作。也能够用来探测从那个方向来的哪种音频信息最先达到麦克风以及用来强制麦克风阵列接受指定方向的音频信息。

一些语音处理的概念:

回声消除(acoustic echo cancellation, AEC)
当用户的声音从麦克风返回时,就会产生回声。最简单的例子就是用户在打电话时能够听到自己的声音,这些声音有一些延迟,会在对方那里重复一段时间。回声消除通过提取发声者的声音模式,然后根据这一模式从麦克风接收到的音频中挑选出特定的音频来消除回声。

回声抑制(acoustic echo suppression, AES)
它是指通过一系列的算法来进一步消除AEC处理后所遗留的回声。

自动增益控制(acoustic gain control, AGS)
它涉及到一些算法用来使用户的声音的振幅与时间保持一致。例如当用户靠近或者或远离麦克风时,声音会出现变得响亮或更柔和,AGC通过算法使得这一过程变得更加明显。

波束成形(beamforming)
指的是模拟定向麦克风的算法技术。和只有一个麦克风不同,波速成形技术用于麦克风阵列中
(如Kinect
传感器上的麦克风阵列)使得麦克风阵列产生和使用多个固定麦克风的效果相同。

中心削波(center clipping)
用来移除在单向传输中经AEC处理后残留的小的回声。

帧尺寸(Frame Size) AEC算法处理PCM音频样本是是一帧一帧处理的。帧尺寸是样本中音频帧的大小。

获取增益边界(Gain Bounding)
该技术确保麦克风有正确的增益级别。如果增益过高,获取到的信号可能过于饱和,会被剪切掉。这种剪切有非线性的效果,会使得AEC算法失败。如果增益过低,信噪比会比较低,也会使得AEC算法失败或者执行的不好。

噪声填充(Noise Filling)
向中心削波移除了残留的回波信号后的部分信号中添加少量的噪音。和留下空白的沉默信号相比,这能够获得更好的用户体验。

噪声抑制 (NS)
用于从麦克风接收到的音频信号中剔除非言语声音。通过删除背景噪音,实际讲话者的声音能够被麦克风更清楚更明确的捕获到。

Optibeam Kinect传感器从四个麦克风中能够获得11个波束。
这11个波束是逻辑结构,而四个通道是物理结构。Optibeam是一种系统模式用来进行波束成形。

信噪比(Signal-to-Noise Ratio,SNR)
信号噪声比用来度量语音信号和总体背景噪声的比例,信噪比越高越好。

单通道(Single Channel) Kinect传感器有四个麦克风,因此支持4个通道,单通道是一种系统模式用来关闭波束成形。

KinectAudioSource类的一些常用属性



语音识别:
语音识别可以分为两类:对特定命令的识别(recognition of command)和对自由形式的语音的识别(recognition
of free-form dictation)。

自由形式的语音识别需要训练软件来识别特定的声音以提高识别精度。一般做法是让讲话人大声的朗读一系列的语料来使得软件能够识别讲话人声音的特征模式,然后根据这一特征模式来进行识别。

而命令识别(Command recognition)则应用了不同的策略来提高识别精度。和必须识别说话人声音不同,命令识别限制了说话人所讲的词汇的范围。基于这一有限的范围,命令识别可以不需要熟悉讲话人的语音模式就可以推断出说话人想要说的内容。

语音识别关键类:SpeechRecognitionEngine类是语音识别的核心,它负责从Kinect传感器获取处理后的音频数据流,然后分析和解译这些数据流,然后匹配出最合适的语音命令。引擎给基本发声单元一定的权重,如果判断出发声包含特定待识别的命令,就通过事件进行进一步处理,如果不包含,直接丢掉这部分音频数据流。

SpeechRecognitionEngine从一个特定的称之为语法(grammars)的对象中进行查找。Grammar对象由一系列的单个单词或者词语组成。如果我们不关心短语的部分内容,可以使用语法对象中的通配符。选择类(Choices)是通配符类(Wildcard)的一种,它可以包含多个值。

 

代码示例

开启语音流识别:

添加命令识别时的事件绑定和无命令识别时的时间绑定。在启动时定义语音格式,并设置匹配方式。

               speechEngine.SpeechRecognized += SpeechRecognized;

               speechEngine.SpeechRecognitionRejected += SpeechRejected;

               speechEngine.SetInputToAudioStream(

                   kinectSensor.AudioSource.Start(),
new
SpeechAudioFormatInfo(EncodingFormat.Pcm,
16000, 16, 1, 32000, 2, null));

               
speechEngine.RecognizeAsync(RecognizeMode.Multiple);

语法定义示例:

一个tag可以对应多个语音命令。

<grammar
version="1.0"
xml:lang="en-US"
root="rootRule"
tag-format="semantics/1.0-literals"
xmlns="http://www.w3.org/2001/06/grammar">

 
<rule
id="rootRule">

   
<one-of>

     
<item>

       
<tag>PLAY</tag>

       
<one-of>

         
<item>
play </item>

       
</one-of>

     
</item>

     
<item>

       
<tag>PAUSE</tag>

       
<one-of>

         
<item>
pause </item>

         
<item>
stop </item>

       
</one-of>

     
</item>

   
</one-of>

 
</rule>

</grammar>

导入语法定义到语音识别引擎:

添加resource,将上面定义的语法xml文件添加到resource中(示例中命名为Grammar)

               
//Create a grammar from grammar definition XML file.

               
using (var
memoryStream = new
MemoryStream(Encoding.ASCII.GetBytes(Properties.Resources.Grammar)))

               
{

                   
var g =
new
Grammar(memoryStream);

                   speechEngine.LoadGrammar(g);

               
}

语音识别事件

语音识别事件对象中,直接封装了识别后的命令(即语法定义正宗的Tag)和匹配度,时间处理就是根据识别出来的命令做相应的操作。

       
///
<summary>

       
/// Handler for recognizedspeech events.

       
///
</summary>

       
///
<param name="sender">object sending the event.</param>

       
///
<param name="e">event arguments.</param>

       
private
void SpeechRecognized(object
sender, SpeechRecognizedEventArgse)

       
{

           
// Speech utterance confidence below which we treat speechas if it hadn't been heard

           
const
double ConfidenceThreshold= 0.3;

 

           
// Number of degrees in a right angle.

           
const
int DegreesInRightAngle = 90;

 

           
// Number of pixels turtle should move forwards orbackwards each time.

           
const
int DisplacementAmount = 60;

 

           
if (e.Result.Confidence >=ConfidenceThreshold)

           
{

               
switch(e.Result.Semantics.Value.ToString())

               
{

                   
case
"PLAY":

                       lbWords.Content =
"Play";

                       break;

 

                   
case
"PAUSE":

                       lbWords.Content =
"Pause";

                       break;

               
}

           
}

       
}

效果演示

没什么好演示的,就是根据你说的单词。如果是play就显示Play,如果是pause或者stop就显示Pause

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Kinect Kinectforwindows c#