I'm developping a Text-To-Speech application using Microsoft SAPI. I found out that it is possible to add customized prononciations of words in a dictionnary (correct me if I'm wrong). I implemented a function which allows to add words into this dictionnary. Here is my code:
int addPrononciation( const char* addPron, const char* phon )
{
hr = cpLexicon.CoCreateInstance( CLSID_SpLexicon );
hr = cpContainerLexicon.CoCreateInstance( CLSID_SpLexicon );
hr = SpEnumTokens( SPCAT_VOICES, NULL, NULL, &cpEnum );
cpEnum->Item( saveVoice, &cpVoiceToken ); //get saveVoice token defined at line 136
cpVoice->SetVoice( cpVoiceToken ); //Initialization of the voice
hr = cpContainerLexicon->AddLexicon( cpLexicon, eLEXTYPE_APP );
langId = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US );
hr = SpCreatePhoneConverter( langId, NULL, NULL, &cpPhoneConv );
int wchars_num = MultiByteToWideChar( CP_ACP, 0, addPron, -1, NULL, 0 );
wchar_t* pronWstr = new wchar_t[ wchars_num ];
MultiByteToWideChar( CP_ACP, 0, addPron, -1, pronWstr, wchars_num );
int phonWchars_num = MultiByteToWideChar( CP_ACP, 0, phon, -1, NULL, 0 );
wchar_t* phonWstr = new wchar_t[ phonWchars_num ];
MultiByteToWideChar( CP_ACP, 0, phon, -1, phonWstr, phonWchars_num );
if(SUCCEEDED( hr ))
{
hr = cpPhoneConv->PhoneToId( phonWstr, wszId );
hr = cpVoice->Speak( phonWstr, SPF_DEFAULT, NULL );
hr = cpLexicon->AddPronunciation( pronWstr, langId, SPPS_Noun, wszId );
hr = cpVoice->Speak( pronWstr, SPF_DEFAULT, NULL );
if( SUCCEEDED( hr ) )
{
printf( "Success\n" );
}
else
{
printf( "Failed\n" );
}
}
cpEnum.Release();
cpVoiceToken.Release();
cpContainerLexicon.Release();
cpLexicon.Release();
cpPhoneConv.Release();
delete new wchar_t[ wchars_num ];
delete new wchar_t[ phonWchars_num ];
return true;
}
Now I would like to list these words using ISpLexicon::GetWords.
I already read the documentation on the Microsoft website and tried to implement the function, but I can't figure out how to initialize the variable spWordList
.
Here is my code:
ZeroMemory( &spWordList, sizeof( spWordList ) );
if( SUCCEEDED( hr ) )
{
hr = cpLexicon->GetWords( eLEXTYPE_APP, &dwGeneration, &dwCookie, &spWordList );
printf( "Words: %ls\n", spWordList ); //print words but the output is null
}
CoTaskMemFree( spWordList.pvBuffer );
I'm triying to print the words, but the output is null. I think the spWordList
variable is not initialized. Here is a screenshot of the variable values.
How can I initialize it?
I found out how to initialize spWordList
. You have to replace eLEXTYPE_APP
with eLEXTYPE_USER
. However, you can keep both of them like I did. Below you will find an example on how it lists the words.
ZeroMemory( &spWordList, sizeof( spWordList ) );
hr = S_FALSE;
if( hr == S_FALSE )
{
hr = cpLexicon->GetWords( eLEXTYPE_USER | eLEXTYPE_APP, &dwGeneration, &dwCookie, &spWordList );
for( spWord = spWordList.pFirstWord; spWord != NULL; spWord = spWord->pNextWord )
{
for( spWordPron = spWord->pFirstWordPronunciation; spWordPron != NULL; spWordPron = spWordPron->pNextWordPronunciation )
{
printf( "Words in dictionnary: %i\n", dwGeneration );
printf( "Word: %ls\n", spWord->pszWord );
//you can also display the pronunciation of words if you wish
}
}
}
CoTaskMemFree( spWordList.pvBuffer );
In the code, I loop through the entire dictionnary. Notice that the listed words are displayed randomly. I'll update my answer if I find other important information about ISpLexicon::GetWords