FLite won't load voice from file/festvox repository

439 views Asked by At

I'm still in troubles with FLite TTS. After building it into my project (c++ on Ubuntu 16.04) I can't load any voice to perform the TTS conversion. I've tried three ways to initialize the needed voice with no luck.

At first I tried "register_cmu_us_kal" from docs example but it comes with many building errors and won't even compile since it can't find some internally used functions.

Later tried "flite_voice_select" only to get a crash at runtime (then found out no voice was returned cause voice list is empty, am I supposed to populate it? shouldn't the init method do it?)

At last I tired with "flite_voice_load" and got some sort of hint of what was going wrong, yet it's not wroking.

using the "flite_voice_load" call I get the following result:

2020-09-08T12:54:55.099821  DEBUG   TTSFliteManager::TTSTranslate()
Error load voice: lang/lex eng not supported in this binary
2020-09-08T12:55:01.588762  DEBUG   TTSFliteManager::TTSTranslate() voice list = 0
2020-09-08T12:55:01.588814  ERROR   TTSFliteManager::TTSTranslate() NO VOICE SELECTED 0

if I get it right it finds the voice.flitevox file but is missing something else, language? lexicon? I've no idea especially since I'm only using voices provided by FLtie itself so I think the're well done. Looking at functions signatures my understanding is that I can't use "flite_add_voice" nor "flite_add_lang" untill I've a voice loaded, so what other instruction am I missing to actually load a voice file in my app a get the conversion done?

extern "C" {
cst_voice *register_cmu_us_kal(const char*);
}     
...
bool
TTSFliteManager::TTSTranslate(std::string text, std::string destination)
{
    ADD_LOG_DEBUG << "TTSFliteManager::TTSTranslate()";
    cst_voice *voice;
    flite_init();
//    std::string voiceName = "file:///home/user/download/cmu_us_aew.flitevox";
    std::string voiceName = "http://festvox.org/flite/packed/flite-2.0/voices/cmu_us_rxr.flitevox";

    voice = flite_voice_load(voiceName.c_str());
//    voice = flite_voice_select(voiceName.c_str());
//    voice = register_cmu_us_kal(NULL);
    
    
    ADD_LOG_DEBUG << "TTSFliteManager::TTSTranslate() voice list = " << flite_voice_list ;
    
    if(voice == nullptr)
    {
        ADD_LOG_ERROR << "TTSFliteManager::TTSTranslate() NO VOICE SELECTED " << voice;
        return false;
    }
    ADD_LOG_DEBUG << "TTSFliteManager::TTSTranslate() ready to convert text '" << text.c_str() << "' to destination '" << destination.c_str() << "' with voice '" << voice << "'";
    float secs = flite_text_to_speech(text.c_str(),voice,destination.c_str());
    if (secs == 0)
    {
        ADD_LOG_ERROR << "TTSFliteManager::TTSTranslate() ERROR GENERATED AUDIO FILE IS EMPTY";
        return false;
    }
    return true;
    
}

what is particularly confusing and frustrating to me is that from command line it works perfectly so it's all there actually it just doesn't see it. The following command produced a perfectly audible file:

flite -voice file:///home/user/download/cmu_us_aew.flitevox -f /home/user/download/flite-2.0.0-release/doc/intro.txt -o intro.wav
1

There are 1 answers

0
progywannabe On BEST ANSWER

Contrary to the nonsense by ALX23z here is a solution (maybe actually reading documentation and try to implement a solution would have been more helpfull instead):

extern "C" {
cst_voice *register_cmu_us_rms(const char *voxdir);
void unregister_cmu_us_rms(cst_voice *v);
void usenglish_init(cst_voice *v);
cst_lexicon *cmulex_init(void);
}
    
bool
TTSFliteManager::TTSTranslate(std::string text, std::string destination)
{
    ADD_LOG_DEBUG << "TTSFliteManager::TTSTranslate()";
    cst_voice *voice;
    flite_init();
    std::string voiceName = "/home/user/download/cmu_us_rms.flitevox";
//    std::string voiceName = "http://festvox.org/flite/packed/flite-2.0/voices/cmu_us_rms.flitevox";
    flite_add_lang("eng",usenglish_init,cmulex_init);
    flite_add_lang("usenglish",usenglish_init,cmulex_init);

    voice = flite_voice_load(voiceName.c_str());    
    if(voice == nullptr)
    {
        ADD_LOG_ERROR << "TTSFliteManager::TTSTranslate() NO VOICE SELECTED " << voice;
        return false;
    }
    ADD_LOG_DEBUG << "TTSFliteManager::TTSTranslate() ready to convert text '" << text.c_str() << "' to destination '" << destination.c_str() << "' with voice '" << voice << "'";
    float secs = flite_text_to_speech(text.c_str(),voice,destination.c_str());
    if (secs == 0)
    {
        ADD_LOG_ERROR << "TTSFliteManager::TTSTranslate() ERROR GENERATED AUDIO FILE IS EMPTY";
        return false;
    }
    return true;
}

please notice that it perfectly works with local file AND remote file, just uncomment the second "std::string voiceName" (and remove the first) declaration to have the library download the voice from online repository, I went for a local file for obvious performance reasons.