1 /* Copyright (C) 2012, 2018  Olga Yakovleva <yakovleva.o.v@gmail.com> */
2 
3 /* This program is free software: you can redistribute it and/or modify */
4 /* it under the terms of the GNU Lesser General Public License as published by */
5 /* the Free Software Foundation, either version 2.1 of the License, or */
6 /* (at your option) any later version. */
7 
8 /* This program is distributed in the hope that it will be useful, */
9 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
10 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the */
11 /* GNU Lesser General Public License for more details. */
12 
13 /* You should have received a copy of the GNU Lesser General Public License */
14 /* along with this program.  If not, see <http://www.gnu.org/licenses/>. */
15 
16 #include "core/path.hpp"
17 #include "core/exception.hpp"
18 #include "core/config.hpp"
19 #include "core/voice.hpp"
20 #include "core/event_logger.hpp"
21 
22 namespace RHVoice
23 {
voice(const voice_info & info_)24   voice::voice(const voice_info& info_):
25     info(info_),
26     engine_pool(info_)
27   {
28   }
29 
synthesize(const utterance & u,client & c) const30   bool voice::synthesize(const utterance& u,client& c) const
31   {
32     hts_engine_call call(engine_pool,u,c);
33     return call.execute();
34   }
35 
voice_info(unsigned int fmt,const std::string & data_path,language_list & languages)36   voice_info::voice_info(unsigned int fmt,const std::string& data_path,language_list& languages):
37     format(fmt),
38     gender("gender",RHVoice_voice_gender_unknown),
39     enabled("enabled",true),
40     preferred("preferred",false),
41     country("country"),
42     extra_utt_types("extra_utt_types")
43   {
44     gender.define("male",RHVoice_voice_gender_male);
45     gender.define("female",RHVoice_voice_gender_female);
46     set_data_path(data_path);
47     string_property name("name");
48     enum_string_property language_name("language");
49     for(language_list::const_iterator it(languages.begin());it!=languages.end();++it)
50       {
51         language_name.define(it->get_name());
52       }
53     config cfg;
54     cfg.register_setting(name);
55     cfg.register_setting(language_name);
56     cfg.register_setting(country);
57     cfg.register_setting(sample_rate);
58     cfg.register_setting(gender);
59     cfg.register_setting(extra_utt_types);
60     cfg.load(path::join(data_path,"voice.info"));
61     if(!name.is_set())
62       throw file_format_error("Voice name is not set");
63     set_name(name);
64     if(!language_name.is_set())
65       throw file_format_error("Voice language is not set");
66     language_list::iterator lang=languages.find(language_name);
67     voice_language=lang;
68     settings.default_to(voice_language->voice_settings);
69     std::string c(get_country());
70     if(c.size()>=3)
71       {
72         alpha3_country_code=c.substr(c.size()-3,3);
73         if(c.size()==6)
74           alpha2_country_code=c.substr(0,2);
75 }
76   }
77 
register_settings(config & cfg)78   void voice_info::register_settings(config& cfg)
79   {
80     std::string prefix("voices."+get_name());
81     settings.register_self(cfg,prefix);
82     cfg.register_setting(enabled,prefix);
83     cfg.register_setting(preferred,prefix);
84   }
85 
voice_list(const std::vector<std::string> & voice_paths,language_list & languages,const event_logger & logger)86   voice_list::voice_list(const std::vector<std::string>& voice_paths,language_list& languages,const event_logger& logger)
87   {
88     std::string tag("voice_list");
89     for(std::vector<std::string>::const_iterator it=voice_paths.begin();it!=voice_paths.end();++it)
90       {
91         if(path::isdir(*it))
92           {
93             logger.log(tag,RHVoice_log_level_info,std::string("Path: ")+(*it));
94             std::shared_ptr<voice_info> v;
95             version_info ver;
96             try
97               {
98                 resource_description desc("voice",*it);
99                 logger.log(tag,RHVoice_log_level_info,std::string("Voice resource: ")+desc.name.get()+std::string(", format: ")+str::to_string(desc.format.get())+std::string(", revision: ")+str::to_string(desc.revision.get()));
100                 ver=version_info(desc.format,desc.revision);
101                 if(desc.format>=3&&can_add(desc.name,ver))
102                   v.reset(new voice_info(desc.format,*it,languages));
103                 else
104                   logger.log(tag,RHVoice_log_level_error,"Unsupported voice format");
105               }
106             catch(...)
107               {
108                 logger.log(tag,RHVoice_log_level_error,"Voice info creation failed");
109               }
110             if(v)
111               add(v,ver);
112           }
113       }
114   }
115 
operator ()(const voice_info & info) const116   bool voice_search_criteria::operator()(const voice_info& info) const
117   {
118     const language_info& lang=*(info.get_language());
119     if((voice_language==0)||(voice_language==&lang))
120       if(names.empty()||(names.find(info.get_name())!=names.end()))
121         if(!preferred||info.is_preferred())
122           return true;
123     return false;
124   }
125 }
126