I have a windows service generating TTS audio using Microsoft David Desktop voice on Windows Server 2012. When moving it to Windows Server 2016, it returns error 0x80045040. My windows service logon as administrator. Have you seen this error? Note: It can plays other 32bit SAPI voices.
If the window service logon as Local System Account (LSA), there is no error. I have to run to the windows service logon as administrator because it needs to access the shared drives.
Thank you for your help.
Example 1: Error = 0x80045040 aka SPERR_INVALID_REGISTRY_KEY
//using SpeechLib; //References: Interop.SpeechLib
public string SapiGenerateTTS()
{
string ret = "";
string strVoice = "Microsoft David Desktop";
SpVoice spVoice = new SpVoice();
SpFileStream voiceStream = new SpFileStream();
bool bVoiceStreamOpen = false;
try
{
spVoice.Voice = spVoice.GetVoices("name = " + strVoice).Item(0);
voiceStream.Format.Type = SpeechAudioFormatType.SAFT8kHz16BitMono;
string strTrimPathTemp = @"c:\Temp\test.wav";
voiceStream.Open(strTrimPathTemp, SpeechStreamFileMode.SSFMCreateForWrite, true);
bVoiceStreamOpen = true;
spVoice.AudioOutputStream = voiceStream;
string strInputString = "My speech voice is " + strVoice;
spVoice.Speak(strInputString);
spVoice.WaitUntilDone(-1);
ret = strTrimPathTemp;
}
catch(Exception ex)
{
ret = ex.Message;
}
finally
{
if (bVoiceStreamOpen)
voiceStream.Close();
voiceStream = null;
spVoice = null;
}
return ret;
}
Example 2: Error: "Cannot set voice. No matching voice is installed or the voice was disabled".
using System.Speech.Synthesis;
using System.Speech.AudioFormat;
static string GenerateTTS(string strVoice)
{
string ret = "";
SpeechSynthesizer synth = null;
try
{
synth = new SpeechSynthesizer();
synth.SelectVoice(strVoice);
string strTrimPathTemp = @"c:\Temp\test.wav";
SpeechAudioFormatInfo fmtInfo = new SpeechAudioFormatInfo(8000, AudioBitsPerSample.Sixteen, AudioChannel.Mono);
synth.SetOutputToWaveFile(strTrimPathTemp, fmtInfo);
string strInputString = "My speech voice is " + strVoice;
synth.Speak(strInputString);
ret = strTrimPathTemp;
}
catch(Exception ex)
{
ret = ex.Message;
}
finally
{
if (synth != null)
{
synth.Dispose();
}
}
return ret;
}
I met same problem on example 1. Err = 0x80045040 seems default voice token doesn't support. You need to select a good voice token. Reference to set token below.
void SetVoiceToken(DWORD id, LPVOID pParams)
{
ISpVoice* pVoice = (ISpVoice *)pParams;
ISpObjectToken *cpVoiceToken = NULL;
IEnumSpObjectTokens *cpEnum;
SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum);
for (DWORD i = 0; i < id; i++)
{
if (cpVoiceToken)
cpVoiceToken->Release();
cpEnum->Next(1, &cpVoiceToken, NULL);
}
pVoice->SetVoice(cpVoiceToken);
cpVoiceToken->Release();
cpEnum->Release();
}
User contributions licensed under CC BY-SA 3.0