2

首先,C++ 不是我的语言(我是一名 java 程序员)。

我看过 Microsoft SAPI 5.1 的示例,我需要一种方法来打印机器中所有可用的声音。我已经看到了SAPI 的Object 令牌,我对如何使用 CComPtr 进行迭代感到有些困惑。谁能帮我这个。此外,如何选择特定的声音而不是使用默认声音。

根据示例,您可以通过调用以下代码获取默认语音:

ISpVoice * pVoice = NULL;

if (FAILED(::CoInitialize(NULL)))
    return FALSE;

HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);

简而言之:如何列出所有可用的声音以及如何选择声音?

//PS:我不需要把它放在一个组合框中(就像我见过的所有例子一样),我正在为一个 JNI dll 库实现这个,所以一个迭代的例子是更受欢迎的。

4

2 回答 2

4

首先,CComPtr 是对 COM 接口的智能指针抽象,而不是枚举器。

要列出所有声音,您需要枚举SPCAT_VOICES类别中的标记。

HRESULT hr = S_OK;
CComPtr<ISpObjectTokenCategory> cpSpCategory = NULL; 
if (SUCCEEDED(hr = SpGetCategoryFromId(SPCAT_VOICES, &cpSpCategory))) 
{ 
    CComPtr<IEnumSpObjectTokens> cpSpEnumTokens; 
    if (SUCCEEDED(hr = cpSpCategory->EnumTokens(NULL, NULL, &cpSpEnumTokens))) 
   { 
        CComPtr<ISpObjectToken> pSpTok;
        while (SUCCEEDED(hr = cpSpEnumTokens->Next(1,&pSpTok, NULL)))) 
        {
            // do something with the token here; for example, set the voice
            pVoice->SetVoice(pSpTok,FALSE); 
            // NOTE:  IEnumSpObjectTokens::Next will *overwrite* the pointer; must manually release
            pSpTok.Release(); 
        }
   } 
} 

如果你想选择一个特定的声音,你需要指定一个对该声音唯一的属性。 EnumTokens允许您指定必需的和可选的属性。属性实际上是由声音的创建者定义的,但一些常见的属性是

  • 姓名(例如,“Microsoft Anna”)
  • 语言(由数字语言环境 ID 指定)
  • 性别(男/女)
  • 供应商(创建声音的公司名称)

因此,要指定“Microsoft Anna”而不是任何声音,您可以使用

if (SUCCEEDED(hr = cpSpCategory->EnumTokens(L"Name=Microsoft Anna", NULL, &cpSpEnumTokens))) 

代替

if (SUCCEEDED(hr = cpSpCategory->EnumTokens(NULL, NULL, &cpSpEnumTokens))) 
于 2013-07-16T17:58:20.637 回答
0

enum 方法确实有效,但有点笨拙。最好的方法是打开注册表并查看密钥及其属性,您可以在此处找到更多信息:

msdn:SAPI 令牌、类别和注册表

这又是一项工作,所以我在做其他事情的同时创建了一个界面,它可能会对您或其他人有所帮助:

用于枚举和搜索语音令牌的 Sapi 接口

于 2016-03-08T13:02:37.157 回答