SAPI Interface and Unity3d


Enumerating and Changing voices in Unity3d Text To Speech


So, you incorporated the text to speech in to Unity and want to change
the voice, every time you add a new voice, the index changes?  Same here.
I looked around for solutions on the web, but found out that it was a
bit tricky.  Well, frustrated with it I wrote the following code will enumerate installed voices on the
current system, and allow a text search against the voices.  It runs at
start, and is best used attached to a new project, on an object.

Comment if you have any questions or ideas on how to make it better.  Enjoy!


using UnityEngine;
using System.Collections;
using SpeechLib;
using System.Xml;
using System.IO;


public class VoiceTrigger : MonoBehaviour {
    
    private SpVoice voice ;
    private bool seenMe = false;
    
    // "CereVoice Katherine - English (East Coast America)" -- example of name in system panel, and used in normal SAPI C# to call it as voice, but seems unity doesn't support string identifies this way
    // how ever, if you loop through the names as below, and look for .contains("Partial Unique Name") you may be able to just find it that way, since every voice installed could change the integer 
    // representation of the voice, thus if you install a new voice, it may change what speeks in your code.  
 
    void Start () {

      voice = new SpVoice();
      
      int voiceTotal = voice.GetVoices().Count;
      voice.Speak("There are " + voiceTotal + " voices installed on this system, names and index to follow");
      
        int v = 0;
      do
      {

          // depending on version or any other microsoft changes the REG key this is stored in could change, if so, you'll see and hear the full path in the run of the code, also remember to escape
          // the backslash charcter.

          string voiceName = (voice.GetVoices().Item(v).Id.ToString().Replace("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech\\Voices\\Tokens\\", ""));
          print(v + "\t" + voiceName);                  // prints voice name and index to console
          voice.Voice = voice.GetVoices().Item(0);  // to demonstrate on the fly switching of voices
          voice.Speak("Voice Number " + v);         // speaks with default voice
          voice.Voice = voice.GetVoices().Item(v);  // to demonstrate on the fly switching of voices
          voice.Speak(voiceName);
          v++;
      }
      while
      (v <= voiceTotal);  // do not set to something else like >= or the script will never end... and you'll have to crash Unity :/


        // the following allows you to search for a voice in on the local machine that matches the name ... there are probably nicer ways to do this, but my google results didn't yield them.
        v = 0;      //reset counter 
        do
              {
                  string voiceToSearchFor = "zira";
                   string voiceName = (voice.GetVoices().Item(v).Id.ToString().Replace("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech\\Voices\\Tokens\\","").ToLower());

                  print(voiceName.Contains(voiceToSearchFor));

                   if (voiceName.Contains(voiceToSearchFor.ToLower()))  //if it found the voice, set it and use it below.  
                   {
                       voice.Voice = voice.GetVoices().Item(v); 
                       voice.Speak(voiceName + " was found");  
                   }
                   v++;
              }
              while
      (v <= voiceTotal);
    }
}
//as always use at your own risk, even though i have tested it over and over.

Comments

Post a Comment

Popular posts from this blog

Unity3d BlendShapes, too many!