espeak_ros_node.cpp
Go to the documentation of this file.
1 /*
2  * espeak_ros_node.cpp
3  *
4  * Originally based on https://github.com/Teknoman117/linbot
5  *
6  * Modified by Murilo FM (muhrix@gmail.com)
7  * 12 Dec 2013
8  *
9  */
10 
11 #include <speak_lib.h>
12 #include <ros/ros.h>
13 #include <std_msgs/String.h>
14 #include <boost/thread.hpp>
15 #include <boost/thread/mutex.hpp>
16 
17 #include <dynamic_reconfigure/server.h>
18 #include <espeak_ros/EspeakConfig.h>
19 
20 boost::mutex mtx;
21 
22 std::string getVoiceName(int v);
23 std::string getDialectName(int d);
24 
25 void dyn_cfg_callback(espeak_ros::EspeakConfig &cfg, uint32_t level);
26 
27 void espeak_callback(const std_msgs::String::ConstPtr& line) {
28  // lock mutex before calling espeak functions
29  boost::mutex::scoped_lock u_lock(mtx);
30  /* Speak the string */
31  ROS_INFO("[espeak_node]: speaking \"%s\"", line->data.c_str());
32  espeak_Synth(line->data.c_str(), line->data.length()+1, 0, POS_CHARACTER, 0,
33  espeakCHARS_AUTO | espeakPHONEMES | espeakENDPAUSE, NULL, NULL);
34  espeak_Synchronize();
35  //ROS_INFO("Speaking: \"%s\"", line->data.c_str());
36 }
37 
38 int main( int argc, char** argv ) {
39  espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, NULL, 0);
40 
41  ros::init(argc, argv, "espeak_node");
43  ros::NodeHandle priv_n("~");
44 
45  // for list of voices, run "espeak --voices"
46  // voices: "brazil", "default", "english", "lancashire",
47  // "english-rp", "english-wmids", "english-us", "en-scottish"
48  std::string voice_name;
49  // dialects: "pt-br", "en", "en-uk", "en-uk-north",
50  // "en-uk-rp", "en-uk-wmids", "en-us", "en-sc"
51  std::string dialect;
52  espeak_VOICE voice_select;
53 
54  // See speak_lib.h for details and range of the parameters below
55  int rate, volume, pitch, range, punctuation;
56  int voice_num, dialect_num, capitals, wordgap, age, gender;
57 
58  // Fetch default parameters
59  rate = espeak_GetParameter(espeakRATE, 0);
60  volume = espeak_GetParameter(espeakVOLUME, 0);
61  pitch = espeak_GetParameter(espeakPITCH, 0);
62  range = espeak_GetParameter(espeakRANGE, 0);
63  punctuation = espeak_GetParameter(espeakPUNCTUATION, 0);
64  capitals = espeak_GetParameter(espeakCAPITALS, 0);
65  wordgap = espeak_GetParameter(espeakWORDGAP, 0);
66 
67  voice_num = 1;
68  dialect_num = 1;
69 
70  // Fetch (and set if param could not be retrieved) ROS parameters
71  if (priv_n.getParam("voice", voice_num) == false) {
72  priv_n.setParam("voice", voice_num);
73  }
74  if (priv_n.getParam("dialect", dialect_num) == false) {
75  priv_n.setParam("dialect", dialect_num);
76  }
77  if (priv_n.getParam("rate", rate) == false) {
78  priv_n.setParam("rate", rate);
79  }
80  if (priv_n.getParam("volume", volume) == false) {
81  priv_n.setParam("volume", volume);
82  }
83  if (priv_n.getParam("pitch", pitch) == false) {
84  priv_n.setParam("pitch", pitch);
85  }
86  if (priv_n.getParam("punctuation", punctuation) == false) {
87  priv_n.setParam("punctuation", punctuation);
88  }
89  if (priv_n.getParam("capitals", capitals) == false) {
90  priv_n.setParam("capitals", capitals);
91  }
92  if (priv_n.getParam("wordgap", wordgap) == false) {
93  priv_n.setParam("wordgap", wordgap);
94  }
95  priv_n.param("age", age, int(0));
96  priv_n.param("gender", gender, int(2));
97  if (age < 0 || age > 100) {
98  age = 0;
99  }
100  if (gender < 0 || gender > 2) {
101  gender = 2;
102  }
103 
104  voice_name = getVoiceName(voice_num);
105  dialect = getDialectName(dialect_num);
106 
107  std::memset(&voice_select,0,sizeof(voice_select));
108  voice_select.name = voice_name.c_str();
109  voice_select.languages = dialect.c_str();
110  voice_select.age = age; // 0=not specified, or age in years
111  voice_select.gender = gender; // 0=none, 1=male, 2=female
112 
113  // set espeak parameters
114  //if (espeak_SetVoiceByName(voice_name.c_str()) != EE_OK) {
115  // ROS_ERROR("Could not set espeak voice. Aborting.");
116  // return 1;
117  //}
118  if (espeak_SetVoiceByProperties(&voice_select) != EE_OK) {
119  ROS_ERROR("Could not set espeak voice properties. Aborting.");
120  return 1;
121  }
122  //ROS_INFO("Using voice %s", voice_name.c_str());
123  //ROS_INFO("Using dialect %s", dialect.c_str());
124 
125  if (rate < 80 || rate > 450) {
126  ROS_INFO("Parameter rate = %d out of range, using default value", rate);
127  }
128  else {
129  if (espeak_SetParameter(espeakRATE, rate, 0) != EE_OK) {
130  ROS_ERROR("Could not set espeak rate. Aborting.");
131  return 1;
132  }
133  }
134  if (volume < 0 || volume > 200) {
135  ROS_INFO("Parameter volume = %d out of range, using default value", volume);
136  }
137  else {
138  if (espeak_SetParameter(espeakVOLUME, volume, 0) != EE_OK) {
139  ROS_ERROR("Could not set espeak volume. Aborting.");
140  return 1;
141  }
142  }
143  if (pitch < 0 || pitch > 100) {
144  ROS_INFO("Parameter pitch = %d out of range, using default value", pitch);
145  }
146  else {
147  if (espeak_SetParameter(espeakPITCH, pitch, 0) != EE_OK) {
148  ROS_ERROR("Could not set espeak pitch. Aborting.");
149  return 1;
150  }
151  }
152  if (range < 0 || range > 100) {
153  ROS_INFO("Parameter range = %d out of range, using default value", range);
154  }
155  else {
156  if (espeak_SetParameter(espeakRANGE, range, 0) != EE_OK) {
157  ROS_ERROR("Could not set espeak range. Aborting.");
158  return 1;
159  }
160  }
161  if (punctuation < 0 || punctuation > 2) {
162  ROS_INFO("Parameter punctuation out of range, using default value");
163  }
164  else {
165  if (espeak_SetParameter(espeakPUNCTUATION,
166  espeak_PUNCT_TYPE(punctuation), 0) != EE_OK) {
167  ROS_ERROR("Could not set espeak punctuation. Aborting.");
168  return 1;
169  }
170  }
171  if (capitals < 0 || capitals > 3) {
172  ROS_INFO("Parameter capitals out of range, using default value");
173  }
174  else {
175  if (espeak_SetParameter(espeakCAPITALS, capitals, 0) != EE_OK) {
176  ROS_ERROR("Could not set espeak capitals. Aborting.");
177  return 1;
178  }
179  }
180  if (wordgap < 0 || wordgap > 1000 || wordgap % 10 != 0) {
181  ROS_INFO("Parameter wordgap out of range, using default value");
182  }
183  else {
184  if (espeak_SetParameter(espeakWORDGAP, wordgap, 0) != EE_OK) {
185  ROS_ERROR("Could not set espeak wordgap. Aborting.");
186  return 1;
187  }
188  }
189 
190  dynamic_reconfigure::Server<espeak_ros::EspeakConfig> server;
191  dynamic_reconfigure::Server<espeak_ros::EspeakConfig>::CallbackType f;
192  f = boost::bind(&dyn_cfg_callback, _1, _2);
193  server.setCallback(f);
194 
195  ros::Subscriber sub = n.subscribe("/espeak_node/speak_line", 20, espeak_callback);
196 
197  ros::spin();
198  while (n.ok());
199  return 0;
200 }
201 
202 void dyn_cfg_callback(espeak_ros::EspeakConfig &cfg, uint32_t level) {
203  // lock mutex before calling espeak functions
204  boost::mutex::scoped_lock u_lock(mtx);
205 
206  std::string voice, dialect;
207  voice = getVoiceName(cfg.voice);
208  dialect = getDialectName(cfg.dialect);
209 
210  espeak_VOICE voice_select;
211  std::memset(&voice_select,0,sizeof(voice_select));
212  voice_select.name = voice.c_str();
213  voice_select.languages = dialect.c_str();
214  voice_select.age = cfg.age; // 0=not specified, or age in years
215  voice_select.gender = cfg.gender; // 0=none, 1=male, 2=female
216 
217  if (espeak_SetVoiceByProperties(&voice_select) != EE_OK) {
218  ROS_ERROR("[espeak_node]: Could not set espeak voice properties. Aborting.");
219  return;
220  }
221  //ROS_INFO("[espeak_node]: Using voice %s", voice.c_str());
222  //ROS_INFO("[espeak_node]: Using dialect %s", dialect.c_str());
223 
224  if (espeak_SetParameter(espeakRATE, cfg.rate, 0) != EE_OK) {
225  ROS_ERROR("[espeak_node]: Could not set espeak rate. Aborting.");
226  return;
227  }
228  if (espeak_SetParameter(espeakVOLUME, cfg.volume, 0) != EE_OK) {
229  ROS_ERROR("[espeak_node]: Could not set espeak volume. Aborting.");
230  return;
231  }
232  if (espeak_SetParameter(espeakPITCH, cfg.pitch, 0) != EE_OK) {
233  ROS_ERROR("[espeak_node]: Could not set espeak pitch. Aborting.");
234  return;
235  }
236  if (espeak_SetParameter(espeakRANGE, cfg.range, 0) != EE_OK) {
237  ROS_ERROR("[espeak_node]: Could not set espeak range. Aborting.");
238  return;
239  }
240  if (espeak_SetParameter(espeakPUNCTUATION,
241  espeak_PUNCT_TYPE(cfg.punctuation), 0) != EE_OK) {
242  ROS_ERROR("[espeak_node]: Could not set espeak punctuation. Aborting.");
243  return;
244  }
245  if (espeak_SetParameter(espeakCAPITALS, cfg.capitals, 0) != EE_OK) {
246  ROS_ERROR("[espeak_node]: Could not set espeak capitals. Aborting.");
247  return;
248  }
249  int wordgap = cfg.wordgap % 10;
250  if (espeak_SetParameter(espeakWORDGAP, wordgap, 0) != EE_OK) {
251  ROS_ERROR("[espeak_node]: Could not set espeak wordgap. Aborting.");
252  return;
253  }
254 }
255 
256 std::string getVoiceName(int v) {
257  std::string voice;
258  switch (v) {
259  case 0: voice.assign("default");
260  break;
261  case 1: voice.assign("english");
262  break;
263  case 2: voice.assign("lancashire");
264  break;
265  case 3: voice.assign("english-rp");
266  break;
267  case 4: voice.assign("english-wmids");
268  break;
269  case 5: voice.assign("english-us");
270  break;
271  case 6: voice.assign("en-scottish");
272  break;
273  case 7: voice.assign("brazil");
274  break;
275  default: voice.assign("english");
276  break;
277  }
278  return voice;
279 }
280 std::string getDialectName(int d) {
281  std::string dialect;
282  switch (d) {
283  case 0: dialect.assign("en");
284  break;
285  case 1: dialect.assign("en-uk");
286  break;
287  case 2: dialect.assign("en-uk-north");
288  break;
289  case 3: dialect.assign("en-uk-rp");
290  break;
291  case 4: dialect.assign("en-uk-wmids");
292  break;
293  case 5: dialect.assign("en-us");
294  break;
295  case 6: dialect.assign("en-sc");
296  break;
297  case 7: dialect.assign("pt-br");
298  break;
299  default: dialect.assign("en-uk");
300  break;
301  }
302  return dialect;
303 }
f
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
int main(int argc, char **argv)
void espeak_callback(const std_msgs::String::ConstPtr &line)
#define ROS_INFO(...)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
ROSCPP_DECL void spin()
boost::mutex mtx
void dyn_cfg_callback(espeak_ros::EspeakConfig &cfg, uint32_t level)
bool getParam(const std::string &key, std::string &s) const
std::string getDialectName(int d)
bool ok() const
std::string getVoiceName(int v)
#define ROS_ERROR(...)
void setParam(const std::string &key, const XmlRpc::XmlRpcValue &v) const


espeak_ros
Author(s): Murilo FM
autogenerated on Wed Jan 3 2018 03:47:57