(转载请注明出处)
使用SDK: Kinect for Windows SDK v2.0 public preview
这次探讨语音识别。之前都是一节写两部分,这次反过来了,分为上下两部分。
语音识别算是使用官方SDK的一个理由吧,不然都用OpenNI了,毕竟微软在SR(语音识别)上的成果还是不错的。
首先,您需要下载语音识别的SDK、运行时库以及您想支持的运行时语言,运行时语言里面SR代表语音识别,
TTS代表文本转语音,根据您的选择吧。本人选择下载了美国英语与大陆汉语。当然,坑爹的微软还专门为Kinect
准备Kinect运行时语言,支持语言较少,不过连日语都支持,竟然不支持汉语
或许仅仅是日语发音简单吧。
如果您和本人一样使用的是VS Express,那么请再下载WDK7.1,这个语音库需要一点点ATL支
持(貌似就COM智能指针),坑爹的微软在Express里面没有ATL库,为了获取合法ATL库需要下载这个
WDK7.1,里面有能合法使用的ALT库。我直接安装到C盘,请在项目里面包含这三个库的目录
语音平台、WDK、Kinect
有您自己的需要请自行包含其他库,最好将语音平台放到第一位。
目前语音识别应该只能识别PCM编码,处理后的数据是浮点编码,我们不能直接使用SDK默认提供的IStream。
是的,基于COM组件的通用性,我们只需继承IStream实现一个Stream类即可完成音频流的处理。
这个类主要实现Read方法即可,Seek方法在SR中也算比较重要不过Kinect还不支持,这个方法直接返回S_OK即可
实现这个类有两种办法,一种是基于前一节说的音频帧。自己用一个比较大的缓冲区(最好设计上是循环的),
获取音频帧再将数据写在里面,Read时将数据写入即可,比较麻烦。还有一个就是SDK提供例子里面使用的:
傀儡战术。
获取SDK提供的默认的IStream,Read的时候Read这个傀儡即可,数据获取完毕后进行转换即可,代码如下:
// IStream Read方法的实现
STDMETHODIMP KinectAudioStreamWrapper::Read(void *pBuffer, ULONG cbBuffer, ULONG *pcbRead){
// 参数检查
if (!pBuffer || !pcbRead) return E_INVALIDARG;
// 在读取前未使用 m_SpeechActive 返回S_OK
if (!m_SpeechActive){
*pcbRead = cbBuffer;
return S_OK;
}
HRESULT hr = S_OK;
// 目标是将浮点编码转换成16位PCM编码
INT16* const p16Buffer = reinterpret_cast<INT16*>(pBuffer);
// 长度倍数
const int multiple = sizeof(float) / sizeof(INT16);
// 检查缓冲区释放足够
auto float_buffer_size = cbBuffer / multiple;
if (float_buffer_size &g