eSpeak NG is an open source speech synthesizer that supports more than hundred languages and accents.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

voicedlg.cpp 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. /***************************************************************************
  2. * Copyright (C) 2005, 2006 by Jonathan Duddington *
  3. * [email protected] *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU General Public License as published by *
  7. * the Free Software Foundation; either version 2 of the License, or *
  8. * (at your option) any later version. *
  9. * *
  10. * This program is distributed in the hope that it will be useful, *
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  13. * GNU General Public License for more details. *
  14. * *
  15. * You should have received a copy of the GNU General Public License *
  16. * along with this program; if not, write to the *
  17. * Free Software Foundation, Inc., *
  18. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  19. ***************************************************************************/
  20. #include "wx/wx.h"
  21. #include "main.h"
  22. #include "speech.h"
  23. #include "voice.h"
  24. #include "spect.h"
  25. #include "options.h"
  26. #include "wx/dialog.h"
  27. #include "wx/textctrl.h"
  28. #include "wx/checkbox.h"
  29. #include "wx/txtstrm.h"
  30. #include "wx/wfstream.h"
  31. #include "wx/filename.h"
  32. VoiceDlg *voicedlg = NULL;
  33. voice_t voice_data;
  34. USHORT voice_pcnt[N_PEAKS+1][3];
  35. static void VoiceSetup()
  36. {//=====================
  37. int pk;
  38. voice_t *v = &voice_data;
  39. for(pk=0; pk<N_PEAKS; pk++)
  40. {
  41. v->freq[pk] = int(voice_pcnt[pk][0] * 2.56001 * voice_pcnt[N_PEAKS][0] / 100.0);
  42. v->height[pk] = int(voice_pcnt[pk][1] * 2.56001 * voice_pcnt[N_PEAKS][1] / 100.0);
  43. v->width[pk] = int(voice_pcnt[pk][2] * 2.56001 * voice_pcnt[N_PEAKS][2] / 100.0);
  44. }
  45. }
  46. static void VoiceInit()
  47. {//====================
  48. int pk, j;
  49. voice_t *v;
  50. v = &voice_data;
  51. v->pitch_base = 71 << 12;
  52. v->pitch_range = 0x1000; // default = 0x1000
  53. for(pk=0; pk<N_PEAKS+1; pk++)
  54. {
  55. for(j=0; j<3; j++)
  56. voice_pcnt[pk][j] = 100;
  57. }
  58. VoiceSetup();
  59. voice = v;
  60. } // end of voice_init
  61. #define VD_DEFAULTS 401
  62. #define VD_LOAD 402
  63. #define VD_SAVE 403
  64. #define VD_PITCHCHOICE 404
  65. #define VD_PITCH1 405
  66. #define VD_PITCH2 406
  67. #define VD_USEPITCH 407
  68. wxString pitchchoices[3] = {_T("From spectrum"),_T("Standard"),_T("Monotone")};
  69. BEGIN_EVENT_TABLE(VoiceDlg, wxPanel)
  70. EVT_BUTTON(VD_DEFAULTS,VoiceDlg::OnCommand)
  71. EVT_BUTTON(VD_LOAD,VoiceDlg::OnCommand)
  72. EVT_BUTTON(VD_SAVE,VoiceDlg::OnCommand)
  73. EVT_SPINCTRL(VD_PITCH1,VoiceDlg::OnSpin)
  74. EVT_SPINCTRL(VD_PITCH2,VoiceDlg::OnSpin)
  75. EVT_CHECKBOX(VD_USEPITCH,VoiceDlg::OnCommand)
  76. EVT_COMBOBOX(VD_PITCHCHOICE,VoiceDlg::OnCommand)
  77. END_EVENT_TABLE()
  78. VoiceDlg::VoiceDlg(wxWindow *parent) : wxPanel(parent)
  79. {//=========================================================
  80. int ix, j;
  81. int y;
  82. wxString string;
  83. voice_t *v;
  84. wxString captions[3] = {_T("Freq"),_T("Height"),_T("Width")};
  85. voice_p = v = &voice_data;
  86. VoiceInit();
  87. pitch1 = 80;
  88. pitch2 = 120;
  89. for(j=0; j<3; j++)
  90. new wxStaticText(this,-1,captions[j],wxPoint(34+j*56,6));
  91. y = 26;
  92. for(ix=0; ix<N_PEAKS+1; ix++)
  93. {
  94. if(ix==N_PEAKS)
  95. {
  96. string = _T("All");
  97. y += 8;
  98. }
  99. else
  100. string.Printf(_T("%2d"),ix);
  101. vd_labpk[ix] = new wxStaticText(this,-1,string,wxPoint(8,y+2));
  102. for(j=0; j<3; j++)
  103. {
  104. string.Printf(_T("%d"),voice_pcnt[ix][j]);
  105. vd[ix][j] = new wxSpinCtrl(this,-1,string,
  106. wxPoint(32+j*56,y),wxSize(52,22),wxSP_ARROW_KEYS,0,300);
  107. }
  108. y += 26;
  109. }
  110. for(ix=6; ix<N_PEAKS; ix++)
  111. vd[ix][2]->Hide();
  112. vd_defaults = new wxButton(this,VD_DEFAULTS,_T("Defaults"),wxPoint(32,293));
  113. y = 324;
  114. vd_pitch1 = new wxSpinCtrl(this,VD_PITCH1,_T("80"),
  115. wxPoint(32,y),wxSize(52,24),wxTE_CENTRE,60,500);
  116. vd_pitch2 = new wxSpinCtrl(this,VD_PITCH2,_T("120"),
  117. wxPoint(88,y),wxSize(52,24),wxTE_CENTRE,60,500);
  118. vd_lab[1] = new wxStaticText(this,-1,_T("Hz"),wxPoint(142,y+2));
  119. vd_usepitch = new wxCheckBox(this,VD_USEPITCH,_T("Pitch from spectrum"),
  120. wxPoint(4,y+24));
  121. // vd_load = new wxButton(this,VD_LOAD,_T("Load"),wxPoint(16,y+56));
  122. // vd_save = new wxButton(this,VD_SAVE,_T("Save"),wxPoint(106,y+56));
  123. y = 422;
  124. vd_duration = new wxTextCtrl(this,-1,_T(""),
  125. wxPoint(4,y),wxSize(52,24),wxTE_CENTRE);
  126. vd_lab[2] = new wxStaticText(this,-1,_T("Duration"),wxPoint(60,y+2));
  127. y = 422;
  128. vd_pitchchoice = new wxComboBox(this,VD_PITCHCHOICE,_T("Standard"),
  129. wxPoint(4,y+30),wxSize(192,24),3,pitchchoices);
  130. vd_pitchgraph = new ByteGraph(this,wxPoint(0,y+60),wxSize(200,100));
  131. vd_pitchgraph->SetData(128,env_fall);
  132. vd_pitchgraph->Show();
  133. } // end of VoiceDlg::VoiceDlg
  134. void VoiceDlg::OnCommand(wxCommandEvent& event)
  135. {//============================================
  136. // JSD EVT_COMBOBOX causes GDB lockup if a breakpoint is set
  137. int id;
  138. int ix, j;
  139. switch(id = event.GetId())
  140. {
  141. case VD_DEFAULTS:
  142. for(ix=0; ix<N_PEAKS+1; ix++)
  143. {
  144. for(j=0; j<3; j++)
  145. {
  146. voice_pcnt[ix][j] = 100;
  147. vd[ix][j]->SetValue(_T("100"));
  148. }
  149. }
  150. VoiceSetup();
  151. break;
  152. case VD_LOAD:
  153. Load();
  154. break;
  155. case VD_SAVE:
  156. Save();
  157. break;
  158. case VD_USEPITCH:
  159. case VD_PITCHCHOICE:
  160. if(currentcanvas != NULL)
  161. SetFromSpect(currentcanvas->spectseq);
  162. break;
  163. }
  164. if(currentcanvas != NULL) currentcanvas->SetFocus();
  165. } // end of VoiceDlg::OnCommand
  166. void VoiceDlg::ReadParams()
  167. {//========================
  168. int ix, j;
  169. pitchenv.pitch1 = vd_pitch1->GetValue();
  170. pitchenv.pitch2 = vd_pitch2->GetValue();
  171. voice_data.pitch_base = (pitchenv.pitch1 - 9) << 12;
  172. voice_data.pitch_range = (pitchenv.pitch2 - pitchenv.pitch1) * 108;
  173. for(ix=0; ix<N_PEAKS+1; ix++)
  174. {
  175. for(j=0; j<3; j++)
  176. {
  177. voice_pcnt[ix][j] = vd[ix][j]->GetValue();
  178. }
  179. }
  180. VoiceSetup();
  181. } // end of VoiceDlg::ReadParams
  182. void VoiceDlg::WriteParams()
  183. {//========================
  184. int ix;
  185. voice_t *v = voice;
  186. int val1, val2;
  187. val1 = (v->pitch_base >> 12) + 9;
  188. val2 = v->pitch_range/108 + val1;
  189. vd_pitch1->SetValue(val1);
  190. vd_pitch2->SetValue(val2);
  191. for(ix=0; ix<N_PEAKS; ix++)
  192. {
  193. vd[ix][0]->SetValue(int(float(v->freq[ix]) / 2.56001 + 0.5));
  194. vd[ix][1]->SetValue(int(float(v->height[ix]) / 2.56001 + 0.5));
  195. vd[ix][2]->SetValue(int(float(v->width[ix]) / 2.56001 + 0.5));
  196. }
  197. vd[ix][0]->SetValue(100);
  198. vd[ix][1]->SetValue(100);
  199. vd[ix][2]->SetValue(100);
  200. } // end of VoiceDlg::WriteParams
  201. void VoiceDlg::OnSpin(wxSpinEvent& event)
  202. {//======================================
  203. ReadParams();
  204. }
  205. void VoiceDlg::Save()
  206. {//==================
  207. int pk;
  208. wxString filename;
  209. FILE *f;
  210. filename = wxFileSelector(_T("Save voice"),path_voices,_T(""),_T(""),_T("*"),wxSAVE);
  211. if(filename.IsEmpty())
  212. return;
  213. f = fopen(filename.mb_str(wxConvLocal),"w");
  214. if(f == NULL)
  215. {
  216. wxLogError(_T("Failed to open '%s'"),filename.c_str());
  217. return;
  218. }
  219. wxFileName fn(filename);
  220. path_voices = fn.GetPath();
  221. ReadParams();
  222. fprintf(f,"%3d %3d\n",vd_pitch1->GetValue(),vd_pitch2->GetValue());
  223. for(pk=0; pk<N_PEAKS+1; pk++)
  224. {
  225. fprintf(f,"%3d %3d %3d\n",voice_pcnt[pk][0],voice_pcnt[pk][1],voice_pcnt[pk][2]);
  226. }
  227. fclose(f);
  228. } // end of VoiceDlg::Save
  229. void VoiceDlg::Load()
  230. {//===============================
  231. wxString filename;
  232. int pk, j;
  233. filename = wxFileSelector(_T("Load voice"),path_voices,_T(""),_T(""),_T("*"),wxOPEN);
  234. if(filename.IsEmpty()) return;
  235. wxFileInputStream stream(filename);
  236. if(stream.Ok() == FALSE)
  237. {
  238. wxLogError(_T("Failed to open '%s'"),filename.c_str());
  239. return;
  240. }
  241. wxFileName fn(filename);
  242. path_voices = fn.GetPath();
  243. wxTextInputStream s(stream);
  244. s >> pitch1;
  245. s >> pitch2;
  246. for(pk=0; pk<N_PEAKS+1; pk++)
  247. {
  248. for(j=0; j<3; j++)
  249. {
  250. s >> voice_pcnt[pk][j];
  251. SetSpinCtrl(vd[pk][j],voice_pcnt[pk][j]);
  252. }
  253. }
  254. SetSpinCtrl(voicedlg->vd_pitch1,pitch1);
  255. SetSpinCtrl(voicedlg->vd_pitch2,pitch2);
  256. ReadParams();
  257. } // end of VoiceDlg::Load
  258. void VoiceDlg::SetFromSpect(SpectSeq* spect)
  259. {//=========================================
  260. if(spect==NULL) return;
  261. if(vd_pitchchoice->GetValue() == _T("From spectrum"))
  262. {
  263. pitchenv = spect->pitchenv;
  264. }
  265. else
  266. if(vd_pitchchoice->GetValue() == _T("Monotone"))
  267. {
  268. memset(pitchenv.env,127,128);
  269. }
  270. else
  271. if(vd_pitchchoice->GetValue() == _T("Standard"))
  272. {
  273. memcpy(pitchenv.env,env_fall,128);
  274. }
  275. vd_pitchgraph->SetData(128,pitchenv.env);
  276. vd_pitchgraph->Show();
  277. if(vd_usepitch->GetValue())
  278. {
  279. SetSpinCtrl(vd_pitch1,spect->pitch1);
  280. SetSpinCtrl(vd_pitch2,spect->pitch2);
  281. }
  282. else
  283. {
  284. SetSpinCtrl(vd_pitch1,pitch1);
  285. SetSpinCtrl(vd_pitch2,pitch2);
  286. }
  287. } // end of VoiceDlg::SetFromSpect