Would copying registry entries to get access to all installed TTS voices be against the MS TOS?

AlexS 40 Reputation points
2024-08-26T07:33:56.2533333+00:00

Hello,

I'm building an accessibility app that uses TTS voices already installed on a Windows 10/11 machine. However, GetInstalledVoices() provided by the SpeechSynthesizer class only gives me two options despite having installed German, English, and Dutch language packs. I need at least one voice per language to be available.

After some research, I discovered voices are registered at different registry locations: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices and HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech_OneCore\Voices. Unfortunately, only the voices in the first location are accessible by the SpeechSynthesizer.

All solutions I can find for this suggest I copy the voices from one location to the other. However, I'm worried this might be against the Microsoft TOS.

.NET
.NET
Microsoft Technologies based on the .NET software framework.
3,907 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
11,001 questions
{count} votes

Accepted answer
  1. Castorix31 85,711 Reputation points
    2024-08-26T09:19:25.77+00:00

    You don't need to copy registry keys with SpeechLib

    You can use SpObjectTokenCategory.SetId with the 2nd registry path to get the voices.

    Test :

    // Add reference to : Microsoft Speech Object Library (SAPI)
    

    At beginning :

    SpVoice voice = new SpVoice();
    

    Then :

    
    {
        ISpVoice pVoice = (ISpVoice)voice;
        SpObjectTokenCategory otc = new SpObjectTokenCategory();
        //otc.SetId("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech\\Voices");
        otc.SetId("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech_OneCore\\Voices");
        ISpeechObjectTokens tokenEnum = otc.EnumerateTokens();
        int nTokenCount = tokenEnum.Count;
        Console.WriteLine("Number of voices: {0}", nTokenCount);
        foreach (ISpeechObjectToken sot in tokenEnum)
        {
            Console.WriteLine("Voice : {0}", sot.GetDescription());
            {
                pVoice.SetVoice((ISpObjectToken)sot);
                try
                {
                    uint n = 0;                       
                    pVoice.Speak("Hello! This is a test", 0, out n);                        
                }
                catch (System.Exception ex)
                {
                    Console.WriteLine("Cannot speak with the voice : {0}", sot.GetDescription());
                }
                Marshal.ReleaseComObject(sot);
            }
        }
    }
    
    
    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.