Click here to Skip to main content
15,892,737 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
I am try to write a C# text-to-speech applicatoin that can choose between voices. I have the default voice (Anna) working. I have run the Mike and Mary loader (Sp5TTIntXP.exe) and they show up when in the following code:

C#
public static ISpeechObjectTokens aSOT;
.
.
.
SpVoice tempVoice = new SpVoice();
aSOT = tempVoice.GetVoices();
voiceDescr = new List<string>();
for (int i = 0; i <= aSOT.Count-1; i++)
{
    voiceDescr.Add(aSOT.Item(i).GetDescription());
}

However, the code below only works if 'i' is set to the default voice (0)

C#
SpVoice outVoice = new SpVoice();
           
outVoice.Voice = outVoice.GetVoices().Item(i);

Can someone help me, please?
I am building this on Win7 (x64) platform with VS10 in C#
Posted
Updated 7-May-12 11:56am

First of all, I don't understand, why, having .NET and C#, to use SAPI directly, when you can use the ready-to-use assembly "System.Speech.dll", which is already installed in the GAC, so you can reference it using the tab ".NET" of the "Add Reference" dialog. You can traverse installed voices in this way and use one or all of the installed ones:

C#
namespace Voice {
    using System.Speech.Synthesis;

    class Program {

        static void Main(string[] args) {
            using (SpeechSynthesizer synthesizer = new SpeechSynthesizer()) {
                synthesizer.SetOutputToDefaultAudioDevice();
                PromptBuilder builder = new PromptBuilder();
                builder.AppendText("You can use different voices!");
                foreach (InstalledVoice voice in synthesizer.GetInstalledVoices()) {
                    synthesizer.SelectVoice(voice.VoiceInfo.Name);
                    synthesizer.Speak(builder);
                } //loop
            } //using
        } //Main

    } //Program

} //namespace Voice

At least, you can see what voices are really installed by examining of the collection returned as synthesizer.GetInstalledVoices().

—SA
 
Share this answer
 
Comments
El_Codero 7-May-12 18:42pm    
My 5. I also recommending OP to use SpeechSynthesizer, but saved my time to write it because of your solution. In addition if OP have to use COM-Library for some reasons, see below post ;) Regards
Sergey Alexandrovich Kryukov 7-May-12 18:47pm    
Thank you, Björn.
--SA
Gary Neal Brown 7-May-12 20:06pm    
This worked fine up to the point of selecting the second voice. Microsoft Anna spoke, but Microsoft Mary crashed with the following message:
" Cannot set voice. No matching voice is installed or the voice was disabled"
voice.VoiceInfo.Name contained "Microsoft Mary", so it had to be in the list of installed voices
Sergey Alexandrovich Kryukov 7-May-12 20:26pm    
Strange. This exception would be thrown if you simply put some gibberish instead of real name. Are you sure you use exactly this code? Do you really see 3 elements in the voice collection? If so, it would be very strange, as if the voice would be "incompletely installed" as if you appears in the registry but does not actually work -- I would not know how to reproduce such situation. Perhaps something is broken in your installation of voices. I have only one voice installed, did not want to install one more just for answering this question, but this code certainly works.
--SA
Gary Neal Brown 7-May-12 20:34pm    
I copy/pasted the code. I even made a new project with only your code in it. Same error.
To be fair, when I did a search on for Microsoft Voice Installation on Google, no one is having having any luck with Win 7. Win 8 looks to have fixed it, but my customer wants to choose voices now.
Hi,

your second part of code looks confusing, you've to set explicit index of the voices you want to choose.

this quick sample works well for me:

XML
SpVoice tempVoice = new SpVoice();
            var aSOT = tempVoice.GetVoices();
            List<string> voiceDescr = new List<string>();
            for (int i = 0; i <= aSOT.Count - 1; i++)
            {
                voiceDescr.Add(aSOT.Item(i).GetDescription());

            }



C#
foreach (var voices in voiceDescr)
            {
                if (voices.ToString() == "Microsoft Anna")
                {
                    SpVoice outVoice = new SpVoice();
                    string temp = "";
                    outVoice.Voice = outVoice.GetVoices().Item(0);
                }
            }



With Best Regards
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 7-May-12 18:47pm    
I don't know why using of a COM-based interface could be useful in this case, but it looks like a correct solution, my 5.
There are some features which are not available in .NET System.Speech; only in this case one should look for something else.
--SA
El_Codero 7-May-12 18:57pm    
Agree, I would say in this case OP should prefer using System.Speech library because of just using standard voices. Just want to add that I had some problems with older voices a while ago, in this case I had to use COM-based interface. Thank you for vote.
Sergey Alexandrovich Kryukov 7-May-12 19:38pm    
Interesting. I saw some functionality in recognizers which would need direct use of SAPI, for more advanced features; and never knew about the problems with synthesis (which is apparently less problematic in general).
--SA
Gary Neal Brown 7-May-12 20:07pm    
Item(0) worked in my code as well, I just can't get any other voices to speak

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900