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.

formantdlg.cpp 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. /***************************************************************************
  2. * Copyright (C) 2006 to 2007 by Jonathan Duddington *
  3. * email: [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 3 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 see: *
  17. * <http://www.gnu.org/licenses/>. *
  18. ***************************************************************************/
  19. // For compilers that support precompilation, includes "wx/wx.h".
  20. #include "wx/wx.h"
  21. #include "wx/mdi.h"
  22. #include "speak_lib.h"
  23. #include "main.h"
  24. #include "speech.h"
  25. #include "phoneme.h"
  26. #include "synthesize.h"
  27. #include "voice.h"
  28. #include "spect.h"
  29. #include "wx/textctrl.h"
  30. #include "wx/checkbox.h"
  31. FormantDlg *formantdlg=NULL;
  32. ByteGraph *pitchgraph=NULL;
  33. BEGIN_EVENT_TABLE(FormantDlg, wxPanel)
  34. EVT_BUTTON(T_ZOOMOUT,FormantDlg::OnCommand)
  35. EVT_BUTTON(T_ZOOMIN,FormantDlg::OnCommand)
  36. EVT_SPINCTRL(-1,FormantDlg::OnSpin)
  37. // EVT_SPINCTRL(T_TIMESEQ,FormantDlg::OnSpin)
  38. // EVT_SPINCTRL(T_AMPFRAME,FormantDlg::OnSpin)
  39. // EVT_SPINCTRL(T_TIMEFRAME,FormantDlg::OnSpin)
  40. END_EVENT_TABLE()
  41. int use_spin_controls=0;
  42. void FormantDlg::OnCommand(wxCommandEvent& event)
  43. {//=============================================
  44. int id;
  45. if(currentcanvas == NULL)
  46. return;
  47. switch(id = event.GetId())
  48. {
  49. case T_ZOOMIN:
  50. case T_ZOOMOUT:
  51. currentcanvas->OnZoom(id);
  52. break;
  53. case T_AMPLITUDE:
  54. currentcanvas->RefreshDialogValues(0);
  55. break;
  56. case T_TIMEFRAME:
  57. case T_AMPFRAME:
  58. currentcanvas->RefreshDialogValues(1);
  59. break;
  60. }
  61. currentcanvas->SetFocus();
  62. }
  63. void FormantDlg::OnSpin(wxSpinEvent& event)
  64. {//=============================================
  65. int id;
  66. if(currentcanvas == NULL)
  67. return;
  68. switch(id = event.GetId())
  69. {
  70. case T_AMPFRAME:
  71. currentcanvas->RefreshDialogValues(1);
  72. break;
  73. default:
  74. currentcanvas->RefreshDialogValues(0);
  75. break;
  76. }
  77. currentcanvas->SetFocus();
  78. }
  79. FormantDlg::FormantDlg(wxWindow *parent) : wxPanel(parent,-1,wxDefaultPosition,wxSize(400,1000))
  80. {//=============================================================================================
  81. int ix;
  82. int y;
  83. int xplace;
  84. int id;
  85. wxString string;
  86. wxString control_name;
  87. int height;
  88. int width;
  89. int x;
  90. int y2 = 420;
  91. int y3 = 520;
  92. wxClientDisplayRect(&x,&y,&width, &height);
  93. #ifdef PLATFORM_WINDOWS
  94. if(height <= 768)
  95. {
  96. y2 = 410;
  97. y3 = 508;
  98. }
  99. #else
  100. if(height <= 800)
  101. {
  102. y2 = 378;
  103. y3 = 456;
  104. }
  105. #endif
  106. y = 24;
  107. xplace = 28;
  108. id = 201;
  109. new wxStaticText(this,-1,_T("Formants"),wxPoint(4,5));
  110. new wxStaticText(this,-1,_T(" Ht Width (Klatt)"),wxPoint(78,5),wxSize(300,20));
  111. new wxStaticText(this,-1,_T("Bw Ap Bp"),wxPoint(188,29),wxSize(300,20));
  112. for(ix=0; ix < 8; ix++)
  113. {
  114. string.Printf(_T("%d"),ix);
  115. t_labpk[ix] = new wxStaticText(this,id++,string,
  116. wxPoint(xplace-22,y+1+24*ix));
  117. if(ix < 7)
  118. {
  119. control_name.Printf(_T("Formant %d"),ix);
  120. t_pkfreq[ix] = new wxTextCtrl(this,id++,_T(""),
  121. wxPoint(xplace,y+24*ix),wxSize(44,20),
  122. wxTE_CENTRE,wxDefaultValidator,control_name);
  123. }
  124. control_name.Printf(_T("Height %d"),ix);
  125. t_pkheight[ix] = new wxTextCtrl(this,id++,_T(""),
  126. wxPoint(xplace+46,y+24*ix),wxSize(36,20),
  127. wxTE_CENTRE,wxDefaultValidator,control_name);
  128. if(ix < 6)
  129. {
  130. control_name.Printf(_T("Width %d"),ix);
  131. t_pkwidth[ix] = new wxTextCtrl(this,id++,_T(""),
  132. wxPoint(xplace+84,y+24*ix),wxSize(60,20),
  133. wxTE_CENTRE,wxDefaultValidator,control_name);
  134. }
  135. if((ix == 0) || (ix > 6)) continue;
  136. if(ix < 4)
  137. {
  138. control_name.Printf(_T("Klatt bandwidth %d"),ix);
  139. t_klt_bw[ix] = new wxTextCtrl(this,id++,_T(""),
  140. wxPoint(xplace+150,y+24*ix),wxSize(40,20),
  141. wxTE_CENTRE,wxDefaultValidator,control_name);
  142. }
  143. control_name.Printf(_T("Klatt parallal %d"),ix);
  144. t_klt_ap[ix] = new wxTextCtrl(this,id++,_T(""),
  145. wxPoint(xplace+192,y+24*ix),wxSize(36,20),
  146. wxTE_CENTRE,wxDefaultValidator,control_name);
  147. control_name.Printf(_T("Klatt parallel bandwidth %d"),ix);
  148. t_klt_bp[ix] = new wxTextCtrl(this,id++,_T(""),
  149. wxPoint(xplace+230,y+24*ix),wxSize(40,20),
  150. wxTE_CENTRE,wxDefaultValidator,control_name);
  151. }
  152. y=224;
  153. if(use_spin_controls)
  154. {
  155. t_timeframe = new wxSpinCtrl(this,T_TIMEFRAME,_T(""), wxPoint(6,y+0), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Frame length"));
  156. }
  157. else
  158. {
  159. tt_timeframe = new wxTextCtrl(this,T_TIMEFRAME,_T(""), wxPoint(6,y+0), wxSize(52,24), wxTE_CENTRE,wxDefaultValidator,_T("Frame length"));
  160. }
  161. t_orig_frame = new wxStaticText(this,-1,_T("mS"),wxPoint(61,y+8));
  162. t_ampframe = new wxSpinCtrl(this,T_AMPFRAME,_T(""), wxPoint(104,y+0), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Frame amplitude"));
  163. t_lab[3] = new wxStaticText(this,-1,_T("% amp - Frame"),wxPoint(159,y+8));
  164. y += 40;
  165. s_klatt[KLATT_AV] = new wxSpinCtrl(this,T_AV,_T(""), wxPoint(6,y), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Klatt AV"));
  166. t_klatt[KLATT_AV] = new wxStaticText(this,-1,_T("AV"),wxPoint(61,y+4));
  167. s_klatt[KLATT_FNZ] = new wxSpinCtrl(this,T_FNZ,_T(""), wxPoint(104,y), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Klatt FNZ"));
  168. t_klatt[KLATT_FNZ] = new wxStaticText(this,-1,_T("FNZ"),wxPoint(159,y+4));
  169. y += 28;
  170. s_klatt[KLATT_Tilt] = new wxSpinCtrl(this,T_TILT,_T(""), wxPoint(6,y), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Klatt tilt"));
  171. t_klatt[KLATT_Tilt] = new wxStaticText(this,-1,_T("Tilt"),wxPoint(61,y+4));
  172. s_klatt[KLATT_Aspr] = new wxSpinCtrl(this,T_ASPR,_T(""), wxPoint(104,y), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Klatt aspiration"));
  173. t_klatt[KLATT_Aspr] = new wxStaticText(this,-1,_T("Aspr"),wxPoint(159,y+4));
  174. s_klatt[KLATT_Skew] = new wxSpinCtrl(this,T_SKEW,_T(""), wxPoint(202,y), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Klatt skew"));
  175. t_klatt[KLATT_Skew] = new wxStaticText(this,-1,_T("Skew"),wxPoint(257,y+4));
  176. y += 28;
  177. s_klatt[KLATT_AVp] = new wxSpinCtrl(this,T_AVP,_T(""), wxPoint(6,y), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Klatt AVp"));
  178. t_klatt[KLATT_AVp] = new wxStaticText(this,-1,_T("AVp"),wxPoint(61,y+4));
  179. s_klatt[KLATT_Fric] = new wxSpinCtrl(this,T_FRIC,_T(""), wxPoint(104,y), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Klatt fric amp"));
  180. t_klatt[KLATT_Fric] = new wxStaticText(this,-1,_T("Fric"),wxPoint(159,y+4));
  181. s_klatt[KLATT_FricBP] = new wxSpinCtrl(this,T_FRICBP,_T(""), wxPoint(202,y), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Klatt fric bandwidth"));
  182. t_klatt[KLATT_FricBP] = new wxStaticText(this,-1,_T("FricBP"),wxPoint(257,y+4));
  183. y += 28;
  184. s_klatt[KLATT_Kopen] = new wxSpinCtrl(this,T_KOPEN,_T(""), wxPoint(6,y), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Klatt KOpen"));
  185. t_klatt[KLATT_Kopen] = new wxStaticText(this,-1,_T("kopen"),wxPoint(61,y+4));
  186. s_klatt[KLATT_Turb] = new wxSpinCtrl(this,T_TURB,_T(""), wxPoint(104,y), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Klatt turbulence"));
  187. t_klatt[KLATT_Turb] = new wxStaticText(this,-1,_T("Turb"),wxPoint(159,y+4));
  188. t_zoomout = new wxButton(this,T_ZOOMOUT,_T("Zoom-"),wxPoint(16,y2));
  189. t_zoomin = new wxButton(this,T_ZOOMIN,_T("Zoom+"),wxPoint(106,y2));
  190. y = y2 + 46;
  191. t_amplitude = new wxSpinCtrl(this,T_AMPLITUDE,_T(""),
  192. wxPoint(6,y),wxSize(52,24),wxTE_CENTRE,0,y+130,0,_T("Sequence amp"));
  193. t_lab[2] = new wxStaticText(this,-1,_T("% amp - Sequence"),wxPoint(61,y+4));
  194. // t_timeseq = new wxSpinCtrl(this,T_TIMESEQ,_T(""),
  195. // wxPoint(6,400),wxSize(52,24),wxTE_CENTRE,0,500);
  196. t_orig_seq = new wxStaticText(this,-1,_T("mS"),wxPoint(61,y+30));
  197. t_pitch = new wxStaticText(this,-1,_T(""),wxPoint(4,y3),wxSize(192,24));
  198. pitchgraph = new ByteGraph(this,wxPoint(0,y3+18),wxSize(200,140));
  199. pitchgraph->SetData(128,env_fall);
  200. pitchgraph->ShowSpectrum(1);
  201. pitchgraph->Show();
  202. }
  203. void FormantDlg::GetValues(SpectSeq *spectseq, int frame)
  204. {//======================================================
  205. int ix;
  206. wxString value;
  207. long num;
  208. SpectFrame *sf;
  209. if(spectseq->frames == NULL)
  210. return;
  211. sf = spectseq->frames[frame];
  212. if(use_spin_controls == 0)
  213. {
  214. formantdlg->tt_timeframe->GetValue().ToLong(&num);
  215. sf->length_adjust = num - spectseq->GetFrameLength(frame,0,NULL);
  216. }
  217. for(ix=0; ix < 8; ix++)
  218. {
  219. if(ix < 7)
  220. {
  221. num = 0;
  222. value = t_pkfreq[ix]->GetValue();
  223. value.ToLong(&num);
  224. sf->peaks[ix].pkfreq = num;
  225. }
  226. num = 0;
  227. value = t_pkheight[ix]->GetValue();
  228. value.ToLong(&num);
  229. sf->peaks[ix].pkheight = num << 6;
  230. if(ix < 6)
  231. {
  232. num = 0;
  233. value = t_pkwidth[ix]->GetValue();
  234. value.ToLong(&num);
  235. sf->peaks[ix].pkwidth = sf->peaks[ix].pkright = num*2;
  236. if((ix < 3) && ((value = value.AfterFirst('/')) != wxEmptyString))
  237. {
  238. num = 0;
  239. value.ToLong(&num);
  240. sf->peaks[ix].pkright = num*2;
  241. }
  242. }
  243. }
  244. for(ix=1; ix < 7; ix++)
  245. {
  246. if(ix < 4)
  247. {
  248. num = 0;
  249. value = t_klt_bw[ix]->GetValue();
  250. value.ToLong(&num);
  251. sf->peaks[ix].klt_bw = num;
  252. }
  253. num = 0;
  254. value = t_klt_ap[ix]->GetValue();
  255. value.ToLong(&num);
  256. sf->peaks[ix].klt_ap = num;
  257. num = 0;
  258. value = t_klt_bp[ix]->GetValue();
  259. value.ToLong(&num);
  260. sf->peaks[ix].klt_bp = num;
  261. }
  262. } // end of FormantDlg::GetValues
  263. void FormantDlg::ShowFrame(SpectSeq *spectseq, int frame, int pk, int field)
  264. {//==============================================================
  265. int ix;
  266. SpectFrame *sf;
  267. wxString value;
  268. int original_mS;
  269. peak_t *peak;
  270. if(spectseq->frames == NULL)
  271. return;
  272. sf = spectseq->frames[frame];
  273. if(field == 0xff)
  274. {
  275. // indicate the selected peak
  276. // t_select_peak[pk]->SetValue(TRUE);
  277. }
  278. for(ix=0; ix < 8; ix++)
  279. {
  280. if(field != 0xff && pk!=ix)
  281. continue;
  282. if(field == 0xff)
  283. {
  284. if(pk==ix)
  285. value.Printf(_T("%d="),ix);
  286. else
  287. value.Printf(_T("%d"),ix);
  288. t_labpk[ix]->SetLabel(value);
  289. }
  290. peak = &(sf->peaks[ix]);
  291. if((field & 1) && (ix < 7))
  292. {
  293. value.Printf(_T("%4d"),sf->peaks[ix].pkfreq);
  294. t_pkfreq[ix]->SetValue(value);
  295. }
  296. if(field & 2)
  297. {
  298. value.Printf(_T("%3d"),sf->peaks[ix].pkheight >> 6);
  299. t_pkheight[ix]->SetValue(value);
  300. }
  301. if((field & 4) && (ix < 6))
  302. {
  303. if(sf->peaks[ix].pkwidth == sf->peaks[ix].pkright)
  304. value.Printf(_T("%3d"),sf->peaks[ix].pkwidth/2);
  305. else
  306. value.Printf(_T("%3d/%3d"),sf->peaks[ix].pkwidth/2, sf->peaks[ix].pkright/2);
  307. t_pkwidth[ix]->SetValue(value);
  308. }
  309. if((ix > 0) && (ix < 7))
  310. {
  311. if((field & 8) && (ix < 4))
  312. {
  313. value.Printf(_T("%3d"),peak->klt_bw);
  314. t_klt_bw[ix]->SetValue(value);
  315. }
  316. if(field & 16)
  317. {
  318. value.Printf(_T("%3d"),peak->klt_ap);
  319. t_klt_ap[ix]->SetValue(value);
  320. }
  321. if(field & 32)
  322. {
  323. value.Printf(_T("%3d"),peak->klt_bp);
  324. t_klt_bp[ix]->SetValue(value);
  325. }
  326. }
  327. }
  328. // find the time until the next keyframe
  329. value.Printf(_T("%d"),int(spectseq->GetFrameLength(frame,1,&original_mS)+0.5)); // round to nearest integer
  330. if(use_spin_controls)
  331. t_timeframe->SetValue(value);
  332. else
  333. tt_timeframe->SetValue(value);
  334. value.Printf(_T("%d mS"),original_mS);
  335. t_orig_frame->SetLabel(value);
  336. value.Printf(_T("%3d"),sf->amp_adjust);
  337. t_ampframe->SetValue(value);
  338. for(ix=0; ix<N_KLATTP; ix++)
  339. {
  340. SetSpinCtrl(s_klatt[ix], sf->klatt_param[ix]);
  341. }
  342. } // end of FormantDlg::ShowFrame
  343. BEGIN_EVENT_TABLE(ByteGraph,wxScrolledWindow)
  344. EVT_LEFT_DOWN(ByteGraph::OnMouse)
  345. END_EVENT_TABLE()
  346. static wxBrush BRUSH_FORMANT(wxColour(255,100,50),wxSOLID);
  347. static wxPen PEN_KEYFRAME(wxColour(255,220,100),2,wxSOLID);
  348. static wxPen PEN_KEYFORMANT(wxColour(0,0,0),2,wxSOLID);
  349. ByteGraph::ByteGraph(wxWindow *parent, const wxPoint& pos, const wxSize &size):
  350. wxScrolledWindow(parent,-1,pos,size,wxSUNKEN_BORDER)
  351. {//============================================================
  352. npoints = 0;
  353. show_spectrum = 0;
  354. } // end of ByteGraph::ByteGraph
  355. void ByteGraph::SetData(int nx, unsigned char *data)
  356. {//=================================================
  357. npoints = nx;
  358. graph = data;
  359. Refresh();
  360. } // end of ByteGraph::SetData
  361. void ByteGraph::ShowSpectrum(int yes)
  362. {//==================================
  363. show_spectrum = yes;
  364. }
  365. void ByteGraph::DrawSpectrum(wxDC& dc)
  366. {//===================================
  367. SpectSeq *seq;
  368. SpectFrame *sf;
  369. int ix;
  370. int x, y;
  371. int pk;
  372. double length;
  373. int numframes;
  374. int width, height;
  375. double xscale, yscale;
  376. spectrum_scale = 0;
  377. if(currentcanvas==NULL) return;
  378. if((seq = currentcanvas->spectseq) == NULL) return;
  379. numframes = seq->numframes;
  380. if(numframes == 0) return;
  381. GetClientSize(&width,&height);
  382. if(((length = seq->frames[numframes-1]->time)==0) && (numframes>1))
  383. length = seq->frames[numframes-2]->time;
  384. length = length - seq->frames[0]->time;
  385. yscale = height/3000.0;
  386. spectrum_scale = xscale = width/length;
  387. dc.SetBrush(BRUSH_FORMANT);
  388. dc.SetPen(*wxTRANSPARENT_PEN);
  389. for(ix=0; ix<numframes; ix++)
  390. {
  391. sf = seq->frames[ix];
  392. x = int(sf->time*xscale);
  393. if(sf->keyframe)
  394. {
  395. dc.SetPen(PEN_KEYFRAME);
  396. dc.DrawLine(x,0,x,height);
  397. }
  398. dc.SetPen(*wxTRANSPARENT_PEN);
  399. dc.DrawCircle(x,int(height-(sf->formants[1].freq-200)*yscale),3);
  400. dc.DrawCircle(x,int(height-(sf->formants[2].freq-200)*yscale),3);
  401. dc.DrawCircle(x,int(height-(sf->formants[3].freq-200)*yscale),3);
  402. if(sf->keyframe)
  403. {
  404. dc.SetPen(PEN_KEYFORMANT);
  405. for(pk=1; pk<6; pk++)
  406. {
  407. y = height-int((sf->peaks[pk].pkfreq-200)*yscale);
  408. dc.DrawLine(x-3,y,x+3,y);
  409. }
  410. }
  411. }
  412. }
  413. void ByteGraph::OnDraw(wxDC &dc)
  414. {//============================
  415. int x, y, x2, y2, ix;
  416. int width, height;
  417. double xscale, yscale;
  418. if(show_spectrum) DrawSpectrum(dc);
  419. if(npoints==0) return;
  420. GetClientSize(&width,&height);
  421. xscale = double(width) / npoints;
  422. yscale = double(height) / 256.0;
  423. if(npoints > 8)
  424. {
  425. // draw pitch profile
  426. dc.SetPen(*wxMEDIUM_GREY_PEN);
  427. x = 0;
  428. y = height - int(graph[0]*yscale);
  429. for(ix=1; ix<npoints; ix++)
  430. {
  431. dc.DrawLine(x,y,x2=int(ix*xscale),y2=height - int(graph[ix]*yscale));
  432. x = x2;
  433. y = y2;
  434. }
  435. }
  436. } // end of ByteGraph::OnDraw
  437. void ByteGraph::OnMouse(wxMouseEvent& event)
  438. {//========================================
  439. int ix;
  440. SpectSeq *seq;
  441. double time;
  442. double t0, t1;
  443. double t2=0;
  444. if(currentcanvas==NULL) return;
  445. if((seq = currentcanvas->spectseq) == NULL) return;
  446. wxClientDC dc(this);
  447. PrepareDC(dc);
  448. wxPoint pt(event.GetLogicalPosition(dc));
  449. t0 = t2 = seq->frames[0]->time;
  450. time = (double(pt.x) / spectrum_scale) + t0;
  451. for(ix=1; ix<seq->numframes; ix++)
  452. {
  453. t1=t2;
  454. t2 = seq->frames[ix]->time;
  455. if(time <= t1 + (t2-t1)/2)
  456. {
  457. currentcanvas->SelectFrame(ix-1);
  458. break;
  459. }
  460. }
  461. } // end of ByteGraph::OnMouse