/* * 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; }
int SayTextInit(void) { OSErr err; long response; long mask; VoiceSpec defaultVoiceSpec; VoiceDescription voiceDesc; err = Gestalt(gestaltSpeechAttr, &response); if (err != noErr) { fprintf(stderr,"can't init Mac Speech Synthesis\n"); return(1); } mask = 1 << gestaltSpeechMgrPresent; if ((response & mask) == 0) { fprintf(stderr,"Mac Speech not supported\n"); return(1); } err = GetVoiceDescription(nil, &voiceDesc, sizeof(voiceDesc)); defaultVoiceSpec = voiceDesc.voice; err = NewSpeechChannel( &defaultVoiceSpec, &channel ); if (err != noErr) { DisposeSpeechChannel(channel); fprintf(stderr,"Failed to open a speech channel\n"); return(1); } last_speech_text[0] = '\0'; last_speech_time = (time_t)0; return(0); }
/* * 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; }