用户操作
[即时聊天] [发私信] [加为好友]
汉飞扬ID:artlife
111481次访问,排名843,好友2人,关注者22人。
汉飞扬是一直从事.net平台开发的专业团队,从2005年10月开始研究.net 3.0.到现在为止已经开发出多个基于.net 3.0平台的成功案例,部分案例在Vista发布大会和Windows创新日大会上进行了演示.目前,汉飞扬团队已经达到50多人,其中参与过.net 3.0,XBAP,SilverLight开发项目的有20人,并有专业的WPF设计美术师.汉飞扬欢迎大家与我们合作.
artlife的文章
原创 59 篇
翻译 2 篇
转载 14 篇
评论 81 篇
汉飞扬的公告
我们专注于Vista相关新技术的研发.
在WPF WCF WF Vista语音技术方面都有成功案例,如果希望在这些方面进行交流和合作,请与我们联系.
团队全家福 联系方式如下:邵宏钢
中讯汉扬科技发展有限公司 shaohonggang@artmtech.com 010-82826969-405
纳新通告:由于承接的业务增加,汉飞扬团队正在纳新,详情见Blog纳新通知。
最近评论
diegoeddy:有源码么?
diegoeddy:有源码么?
diegoeddy:有源码么?
diegoeddy:你好,那个Demo下不了。能提供新的下载地址吗?
liseo1:
网络营销策划 网络公关 品牌管理 搜索引擎公关 搜索引擎排名 网站优化 软文发布 QQ:441843869
工业门
文章分类
收藏
    相册
    团队全家福
    Windows Vista
    Biztalk muyanpeng@汉飞扬(RSS)
    Clark Zheng(RSS)
    stswordman
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    翻译 Voice-Activated Web Browsing收藏

    新一篇: 语音辨识的常见问题集 | 旧一篇: [语音合成技术第四讲]使用C++实现语音识别

     
    []Voice-Activated Web Browsing
    这篇文章是关于一个ActiveX控制器,这个东西可以植入HTML WEB 页面提供一个活性的声音voice-activated菜单目录
    要编译这个代码,你需要VC6,微软提供的下面这个东西Microsoft's Speech SDK 5.1以及Internet Explorer headers这个东西.上面的这些东西是XP 里面自带的.
    样本程序
    这个演示方案是一个简单网页,其中有两个<iframe>要素:第一<iframe>嵌入了ActiveX控件,而第二个展现了内容.
    编译及注册webvoicectl.dll,找一个叫DEMO 的文件夹,然后双击里面的webvoice.html.你应该在界面的左侧看到树型控件,如上图.按下“voice”按钮,大型语音引擎被装载需要一些等待时间。
    装载完毕,你可以说“go to class one来启动浏览器控件会发出确认“please confirm class one在给与"positive".答复后,需求的项目会在右面显示。
    任何时候当说“help”就可以得到命令菜单。如果你刚刚运行一个页面,帮助的回答可以在上方,下方以及界面的顶端,底端滚动显示,也可以后退或者浏览。说出滚动方式,然后再说"navigate"就可以回到浏览模式。
    提示:将麦克风音量调低于可以避免产生回音。
    软件背景
    附上这篇文章相关的技术
    • ATL, ActiveX (and wide character string manipulation) 一种广泛的字符处理技术?
    • Tree view searching, expanding and collapsing 在树状视图中查找,节点的展开和合并
    • Owner drawn buttons, edit controls and static controls 所有者绘制按钮,编辑控件和静态控件
    • Image lists, overlays (and painting inside an ATL composite control) 图像列表,,覆盖(在内部绘制一个ATL组件)
    • Using Microsoft's MSXML parser to load and manipulate an XML file 使用Microsoft's MSXML解析器来装载和操作一个XML文件
    • Using C++ to interface with the web browser and the html page 使用C++来对web浏览器和html页面定义接口。
    • SAPI 5.1, speech recognition and text to speech engines and Visemes     SAPI 5.1,语音识别和语音引擎,以及基本嘴型识别
    当然在项目中使用时你不需要明白上面所有的东西,但是你可以找到一些有用的方案(一些其他代码工程文档)
    创建自己的菜单树形结构
    你的菜单项目是从配置文件“data/WebVoice.xml”(文件名字暂时写成了硬编码)中读取的。这个文件中包含了菜单树和SAPI 语法的信息。这些内容被保存在一种具有关键字结构的数组中,为了之后的修补。下面显示了一个简短的XML 例子以及关键字结构。
     
     <!-- WebVoice.xml -->
     <menu>
        <item>
          <mid>1</mid>                    <!- menu item id -->       
          <pid>0</pid>                    <!- parent id -->       
          <txt>Class One</txt>            <!- menu text and grammar phrase -->  
          <ref>../html/class1.html</ref> <!- hyperlink reference -->
        </item>
        <item>
          <mid>2</mid>
          <pid>1</pid>
          <txt>Source One</txt>
          <ref>../html/src1.html</ref>
        </item>
        <!- more items here -- >
    </menu>
     
     typedef struct tag_key
    {
     int mid;
     int pid;
     int chd;
     HTREEITEM hItem;
     HTREEITEM hParent;
     char txt[32];
     char ref[128];
    }KEY;
     
    KEY aKeys[NUMBER_OF_KEYS];
     
    你必须仔细以保证菜单项目的“id”是有序的,并且保证此节点的上级节点(parent id)在树中是这样的结构。现在装载的时候是没有错误检查的,所以不合法的XML 文件会导致这个控件不能使用。
    SAPI 初始化
    网络声音控件通过InitSapi() 这个方法来完成SAPI 的初始化,如下:
    1. 创建语音引擎
    2. 创建识别内容.
    3. 为从识别引擎返回的信息设置一种通知机制(windows 消息)
    4. 设置识别的事件
    5. 装载特殊语法文件
    6. 创建文本—>语音引擎(TTS
    7. 设置TTS事件.
    8. 为从TTS 返回的信息设置一种通知机制(windows 消息)
    9. 设置活动规则
    语音SDK 文档和样例清楚的显示了SAPI 初始化的调用,所以我不会再次说明。但是,静态语法文件和动态语法却需要一些说明。
    SAPI 语法
    SAPI 语法在运行的时候从一个XML 文件中被静态的装载网络声音控件运用2个方法静态的部分从 Grammar.xml 被装载, 此文件有如下格式:
    <PRE lang=xml nd="38"><GRAMMAR LANGID="409">
     <DEFINE>
        <ID NAME="RID_Tree"     VAL="1001"/>
        <ID NAME="RID_MenuItem" VAL="1004"/>
     </DEFINE>
     <RULE ID="RID_Tree" TOPLEVEL="ACTIVE">
        <L>
          <P>open</P>
          <P>go to</P>
        </L>
        <RULEREF REFID="RID_MenuItem" />
     </RULE>
     <RULE ID="RID_MenuItem" DYNAMIC="TRUE">
        <L PROPID="RID_MenuItem">
          <P VAL="1">Dummy Item</P>
        </L>
     </RULE>
     <!-more rules -->
    </GRAMMAR>
    </PRE>
    正如你看到的这个文件片段创建了2个规则。第一个规则,RID_Tree, 定义了静态浏览短语,并且与第二个叫做RID_MenuItem 规则相关联 第二个规则掌握了一个假值短语,此短语在运行时会被菜单项目的名字所替换。这个文件被SAPI 程序的 gc.exe编译到Grammar.cfg ,然后被装载进DLL 中的资源文件。动态规则是如下被添加的:
    <PRE id=pre3 style="MARGIN-TOP: 0px" nd="43">HRESULT CWebVoice::LoadGrammar()
    {
     USES_CONVERSION; 
     HRESULT hr;
     
     SPPROPERTYINFO pi;
     ZeroMemory(&pi,sizeof(SPPROPERTYINFO));
     pi.ulId      = RID_MenuItem; // property ID
     pi.vValue.vt = VT_UI4;
     
     // add menu items to the dynamic grammar rule
     for(int i=0; i < m_nNumKeys; i++) {
        pi.vValue.ulVal = i+1;     // Property_Value == data_index + 1
        hr=m_cpGrammar->AddWordTransition(hRule,NULL,
             T2W(aKeys[i].txt),L" ",SPWT_LEXICAL,1,&pi);
        if(FAILED(hr)) return hr;
     }
     
     // add a wildcard phrase
     pi.vValue.ulVal = 0;
     hr=m_cpGrammar->AddWordTransition(hRule,
         NULL, L"*", L" ", SPWT_LEXICAL, 1, &pi);
     if(FAILED(hr)) return hr;
     
     hr=m_cpGrammar->Commit(NULL);                  if(FAILED(hr)) return hr;
     hr=m_cpGrammar->SetGrammarState(SPGS_ENABLED); if(FAILED(hr)) return hr;
     return hr;
    }
    </PRE>
    注意,每个短语(从 aKeys[i].txt 中取出的) 都被分配了一个RID_MenuItem属性ID 和唯一的属性值 (1  m_nNumKeys 之间) 然后通过AddWordTransition()方法,这个短语被添加到语法中。也注意一个规则,如果捕捉到在文法中不存在的短语,在最后会添加("*")
    识别
    识别引擎把说出的词与运行的文法规则做比较. 不论引擎识别还是没有识别,一个回叫程序会被运行来控制语音请求。如下显示了此识别控制器的部分逻辑:
    如果识别规则匹配了,就会在静态变量ind  中储存其属性值,在确认之后,被传递给HandleConfirm(ind) 方法。此方法使用此识别规则去找出数据数组(aKeys[ind]),然后得到正确的数据对象。如果成功,树会展开,显示所选择的项目并且超链接。
    Points of Interest
    每次我开发一个ActiveX 控件或者一个基于ATL 的网络浏览器插件,我不得不复习如何去使用这广泛的字符集合;SAPI 使用专有的广泛字符集合。如果你的代码不需要在Win98 系统上运行,那么你只需要定义UNICODE 并且字符被定义成TCHAR*这样子, 常规API 的调用就没问题了。如果Win98 用户是必须被考虑的,那么当你使用Win32 API 时,必须使multibyte 转换成wide-string 幸运的是,ATL <atlbase.h> 中定义了一些转换宏。你只需在需要转换字符串的方法前面使用宏USES_CONVERSION,然后使用宏W2T()或者T2W()来完成相应的转换. 无疑这些宏是令人担忧的毕竟在每次转换运行的时候,这些宏需要分配内存空间,复制字符串,然后释放掉内存空间。但是,这些宏非常的方便和简洁,我已经在我的MFC 程序中引用 <atlbase.h> .
    我遇到的另一个问题是需要使用自定义按钮-标准的对话框背景灰色在web 页面上并不支持。使用MFC 时,我可以重载WM_CTLCOLOR消息然后在那时变换背景色使用 ATL 时,我发现我得生成自定义按钮,然后控制WM_DRAWITEM消息. 一切很顺利直到我发现我需要标签按钮和瞬时按钮,然后我就得自己编码实现需要的结果。一切都很有趣只不过在我开始SAPI 编码前花了我一些时间。
    Microsoft Speech SDK 5.1 下载大小是68 MB如果你需要用你的代码给SAPI 运行模块打包,那就必须下载完整包,大小为131.58 MB.
    不幸的是 Microsoft 没有给运行模块打包。连你的客户端也必须下载SDK (包括额外的30MB 的开发代码和文档说明) 或者你自己必须准备一个运行模块包,作为程序的一个单独的下载部分。
    修订
    • 2004129 - 为避免Win98 问题而子类化了图象控制,并且修正了demo 中的小的脚本错误。
    Recognition
    识别
    The recognition engine compares your spoken words to the active grammar rule. When either a recognition or a false recognition is made by the engine, your callback routine is called to handle the request. The following shows a section of the recognition handler:
     
    该识别引擎将口语单词与主动语态语法规则进行对比。当此引擎产生一个识别或者错误识别时,将调入你的用于处理此请求的复查程序。下面说明了识别处理程序的一部分。
     
    <PRE id=pre4 style="MARGIN-TOP: 0px" nd="56">void CWebVoice::ExecuteCommand(ISpRecoResult *pPhrase, HWND hWnd)
    {
     USES_CONVERSION;
     SPPHRASE *pElements;
     static int ind;
     int pos;
     
     if (SUCCEEDED(pPhrase->GetPhrase(&pElements))) { 
        m_cpRecoCtxt->Pause(NULL);           // pause recognition while loading
       
        switch (pElements->Rule.ulId ) {
        case RID_Tree:
          pos=pElements->pProperties->vValue.ulVal;
          ind=pos-1;              // store the index into the data array
          SetActiveRule(RID_Confirm);        // change the active rule
          wcscpy(wcs,L"Please confirm: \r\n");
          wcscat(wcs,T2W(aKeys[ind].txt));
          HandleReply(0,wcs);
          break;
        case RID_Confirm:
          pos=pElements->pProperties->vValue.ulVal;
          switch(pos) {
          case 1:
            HandleConfirm(ind);       // expand the tree and navigate to item
            SetActiveRule(RID_View); // change the active rule
            break;
          case 2:
          default:SetActiveRule(RID_Tree); HandleReply(MID_Tree,NULL); break;
          break;
          }
        // more cases for other rules
        default: SetActiveRule(RID_Tree); HandleReply(RID_Tree,NULL); break;
        }
        ::CoTaskMemFree(pElements);
        m_cpRecoCtxt->Resume(NULL);
     }
    }</PRE>
    When a navigation rule is matched, it's property value is stored in the static variable ind and, after confirmation, is passed to the HandleConfirm(ind) funtion(此处原文拼写错误,应为function which uses it to index the data array (aKeys[ind]) and retrieve the correct data item. If successful the tree view will be opened to show the selection and the hyperlink will be navigated
    当符合导航规则时,其特性值将先被存储在静态变量ind中,确认后,再传输给HandleConfirm(ind)函数。该函数利用此特性值将数据组(aKeys[ind])编入索引中,并重新得到正确的数据项目。如果成功,打开的树状图将给出选择结果,超链接也将可以被通过。
    Points of Interest
    重要的几点
    Every time I write an ActiveX control or a Web Browser plugin in ATL I have to re-learn how to use wide character strings; and SAPI uses wide character strings exclusively. If your code does not have to run on Win98 then you can just define UNICODE and as long as your strings are defined as TCHAR*, the usual API calls will work fine.
    每一次我向ATI(应用程序接口)写入ActiveX(微软倡导的ActiveX 网络化多媒体对象技术)或是网络浏览器插件中,我的不得不重新学习怎样使用宽字符串;并且宽字符串为SAPI所专用。如果你的代码并不是必须要在Win98环境下运行,只要你的字符串定义为TCHAR*,那就值只需定义UNICODE(统一的字符编码标准, 采用双字节对字符进行编码),在这种情况下,通常的API调用工作良好。
    But if discounting Win98 users is not an option then you are forced to convert from multibyte to wide-string whenever you use the Win32 API. Fortunately, ATL has a wonderful set of conversion macros defined in <atlbase.h>. You just place the macro USES_CONVERSION at the beginning of each function that needs to convert strings then use the W2T() or T2W() macros to perform the conversion.
    但是如果不能选择减少Win98用户的数量,那无论你什么时候使用Win32 API时,都必须把多字节转换成宽字符串。幸运的是,ATL<atlbase.h>中定义了一组相当好的转换宏指令。你只需要把宏指令USES_CONVERSION放在每个需要转换字符串的函数的起始位置,再用W2T() 或者 T2W()宏指令来完成转换。
    I have no doubt that the overhead to these macros is alarming -after all they have to allocate memory, copy the string then release memory in each conversion call. However these macros are so convenient and tidy that I've even started including <atlbase.h> in my MFC programs.
    我毫不怀疑的认为,对这些宏指令的总的操作是令人担忧的,因为毕竟必须要分配储存器和复制字符串,在每个转换请求时还要释放储存器。尽管这些宏指令很方便、很精简,以至于我干脆以包含<atlbase.h>的头文件来开始我的MFCMicrosoft Foundation Class, MS-Visual C++的类库)程序。
    Another problem I encountered was the need to use owner draw buttons -the standard dialog-box grey does not cut it on a web page. In MFC I would override the WM_CTLCOLOR message and change the background colour there. In ATL I found that I had to make the buttons owner-drawn then handle the WM_DRAWITEM message.
    我遇到的另一个问题是,需要使用属主拖曳按钮-标准对话框的灰色在网页上无法停止(对这里的翻译我比较费解,需要你的专业知识来校正~。在MFC中,我可以替换WM_CTLCOLOR信息,并在其中改变背景颜色。在ALT中,我发现我不得不生成属主拖曳式按钮,再处理WM_DRAWITEM信息。
    All well and good but then I discovered that I needed both a toggle button and a momentary button and that I now needed to code the required responses myself. It was all great fun but it took some time before I was able to get to the SAPI part of the code.
    这样也好,不过我发现触发按钮和瞬时按钮都是必需的,而且现在我还得自己对请求回应进行编码。这倒是非常有趣,但我要花掉很多时间,才能到编码的SAPI部分。
    The Microsoft Speech SDK 5.1 is a 68 MB download and if you need to package the SAPI runtime modules with your code, you must download the full redistribution package which is 131.58 MB.
    微软语音SDKSoftware Development Kit, 软件开发工具包)5.1是一个68Mb的下载文件。如果你需要把SAPI运行时间模型和你的编码进行打包,你必须下载一个131.58Mb的重新分配的完整安装包。
    Unfortunately Microsoft does not package the runtime modules by themselves. Either your clients must download the SDK (including the extra 30 MB of developer code and documentation) or you must prepare a runtime module package yourself as a separate download from your application.
    不幸的是,微软并没有自己打包运行时间模型。你的客户必须下载SDK(包括额外的30Mb开发者编码和文件),或者你必须自己准备一个运行时间模型,作为你的应用软件的一个单独的下载文件。
    Revisions
    修正
    • 29 January 2004 -Subclassed picture control to avoid Win98 problems and fixed small script error in the demo
    • 2004129用来避免Win98问题和演示中固定小脚本错误的子图片控制器

    About Geoff Bailey

    关于**
    ……
     
    THE END
     
    原文地址:http://www.codeproject.com/audio/WebVoicePkg.asp
     

    发表于 @ 2006年12月21日 10:06:00|评论(loading...)|编辑

    新一篇: 语音辨识的常见问题集 | 旧一篇: [语音合成技术第四讲]使用C++实现语音识别

    评论

    #bcc_paul 发表于2007-06-05 10:39:30  IP: 60.209.248.*
    请问如何关闭语音识别器中多余的功能?
    在Vista中使用语音识别时,系统会启用Vista的语音识别器,
    通过语音识别器进行语音识别。该语音识别器提供了很多实用
    的功能,比如:说“开始”会打开系统的开始菜单等等。
    但是,如果只想在自己开发的应用程序中使用识别命令,比如
    说“开始”用来打开一个文档等等,既如何屏蔽掉识别器原有的
    所有识别功能,而让识别器只为一个应用程序服务?
    一直没有找到解决方法,希望能得到你们的帮助。
    #bcc_paul 发表于2007-06-05 11:03:05  IP: 60.209.248.*
    请问如何只识别英文?
    在中文系统Vista下带有Microsoft 语音识别器8.0(中文版),
    可以同时识别英文和中文,如果只想识别英文,关闭中文识别
    功能,该怎么做?
    一直没有找到解决方法,希望能得到你们的帮助。
    #chxs2006 发表于2007-07-28 11:53:59  IP: 59.155.193.*
    请问我在xp上开发的语音识别的系统,为什么到了vista上面不能识别呢?
    一直没有找到解决的办法,希望得到你们的帮助.
    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © 汉飞扬