List voice attributes in Windows SAPI

Sorry if this is not the correct forum to ask this question.

I am using the Windows Speech API and am able to loop through all installed voices. However I am having a hard time extracting the attributes of each voice. e.g. gender, language, name.

I know these exist because it's possible to search for voices by gender and language, and they are shown in the Windows accessibility UI.

This is my code for looping:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
if ( FAILED( ::CoInitialize( NULL ) ) )
    return 1;

HRESULT hr = S_OK;

CComPtr<ISpVoice> cpVoice; //Will send data to ISpStream
CComPtr<ISpStream> cpStream; //Will contain IStream
CComPtr<IStream> cpBaseStream; //raw data
ISpObjectToken* cpToken( NULL ); //Will set voice characteristics

GUID guidFormat;
WAVEFORMATEX* pWavFormatEx = nullptr;

hr = cpVoice.CoCreateInstance( CLSID_SpVoice );

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 );
            WCHAR *pID = NULL;
            hr = pSpTok->GetId( &pID );
            // This succeeds, pID is "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Tokens\TTS_MS_EN-US_DAVID_11.0" 
            WCHAR *pName = NULL;
            pSpTok->GetStringValue( L"name", &pName );
            // pName, pGender and pLanguage are all null
            WCHAR *pGender = NULL;
            pSpTok->GetStringValue( L"gender", &pGender );
            WCHAR *pLanguage = NULL;
            pSpTok->GetStringValue( L"language", &pLanguage );
            LONG index = 0;
            WCHAR *key = NULL;
            while ( SUCCEEDED( hr = pSpTok->EnumKeys( index, &key ) ) )
            {
                // Gets some elements
                WCHAR* pValue = NULL;
                pSpTok->GetStringValue( key, &pValue );
                // Loops once, key value is "Attributes"
                index++;
            }
            index = 0;
            while ( SUCCEEDED( hr = pSpTok->EnumValues( index, &key ) ) )
            {
                // Loops many times, but none of these have what I need
                WCHAR* pValue = NULL;
                pSpTok->GetStringValue( key, &pValue );
                index++;
            }
            // NOTE:  IEnumSpObjectTokens::Next will *overwrite* the pointer; must manually release
            pSpTok.Release();
        }
    }
}


As a side note if anyone can let me know how to install the PDB files for SAPI so I can inspect the class contents I would be very grateful.
Last edited on
Registered users can post here. Sign in or register to post.