Commit 93daad09 authored by jwendt's avatar jwendt
Browse files

Voices can now also be loaded in deployed version. Better error indication if no voices are loaded

parent 9e8b67d1
......@@ -39,6 +39,9 @@ big_data_dir = @ITA_VACORE_BIG_DATA_DIR@
# Inside scene data directory
InsideSceneData = @INSIDE_SCENE_DATA@
# Path for TTS Voices of CereVoice
voices_dir = data/Voices
[Files]
......
......@@ -18,6 +18,7 @@
#include <iomanip>
#include <VistaTools/VistaFileSystemDirectory.h>
#include <VistaTools/VistaFileSystemFile.h>
......@@ -104,6 +105,11 @@ const float* CVATextToSpeechSignalSource::GetStreamBlock( const CVAAudiostreamSt
void CVATextToSpeechSignalSource::HandleRegistration( IVACore* pCore )
{
m_pAssociatedCore = pCore;
std::string voices_dir = pCore->SubstituteMacros("$(voices_dir)");
if (voices_dir != "$(voices_dir)")
TTSEngine::getInstance().SetAdditionalVoicePath(voices_dir);
if (TTSEngine::getInstance().getEngine() == NULL)
TTSEngine::getInstance().Init();
}
void CVATextToSpeechSignalSource::HandleUnregistration( IVACore* )
......@@ -250,6 +256,10 @@ void CVATextToSpeechSignalSource::SetParameters( const CVAStruct& oParams )
CPRCEN_engine_channel_to_file(TTSEngine::getInstance().getEngine(), chan, "D:/work/tts.wav", CPRCEN_RIFF); /* File output on channel */
#endif
CPRC_abuf* buf = CPRCEN_engine_channel_speak(TTSEngine::getInstance().getEngine(), chan, sText.c_str(), sText.length(), true);
if (buf == NULL){
VA_WARN("CVATextToSpeechSignalSource", "Cannot create an audio file, probably no voice is available!");
return;
}
data.visemes += "</speech>\n";
//data.visemes += "<event id=\"" + id + "\" start=\"0\" message=\"speech started\" />";
......@@ -421,34 +431,49 @@ void CVATextToSpeechSignalSource::VisemeProcessing(CPRC_abuf * abuf, void * user
#endif
}
CVATextToSpeechSignalSource::TTSEngine::TTSEngine(){
void CVATextToSpeechSignalSource::TTSEngine::Init(){
#ifdef VACORE_WITH_TTS_SIGNAL_SOURCE
if (m_pTTSEngine!=NULL)
CPRCEN_engine_delete(m_pTTSEngine);
m_pTTSEngine = CPRCEN_engine_new();
std::string voices_path = CEREVOICE_VOICES_PATH;
VA_INFO("CVATextToSpeechSignalSource", "CereVoice voices are searched in \"" + voices_path + "\"");
SetAdditionalVoicePath(CEREVOICE_VOICES_PATH);//this is defined by the FindVCereVoice cmake script, but cannot be used e.g. for deployed VAServers
VistaFileSystemDirectory voicesDir(voices_path);
if (!voicesDir.Exists()){
VA_WARN("CVATextToSpeechSignalSource", "The voices directory does not exist!");
return;
}
for (std::string voices_path : m_VoicePaths){
VA_INFO("CVATextToSpeechSignalSource", "CereVoice voices are searched in \"" + voices_path + "\"");
for (auto it = voicesDir.begin(); it != voicesDir.end(); ++it){
std::string name = (*it)->GetName();
std::size_t suffix_pos = name.find(".voice");
if (suffix_pos == std::string::npos)
VistaFileSystemDirectory voicesDir(voices_path);
if (!voicesDir.Exists()){
VA_WARN("CVATextToSpeechSignalSource", "The voices directory does not exist!");
continue;
std::string licence_file = name.substr(0, suffix_pos) + ".lic";
CPRCEN_engine_load_voice(m_pTTSEngine, licence_file.c_str(), NULL, name.c_str(), CPRC_VOICE_LOAD);
VA_INFO("CVATextToSpeechSignalSource", "Loaded voice \"" + name + "\"");
}
for (auto it = voicesDir.begin(); it != voicesDir.end(); ++it){
std::string name = (*it)->GetName();
std::size_t suffix_pos = name.find(".voice");
if (suffix_pos == std::string::npos)
continue;
std::string licence_file = name.substr(0, suffix_pos) + ".lic";
VistaFileSystemFile licenseFile(licence_file);
if (!licenseFile.Exists()){
VA_WARN("CVATextToSpeechSignalSource", "The associated license file ("+licence_file+") does not exist, cannot load voice");
continue;
}
CPRCEN_engine_load_voice(m_pTTSEngine, licence_file.c_str(), NULL, name.c_str(), CPRC_VOICE_LOAD);
VA_INFO("CVATextToSpeechSignalSource", "Loaded voice \"" + name + "\"");
}
}
//now check for the sampled voices which sample rate we have
m_sampleRate = -1.0;
int num_voices = CPRCEN_engine_get_voice_count(getEngine());
if (num_voices == 0){
VA_WARN("CVATextToSpeechSignalSource", "No voices were loaded!!!!! TTS will not work!!!!!");
}
for (int i = 0; i < num_voices; i++) {
std::string strSamplerate = CPRCEN_engine_get_voice_info(getEngine(), i, "SAMPLE_RATE");
float rate = std::stof(strSamplerate);
......@@ -499,6 +524,19 @@ std::string CVATextToSpeechSignalSource::TTSEngine::PhonemeToViseme(std::string
return it2->second;
}
void CVATextToSpeechSignalSource::TTSEngine::SetAdditionalVoicePath(std::string _path)
{
if (_path.empty())
return;
for (std::string contained_path : m_VoicePaths){
if (contained_path == _path)
return;
}
m_VoicePaths.push_back(_path);
}
void CVATextToSpeechSignalSource::TTSEngine::SetupPhonemeMapping(){
if (m_phonemeToId.size() > 0)
......
......@@ -77,12 +77,13 @@ private:
class TTSEngine{
//This is a wrapper for the CereVoice TTS Engine, which has to be only initialized once and not for each TTSignalSource
public:
TTSEngine();
TTSEngine() { m_pTTSEngine = NULL; };
~TTSEngine();
static TTSEngine& getInstance(){
static TTSEngine instance; // Guaranteed to be destroyed.
return instance;// Instantiated on first use.
}
void Init();
void SetupPhonemeMapping();
TTSEngine(TTSEngine const&) = delete; //to avoid copies being made etc.
......@@ -92,6 +93,8 @@ private:
float getSampleRate() const;
std::string PhonemeToViseme(std::string phoneme);
void SetAdditionalVoicePath(std::string _path);
private:
/*The engine maintains the list of
loaded voices and makes them available to synthesis channels. */
......@@ -99,6 +102,7 @@ private:
std::map<std::string, int> m_phonemeToId;
std::map<int, std::string> m_idToViseme;
float m_sampleRate;
std::vector<std::string> m_VoicePaths;
};
struct UserCallbackData{
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment