/* * Case-insensitive match on NAME. */ static int getVoiceSpec(char *name, VoiceSpec *vspec) { OSErr theErr = noErr; short nvoices; long vindex; VoiceDescription vdesc; DEBUG1("looking for voice %s", name); theErr = CountVoices(&nvoices); if (theErr != noErr) { errorMsg("CountVoices failed", theErr); } else { for (vindex = 1; vindex <= nvoices; vindex++) { theErr = GetIndVoice(vindex, vspec); if (theErr != noErr) { errorMsg("GetIndVoice failed", theErr); } else { theErr = GetVoiceDescription(vspec, &vdesc, sizeof(VoiceDescription)); if (theErr != noErr) { errorMsg("GetVoiceDescription failed", theErr); } else if (strncasecmp(name, vdesc.name+1, vdesc.name[0]) == 0) { DEBUG3("found voice %s: creator=%d, id=%d", name, vspec->creator, vspec->id); return 0; } } } } return -1; }
/*------------------------------------ cmd_VoiceMax ---*/ Pvoid cmd_VoiceMax(SpeakPtr xx) { EnterCallback(); if (xx) { Atom response[1]; short voiceCount; CountVoices(&voiceCount); SETLONG(response, long(voiceCount)); outlet_anything(xx->fResultOut, gVoiceMaxSymbol, 1, response); } ExitMaxMessageHandler() } /* cmd_VoiceMax */
/* * The constructor for the ofxSpeechSynthesizer sets the status of the synthesizer * as well as populates the list of voices available in the system. This way one * can call listVoices and then initialize the synthesizer with one of those * available voices. */ ofxSpeechSynthesizer::ofxSpeechSynthesizer() { isSpeaking = false; //-- Populate the list of available voices in the system. OSErr errorStatus = noErr; short numberOfVoices; VoiceSpec theVoiceSpec; errorStatus = CountVoices(&numberOfVoices); if(!errorStatus) { for(int voiceIndex = 1; voiceIndex <= numberOfVoices; voiceIndex++) { VoiceDescription theVoiceDescription; errorStatus = GetIndVoice(voiceIndex, &theVoiceSpec); if(!errorStatus) { errorStatus = GetVoiceDescription(&theVoiceSpec, &theVoiceDescription, sizeof(theVoiceDescription)); } //-- Get the voice's name and add it to the list of available voices //-- The voices available vary depending on the version of the OS. if(!errorStatus) { size_t voiceNameLength = theVoiceDescription.name[0]; char voiceName[voiceNameLength]; for(int i=0; i < voiceNameLength; i++) { voiceName[i] = theVoiceDescription.name[i+1]; } std::string aVoice = std::string(voiceName, voiceNameLength); voices[aVoice] = voiceIndex; } } } }
// ---------------------------------------------------------- std::vector<std::string> ofxAudioUnitSpeechSynth::getAvailableVoices() // ---------------------------------------------------------- { SInt16 numVoices = 0; CountVoices(&numVoices); std::vector<std::string> voiceNames; // voices seem to be 1-indexed instead of 0-indexed for(int i = 1; i <= numVoices; i++) { VoiceSpec vSpec; VoiceDescription vDesc; GetIndVoice(i, &vSpec); GetVoiceDescription(&vSpec, &vDesc, sizeof(VoiceDescription)); string name = string((const char *)vDesc.name); // the first "character" in vDesc.name is actually just the length // of the string. We're tossing it out here by making a substring. voiceNames.push_back(string(name, 1, name[0])); } return voiceNames; }