This removes the GUI part of espeakedit, keeping the part that is
responsible for compiling the voice and intonation data. The
motivation for this is:
1. the voice and intonation data compilation will move into
libespeak-ng after removing the wxWidgets logic and converting
the code to C;
2. the espeakedit code is tightly coupled to the internals of
libespeak-ng at a source code level, not a binary/API level,
making the code harder to maintain;
3. a new GUI will be written in Qt that better supports creating
and editing voices and languages.
master
| @@ -82,17 +82,10 @@ libespeak_ng_SOURCE = \ | |||
| espeakedit_SOURCE = \ | |||
| src/compiledata.cpp \ | |||
| src/espeakedit.cpp \ | |||
| src/extras.cpp \ | |||
| src/formantdlg.cpp \ | |||
| src/menus.cpp \ | |||
| src/options.cpp \ | |||
| src/prosodydisplay.cpp \ | |||
| src/spect.cpp \ | |||
| src/spectdisplay.cpp \ | |||
| src/spectseq.cpp \ | |||
| src/transldlg.cpp \ | |||
| src/voicedlg.cpp \ | |||
| src/vowelchart.cpp | |||
| src/spectseq.cpp | |||
| if OPT_KLATT | |||
| common_FLAGS += -DINCLUDE_KLATT | |||
| @@ -53,18 +53,16 @@ extern wxString path_dictsource; | |||
| extern wxString path_phsource; | |||
| extern wxString path_phfile; | |||
| extern char path_dsource[sizeof(path_home)+20]; | |||
| extern char path_source[sizeof(path_home)+20]; | |||
| extern wxProgressDialog *progress; | |||
| extern int progress_max; | |||
| extern int gui_flag; | |||
| extern char voice_name2[40]; | |||
| extern void FindPhonemesUsed(void); | |||
| extern "C" int utf8_in(int *c, const char *buf); | |||
| extern "C" int utf8_out(unsigned int c, char *buf); | |||
| extern void DrawEnvelopes(); | |||
| extern void ReadPhondataManifest(); | |||
| char path_source[sizeof(path_home)+20]; | |||
| typedef struct { | |||
| const char *mnem; | |||
| @@ -949,159 +947,6 @@ static void PrintPhonemesUsed(FILE *f, const char *dsource, const char *dictname | |||
| static wxString CompileAllDictionaries() | |||
| {//===================================== | |||
| wxString filename; | |||
| wxFileName fname; | |||
| wxString dictstr; | |||
| wxString filetype; | |||
| wxString report = _T(""); | |||
| int err; | |||
| int errors = 0; | |||
| int dict_count = 0; | |||
| FILE *f_in; | |||
| FILE *log; | |||
| FILE *f_phused; | |||
| char dictname[80]; | |||
| char fname_log[sizeof(path_dsource)+20]; | |||
| char save_voice_name[80]; | |||
| char path[sizeof(path_home)+40]; // path_dsource+20 | |||
| char buf[200]; | |||
| char voicename[80]; | |||
| if(!wxDirExists(path_dictsource)) | |||
| { | |||
| if(gui_flag) | |||
| { | |||
| wxString dirname = wxDirSelector(_T("Directory of dictionary files"),path_phsource); | |||
| if(!dirname.IsEmpty()) | |||
| { | |||
| path_dictsource = dirname; | |||
| strncpy0(path_dsource,path_dictsource.mb_str(wxConvLocal),sizeof(path_dsource)-1); | |||
| strcat(path_dsource,"/"); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| fprintf(stderr,"Can't find dictionary files: %s\n",path_dsource); | |||
| } | |||
| } | |||
| wxDir dir(path_dictsource); | |||
| if(!dir.IsOpened()) | |||
| { | |||
| return(_T(" No dictionaries")); | |||
| } | |||
| strcpy(save_voice_name,voice_name2); | |||
| sprintf(fname_log,"%s%s",path_dsource,"dict_log"); | |||
| log = fopen(fname_log,"w"); | |||
| if(log != 0) | |||
| { | |||
| fprintf(log, "%s", utf8_bom); | |||
| } | |||
| sprintf(fname_log,"%s%s",path_dsource,"dict_phonemes"); | |||
| f_phused = fopen(fname_log,"w"); | |||
| if(f_phused) | |||
| { | |||
| fprintf(f_phused,"Phonemes which are used in the *_rules and *_list files\n"); | |||
| } | |||
| bool cont = dir.GetFirst(&filename, _T("*_rules*"), wxDIR_FILES); | |||
| while ( cont ) | |||
| { | |||
| fname = wxFileName(filename); | |||
| filetype = fname.GetName().AfterLast('_'); | |||
| if((filetype != _T("rules")) && (filetype != _T("rules.txt"))) | |||
| { | |||
| cont = dir.GetNext(&filename); | |||
| continue; | |||
| } | |||
| dictstr = fname.GetName().BeforeLast('_'); | |||
| strcpy(dictname,dictstr.mb_str(wxConvLocal)); | |||
| dict_count++; | |||
| strcpy(voicename,dictname); | |||
| // read the *_rules file to see if a phoneme table is specified though a voice name | |||
| sprintf(path,"%s%s_rules.txt",path_dsource,dictname); | |||
| if((f_in = fopen(path,"r")) == NULL) | |||
| { | |||
| sprintf(path,"%s%s_rules",path_dsource,dictname); | |||
| f_in = fopen(path,"r"); | |||
| } | |||
| if(f_in != NULL) | |||
| { | |||
| unsigned int ix; | |||
| unsigned int c; | |||
| for(ix=0; ix<20; ix++) | |||
| { | |||
| if(fgets(buf,sizeof(buf),f_in) == NULL) | |||
| break; | |||
| if(memcmp(buf,"//voice=",8)==0) | |||
| { | |||
| for(ix=0; ix<sizeof(voicename); ix++) | |||
| { | |||
| if(isspace(c = buf[ix+8])) | |||
| { | |||
| break; | |||
| } | |||
| voicename[ix] = c; | |||
| } | |||
| voicename[ix] = 0; | |||
| break; | |||
| } | |||
| } | |||
| fclose(f_in); | |||
| } | |||
| if(LoadVoice(voicename,1) == NULL) | |||
| { | |||
| wxLogError(wxString::Format(_T("Can't find voice '%s' for dictionary '%s'"), wxString(voicename, wxConvLocal).c_str(), dictstr.c_str())); | |||
| report = report + dictstr + _T(" No Voice, "); | |||
| errors ++; | |||
| } | |||
| else | |||
| if((err = CompileDictionary(path_dsource, dictname,log,NULL,0)) > 0) | |||
| { | |||
| report = report + dictstr + wxString::Format(_T(" %d, "),err); | |||
| errors += err; | |||
| } | |||
| if(f_phused != NULL) | |||
| { | |||
| memset(phoneme_tab_flags,0,sizeof(phoneme_tab_flags)); | |||
| FindPhonemesUsed(); | |||
| PrintPhonemesUsed(f_phused, path_dsource, dictname); | |||
| } | |||
| cont = dir.GetNext(&filename); | |||
| } | |||
| if(log != NULL) | |||
| fclose(log); | |||
| if(f_phused != NULL) | |||
| fclose(f_phused); | |||
| LoadVoiceVariant(save_voice_name,0); | |||
| if(errors == 0) | |||
| return(wxString::Format(_T(" Compiled %d dictionaries"),dict_count)); | |||
| else | |||
| { | |||
| return(_T(" Dictionary errors: ") + report); | |||
| } | |||
| } // end of CompileAllDictionaries | |||
| static void error(const char *format, const char *string) | |||
| {//====================================================== | |||
| if(string==NULL) | |||
| @@ -3283,9 +3128,6 @@ static void StartPhonemeTable(const char *name) | |||
| return; | |||
| } | |||
| if(gui_flag) | |||
| progress->Update(n_phoneme_tabs); | |||
| memset(&phoneme_tab_list2[n_phoneme_tabs], 0, sizeof(PHONEME_TAB_LIST)); | |||
| phoneme_tab_list2[n_phoneme_tabs].phoneme_tab_ptr = phoneme_tab2 = p; | |||
| strncpy0(phoneme_tab_list2[n_phoneme_tabs].name, name, N_PHONEME_TAB_NAME); | |||
| @@ -3652,14 +3494,7 @@ make_envs(); | |||
| sprintf(fname,"%scompile_prog_log",path_source); | |||
| f_prog_log = fopen_log(f_errors,fname,"wb"); | |||
| if(gui_flag) | |||
| { | |||
| progress = new wxProgressDialog(_T("Compiling"),_T(""),progress_max); | |||
| } | |||
| else | |||
| { | |||
| fprintf(stderr,"Compiling phoneme data: %s\n",path_source); | |||
| } | |||
| fprintf(stderr,"Compiling phoneme data: %s\n",path_source); | |||
| // write a word so that further data doesn't start at displ=0 | |||
| Write4Bytes(f_phdata,version_phdata); | |||
| @@ -3691,18 +3526,10 @@ fprintf(f_errors,"\nRefs %d, Reused %d\n",count_references,duplicate_references | |||
| LoadVoice(voice_name2,0); | |||
| CompileReport(); | |||
| if(gui_flag != 0) | |||
| report_dict = CompileAllDictionaries(); | |||
| #ifdef MAKE_ENVELOPES | |||
| DrawEnvelopes(); | |||
| #endif | |||
| if(gui_flag) | |||
| { | |||
| delete progress; | |||
| } | |||
| if(resample_count > 0) | |||
| { | |||
| fprintf(f_errors, "\n%d WAV files resampled to %d Hz\n", resample_count, samplerate_native); | |||
| @@ -35,15 +35,12 @@ | |||
| #include "speak_lib.h" | |||
| #include "espeak_ng.h" | |||
| #include "main.h" | |||
| #include "speech.h" | |||
| #include "options.h" | |||
| #include "phoneme.h" | |||
| #include "synthesize.h" | |||
| #include "voice.h" | |||
| #include "spect.h" | |||
| #include "translate.h" | |||
| #include "prosodydisplay.h" | |||
| static const char *about_string2 = "espeakedit: %s\nAuthor: Jonathan Duddington (c) 2009\n\n" | |||
| "Licensed under GNU General Public License version 3\n" | |||
| @@ -54,43 +51,20 @@ static const char *about_string = "<font size=0><b>espeakedit </b> %s<br>Author: | |||
| "<a href=\"http://espeak.sourceforge.net/\">http://espeak.sourceforge.net</a><br>" | |||
| "Licensed under <a href=\"http://espeak.sourceforge.net/license.html\">GNU General Public License version 3</a></font>"; | |||
| const char *path_data; | |||
| extern void TestTest(int control); | |||
| extern void CompareLexicon(int); | |||
| extern void ConvertToUtf8(); | |||
| extern void DictionaryFormat(const char *dictname); | |||
| extern void DictionarySort(const char *dictname); | |||
| extern void init_z(); | |||
| extern void ConfigInit(bool use_defaults); | |||
| extern void CompilePhonemeData(void); | |||
| extern void CompileSampleRate(void); | |||
| extern espeak_ng_STATUS CompileIntonation(FILE *log); | |||
| extern void InitSpectrumDisplay(); | |||
| extern void InitProsodyDisplay(); | |||
| extern void InitWaveDisplay(); | |||
| extern void VowelChart(int control, char *fname); | |||
| extern void MakeVowelLists(void); | |||
| extern void MakeWordFreqList(); | |||
| extern wxMenu *speak_menu; | |||
| extern wxMenu *data_menu; | |||
| MyFrame *myframe = NULL; | |||
| SpectDisplay *currentcanvas = NULL; | |||
| ProsodyDisplay *prosodycanvas = NULL; | |||
| wxNotebook *notebook = NULL; | |||
| wxNotebook *screenpages = NULL; | |||
| wxProgressDialog *progress; | |||
| int progress_max; | |||
| int gui_flag = 0; | |||
| int frame_x, frame_y, frame_w, frame_h; | |||
| int adding_page = 0; // fix for wxWidgets (2,8,7) bug, adding first page to a wxNotebook gives emptystring for GetPageTex() in Notebook_Page_Changed event. | |||
| class MyApp: public wxApp | |||
| { | |||
| public: | |||
| bool OnInit(void); | |||
| int OnExit(void); | |||
| }; | |||
| IMPLEMENT_APP(MyApp) | |||
| @@ -100,7 +74,6 @@ wxString AppName = _T("espeakedit"); | |||
| int MyApp::OnExit() | |||
| {//================ | |||
| ConfigSave(1); | |||
| return(0); | |||
| } | |||
| @@ -127,6 +100,13 @@ if(argc > 1) | |||
| const char *p = argv[1]; | |||
| while((param[j] = p[j]) != 0) j++; | |||
| #endif | |||
| } | |||
| else | |||
| { | |||
| param[0] = '-'; | |||
| param[1] = 'h'; | |||
| param[2] = 0; | |||
| } | |||
| if((strcmp(param,"--help")==0) || (strcmp(param,"-h")==0)) | |||
| { | |||
| @@ -151,764 +131,3 @@ if(argc > 1) | |||
| } | |||
| exit(0); | |||
| } | |||
| ConfigInit(false); | |||
| gui_flag = 1; | |||
| // It seems that the wctype functions don't work until the locale has been set | |||
| // to something other than the default "C". Then, not only Latin1 but also the | |||
| // other characters give the correct results with iswalpha() etc. | |||
| if(setlocale(LC_CTYPE,"en_US.UTF-8") == NULL) | |||
| { | |||
| if(setlocale(LC_CTYPE,"UTF-8") == NULL) | |||
| setlocale(LC_CTYPE,""); | |||
| } | |||
| if((frame_w == 0) || (frame_h == 0)) | |||
| { | |||
| frame_w = 800; | |||
| frame_h = 768; | |||
| } | |||
| // Create the main frame window | |||
| myframe = new MyFrame(NULL, -1, AppName, wxPoint(frame_x, frame_y), wxSize(frame_w, frame_h), | |||
| wxDEFAULT_FRAME_STYLE | | |||
| wxNO_FULL_REPAINT_ON_RESIZE | | |||
| wxHSCROLL | wxVSCROLL); | |||
| // Make a menubar | |||
| myframe->SetMenuBar(MakeMenu(0, voice_name2)); | |||
| myframe->CreateStatusBar(); | |||
| myframe->SetVoiceTitle(voice_name2); | |||
| // myframe->Maximize(); | |||
| myframe->Show(TRUE); | |||
| SetTopWindow(myframe); | |||
| wxInitAllImageHandlers(); | |||
| // wxImage::AddHandler(wxPNGHandler); | |||
| wxLogStatus(_T("Using espeak_data at: ")+wxString(path_home, wxConvLocal)); | |||
| return TRUE; | |||
| } | |||
| BEGIN_EVENT_TABLE(MyFrame, wxFrame) | |||
| EVT_CHAR(MyFrame::OnKey) | |||
| EVT_MENU(MENU_ABOUT, MyFrame::OnAbout) | |||
| EVT_MENU(MENU_DOCS, MyFrame::OnAbout) | |||
| EVT_MENU(MENU_SPECTRUM, MyFrame::OnNewWindow) | |||
| EVT_MENU(MENU_SPECTRUM2, MyFrame::OnNewWindow) | |||
| EVT_MENU(MENU_PROSODY, MyFrame::OnProsody) | |||
| EVT_MENU(MENU_OPT_SPEED, MyFrame::OnOptions) | |||
| EVT_MENU(MENU_OPT_PUNCT, MyFrame::OnOptions) | |||
| EVT_MENU(MENU_OPT_SPELL, MyFrame::OnOptions) | |||
| EVT_MENU(MENU_OPT_SPELL2, MyFrame::OnOptions) | |||
| EVT_MENU(MENU_PATH_DATA, MyFrame::OnOptions) | |||
| EVT_MENU(MENU_PATH0, MyFrame::OnOptions) | |||
| EVT_MENU(MENU_PATH1, MyFrame::OnOptions) | |||
| EVT_MENU(MENU_PATH2, MyFrame::OnOptions) | |||
| EVT_MENU(MENU_PATH3, MyFrame::OnOptions) | |||
| EVT_MENU(MENU_PATH4, MyFrame::OnOptions) | |||
| EVT_MENU(MENU_COMPILE_PH, MyFrame::OnTools) | |||
| EVT_MENU(MENU_COMPILE_PH2, MyFrame::OnTools) | |||
| EVT_MENU(MENU_COMPILE_DICT, MyFrame::OnTools) | |||
| EVT_MENU(MENU_COMPILE_DICT_DEBUG, MyFrame::OnTools) | |||
| EVT_MENU(MENU_FORMAT_DICTIONARY, MyFrame::OnTools) | |||
| EVT_MENU(MENU_SORT_DICTIONARY, MyFrame::OnTools) | |||
| EVT_MENU(MENU_COMPILE_MBROLA, MyFrame::OnTools) | |||
| EVT_MENU(MENU_COMPILE_INTONATION, MyFrame::OnTools) | |||
| EVT_MENU(MENU_QUIT, MyFrame::OnQuit) | |||
| EVT_MENU(MENU_SPEAK_TRANSLATE, MyFrame::OnSpeak) | |||
| EVT_MENU(MENU_SPEAK_RULES, MyFrame::OnSpeak) | |||
| EVT_MENU(MENU_SPEAK_IPA, MyFrame::OnSpeak) | |||
| EVT_MENU(MENU_SPEAK_TEXT, MyFrame::OnSpeak) | |||
| EVT_MENU(MENU_SPEAK_FILE, MyFrame::OnSpeak) | |||
| EVT_MENU(MENU_SPEAK_STOP, MyFrame::OnSpeak) | |||
| EVT_MENU(MENU_SPEAK_PAUSE, MyFrame::OnSpeak) | |||
| EVT_MENU(MENU_SPEAK_VOICE, MyFrame::OnSpeak) | |||
| EVT_MENU(MENU_SPEAK_VOICE_VARIANT, MyFrame::OnSpeak) | |||
| EVT_MENU(MENU_LOAD_WAV, MyFrame::OnTools) | |||
| EVT_MENU(MENU_VOWELCHART1, MyFrame::OnTools) | |||
| EVT_MENU(MENU_VOWELCHART2, MyFrame::OnTools) | |||
| EVT_MENU(MENU_VOWELCHART3, MyFrame::OnTools) | |||
| EVT_MENU(MENU_LEXICON_RU, MyFrame::OnTools) | |||
| EVT_MENU(MENU_LEXICON_BG, MyFrame::OnTools) | |||
| EVT_MENU(MENU_LEXICON_DE, MyFrame::OnTools) | |||
| EVT_MENU(MENU_LEXICON_IT, MyFrame::OnTools) | |||
| EVT_MENU(MENU_LEXICON_TEST, MyFrame::OnTools) | |||
| EVT_MENU(MENU_TO_UTF8, MyFrame::OnTools) | |||
| EVT_MENU(MENU_COUNT_WORDS, MyFrame::OnTools) | |||
| EVT_MENU(MENU_TEST, MyFrame::OnTools) | |||
| EVT_MENU(MENU_TEST2, MyFrame::OnTools) | |||
| EVT_MENU(SPECTSEQ_SAVE, MyFrame::PageCmd) | |||
| EVT_MENU(SPECTSEQ_SAVEAS, MyFrame::PageCmd) | |||
| EVT_MENU(SPECTSEQ_SAVESELECT, MyFrame::PageCmd) | |||
| EVT_MENU(SPECTSEQ_CLOSE, MyFrame::PageCmd) | |||
| EVT_MENU(SPECTSEQ_SAVEPITCH, MyFrame::PageCmd) | |||
| EVT_MENU(MENU_CLOSE_ALL, MyFrame::PageCmd) | |||
| EVT_NOTEBOOK_PAGE_CHANGED(ID_SCREENPAGES, MyFrame::OnPageChanged) | |||
| EVT_TIMER(1, MyFrame::OnTimer) | |||
| END_EVENT_TABLE() | |||
| MyFrame::~MyFrame(void) | |||
| {//==================== | |||
| myframe->Maximize(false); | |||
| myframe->Show(false); | |||
| myframe->Iconize(false); // os=Windows, get the non-iconsized size | |||
| myframe->GetPosition(&frame_x, &frame_y); | |||
| myframe->GetSize(&frame_w, &frame_h); | |||
| } | |||
| MyFrame::MyFrame(wxWindow *parent, const wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, | |||
| const long style): | |||
| wxFrame(parent, id, title, pos, size, style) | |||
| {//=================================================================================================================== | |||
| // Main Frame constructor | |||
| int error_flag = 0; | |||
| int result; | |||
| int param; | |||
| int srate; | |||
| notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxSize(312,760)); | |||
| // notebook->AddPage(voicedlg,_T("Voice"),FALSE); | |||
| formantdlg = new FormantDlg(notebook); | |||
| notebook->AddPage(formantdlg,_T(" Spect"),FALSE); | |||
| voicedlg = new VoiceDlg(notebook); | |||
| transldlg = new TranslDlg(notebook); | |||
| notebook->AddPage(transldlg,_T("Text"),TRUE); | |||
| screenpages = new wxNotebook(this, ID_SCREENPAGES, wxDefaultPosition, wxSize(554,702)); | |||
| wxBoxSizer *framesizer = new wxBoxSizer( wxHORIZONTAL ); | |||
| framesizer->Add( | |||
| notebook, | |||
| 0, // make horizontally stretchable | |||
| wxEXPAND | // make vertically stretchable | |||
| wxALL, // and make border all around | |||
| 4 ); // set border width | |||
| framesizer->Add( | |||
| screenpages, | |||
| 1, // make horizontally stretchable | |||
| wxEXPAND | // make vertically stretchable | |||
| wxALL, // and make border all around | |||
| 4 ); // set border width | |||
| SetSizer( framesizer ); // use the sizer for layout | |||
| framesizer->SetSizeHints( this ); // set size hints to honour minimum size | |||
| SetSize(pos.x, pos.y, size.GetWidth(), size.GetHeight()); | |||
| LoadConfig(); | |||
| if((result = LoadPhData(&srate)) != 1) | |||
| { | |||
| if(result == -1) | |||
| wxLogError(_T("Failed to read espeak-data/phontab,phondata,phonindex\nPath = ")+wxString(path_home,wxConvLocal)+_T("\n\nThe 'eSpeak' package needs to be installed")); | |||
| else | |||
| wxLogError(_T("Wrong version of espeak-data at:\n")+ wxString(path_home,wxConvLocal)+_T("\nVersion 0x%x (expects 0x%x)"),result,version_phdata); | |||
| error_flag = 1; | |||
| srate = 22050; | |||
| } | |||
| WavegenInit(srate,0); | |||
| WavegenInitSound(); | |||
| f_trans = stdout; | |||
| option_ssml = 1; | |||
| option_phoneme_input = 1; | |||
| // if(LoadVoice(voice_name,0) == NULL) | |||
| if(SetVoiceByName(voice_name2) != EE_OK) | |||
| { | |||
| if(error_flag==0) | |||
| wxLogError(_T("Failed to load voice data")); | |||
| strcpy(dictionary_name,"en"); | |||
| } | |||
| WavegenSetVoice(voice); | |||
| for(param=0; param<N_SPEECH_PARAM; param++) | |||
| param_stack[0].parameter[param] = param_defaults[param]; | |||
| SetParameter(espeakRATE,option_speed,0); | |||
| SetSpeed(3); | |||
| SynthesizeInit(); | |||
| InitSpectrumDisplay(); | |||
| InitProsodyDisplay(); | |||
| // InitWaveDisplay(); | |||
| espeak_ListVoices(NULL); | |||
| m_timer.SetOwner(this,1); | |||
| m_timer.Start(500); /* 0.5 timer */ | |||
| } // end of MyFrame::MyFrame | |||
| void MyFrame::SetVoiceTitle(char *voice_name) | |||
| {//========================================== | |||
| char buf[100]; | |||
| if(samplerate_native == 22050) | |||
| sprintf(buf, " - %s voice", voice_name); | |||
| else | |||
| sprintf(buf, " - %s voice %dHz", voice_name, samplerate_native); | |||
| SetTitle(AppName + wxString(buf,wxConvLocal)); | |||
| if((data_menu != NULL) && (translator != NULL)) | |||
| { | |||
| sprintf(buf,"Compile &dictionary '%s'",translator->dictionary_name); | |||
| data_menu->SetLabel(MENU_COMPILE_DICT, wxString(buf,wxConvLocal)); | |||
| sprintf(buf,"&Layout '%s_rules' file",translator->dictionary_name); | |||
| data_menu->SetLabel(MENU_FORMAT_DICTIONARY, wxString(buf,wxConvLocal)); | |||
| sprintf(buf,"&Sort '%s_rules' file",translator->dictionary_name); | |||
| data_menu->SetLabel(MENU_SORT_DICTIONARY, wxString(buf,wxConvLocal)); | |||
| } | |||
| } | |||
| void MyFrame::PageCmd(wxCommandEvent& event) | |||
| {//========================================= | |||
| int pagenum; | |||
| int ix; | |||
| int n_pages; | |||
| SpectDisplay *page; | |||
| // if(currentcanvas != NULL) | |||
| { | |||
| pagenum = screenpages->GetSelection(); | |||
| switch(event.GetId()) | |||
| { | |||
| case SPECTSEQ_SAVE: | |||
| currentcanvas->Save(currentcanvas->savepath); | |||
| break; | |||
| case SPECTSEQ_SAVEAS: | |||
| currentcanvas->Save(); | |||
| screenpages->SetPageText(screenpages->GetSelection(), currentcanvas->spectseq->name+_T(" ²")); | |||
| break; | |||
| case SPECTSEQ_SAVESELECT: | |||
| currentcanvas->Save(_T(""), 1); | |||
| break; | |||
| case SPECTSEQ_CLOSE: | |||
| if(screenpages->GetPageText(pagenum) != _T("Prosody")) | |||
| { | |||
| currentcanvas->OnActivate(0); | |||
| } | |||
| screenpages->DeletePage(pagenum); | |||
| if((n_pages = screenpages->GetPageCount()) > 0) | |||
| { | |||
| if(pagenum >= n_pages) | |||
| pagenum--; | |||
| page = (SpectDisplay *)screenpages->GetPage(pagenum); | |||
| if(screenpages->GetPageText(pagenum) == _T("Prosody")) | |||
| { | |||
| MakeMenu(3, NULL); | |||
| } | |||
| else | |||
| { | |||
| page->OnActivate(1); | |||
| MakeMenu(2, NULL); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| MakeMenu(1, NULL); | |||
| } | |||
| break; | |||
| case MENU_CLOSE_ALL: | |||
| n_pages = screenpages->GetPageCount(); | |||
| for(ix=n_pages-1; ix>=0; ix--) | |||
| { | |||
| screenpages->DeletePage(ix); | |||
| } | |||
| currentcanvas = NULL; | |||
| MakeMenu(1, NULL); | |||
| break; | |||
| case SPECTSEQ_SAVEPITCH: | |||
| currentcanvas->SavePitchenv(currentcanvas->spectseq->pitchenv); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| void MyFrame::OnPageChanged(wxNotebookEvent& event) | |||
| {//================================================= | |||
| int pagenum; | |||
| wxString title; | |||
| SpectDisplay *page; | |||
| pagenum = event.GetSelection(); | |||
| if(event.GetId() == ID_SCREENPAGES) | |||
| { | |||
| title = screenpages->GetPageText(pagenum); | |||
| if((title != _T("Prosody")) && (adding_page != 2)) | |||
| { | |||
| page = (SpectDisplay *)screenpages->GetPage(pagenum); | |||
| if(page != currentcanvas) | |||
| { | |||
| if(currentcanvas != NULL) | |||
| { | |||
| currentcanvas->OnActivate(0); | |||
| } | |||
| page->OnActivate(1); | |||
| } | |||
| MakeMenu(2, NULL); | |||
| } | |||
| else | |||
| { | |||
| MakeMenu(3, NULL); | |||
| } | |||
| } | |||
| adding_page = 0; // work around for wxNotebook bug (version 2.8.7) | |||
| } | |||
| void MyFrame::OnKey(wxKeyEvent& event) | |||
| { | |||
| int key; | |||
| key = event.GetKeyCode(); | |||
| if((currentcanvas != NULL) && (currentcanvas != FindFocus())) | |||
| { | |||
| if((key == WXK_F1) || (key == WXK_F2)) | |||
| { | |||
| currentcanvas->OnKey(event); | |||
| currentcanvas->SetFocus(); | |||
| return; | |||
| } | |||
| } | |||
| event.Skip(); | |||
| } | |||
| void MyFrame::OnTimer(wxTimerEvent &event) | |||
| //**************************************** | |||
| { | |||
| SynthOnTimer(); | |||
| } | |||
| void MyFrame::OnQuit(wxCommandEvent& event) | |||
| { | |||
| switch(event.GetId()) | |||
| { | |||
| case MENU_QUIT: | |||
| Close(TRUE); | |||
| break; | |||
| case MENU_CLOSE_ALL: | |||
| break; | |||
| } | |||
| } | |||
| class HtmlWindow: public wxHtmlWindow | |||
| { | |||
| public: | |||
| HtmlWindow(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style); | |||
| void OnLinkClicked(const wxHtmlLinkInfo& link); | |||
| }; | |||
| HtmlWindow::HtmlWindow(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style): | |||
| wxHtmlWindow(parent, id, pos, size, style) | |||
| { | |||
| } | |||
| void HtmlWindow::OnLinkClicked(const wxHtmlLinkInfo& link) | |||
| { | |||
| if(wxLaunchDefaultBrowser(link.GetHref()) == FALSE) | |||
| wxLogStatus(_T("Failed to launch default browser: "+link.GetHref())); | |||
| } | |||
| void MyFrame::OnAbout(wxCommandEvent& event) | |||
| {//========================================= | |||
| int result; | |||
| char buf[300]; | |||
| wxString url_docs; | |||
| switch(event.GetId()) | |||
| { | |||
| case MENU_ABOUT: | |||
| { | |||
| wxDialog dlg(this, wxID_ANY, wxString(_("About"))); | |||
| sprintf(buf,about_string,espeak_Info(NULL)); | |||
| HtmlWindow *html = new HtmlWindow(&dlg, wxID_ANY, wxDefaultPosition, wxSize(380, 160), wxHW_SCROLLBAR_NEVER); | |||
| html -> SetBorders(0); | |||
| html -> SetPage(wxString(buf,wxConvLocal)); | |||
| html -> SetSize(html -> GetInternalRepresentation() -> GetWidth(), | |||
| html -> GetInternalRepresentation() -> GetHeight()); | |||
| wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL); | |||
| topsizer -> Add(html, 1, wxALL, 10); | |||
| //#if wxUSE_STATLINE | |||
| // topsizer -> Add(new wxStaticLine(&dlg, wxID_ANY), 0, wxEXPAND | wxLEFT | wxRIGHT, 10); | |||
| //#endif // wxUSE_STATLINE | |||
| wxButton *bu1 = new wxButton(&dlg, wxID_OK, _("OK")); | |||
| bu1 -> SetDefault(); | |||
| topsizer -> Add(bu1, 0, wxALL | wxALIGN_RIGHT, 15); | |||
| dlg.SetSizer(topsizer); | |||
| topsizer -> Fit(&dlg); | |||
| dlg.ShowModal(); | |||
| } | |||
| break; | |||
| case MENU_DOCS: | |||
| strcpy(buf,"/docs/docindex.html"); | |||
| url_docs = wxGetCwd() + wxString(buf,wxConvLocal); // look for "docs" in the current directory | |||
| if(!wxFileExists(url_docs)) | |||
| { | |||
| strcpy(buf,"http://espeak.sourceforge.net/docindex.html"); | |||
| url_docs = wxString(buf,wxConvLocal); | |||
| } | |||
| else | |||
| { | |||
| url_docs = _T("file://") + url_docs; | |||
| } | |||
| result = wxLaunchDefaultBrowser(url_docs); | |||
| if(result == 0) | |||
| wxLogStatus(_T("Failed to launch default browser: "+url_docs)); | |||
| break; | |||
| } | |||
| } | |||
| void OnOptions2(int event_id) | |||
| {//========================== | |||
| wxString string; | |||
| int value; | |||
| switch(event_id) | |||
| { | |||
| case MENU_OPT_SPEED: | |||
| value = wxGetNumberFromUser(_T(""),_T(""),_T("Speed"),option_speed,80,500); | |||
| if(value > 0) | |||
| { | |||
| option_speed = value; | |||
| SetParameter(espeakRATE,option_speed,0); | |||
| SetSpeed(3); | |||
| } | |||
| break; | |||
| case MENU_OPT_PUNCT: | |||
| transldlg->t_source->SetValue(_T("<tts:style field=\"punctuation\" mode=\"all\">\n")); | |||
| transldlg->t_source->SetInsertionPointEnd(); | |||
| notebook->SetSelection(1); | |||
| break; | |||
| case MENU_OPT_SPELL: | |||
| transldlg->t_source->SetValue(_T("<say-as interpret-as=\"characters\">\n")); | |||
| transldlg->t_source->SetInsertionPointEnd(); | |||
| notebook->SetSelection(1); | |||
| break; | |||
| case MENU_OPT_SPELL2: | |||
| transldlg->t_source->SetValue(_T("<say-as interpret-as=\"tts:char\">\n")); | |||
| transldlg->t_source->SetInsertionPointEnd(); | |||
| notebook->SetSelection(1); | |||
| break; | |||
| case MENU_PATH_DATA: | |||
| string = wxDirSelector(_T("espeak_data directory"), path_espeakdata); | |||
| if(!string.IsEmpty()) | |||
| { | |||
| if(!wxDirExists(string+_T("/voices"))) | |||
| { | |||
| wxLogError(_T("No 'voices' directory in ") + string); | |||
| break; | |||
| } | |||
| path_espeakdata = string; | |||
| wxLogMessage(_T("Quit and restart espeakedit to use the new espeak_data location")); | |||
| } | |||
| break; | |||
| case MENU_PATH0: | |||
| string = wxFileSelector(_T("Master phonemes file"),wxFileName(path_phfile).GetPath(), | |||
| _T("phonemes"),_T(""),_T("*"),wxOPEN); | |||
| if(!string.IsEmpty()) | |||
| { | |||
| path_phfile = string; | |||
| } | |||
| break; | |||
| case MENU_PATH1: | |||
| string = wxDirSelector(_T("Phoneme source directory"),path_phsource); | |||
| if(!string.IsEmpty()) | |||
| { | |||
| path_phsource = string; | |||
| } | |||
| break; | |||
| case MENU_PATH2: | |||
| string = wxDirSelector(_T("Dictionary source directory"),path_dictsource); | |||
| if(!string.IsEmpty()) | |||
| { | |||
| path_dictsource = string; | |||
| } | |||
| break; | |||
| case MENU_PATH3: | |||
| string = wxFileSelector(_T("Sound output file"),wxFileName(path_speech).GetPath(), | |||
| _T(""),_T("WAV"),_T("*"),wxSAVE); | |||
| if(!string.IsEmpty()) | |||
| { | |||
| path_speech = string; | |||
| } | |||
| break; | |||
| case MENU_PATH4: | |||
| string = wxFileSelector(_T("Voice file to modify formant peaks"),wxFileName(path_speech).GetPath(), | |||
| _T(""),_T(""),_T("*"),wxOPEN); | |||
| if(!string.IsEmpty()) | |||
| { | |||
| path_modifiervoice = string; | |||
| } | |||
| break; | |||
| } | |||
| ConfigSetPaths(); | |||
| } | |||
| void MyFrame::OnOptions(wxCommandEvent& event) | |||
| {//=========================================== | |||
| OnOptions2(event.GetId()); | |||
| } | |||
| void DisplayErrorFile(const char *fname) | |||
| {//===================================== | |||
| int len; | |||
| FILE *f; | |||
| char *msg; | |||
| wxString msg_string; | |||
| len = GetFileLength(fname); | |||
| if(len > 0) | |||
| { | |||
| if(len > 1500) | |||
| len = 1500; // restrict length to prevent crash in wxLogMessage() | |||
| msg = (char *)malloc(len+1); | |||
| if(msg != NULL) | |||
| { | |||
| f = fopen(fname,"r"); | |||
| len = fread(msg,1, len, f); | |||
| fclose(f); | |||
| msg[len] = 0; | |||
| msg_string = wxString(msg,wxConvUTF8); | |||
| wxLogMessage(msg_string); | |||
| free(msg); | |||
| } | |||
| } | |||
| } // end of DisplayErrorFile | |||
| void MyFrame::OnTools(wxCommandEvent& event) | |||
| {//========================================= | |||
| int err; | |||
| FILE *log; | |||
| int debug_flag=0; | |||
| char fname_log[sizeof(path_dsource)+12]; | |||
| char err_fname[sizeof(path_home)+15]; | |||
| static unsigned const char utf8_bom[] = {0xef,0xbb,0xbf,0}; | |||
| switch(event.GetId()) | |||
| { | |||
| case MENU_TEST: | |||
| TestTest(0); | |||
| break; | |||
| case MENU_TEST2: | |||
| TestTest(2); | |||
| break; | |||
| case MENU_TO_UTF8: | |||
| ConvertToUtf8(); | |||
| break; | |||
| case MENU_COUNT_WORDS: | |||
| MakeWordFreqList(); | |||
| break; | |||
| case MENU_LEXICON_RU: | |||
| case MENU_LEXICON_BG: | |||
| case MENU_LEXICON_DE: | |||
| case MENU_LEXICON_IT: | |||
| case MENU_LEXICON_TEST: | |||
| CompareLexicon(event.GetId()); // Compare a lexicon with _rules translation | |||
| break; | |||
| case MENU_COMPILE_PH: | |||
| CompilePhonemeData(); | |||
| SetVoiceTitle(voice_name2); | |||
| break; | |||
| case MENU_COMPILE_PH2: | |||
| CompileSampleRate(); | |||
| SetVoiceTitle(voice_name2); | |||
| break; | |||
| case MENU_COMPILE_MBROLA: | |||
| { | |||
| wxString filepath = wxFileSelector(_T("Read Mbrola phonemes file"),path_phsource+_T("/mbrola"),_T(""),_T(""),_T("*"),wxOPEN); | |||
| espeak_ng_CompileMbrolaVoice(filepath.mb_str(wxConvLocal), stdout); | |||
| } | |||
| break; | |||
| case MENU_COMPILE_INTONATION: | |||
| { | |||
| FILE *f_errors; | |||
| char fname_errors[sizeof(path_source)+120]; | |||
| sprintf(fname_errors,"%s%s",path_source,"error_intonation"); | |||
| if((f_errors = fopen(fname_errors,"w")) == NULL) | |||
| f_errors = stderr; | |||
| espeak_ng_STATUS status = CompileIntonation(f_errors); | |||
| if (f_errors != stderr) | |||
| fclose(f_errors); | |||
| if (status == ENE_COMPILE_ERRORS) | |||
| DisplayErrorFile(fname_errors); | |||
| } | |||
| break; | |||
| case MENU_COMPILE_DICT_DEBUG: | |||
| debug_flag =1; // and drop through to next case | |||
| case MENU_COMPILE_DICT: | |||
| sprintf(fname_log,"%s%s",path_dsource,"dict_log"); | |||
| log = fopen(fname_log,"w"); | |||
| if(log != NULL) | |||
| { | |||
| fprintf(log, "%s", utf8_bom); | |||
| } | |||
| LoadDictionary(translator, translator->dictionary_name, 0); | |||
| if((err = CompileDictionary(path_dsource,translator->dictionary_name,log,err_fname,debug_flag)) < 0) | |||
| { | |||
| wxLogError(_T("Can't access file:\n")+wxString(err_fname,wxConvLocal)); | |||
| wxString dir = wxDirSelector(_T("Directory containing dictionary files"),path_dictsource); | |||
| if(!dir.IsEmpty()) | |||
| { | |||
| path_dictsource = dir; | |||
| strncpy0(path_dsource,path_dictsource.mb_str(wxConvLocal),sizeof(path_dsource)-1); | |||
| strcat(path_dsource,"/"); | |||
| } | |||
| break; | |||
| } | |||
| wxLogStatus(_T("Compiled '")+wxString(dictionary_name,wxConvLocal)+_T("', %d errors"),err); | |||
| if(log != NULL) | |||
| { | |||
| fclose(log); | |||
| if(err > 0) | |||
| { | |||
| // display the error messages | |||
| DisplayErrorFile(fname_log); | |||
| } | |||
| } | |||
| break; | |||
| case MENU_FORMAT_DICTIONARY: | |||
| DictionaryFormat(dictionary_name); | |||
| break; | |||
| case MENU_SORT_DICTIONARY: | |||
| DictionarySort(dictionary_name); | |||
| break; | |||
| case MENU_VOWELCHART1: | |||
| MakeVowelLists(); | |||
| break; | |||
| case MENU_VOWELCHART2: | |||
| VowelChart(2,NULL); | |||
| break; | |||
| case MENU_VOWELCHART3: | |||
| VowelChart(3,NULL); | |||
| break; | |||
| case MENU_LOAD_WAV: | |||
| // LoadWavFile(); | |||
| break; | |||
| } | |||
| } | |||
| void MyFrame::OnSpeak(wxCommandEvent& event) | |||
| {//========================================= | |||
| switch(event.GetId()) | |||
| { | |||
| case MENU_SPEAK_TRANSLATE: | |||
| case MENU_SPEAK_RULES: | |||
| case MENU_SPEAK_IPA: | |||
| case MENU_SPEAK_TEXT: | |||
| transldlg->OnCommand(event); | |||
| break; | |||
| case MENU_SPEAK_FILE: | |||
| out_ptr = NULL; | |||
| transldlg->SpeakFile(); | |||
| break; | |||
| case MENU_SPEAK_STOP: | |||
| SpeakNextClause(NULL,NULL,2); | |||
| break; | |||
| case MENU_SPEAK_PAUSE: | |||
| out_ptr = NULL; | |||
| SpeakNextClause(NULL,NULL,3); | |||
| if(SynthStatus() & 2) | |||
| speak_menu->SetLabel(MENU_SPEAK_PAUSE,_T("&Resume")); | |||
| else | |||
| { | |||
| speak_menu->SetLabel(MENU_SPEAK_PAUSE,_T("&Pause")); | |||
| } | |||
| break; | |||
| case MENU_SPEAK_VOICE: | |||
| transldlg->ReadVoice(0); | |||
| SetVoiceTitle(voice_name2); | |||
| break; | |||
| case MENU_SPEAK_VOICE_VARIANT: | |||
| transldlg->ReadVoice(1); | |||
| SetVoiceTitle(voice_name2); | |||
| break; | |||
| } | |||
| } | |||
| @@ -1,574 +0,0 @@ | |||
| /*************************************************************************** | |||
| * Copyright (C) 2006 to 2007 by Jonathan Duddington * | |||
| * email: [email protected] * | |||
| * * | |||
| * This program is free software; you can redistribute it and/or modify * | |||
| * it under the terms of the GNU General Public License as published by * | |||
| * the Free Software Foundation; either version 3 of the License, or * | |||
| * (at your option) any later version. * | |||
| * * | |||
| * This program is distributed in the hope that it will be useful, * | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
| * GNU General Public License for more details. * | |||
| * * | |||
| * You should have received a copy of the GNU General Public License * | |||
| * along with this program; if not, write see: * | |||
| * <http://www.gnu.org/licenses/>. * | |||
| ***************************************************************************/ | |||
| // For compilers that support precompilation, includes "wx/wx.h". | |||
| #include "wx/wx.h" | |||
| #include "wx/mdi.h" | |||
| #include "speak_lib.h" | |||
| #include "main.h" | |||
| #include "speech.h" | |||
| #include "phoneme.h" | |||
| #include "synthesize.h" | |||
| #include "voice.h" | |||
| #include "spect.h" | |||
| #include "wx/textctrl.h" | |||
| #include "wx/checkbox.h" | |||
| FormantDlg *formantdlg=NULL; | |||
| ByteGraph *pitchgraph=NULL; | |||
| BEGIN_EVENT_TABLE(FormantDlg, wxPanel) | |||
| EVT_BUTTON(T_ZOOMOUT,FormantDlg::OnCommand) | |||
| EVT_BUTTON(T_ZOOMIN,FormantDlg::OnCommand) | |||
| EVT_SPINCTRL(-1,FormantDlg::OnSpin) | |||
| // EVT_SPINCTRL(T_TIMESEQ,FormantDlg::OnSpin) | |||
| // EVT_SPINCTRL(T_AMPFRAME,FormantDlg::OnSpin) | |||
| // EVT_SPINCTRL(T_TIMEFRAME,FormantDlg::OnSpin) | |||
| END_EVENT_TABLE() | |||
| int use_spin_controls=0; | |||
| void FormantDlg::OnCommand(wxCommandEvent& event) | |||
| {//============================================= | |||
| int id; | |||
| if(currentcanvas == NULL) | |||
| return; | |||
| switch(id = event.GetId()) | |||
| { | |||
| case T_ZOOMIN: | |||
| case T_ZOOMOUT: | |||
| currentcanvas->OnZoom(id); | |||
| break; | |||
| case T_AMPLITUDE: | |||
| currentcanvas->RefreshDialogValues(0); | |||
| break; | |||
| case T_TIMEFRAME: | |||
| case T_AMPFRAME: | |||
| currentcanvas->RefreshDialogValues(1); | |||
| break; | |||
| } | |||
| currentcanvas->SetFocus(); | |||
| } | |||
| void FormantDlg::OnSpin(wxSpinEvent& event) | |||
| {//============================================= | |||
| int id; | |||
| if(currentcanvas == NULL) | |||
| return; | |||
| switch(id = event.GetId()) | |||
| { | |||
| case T_AMPFRAME: | |||
| currentcanvas->RefreshDialogValues(1); | |||
| break; | |||
| default: | |||
| currentcanvas->RefreshDialogValues(0); | |||
| break; | |||
| } | |||
| currentcanvas->SetFocus(); | |||
| } | |||
| FormantDlg::FormantDlg(wxWindow *parent) : wxPanel(parent,-1,wxDefaultPosition,wxSize(400,800)) | |||
| {//============================================================================================= | |||
| int ix; | |||
| int y; | |||
| int xplace; | |||
| int id; | |||
| wxString string; | |||
| wxString control_name; | |||
| int height; | |||
| int width; | |||
| int x; | |||
| int y2 = 420; | |||
| int y3 = 520; | |||
| wxClientDisplayRect(&x,&y,&width, &height); | |||
| #ifdef PLATFORM_WINDOWS | |||
| if(height <= 768) | |||
| { | |||
| y2 = 410; | |||
| y3 = 508; | |||
| } | |||
| #else | |||
| if(height <= 800) | |||
| { | |||
| y2 = 378; | |||
| y3 = 456; | |||
| } | |||
| #endif | |||
| y = 24; | |||
| xplace = 28; | |||
| id = 201; | |||
| new wxStaticText(this,-1,_T("Formants"),wxPoint(4,5)); | |||
| new wxStaticText(this,-1,_T(" Ht Width (Klatt)"),wxPoint(78,5),wxSize(300,20)); | |||
| new wxStaticText(this,-1,_T("Bw Ap Bp"),wxPoint(188,29),wxSize(300,20)); | |||
| for(ix=0; ix < 8; ix++) | |||
| { | |||
| string.Printf(_T("%d"),ix); | |||
| t_labpk[ix] = new wxStaticText(this,id++,string, | |||
| wxPoint(xplace-22,y+1+24*ix)); | |||
| if(ix < 7) | |||
| { | |||
| control_name.Printf(_T("Formant %d"),ix); | |||
| t_pkfreq[ix] = new wxTextCtrl(this,id++,_T(""), | |||
| wxPoint(xplace,y+24*ix),wxSize(44,20), | |||
| wxTE_CENTRE,wxDefaultValidator,control_name); | |||
| } | |||
| control_name.Printf(_T("Height %d"),ix); | |||
| t_pkheight[ix] = new wxTextCtrl(this,id++,_T(""), | |||
| wxPoint(xplace+46,y+24*ix),wxSize(36,20), | |||
| wxTE_CENTRE,wxDefaultValidator,control_name); | |||
| if(ix < 6) | |||
| { | |||
| control_name.Printf(_T("Width %d"),ix); | |||
| t_pkwidth[ix] = new wxTextCtrl(this,id++,_T(""), | |||
| wxPoint(xplace+84,y+24*ix),wxSize(60,20), | |||
| wxTE_CENTRE,wxDefaultValidator,control_name); | |||
| } | |||
| if((ix == 0) || (ix > 6)) continue; | |||
| if(ix < 4) | |||
| { | |||
| control_name.Printf(_T("Klatt bandwidth %d"),ix); | |||
| t_klt_bw[ix] = new wxTextCtrl(this,id++,_T(""), | |||
| wxPoint(xplace+150,y+24*ix),wxSize(40,20), | |||
| wxTE_CENTRE,wxDefaultValidator,control_name); | |||
| } | |||
| control_name.Printf(_T("Klatt parallal %d"),ix); | |||
| t_klt_ap[ix] = new wxTextCtrl(this,id++,_T(""), | |||
| wxPoint(xplace+192,y+24*ix),wxSize(36,20), | |||
| wxTE_CENTRE,wxDefaultValidator,control_name); | |||
| control_name.Printf(_T("Klatt parallel bandwidth %d"),ix); | |||
| t_klt_bp[ix] = new wxTextCtrl(this,id++,_T(""), | |||
| wxPoint(xplace+230,y+24*ix),wxSize(40,20), | |||
| wxTE_CENTRE,wxDefaultValidator,control_name); | |||
| } | |||
| y=224; | |||
| if(use_spin_controls) | |||
| { | |||
| t_timeframe = new wxSpinCtrl(this,T_TIMEFRAME,_T(""), wxPoint(6,y+0), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Frame length")); | |||
| } | |||
| else | |||
| { | |||
| tt_timeframe = new wxTextCtrl(this,T_TIMEFRAME,_T(""), wxPoint(6,y+0), wxSize(52,24), wxTE_CENTRE,wxDefaultValidator,_T("Frame length")); | |||
| } | |||
| t_orig_frame = new wxStaticText(this,-1,_T("mS"),wxPoint(61,y+8)); | |||
| t_ampframe = new wxSpinCtrl(this,T_AMPFRAME,_T(""), wxPoint(104,y+0), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Frame amplitude")); | |||
| t_lab[3] = new wxStaticText(this,-1,_T("% amp - Frame"),wxPoint(159,y+8)); | |||
| y += 40; | |||
| s_klatt[KLATT_AV] = new wxSpinCtrl(this,T_AV,_T(""), wxPoint(6,y), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Klatt AV")); | |||
| t_klatt[KLATT_AV] = new wxStaticText(this,-1,_T("AV"),wxPoint(61,y+4)); | |||
| s_klatt[KLATT_FNZ] = new wxSpinCtrl(this,T_FNZ,_T(""), wxPoint(104,y), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Klatt FNZ")); | |||
| t_klatt[KLATT_FNZ] = new wxStaticText(this,-1,_T("FNZ"),wxPoint(159,y+4)); | |||
| y += 28; | |||
| s_klatt[KLATT_Tilt] = new wxSpinCtrl(this,T_TILT,_T(""), wxPoint(6,y), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Klatt tilt")); | |||
| t_klatt[KLATT_Tilt] = new wxStaticText(this,-1,_T("Tilt"),wxPoint(61,y+4)); | |||
| s_klatt[KLATT_Aspr] = new wxSpinCtrl(this,T_ASPR,_T(""), wxPoint(104,y), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Klatt aspiration")); | |||
| t_klatt[KLATT_Aspr] = new wxStaticText(this,-1,_T("Aspr"),wxPoint(159,y+4)); | |||
| s_klatt[KLATT_Skew] = new wxSpinCtrl(this,T_SKEW,_T(""), wxPoint(202,y), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Klatt skew")); | |||
| t_klatt[KLATT_Skew] = new wxStaticText(this,-1,_T("Skew"),wxPoint(257,y+4)); | |||
| y += 28; | |||
| s_klatt[KLATT_AVp] = new wxSpinCtrl(this,T_AVP,_T(""), wxPoint(6,y), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Klatt AVp")); | |||
| t_klatt[KLATT_AVp] = new wxStaticText(this,-1,_T("AVp"),wxPoint(61,y+4)); | |||
| 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")); | |||
| t_klatt[KLATT_Fric] = new wxStaticText(this,-1,_T("Fric"),wxPoint(159,y+4)); | |||
| 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")); | |||
| t_klatt[KLATT_FricBP] = new wxStaticText(this,-1,_T("FricBP"),wxPoint(257,y+4)); | |||
| y += 28; | |||
| s_klatt[KLATT_Kopen] = new wxSpinCtrl(this,T_KOPEN,_T(""), wxPoint(6,y), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Klatt KOpen")); | |||
| t_klatt[KLATT_Kopen] = new wxStaticText(this,-1,_T("kopen"),wxPoint(61,y+4)); | |||
| s_klatt[KLATT_Turb] = new wxSpinCtrl(this,T_TURB,_T(""), wxPoint(104,y), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Klatt turbulence")); | |||
| t_klatt[KLATT_Turb] = new wxStaticText(this,-1,_T("Turb"),wxPoint(159,y+4)); | |||
| t_zoomout = new wxButton(this,T_ZOOMOUT,_T("Zoom-"),wxPoint(16,y2)); | |||
| t_zoomin = new wxButton(this,T_ZOOMIN,_T("Zoom+"),wxPoint(106,y2)); | |||
| y = y2 + 46; | |||
| t_amplitude = new wxSpinCtrl(this,T_AMPLITUDE,_T(""), | |||
| wxPoint(6,y),wxSize(52,24),wxTE_CENTRE,0,y+130,0,_T("Sequence amp")); | |||
| t_lab[2] = new wxStaticText(this,-1,_T("% amp - Sequence"),wxPoint(61,y+4)); | |||
| // t_timeseq = new wxSpinCtrl(this,T_TIMESEQ,_T(""), | |||
| // wxPoint(6,400),wxSize(52,24),wxTE_CENTRE,0,500); | |||
| t_orig_seq = new wxStaticText(this,-1,_T("mS"),wxPoint(61,y+30)); | |||
| t_pitch = new wxStaticText(this,-1,_T(""),wxPoint(4,y3),wxSize(192,24)); | |||
| pitchgraph = new ByteGraph(this,wxPoint(0,y3+18),wxSize(200,140)); | |||
| pitchgraph->SetData(128,env_fall); | |||
| pitchgraph->ShowSpectrum(1); | |||
| pitchgraph->Show(); | |||
| } | |||
| void FormantDlg::GetValues(SpectSeq *spectseq, int frame) | |||
| {//====================================================== | |||
| int ix; | |||
| wxString value; | |||
| long num; | |||
| SpectFrame *sf; | |||
| if(spectseq->frames == NULL) | |||
| return; | |||
| sf = spectseq->frames[frame]; | |||
| if(use_spin_controls == 0) | |||
| { | |||
| formantdlg->tt_timeframe->GetValue().ToLong(&num); | |||
| sf->length_adjust = num - spectseq->GetFrameLength(frame,0,NULL); | |||
| } | |||
| for(ix=0; ix < 8; ix++) | |||
| { | |||
| if(ix < 7) | |||
| { | |||
| num = 0; | |||
| value = t_pkfreq[ix]->GetValue(); | |||
| value.ToLong(&num); | |||
| sf->peaks[ix].pkfreq = num; | |||
| } | |||
| num = 0; | |||
| value = t_pkheight[ix]->GetValue(); | |||
| value.ToLong(&num); | |||
| sf->peaks[ix].pkheight = num << 6; | |||
| if(ix < 6) | |||
| { | |||
| num = 0; | |||
| value = t_pkwidth[ix]->GetValue(); | |||
| value.ToLong(&num); | |||
| sf->peaks[ix].pkwidth = sf->peaks[ix].pkright = num*2; | |||
| if((ix < 3) && ((value = value.AfterFirst('/')) != wxEmptyString)) | |||
| { | |||
| num = 0; | |||
| value.ToLong(&num); | |||
| sf->peaks[ix].pkright = num*2; | |||
| } | |||
| } | |||
| } | |||
| for(ix=1; ix < 7; ix++) | |||
| { | |||
| if(ix < 4) | |||
| { | |||
| num = 0; | |||
| value = t_klt_bw[ix]->GetValue(); | |||
| value.ToLong(&num); | |||
| sf->peaks[ix].klt_bw = num; | |||
| } | |||
| num = 0; | |||
| value = t_klt_ap[ix]->GetValue(); | |||
| value.ToLong(&num); | |||
| sf->peaks[ix].klt_ap = num; | |||
| num = 0; | |||
| value = t_klt_bp[ix]->GetValue(); | |||
| value.ToLong(&num); | |||
| sf->peaks[ix].klt_bp = num; | |||
| } | |||
| } // end of FormantDlg::GetValues | |||
| void FormantDlg::ShowFrame(SpectSeq *spectseq, int frame, int pk, int field) | |||
| {//============================================================== | |||
| int ix; | |||
| SpectFrame *sf; | |||
| wxString value; | |||
| int original_mS; | |||
| peak_t *peak; | |||
| if(spectseq->frames == NULL) | |||
| return; | |||
| sf = spectseq->frames[frame]; | |||
| if(field == 0xff) | |||
| { | |||
| // indicate the selected peak | |||
| // t_select_peak[pk]->SetValue(TRUE); | |||
| } | |||
| for(ix=0; ix < 8; ix++) | |||
| { | |||
| if(field != 0xff && pk!=ix) | |||
| continue; | |||
| if(field == 0xff) | |||
| { | |||
| if(pk==ix) | |||
| value.Printf(_T("%d="),ix); | |||
| else | |||
| value.Printf(_T("%d"),ix); | |||
| t_labpk[ix]->SetLabel(value); | |||
| } | |||
| peak = &(sf->peaks[ix]); | |||
| if((field & 1) && (ix < 7)) | |||
| { | |||
| value.Printf(_T("%4d"),sf->peaks[ix].pkfreq); | |||
| t_pkfreq[ix]->SetValue(value); | |||
| } | |||
| if(field & 2) | |||
| { | |||
| value.Printf(_T("%3d"),sf->peaks[ix].pkheight >> 6); | |||
| t_pkheight[ix]->SetValue(value); | |||
| } | |||
| if((field & 4) && (ix < 6)) | |||
| { | |||
| if(sf->peaks[ix].pkwidth == sf->peaks[ix].pkright) | |||
| value.Printf(_T("%3d"),sf->peaks[ix].pkwidth/2); | |||
| else | |||
| value.Printf(_T("%3d/%3d"),sf->peaks[ix].pkwidth/2, sf->peaks[ix].pkright/2); | |||
| t_pkwidth[ix]->SetValue(value); | |||
| } | |||
| if((ix > 0) && (ix < 7)) | |||
| { | |||
| if((field & 8) && (ix < 4)) | |||
| { | |||
| value.Printf(_T("%3d"),peak->klt_bw); | |||
| t_klt_bw[ix]->SetValue(value); | |||
| } | |||
| if(field & 16) | |||
| { | |||
| value.Printf(_T("%3d"),peak->klt_ap); | |||
| t_klt_ap[ix]->SetValue(value); | |||
| } | |||
| if(field & 32) | |||
| { | |||
| value.Printf(_T("%3d"),peak->klt_bp); | |||
| t_klt_bp[ix]->SetValue(value); | |||
| } | |||
| } | |||
| } | |||
| // find the time until the next keyframe | |||
| value.Printf(_T("%d"),int(spectseq->GetFrameLength(frame,1,&original_mS)+0.5)); // round to nearest integer | |||
| if(use_spin_controls) | |||
| t_timeframe->SetValue(value); | |||
| else | |||
| tt_timeframe->SetValue(value); | |||
| value.Printf(_T("%d mS"),original_mS); | |||
| t_orig_frame->SetLabel(value); | |||
| value.Printf(_T("%3d"),sf->amp_adjust); | |||
| t_ampframe->SetValue(value); | |||
| for(ix=0; ix<N_KLATTP; ix++) | |||
| { | |||
| SetSpinCtrl(s_klatt[ix], sf->klatt_param[ix]); | |||
| } | |||
| } // end of FormantDlg::ShowFrame | |||
| BEGIN_EVENT_TABLE(ByteGraph,wxScrolledWindow) | |||
| EVT_LEFT_DOWN(ByteGraph::OnMouse) | |||
| END_EVENT_TABLE() | |||
| static wxBrush BRUSH_FORMANT(wxColour(255,100,50),wxSOLID); | |||
| static wxPen PEN_KEYFRAME(wxColour(255,220,100),2,wxSOLID); | |||
| static wxPen PEN_KEYFORMANT(wxColour(0,0,0),2,wxSOLID); | |||
| ByteGraph::ByteGraph(wxWindow *parent, const wxPoint& pos, const wxSize &size): | |||
| wxScrolledWindow(parent,-1,pos,size,wxSUNKEN_BORDER) | |||
| {//============================================================ | |||
| npoints = 0; | |||
| show_spectrum = 0; | |||
| } // end of ByteGraph::ByteGraph | |||
| void ByteGraph::SetData(int nx, unsigned char *data) | |||
| {//================================================= | |||
| npoints = nx; | |||
| graph = data; | |||
| Refresh(); | |||
| } // end of ByteGraph::SetData | |||
| void ByteGraph::ShowSpectrum(int yes) | |||
| {//================================== | |||
| show_spectrum = yes; | |||
| } | |||
| void ByteGraph::DrawSpectrum(wxDC& dc) | |||
| {//=================================== | |||
| SpectSeq *seq; | |||
| SpectFrame *sf; | |||
| int ix; | |||
| int x, y; | |||
| int pk; | |||
| double length; | |||
| int numframes; | |||
| int width, height; | |||
| double xscale, yscale; | |||
| spectrum_scale = 0; | |||
| if(currentcanvas==NULL) return; | |||
| if((seq = currentcanvas->spectseq) == NULL) return; | |||
| numframes = seq->numframes; | |||
| if(numframes == 0) return; | |||
| GetClientSize(&width,&height); | |||
| if(((length = seq->frames[numframes-1]->time)==0) && (numframes>1)) | |||
| length = seq->frames[numframes-2]->time; | |||
| length = length - seq->frames[0]->time; | |||
| yscale = height/3000.0; | |||
| spectrum_scale = xscale = width/length; | |||
| dc.SetBrush(BRUSH_FORMANT); | |||
| dc.SetPen(*wxTRANSPARENT_PEN); | |||
| for(ix=0; ix<numframes; ix++) | |||
| { | |||
| sf = seq->frames[ix]; | |||
| x = int(sf->time*xscale); | |||
| if(sf->keyframe) | |||
| { | |||
| dc.SetPen(PEN_KEYFRAME); | |||
| dc.DrawLine(x,0,x,height); | |||
| } | |||
| dc.SetPen(*wxTRANSPARENT_PEN); | |||
| dc.DrawCircle(x,int(height-(sf->formants[1].freq-200)*yscale),3); | |||
| dc.DrawCircle(x,int(height-(sf->formants[2].freq-200)*yscale),3); | |||
| dc.DrawCircle(x,int(height-(sf->formants[3].freq-200)*yscale),3); | |||
| if(sf->keyframe) | |||
| { | |||
| dc.SetPen(PEN_KEYFORMANT); | |||
| for(pk=1; pk<6; pk++) | |||
| { | |||
| y = height-int((sf->peaks[pk].pkfreq-200)*yscale); | |||
| dc.DrawLine(x-3,y,x+3,y); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void ByteGraph::OnDraw(wxDC &dc) | |||
| {//============================ | |||
| int x, y, x2, y2, ix; | |||
| int width, height; | |||
| double xscale, yscale; | |||
| if(show_spectrum) DrawSpectrum(dc); | |||
| if(npoints==0) return; | |||
| GetClientSize(&width,&height); | |||
| xscale = double(width) / npoints; | |||
| yscale = double(height) / 256.0; | |||
| if(npoints > 8) | |||
| { | |||
| // draw pitch profile | |||
| dc.SetPen(*wxMEDIUM_GREY_PEN); | |||
| x = 0; | |||
| y = height - int(graph[0]*yscale); | |||
| for(ix=1; ix<npoints; ix++) | |||
| { | |||
| dc.DrawLine(x,y,x2=int(ix*xscale),y2=height - int(graph[ix]*yscale)); | |||
| x = x2; | |||
| y = y2; | |||
| } | |||
| } | |||
| } // end of ByteGraph::OnDraw | |||
| void ByteGraph::OnMouse(wxMouseEvent& event) | |||
| {//======================================== | |||
| int ix; | |||
| SpectSeq *seq; | |||
| double time; | |||
| double t0, t1; | |||
| double t2=0; | |||
| if(currentcanvas==NULL) return; | |||
| if((seq = currentcanvas->spectseq) == NULL) return; | |||
| wxClientDC dc(this); | |||
| PrepareDC(dc); | |||
| wxPoint pt(event.GetLogicalPosition(dc)); | |||
| t0 = t2 = seq->frames[0]->time; | |||
| time = (double(pt.x) / spectrum_scale) + t0; | |||
| for(ix=1; ix<seq->numframes; ix++) | |||
| { | |||
| t1=t2; | |||
| t2 = seq->frames[ix]->time; | |||
| if(time <= t1 + (t2-t1)/2) | |||
| { | |||
| currentcanvas->SelectFrame(ix-1); | |||
| break; | |||
| } | |||
| } | |||
| } // end of ByteGraph::OnMouse | |||
| @@ -1,190 +0,0 @@ | |||
| #include "wx/toolbar.h" | |||
| #include "wx/laywin.h" | |||
| #include "wx/progdlg.h" | |||
| #include "wx/notebook.h" | |||
| typedef unsigned short USHORT; | |||
| typedef unsigned char UCHAR; | |||
| extern wxMenuBar *MakeMenu(int type, const char *dict_name); | |||
| extern wxString path_phsource; | |||
| extern wxString path_speaktext; | |||
| extern wxString path_speech; | |||
| extern wxProgressDialog *progress; | |||
| extern int progress_max; | |||
| extern int gui_flag; | |||
| extern char *WavFileName(); | |||
| extern char voice_name2[40]; | |||
| class SpectDisplay; | |||
| // Define a new application | |||
| class MyApp: public wxApp | |||
| { | |||
| public: | |||
| bool OnInit(void); | |||
| int OnExit(void); | |||
| }; | |||
| // Define a new frame | |||
| class MyFrame: public wxFrame | |||
| { | |||
| public: | |||
| MyFrame(wxWindow *parent, const wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, const long style); | |||
| ~MyFrame(void); | |||
| void OnAbout(wxCommandEvent& event); | |||
| void OnQuit(wxCommandEvent& event); | |||
| void OnOptions(wxCommandEvent& event); | |||
| void OnSpeak(wxCommandEvent& event); | |||
| void OnTools(wxCommandEvent& event); | |||
| void OnKey(wxKeyEvent& event); | |||
| void OnTimer(wxTimerEvent& event); | |||
| void LoadWavFile(void); | |||
| void OnNewWindow(wxCommandEvent& event); | |||
| void OnProsody(wxCommandEvent& event); | |||
| void PageCmd(wxCommandEvent& event); | |||
| void SetVoiceTitle(char *voice_name); | |||
| void OnPageChanged(wxNotebookEvent& event); | |||
| protected: | |||
| wxTimer m_timer; | |||
| DECLARE_EVENT_TABLE() | |||
| }; | |||
| #ifdef deleted | |||
| class MyChild: public wxPanel | |||
| { | |||
| public: | |||
| SpectDisplay *canvas; | |||
| MyChild(wxNotebook *parent, const wxString& title, const wxPoint& pos, const wxSize& size, const long style); | |||
| ~MyChild(void); | |||
| void OnActivate(wxActivateEvent& event); | |||
| void OnQuit(wxCommandEvent& event); | |||
| void OnSave(wxCommandEvent& event); | |||
| void OnSaveAs(wxCommandEvent& event); | |||
| void OnSaveSelect(wxCommandEvent& event); | |||
| void OnSavePitchenv(wxCommandEvent& event); | |||
| // void OnVoiceDlg(wxCommandEvent& event); | |||
| DECLARE_EVENT_TABLE() | |||
| }; | |||
| #endif | |||
| class TranslDlg : public wxPanel | |||
| {//============================= | |||
| public: | |||
| TranslDlg(wxWindow *parent); | |||
| void OnKey(wxKeyEvent& event); | |||
| void SpeakFile(void); | |||
| void ReadVoice(int variant); | |||
| void OnCommand(wxCommandEvent& event); | |||
| wxTextCtrl* t_source; | |||
| private: | |||
| wxButton *t_translate; | |||
| wxButton *t_process; | |||
| wxTextCtrl* t_phonetic; | |||
| DECLARE_EVENT_TABLE() | |||
| }; | |||
| extern MyFrame *myframe; | |||
| extern wxNotebook* screenpages; | |||
| extern TranslDlg *transldlg; | |||
| extern wchar_t ipa1[256]; | |||
| enum { | |||
| MENU_QUIT = 1, | |||
| MENU_OPEN, | |||
| MENU_SPECTRUM, | |||
| MENU_SPECTRUM2, | |||
| MENU_CLOSE_ALL, | |||
| MENU_ABOUT, | |||
| MENU_DOCS, | |||
| MENU_OPTIONS, | |||
| MENU_OPT_SPEED, | |||
| MENU_OPT_PUNCT, | |||
| MENU_OPT_SPELL, | |||
| MENU_OPT_SPELL2, | |||
| MENU_PATHS, | |||
| MENU_PATH_DATA, | |||
| MENU_PATH0, | |||
| MENU_PATH1, | |||
| MENU_PATH2, | |||
| MENU_PATH3, | |||
| MENU_PATH4, | |||
| MENU_PROSODY, | |||
| MENU_COMPILE_PH, | |||
| MENU_COMPILE_PH2, | |||
| MENU_COMPILE_DICT, | |||
| MENU_COMPILE_DICT_DEBUG, | |||
| MENU_FORMAT_DICTIONARY, | |||
| MENU_SORT_DICTIONARY, | |||
| MENU_COMPILE_MBROLA, | |||
| MENU_COMPILE_INTONATION, | |||
| MENU_SPEAK_TRANSLATE, | |||
| MENU_SPEAK_RULES, | |||
| MENU_SPEAK_IPA, | |||
| MENU_SPEAK_TEXT, | |||
| MENU_SPEAK_FILE, | |||
| MENU_SPEAK_PAUSE, | |||
| MENU_SPEAK_STOP, | |||
| MENU_SPEAK_VOICE, | |||
| MENU_SPEAK_VOICE_VARIANT, | |||
| MENU_LOAD_WAV, | |||
| MENU_VOWELCHART, | |||
| MENU_VOWELCHART1, | |||
| MENU_VOWELCHART2, | |||
| MENU_VOWELCHART3, | |||
| MENU_LEXICON, | |||
| MENU_LEXICON_RU, | |||
| MENU_LEXICON_BG, | |||
| MENU_LEXICON_DE, | |||
| MENU_LEXICON_IT, | |||
| MENU_LEXICON_TEST, | |||
| MENU_TO_UTF8, | |||
| MENU_COUNT_WORDS, | |||
| MENU_TEST, | |||
| MENU_TEST2, | |||
| SPECTSEQ_CLOSE, | |||
| SPECTSEQ_SAVE, | |||
| SPECTSEQ_SAVEAS, | |||
| SPECTSEQ_SAVESELECT, | |||
| SPECTSEQ_SAVEPITCH, | |||
| SPECTSEQ_VOICEDLG, | |||
| ID_SCREENPAGES, | |||
| ID_NOTEBOOK | |||
| }; | |||
| // wxWidgets 3 name changes | |||
| #if wxCHECK_VERSION(3, 0, 0) | |||
| #define wxOPEN wxFD_OPEN | |||
| #define wxSAVE wxFD_SAVE | |||
| #define WXK_PRIOR WXK_PAGEUP | |||
| #define WXK_NEXT WXK_PAGEDOWN | |||
| #endif | |||
| @@ -1,174 +0,0 @@ | |||
| /*************************************************************************** | |||
| * Copyright (C) 2005 to 2013 by Jonathan Duddington * | |||
| * email: [email protected] * | |||
| * * | |||
| * This program is free software; you can redistribute it and/or modify * | |||
| * it under the terms of the GNU General Public License as published by * | |||
| * the Free Software Foundation; either version 3 of the License, or * | |||
| * (at your option) any later version. * | |||
| * * | |||
| * This program is distributed in the hope that it will be useful, * | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
| * GNU General Public License for more details. * | |||
| * * | |||
| * You should have received a copy of the GNU General Public License * | |||
| * along with this program; if not, see: * | |||
| * <http://www.gnu.org/licenses/>. * | |||
| ***************************************************************************/ | |||
| #include "wx/wx.h" | |||
| #include "main.h" | |||
| wxMenu *speak_menu; | |||
| wxMenu *data_menu = NULL; | |||
| wxMenuBar *menu_bar = NULL; | |||
| wxMenuBar *MakeMenu(int type, const char *dict_name) | |||
| {//=================================================== | |||
| char buf[100]; | |||
| wxMenu *old_menu; | |||
| wxMenu *file_menu; | |||
| wxMenu *help_menu; | |||
| wxMenu *option_menu = NULL; | |||
| wxMenu *paths_menu; | |||
| wxMenu *tools_menu; | |||
| wxMenu *voice_menu; | |||
| wxMenu *vowelchart_menu; | |||
| wxMenu *lexicon_menu; | |||
| // FILE MENU | |||
| file_menu = new wxMenu; | |||
| file_menu->Append(MENU_SPECTRUM, _("&Open...")); | |||
| file_menu->Append(MENU_SPECTRUM2, _("O&pen2...")); | |||
| // file_menu->Append(MENU_PROSODY, _T("&Prosody window")); | |||
| if(type<=1) | |||
| { | |||
| } | |||
| else | |||
| if(type==2) | |||
| { | |||
| file_menu->Append(SPECTSEQ_SAVE, _("&Save")); | |||
| file_menu->Append(SPECTSEQ_SAVEAS, _("Save &As...")); | |||
| file_menu->Append(SPECTSEQ_SAVESELECT, _("Save Selection")); | |||
| file_menu->Append(SPECTSEQ_SAVEPITCH, _T("Save Pitch &Envelope")); | |||
| file_menu->Append(SPECTSEQ_CLOSE, _("&Close")); | |||
| file_menu->Append(MENU_CLOSE_ALL, _T("Close &All")); | |||
| } | |||
| else | |||
| if(type==3) | |||
| { | |||
| // file_menu->Append(SPECTSEQ_SAVE, _("&Save")); | |||
| // file_menu->Append(SPECTSEQ_SAVEAS, _("Save &As...")); | |||
| file_menu->Append(SPECTSEQ_CLOSE, _("&Close")); | |||
| file_menu->Append(MENU_CLOSE_ALL, _T("Close &All")); | |||
| } | |||
| file_menu->Append(MENU_QUIT, _("&Quit")); | |||
| if(type==0) | |||
| { | |||
| // Initialization, make all the menus | |||
| // SPEAK_MENU | |||
| speak_menu = new wxMenu; | |||
| speak_menu->Append(MENU_SPEAK_TRANSLATE, _("&Translate")); | |||
| speak_menu->Append(MENU_SPEAK_RULES, _("Show &Rules")); | |||
| speak_menu->Append(MENU_SPEAK_IPA, _("Show &IPA")); | |||
| speak_menu->Append(MENU_SPEAK_TEXT, _("&Speak")); | |||
| speak_menu->AppendSeparator(); | |||
| speak_menu->Append(MENU_SPEAK_FILE, _("Speak &file...")); | |||
| speak_menu->Append(MENU_SPEAK_PAUSE, _("&Pause")); | |||
| speak_menu->Append(MENU_SPEAK_STOP, _("St&op")); | |||
| // VOICE MENU | |||
| voice_menu = new wxMenu; | |||
| voice_menu->Append(MENU_SPEAK_VOICE, _("Select &Voice..")); | |||
| voice_menu->Append(MENU_SPEAK_VOICE_VARIANT, _("Select Voice Va&riant...")); | |||
| // DATA MENU | |||
| data_menu = new wxMenu; | |||
| data_menu->Append(MENU_COMPILE_DICT, _("Compile &dictionary")); | |||
| data_menu->Append(MENU_COMPILE_DICT_DEBUG, _("Compile dictionary (debu&g)")); | |||
| data_menu->Append(MENU_COMPILE_PH, _("Compile &phoneme data 22050Hz")); | |||
| data_menu->Append(MENU_COMPILE_PH2, _("Compile at sample &rate")); | |||
| data_menu->AppendSeparator(); | |||
| data_menu->Append(MENU_COMPILE_MBROLA, _("Compile &mbrola phonemes list...")); | |||
| data_menu->Append(MENU_COMPILE_INTONATION, _("Compile &intonation data")); | |||
| data_menu->AppendSeparator(); | |||
| data_menu->Append(MENU_FORMAT_DICTIONARY, _("&Layout *_rules file")); | |||
| data_menu->Append(MENU_SORT_DICTIONARY, _("&Sort *_rules file")); | |||
| sprintf(buf,"Compile &dictionary '%s'",dict_name); | |||
| data_menu->SetLabel(MENU_COMPILE_DICT, wxString(buf,wxConvLocal)); | |||
| sprintf(buf,"&Layout '%s_rules' file",dict_name); | |||
| data_menu->SetLabel(MENU_FORMAT_DICTIONARY, wxString(buf,wxConvLocal)); | |||
| sprintf(buf,"&Sort '%s_rules' file",dict_name); | |||
| data_menu->SetLabel(MENU_SORT_DICTIONARY, wxString(buf,wxConvLocal)); | |||
| // OPTIONS MENU | |||
| paths_menu = new wxMenu; | |||
| paths_menu->Append(MENU_PATH0, _("Master phonemes file...")); | |||
| paths_menu->Append(MENU_PATH1, _("Phoneme data source...")); | |||
| paths_menu->Append(MENU_PATH2, _("Dictionary data source...")); | |||
| paths_menu->Append(MENU_PATH3, _("Synthesized sound WAV file...")); | |||
| paths_menu->AppendSeparator(); | |||
| paths_menu->Append(MENU_PATH4, _("Voice file to modify formant peaks...")); | |||
| option_menu = new wxMenu; | |||
| option_menu->Append(MENU_PATHS, _("Set &paths"), paths_menu); | |||
| option_menu->Append(MENU_OPT_SPEED, _("Speed...")); | |||
| option_menu->AppendSeparator(); | |||
| option_menu->Append(MENU_OPT_PUNCT, _("Speak punctuation")); | |||
| option_menu->Append(MENU_OPT_SPELL, _("Speak characters")); | |||
| option_menu->Append(MENU_OPT_SPELL2, _("Speak character name")); | |||
| // TOOLS | |||
| vowelchart_menu = new wxMenu; | |||
| vowelchart_menu->Append(MENU_VOWELCHART1, _("From compiled phoneme data")); | |||
| // vowelchart_menu->Append(MENU_VOWELCHART2, _("From list of formants...")); | |||
| vowelchart_menu->Append(MENU_VOWELCHART3, _("From directory of vowel files...")); | |||
| lexicon_menu = new wxMenu; | |||
| lexicon_menu->Append(MENU_LEXICON_RU, _("Russian")); | |||
| lexicon_menu->Append(MENU_LEXICON_BG, _("Bulgarian")); | |||
| lexicon_menu->Append(MENU_LEXICON_DE, _("German")); | |||
| lexicon_menu->Append(MENU_LEXICON_IT, _("Italian")); | |||
| // lexicon_menu->Append(MENU_LEXICON_TEST, _("Test")); | |||
| tools_menu = new wxMenu; | |||
| tools_menu->Append(MENU_VOWELCHART, _("Make &Vowels Chart"), vowelchart_menu); | |||
| // tools_menu->Append(MENU_LOAD_WAV, _T("Analyse WAV file")); | |||
| tools_menu->Append(MENU_LEXICON, _("Process &Lexicon"), lexicon_menu); | |||
| tools_menu->Append(MENU_TO_UTF8, _("Convert file to &UTF8...")); | |||
| tools_menu->Append(MENU_COUNT_WORDS, _("Count word &frequencies...")); | |||
| tools_menu->Append(MENU_TEST , _("Test (temporary)")); | |||
| // tools_menu->Append(MENU_TEST2 , _T("Test2")); | |||
| // HELP MENU | |||
| help_menu = new wxMenu; | |||
| help_menu->Append(MENU_DOCS, _("eSpeak &Documentation")); | |||
| help_menu->Append(MENU_ABOUT, _("&About")); | |||
| menu_bar = new wxMenuBar; | |||
| menu_bar->Append(file_menu, _("&File")); | |||
| menu_bar->Append(speak_menu, _("&Speak")); | |||
| menu_bar->Append(voice_menu, _("&Voice")); | |||
| menu_bar->Append(option_menu, _("&Options")); | |||
| menu_bar->Append(tools_menu, _("&Tools")); | |||
| menu_bar->Append(data_menu, _("&Compile")); | |||
| menu_bar->Append(help_menu, _("&Help")); | |||
| } | |||
| else | |||
| { | |||
| // Just replace the File menu | |||
| old_menu = menu_bar->Replace(0, file_menu, _("&File")); | |||
| delete old_menu; | |||
| } | |||
| return(menu_bar); | |||
| } // end of MakeMenu | |||
| @@ -29,86 +29,20 @@ | |||
| #include "wx/msw/registry.h" | |||
| #endif | |||
| #include "main.h" | |||
| #include "options.h" | |||
| extern "C" void WavegenInit(int samplerate, int wavemult_fact); | |||
| extern void strncpy0(char *to,const char *from, int size); | |||
| extern int GetNumeric(wxTextCtrl *t); | |||
| extern void SetNumeric(wxTextCtrl *t, int value); | |||
| extern int samplerate; | |||
| wxString path_espeakdata; | |||
| wxString path_spectload; | |||
| wxString path_spectload2; | |||
| wxString path_pitches; | |||
| wxString path_wave; | |||
| wxString path_speech; | |||
| wxString path_phfile; | |||
| wxString path_phsource; | |||
| wxString path_dictsource; | |||
| wxString path_speaktext; | |||
| wxString path_modifiervoice; | |||
| wxString path_dir1; | |||
| int option_speed=160; | |||
| char path_source[sizeof(path_home)+20]; | |||
| char path_dsource[sizeof(path_home)+20]; | |||
| char voice_name2[40]; | |||
| BEGIN_EVENT_TABLE(Options, wxDialog) | |||
| EVT_BUTTON(wxID_SAVE,Options::OnCommand) | |||
| EVT_BUTTON(wxID_CLOSE,Options::OnCommand) | |||
| END_EVENT_TABLE() | |||
| Options::Options(wxWindow *parent) : wxDialog(parent,-1,_T("Options"),wxDefaultPosition,wxDefaultSize) | |||
| {//=================================================================================================== | |||
| m_lab[0] = new wxStaticText(this,-1,_T("Sample rate"),wxPoint(72,84)); | |||
| m_samplerate = new wxTextCtrl(this,-1,_T(""),wxPoint(8,80),wxSize(60,24)); | |||
| SetNumeric(m_samplerate,samplerate); | |||
| m_save = new wxButton(this,wxID_SAVE,_T("Save"),wxPoint(8,120)); | |||
| m_close = new wxButton(this,wxID_CLOSE,_T("Cancel"),wxPoint(98,120)); | |||
| Show(); | |||
| } | |||
| Options::~Options() | |||
| {//================ | |||
| int ix; | |||
| for(ix=0; ix < 1; ix++) | |||
| delete m_lab[ix]; | |||
| delete m_samplerate; | |||
| delete m_save; | |||
| delete m_close; | |||
| } | |||
| void Options::OnCommand(wxCommandEvent& event) | |||
| {//=========================================== | |||
| int id; | |||
| int value; | |||
| switch(id = event.GetId()) | |||
| { | |||
| case wxID_SAVE: | |||
| value = GetNumeric(m_samplerate); | |||
| if(value > 0) WavegenInit(value,0); | |||
| Destroy(); | |||
| break; | |||
| case wxID_CLOSE: | |||
| Destroy(); | |||
| break; | |||
| } | |||
| } | |||
| void ConfigSetPaths() | |||
| {//================== | |||
| // set c_string paths from wxStrings | |||
| @@ -188,53 +122,12 @@ void ConfigInit(bool use_defaults) | |||
| pConfig->Read(_T("/spectload"),&path_spectload,basedir+_T("/phsource")); | |||
| pConfig->Read(_T("/spectload2"),&path_spectload2,basedir+_T("/phsource")); | |||
| pConfig->Read(_T("/pitchpath"),&path_pitches,basedir+_T("/pitch")); | |||
| pConfig->Read(_T("/wavepath"),&path_wave,wxEmptyString); | |||
| pConfig->Read(_T("/speechpath"),&path_speech,wxEmptyString); | |||
| pConfig->Read(_T("/voicename"),&string,wxEmptyString); | |||
| strcpy(voice_name2,string.mb_str(wxConvLocal)); | |||
| pConfig->Read(_T("/phsource"),&path_phsource,basedir+_T("/phsource")); | |||
| pConfig->Read(_T("/phfile"),&path_phfile,path_phsource+_T("/phonemes")); | |||
| pConfig->Read(_T("/dictsource"),&path_dictsource,basedir+_T("/dictsource")); | |||
| pConfig->Read(_T("/speaktext"),&path_speaktext,wxEmptyString); | |||
| pConfig->Read(_T("/modifiervoice"),&path_modifiervoice,basedir); | |||
| pConfig->Read(_T("/dir1"),&path_dir1,basedir); | |||
| option_speed = pConfig->Read(_T("/speed"),160); | |||
| frame_x = pConfig->Read(_T("/windowx"), 0l); | |||
| frame_y = pConfig->Read(_T("/windowy"), 0l); | |||
| frame_h = pConfig->Read(_T("/windowh"), 0l); | |||
| frame_w = pConfig->Read(_T("/windoww"), 0l); | |||
| } | |||
| ConfigSetPaths(); | |||
| } // end of ConfigInit | |||
| void ConfigSave(int exit) | |||
| {//====================== | |||
| wxFileConfig *pConfig = (wxFileConfig *)(wxConfigBase::Get()); | |||
| #ifndef PLATFORM_WINDOWS | |||
| // pConfig->Write(_T("/samplerate"),samplerate); | |||
| #endif | |||
| pConfig->Write(_T("/espeakdata"),path_espeakdata); | |||
| pConfig->Write(_T("/spectload"),path_spectload); | |||
| pConfig->Write(_T("/spectload2"),path_spectload2); | |||
| pConfig->Write(_T("/pitchpath"),path_pitches); | |||
| pConfig->Write(_T("/wavepath"),path_wave); | |||
| pConfig->Write(_T("/speechpath"),path_speech); | |||
| pConfig->Write(_T("/voicename"),wxString(voice_name2,wxConvLocal)); | |||
| pConfig->Write(_T("/phsource"),path_phsource); | |||
| pConfig->Write(_T("/phfile"),path_phfile); | |||
| pConfig->Write(_T("/dictsource"),path_dictsource); | |||
| pConfig->Write(_T("/speaktext"),path_speaktext); | |||
| pConfig->Write(_T("/speed"),option_speed); | |||
| pConfig->Write(_T("/modifiervoice"),path_modifiervoice); | |||
| pConfig->Write(_T("/dir1"),path_dir1); | |||
| pConfig->Write(_T("/windowx"),frame_x); | |||
| pConfig->Write(_T("/windowy"),frame_y); | |||
| pConfig->Write(_T("/windoww"),frame_w); | |||
| pConfig->Write(_T("/windowh"),frame_h); | |||
| if(exit) | |||
| delete wxFileConfig::Set((wxFileConfig *)NULL); | |||
| } | |||
| @@ -1,71 +0,0 @@ | |||
| /*************************************************************************** | |||
| * Copyright (C) 2005 to 2007 by Jonathan Duddington * | |||
| * email: [email protected] * | |||
| * Copyright (C) 2013 by Reece H. Dunn * | |||
| * * | |||
| * This program is free software; you can redistribute it and/or modify * | |||
| * it under the terms of the GNU General Public License as published by * | |||
| * the Free Software Foundation; either version 3 of the License, or * | |||
| * (at your option) any later version. * | |||
| * * | |||
| * This program is distributed in the hope that it will be useful, * | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
| * GNU General Public License for more details. * | |||
| * * | |||
| * You should have received a copy of the GNU General Public License * | |||
| * along with this program; if not, see: * | |||
| * <http://www.gnu.org/licenses/>. * | |||
| ***************************************************************************/ | |||
| #ifndef OPTIONS_H | |||
| #define OPTIONS_H | |||
| #include "wx/dialog.h" | |||
| #include "wx/spinctrl.h" | |||
| /** | |||
| *@author Jonathan Duddington | |||
| */ | |||
| extern void ConfigInit(bool use_defaults); | |||
| extern void ConfigSave(int end); | |||
| extern void ConfigSetPaths(); | |||
| extern wxString path_espeakdata; | |||
| extern wxString path_spectload; | |||
| extern wxString path_spectload2; | |||
| extern wxString path_pitches; | |||
| extern wxString path_phfile; | |||
| extern wxString path_phsource; | |||
| extern wxString path_dictsource; | |||
| extern wxString path_modifiervoice; | |||
| extern wxString path_dir1; | |||
| extern int frame_x, frame_y, frame_w, frame_h; | |||
| extern char path_source[sizeof(path_home)+20]; | |||
| extern char path_dsource[sizeof(path_home)+20]; | |||
| extern int option_speed; | |||
| extern void OnOptions2(int event_id); | |||
| // not currently used | |||
| class Options : public wxDialog { | |||
| public: | |||
| Options(wxWindow *parent); | |||
| ~Options(); | |||
| private: | |||
| void OnCommand(wxCommandEvent& event); | |||
| wxButton *m_save; | |||
| wxButton *m_close; | |||
| wxStaticText *m_lab[10]; | |||
| wxTextCtrl *m_samplerate; | |||
| DECLARE_EVENT_TABLE() | |||
| }; | |||
| #endif | |||
| @@ -24,36 +24,11 @@ | |||
| #include "wx/numdlg.h" | |||
| #include "speak_lib.h" | |||
| #include "main.h" | |||
| #include "speech.h" | |||
| #include "phoneme.h" | |||
| #include "synthesize.h" | |||
| #include "prosodydisplay.h" | |||
| #include "translate.h" | |||
| extern MyFrame *myframe; | |||
| extern ProsodyDisplay *prosodycanvas; | |||
| wxMenu *menu_prosody; | |||
| BEGIN_EVENT_TABLE(ProsodyDisplay, wxScrolledWindow) | |||
| EVT_LEFT_DOWN(ProsodyDisplay::OnMouse) | |||
| EVT_RIGHT_DOWN(ProsodyDisplay::OnMouse) | |||
| EVT_CHAR(ProsodyDisplay::OnKey) | |||
| EVT_MENU(-1, ProsodyDisplay::OnMenu) | |||
| END_EVENT_TABLE() | |||
| static wxPen PEN_PITCHENV(wxColour(0,0,255),1,wxSOLID); | |||
| static wxPen PEN_SAMPLED(wxColour(0,200,200),2,wxSOLID); | |||
| static wxPen PEN_PHSELECTED(wxColour(255,0,0),2,wxSOLID); | |||
| static wxPen PEN_PHSTRESSED(wxColour(80,80,196),3,wxSOLID); | |||
| static wxPen PEN_PHSTRESSED2(wxColour(160,160,255),2,wxSOLID); | |||
| typedef struct { | |||
| unsigned int value; | |||
| char *name; | |||
| @@ -131,579 +106,3 @@ void ReadPhondataManifest() | |||
| } | |||
| fclose(f); | |||
| } | |||
| ProsodyDisplay::ProsodyDisplay(wxWindow *parent, const wxPoint& pos, const wxSize& size) | |||
| : wxScrolledWindow(parent, -1, pos, size, | |||
| wxSUNKEN_BORDER | wxNO_FULL_REPAINT_ON_RESIZE) | |||
| {//===================================================================== | |||
| linewidth = size.GetWidth(); | |||
| scalex = 0.5; | |||
| scaley = double(LINESEP*6)/150.0; | |||
| selected_ph = -1; | |||
| SetBackgroundColour(wxColour(245,245,245)); | |||
| } // end of ProsodyDisplay::ProsodyDisplay | |||
| ProsodyDisplay::~ProsodyDisplay() | |||
| {//========================== | |||
| prosodycanvas = NULL; | |||
| } | |||
| extern MNEM_TAB envelope_names[]; | |||
| void InitProsodyDisplay() | |||
| {//====================== | |||
| wxMenu *menu_envelopes; | |||
| int ix; | |||
| wxString string; | |||
| ReadPhondataManifest(); | |||
| menu_envelopes = new wxMenu; | |||
| // entries match those in envelope_data[] in intonation.cpp | |||
| for(ix=0; envelope_names[ix].mnem != NULL; ix++) | |||
| { | |||
| string = wxString(envelope_names[ix].mnem, wxConvLocal); | |||
| menu_envelopes->Append(0x100+envelope_names[ix].value, string); | |||
| } | |||
| menu_prosody = new wxMenu; | |||
| menu_prosody->Append(1,_T("Pitch envelope"),menu_envelopes); | |||
| menu_prosody->Append(2,_T("Amplitude")); | |||
| menu_prosody->Append(3,_T("Length")); | |||
| menu_prosody->Append(4,_T("Play F2")); | |||
| } | |||
| void ProsodyDisplay::RefreshLine(int line) | |||
| {//===================================== | |||
| int x,y; | |||
| CalcScrolledPosition(0,line*FRAMEHEIGHT,&x,&y); | |||
| RefreshRect(wxRect(0,y,linewidth,FRAMEHEIGHT)); | |||
| } | |||
| int ProsodyDisplay::GetWidth(PHONEME_LIST *p) | |||
| {//======================================== | |||
| int w; | |||
| if(p->ph == NULL) | |||
| return(0); | |||
| w = (p->ph->std_length * 2); | |||
| if(w == 0) w = 60; | |||
| if(p->length != 0) | |||
| w = (w * p->length) / 256; | |||
| return(int((w + p->prepause)* scalex) + 1); | |||
| } | |||
| void ProsodyDisplay::SelectPh(int index) | |||
| {//===================================== | |||
| // A phoneme has been selected | |||
| PHONEME_LIST *p; | |||
| const char *emphasized; | |||
| int y1, y2; | |||
| int ix; | |||
| const char *name = "?"; | |||
| char buf[120]; | |||
| char len_string[20]; | |||
| char param_string[20]; | |||
| if(index < 0) return; | |||
| p = &phlist[index]; | |||
| if((p == NULL) || (p->ph == NULL)) return; | |||
| emphasized = ""; | |||
| if(p->stresslevel & 8) | |||
| emphasized = "*"; | |||
| for(ix=0; envelope_names[ix].mnem != NULL; ix++) | |||
| { | |||
| if(envelope_names[ix].value == (p->env & 0xfe)) | |||
| { | |||
| name = envelope_names[ix].mnem; | |||
| break; | |||
| } | |||
| } | |||
| y1 = p->pitch1; | |||
| y2 = p->pitch2; | |||
| len_string[0] = 0; | |||
| param_string[0] = 0; | |||
| if(p->std_length > 0) | |||
| sprintf(len_string," Length %d", p->std_length*2); | |||
| if(p->sound_param != 0) | |||
| sprintf(param_string,", %d", p->sound_param); | |||
| sprintf(buf,"Stress %s%d Amp %2d LengthMod %2d Pitch %3d %3d %s PhFlags %.2x (%s%s)%s", | |||
| emphasized,p->stresslevel&0x7,p->amp, p->length,y1,y2,name,p->ph->phflags, LookupManifest(p->phontab_addr), param_string, len_string); | |||
| wxLogStatus(wxString(buf,wxConvLocal)); | |||
| } | |||
| void ProsodyDisplay::ChangePh(int pitch1, int pitch2) | |||
| {//================================================ | |||
| PHONEME_LIST *p; | |||
| int sign1; | |||
| int sign2; | |||
| if(selected_ph < 0) | |||
| return; | |||
| p = &phlist[selected_ph]; | |||
| sign1 = p->pitch1 - p->pitch2; | |||
| p->pitch1 += pitch1; | |||
| p->pitch2 += (pitch1 + pitch2); | |||
| sign2 = p->pitch1 - p->pitch2; | |||
| if((sign1 != 0) && ((sign1 * sign2) <= 0)) | |||
| { | |||
| // change of sign, change rise to fall | |||
| if(p->env == 1) | |||
| p->env = 0; | |||
| else | |||
| if(p->env == 0) | |||
| p->env = 1; | |||
| } | |||
| } | |||
| void ProsodyDisplay::OnMenu(wxCommandEvent& event) | |||
| {//=============================================== | |||
| int id; | |||
| int value; | |||
| PHONEME_LIST *p; | |||
| id = event.GetId(); | |||
| p = &phlist[selected_ph]; | |||
| if((id & 0xf00) == 0x100) | |||
| { | |||
| // selected a pitch envelope | |||
| p->env = id - 0x100; | |||
| } | |||
| switch(id) | |||
| { | |||
| case 2: | |||
| value = wxGetNumberFromUser(_T(""),_T("Amplitude"),_T(""),p->amp,0,40); | |||
| if(value >= 0) | |||
| p->amp = value; | |||
| break; | |||
| case 3: | |||
| value = wxGetNumberFromUser(_T(""),_T("Length"),_T(""),p->length,1,500); | |||
| if(value >= 0) | |||
| p->length = value; | |||
| break; | |||
| case 4: | |||
| MakeWave2(phlist,numph); | |||
| break; | |||
| } | |||
| SelectPh(selected_ph); | |||
| Refresh(); | |||
| } | |||
| void ProsodyDisplay::OnMouse(wxMouseEvent& event) | |||
| {//============================================ | |||
| int line; | |||
| int ix; | |||
| int xpos=0; | |||
| wxClientDC dc(this); | |||
| PrepareDC(dc); | |||
| wxPoint pt(event.GetLogicalPosition(dc)); | |||
| if(selected_ph >= 0) | |||
| { | |||
| // find line for previously selected phoneme | |||
| for(line=0; line<num_lines; line++) | |||
| if(linetab[line+1] > selected_ph) break; | |||
| RefreshLine(line); | |||
| selected_ph = -1; | |||
| } | |||
| line = pt.y / FRAMEHEIGHT; | |||
| if(line < num_lines) | |||
| { | |||
| // find which phoneme is selected on this line | |||
| for(ix=linetab[line]; (ix<linetab[line+1]) && (ix<numph); ix++) | |||
| { | |||
| xpos += GetWidth(&phlist[ix]); | |||
| if(xpos > pt.x) | |||
| { | |||
| selected_ph = ix; | |||
| SelectPh(selected_ph); | |||
| break; | |||
| } | |||
| } | |||
| RefreshLine(line); | |||
| } | |||
| if(event.RightDown()) | |||
| { | |||
| PopupMenu(menu_prosody); | |||
| } | |||
| } // end of ProsodyDisplay::OnMouse | |||
| void ProsodyDisplay::OnKey(wxKeyEvent& event) | |||
| {//======================================== | |||
| PHONEME_LIST *p; | |||
| int display=1; | |||
| if(selected_ph < 0) | |||
| selected_ph = 0; | |||
| p = &phlist[selected_ph]; | |||
| switch(event.GetKeyCode()) | |||
| { | |||
| case WXK_F2: | |||
| // make and play from this clause | |||
| MakeWave2(phlist,numph); | |||
| break; | |||
| case WXK_LEFT: | |||
| if(selected_ph > 1) | |||
| selected_ph--; | |||
| break; | |||
| case WXK_RIGHT: | |||
| if(selected_ph < (numph-2)) | |||
| selected_ph++; | |||
| break; | |||
| case WXK_UP: | |||
| if(event.ControlDown()) | |||
| ChangePh(-1,2); | |||
| else | |||
| ChangePh(1,0); | |||
| display = 1; | |||
| break; | |||
| case WXK_DOWN: | |||
| if(event.ControlDown()) | |||
| ChangePh(1,-2); | |||
| else | |||
| ChangePh(-1,0); | |||
| break; | |||
| case ',': | |||
| case '<': | |||
| if(p->length > 0) | |||
| p->length--; | |||
| break; | |||
| case '.': | |||
| case '>': | |||
| p->length++; | |||
| break; | |||
| case WXK_TAB: | |||
| display = 0; | |||
| event.Skip(); | |||
| transldlg->SetFocus(); | |||
| break; | |||
| default: | |||
| display = 0; | |||
| event.Skip(); | |||
| break; | |||
| } | |||
| if(display) | |||
| { | |||
| Refresh(); | |||
| SelectPh(selected_ph); | |||
| } | |||
| } // end of ProsodyDisplay::OnKey | |||
| void ProsodyDisplay::DrawEnv(wxDC& dc, int x1, int y1, int width, PHONEME_LIST *ph) | |||
| {//============================================================================== | |||
| int pitchr; | |||
| int pitch; | |||
| int p1; | |||
| int ix; | |||
| int x,y; | |||
| int y2=0; | |||
| unsigned char *env; | |||
| PHONEME_DATA phdata_tone; | |||
| if(width <= 0) return; | |||
| if((pitchr = ph->pitch2 - ph->pitch1) < 0) | |||
| { | |||
| pitchr = -pitchr; | |||
| p1 = ph->pitch2; | |||
| } | |||
| else | |||
| { | |||
| p1 = ph->pitch1; | |||
| } | |||
| if(p1 == 255) return; | |||
| dc.SetPen(PEN_PITCHENV); | |||
| env = envelope_data[ph->env]; | |||
| if((ph->type == phVOWEL) && (ph->tone_ph != 0)) | |||
| { | |||
| // the envelope is given by a Tone phoneme acting on this vowel | |||
| InterpretPhoneme2(ph->tone_ph, &phdata_tone); | |||
| env = GetEnvelope(phdata_tone.pitch_env); | |||
| } | |||
| if(env == NULL) | |||
| return; | |||
| for(ix=0; ix<=width; ix+=4) | |||
| { | |||
| x = int((ix * 127.9)/width); | |||
| pitch = p1 + (pitchr * env[x])/256; | |||
| y = y1-int(pitch * scaley); | |||
| if(ix > 0) | |||
| dc.DrawLine(x1+ix-4,y2,x1+ix,y); | |||
| y2 = y; | |||
| } | |||
| } // end of DrawEnv | |||
| static void GetPhonemeName(PHONEME_TAB *ph, wxString& string) | |||
| {//========================================================== | |||
| string = wxString(WordToString(ph->mnemonic),wxConvLocal); | |||
| } | |||
| void ProsodyDisplay::DrawPitchline(wxDC& dc, int line, int x1, int x2) | |||
| {//================================================================= | |||
| int ix; | |||
| int endix; | |||
| int y; | |||
| int offy; | |||
| int xpos; | |||
| int width; // total width, including pre-pause | |||
| int width2; // width without pre-pause | |||
| int width_env; | |||
| int textwidth, textheight; | |||
| wxString string; | |||
| PHONEME_LIST *p; | |||
| if(linetab[line] >= numph) return; | |||
| offy = (line+1) * FRAMEHEIGHT - 1; | |||
| y = LINEBASE+LINESEP; | |||
| dc.SetPen(*wxLIGHT_GREY_PEN); | |||
| // dc.SetPen(*wxCYAN_PEN); | |||
| for(ix=0; ix<5; ix++) | |||
| { | |||
| dc.DrawLine(0,offy-y,linewidth,offy-y); | |||
| y += LINESEP; | |||
| } | |||
| endix = linetab[line+1]; | |||
| xpos = 0; | |||
| for(ix=linetab[line]; ix<endix; ix++) | |||
| { | |||
| if(ix < 0 || ix > numph-2) break; | |||
| if(xpos > x2) break; // past the redraw region | |||
| p = &phlist[ix]; | |||
| width = GetWidth(p); | |||
| width2 = width - int(p->prepause * scalex) - 1; | |||
| if(xpos+width < x1) | |||
| { | |||
| xpos += width; | |||
| continue; // before the redraw region | |||
| } | |||
| // is this a stressed vowel ? | |||
| if((p->type == phVOWEL) && (p->stresslevel >= 2)) | |||
| { | |||
| if(p->stresslevel >= 4) | |||
| dc.SetPen(PEN_PHSTRESSED); | |||
| else | |||
| dc.SetPen(PEN_PHSTRESSED2); | |||
| dc.DrawLine(xpos,offy-LINEBASE-1,xpos+width,offy-LINEBASE-1); | |||
| } | |||
| // is this phoneme selected ? | |||
| if(ix == selected_ph) | |||
| { | |||
| dc.SetPen(PEN_PHSELECTED); | |||
| dc.DrawLine(xpos,offy-LINEBASE,xpos+width,offy-LINEBASE); | |||
| } | |||
| // draw separator bar | |||
| if(p->newword) | |||
| dc.SetPen(*wxBLACK_PEN); // word boundary | |||
| else | |||
| dc.SetPen(*wxLIGHT_GREY_PEN); | |||
| dc.DrawLine(xpos,offy-LINEBASE,xpos,offy-LINEBASE-LINESEP*6); | |||
| // draw pitch envelope | |||
| if(((p->ph->phflags & phWAVE) == 0) && (p->ph->type != phPAUSE)) | |||
| { | |||
| if(!(p->synthflags & SFLAG_SEQCONTINUE)) | |||
| { | |||
| width_env = width2; | |||
| if(phlist[ix+1].synthflags & SFLAG_SEQCONTINUE) | |||
| width_env += GetWidth(&phlist[ix+1]); | |||
| DrawEnv(dc,xpos+1+(width-width2),offy-LINEBASE,width_env,p); | |||
| } | |||
| } | |||
| else | |||
| if(p->type != phPAUSE) | |||
| { | |||
| // sampled sound, draw a flat line | |||
| dc.SetPen(PEN_SAMPLED); | |||
| dc.DrawLine(xpos+1+(width-width2),offy-LINEBASE-LINESEP, | |||
| xpos+1+width,offy-LINEBASE-LINESEP); | |||
| } | |||
| // show phoneme name from the PHONEME_TAB | |||
| GetPhonemeName(p->ph,string); | |||
| dc.GetTextExtent(string,&textwidth,&textheight); | |||
| dc.DrawText(string,xpos+(width-textwidth/2)/2, offy-LINEBASE); | |||
| xpos += width; | |||
| } | |||
| // draw the separator bar at the end of the line | |||
| if(ix==endix && ix<numph && phlist[ix].newword) | |||
| dc.SetPen(*wxLIGHT_GREY_PEN); | |||
| else | |||
| dc.SetPen(*wxBLACK_PEN); // word boundary or end of list | |||
| dc.DrawLine(xpos,offy-LINEBASE,xpos,offy-LINEBASE-LINESEP*6); | |||
| } // end of ProsodyDisplay::DrawPitchline | |||
| void ProsodyDisplay::OnDraw(wxDC& dc) | |||
| {//================================ | |||
| int x1,y1; | |||
| int vX,vY,vW,vH; // Dimensions of client area in pixels | |||
| int line, start, end; | |||
| GetClientSize(&x1, &y1); | |||
| if(x1 != linewidth) | |||
| { | |||
| LayoutData(NULL, 0); | |||
| } | |||
| wxRegionIterator upd(GetUpdateRegion()); // get the update rect list | |||
| while (upd) | |||
| { | |||
| vX = upd.GetX(); | |||
| vY = upd.GetY(); | |||
| vW = upd.GetW(); | |||
| vH = upd.GetH(); | |||
| CalcUnscrolledPosition(vX,vY,&x1,&y1); | |||
| // Repaint this rectangle, find which lines to redraw | |||
| start = y1/FRAMEHEIGHT; | |||
| end = (y1+vH)/FRAMEHEIGHT; | |||
| for(line=start; line<=end && line<num_lines; line++) | |||
| DrawPitchline(dc,line,x1,x1+vW); | |||
| upd ++ ; | |||
| } | |||
| } // end of ProsodyDisplay::OnDraw | |||
| void ProsodyDisplay::LayoutData(PHONEME_LIST *ph_list, int n_ph) | |||
| {//=========================================================== | |||
| // divide the phoneme list into lines for display | |||
| int xpos; | |||
| int w; | |||
| int ix; | |||
| int height; | |||
| PHONEME_LIST *p; | |||
| if(ph_list != NULL) | |||
| { | |||
| numph = n_ph; | |||
| phlist = ph_list; | |||
| } | |||
| num_lines = 0; | |||
| linetab[0] = 1; | |||
| GetClientSize(&linewidth, &height); | |||
| xpos = linewidth; | |||
| // could improve this to do 'wordwrap' - only split on word boundary | |||
| // or unvoiced phonemes | |||
| for(ix=1; ix<numph-2; ix++) | |||
| { | |||
| p = &phlist[ix]; | |||
| w = GetWidth(p); | |||
| if(w + xpos >= linewidth) | |||
| { | |||
| linetab[num_lines++] = ix; | |||
| xpos = 0; | |||
| } | |||
| xpos += w; | |||
| } | |||
| linetab[num_lines]=numph-2; | |||
| SetScrollbars(SCROLLUNITS,SCROLLUNITS,linewidth/SCROLLUNITS, | |||
| (num_lines*FRAMEHEIGHT)/SCROLLUNITS+1); | |||
| Refresh(); | |||
| } // end of ProsodyDisplay::LayoutData | |||
| extern int adding_page; | |||
| void MyFrame::OnProsody(wxCommandEvent& WXUNUSED(event)) | |||
| {//===================================================== | |||
| // Open the Prosody display window | |||
| int width, height; | |||
| int ix, npages; | |||
| if(prosodycanvas != NULL) | |||
| { | |||
| // The Prosody window is already open | |||
| // ?? select the prosody page ?? | |||
| npages = screenpages->GetPageCount(); | |||
| for(ix=0; ix<npages; ix++) | |||
| { | |||
| if(screenpages->GetPage(ix) == (wxWindow*)prosodycanvas) | |||
| { | |||
| screenpages->ChangeSelection(ix); | |||
| break; | |||
| } | |||
| } | |||
| return; | |||
| } | |||
| screenpages->GetClientSize(&width, &height); | |||
| prosodycanvas = new ProsodyDisplay(screenpages, wxPoint(0, 50), wxSize(width-10, height)); | |||
| adding_page = 2; // work around for wxNotebook bug (version 2.8.7) | |||
| screenpages->AddPage(prosodycanvas, _T("Prosody"), true); | |||
| } | |||
| @@ -1,50 +0,0 @@ | |||
| #define FRAMEHEIGHT 120 | |||
| #define LINEBASE 20 | |||
| #define LINESEP 16 | |||
| #define SCROLLUNITS 20 | |||
| class ProsodyDisplay: public wxScrolledWindow | |||
| {//======================================== | |||
| public: | |||
| ProsodyDisplay(wxWindow *parent, const wxPoint& pos, const wxSize& size); | |||
| ~ProsodyDisplay(); | |||
| virtual void OnDraw(wxDC& dc); | |||
| void OnMouse(wxMouseEvent& event); | |||
| void OnKey(wxKeyEvent& event); | |||
| void OnMenu(wxCommandEvent& event); | |||
| void Save(const wxString &path=_T("")); | |||
| void LayoutData(PHONEME_LIST *phlist, int n_ph); | |||
| private: | |||
| void Redraw(wxDC& dc, int x1, int y1, int x2, int y2); | |||
| void DrawEnv(wxDC& dc, int x1, int y1, int width, PHONEME_LIST *ph); | |||
| void DrawPitchline(wxDC& dc, int line, int x1, int x2); | |||
| void RefreshLine(int line); | |||
| int GetWidth(PHONEME_LIST *p); | |||
| void ChangePh(int pitch1, int pitch2); | |||
| void SelectPh(int index); | |||
| int linewidth; // height for drawing pitch | |||
| double scalex; // scale length values | |||
| double scaley; // scale pitch values | |||
| int selected_ph; | |||
| int numph; | |||
| PHONEME_LIST *phlist; | |||
| int num_lines; | |||
| short linetab[N_PHONEME_LIST/2]; | |||
| DECLARE_EVENT_TABLE() | |||
| }; // end class ProsodyDisplay | |||
| @@ -1,7 +1,7 @@ | |||
| /*************************************************************************** | |||
| * Copyright (C) 2005 to 2007 by Jonathan Duddington * | |||
| * email: [email protected] * | |||
| * Copyright (C) 2013 by Reece H. Dunn * | |||
| * Copyright (C) 2013-2015 by Reece H. Dunn * | |||
| * * | |||
| * This program is free software; you can redistribute it and/or modify * | |||
| * it under the terms of the GNU General Public License as published by * | |||
| @@ -23,12 +23,10 @@ | |||
| #include "speak_lib.h" | |||
| #include "speech.h" | |||
| #include "main.h" | |||
| #include "phoneme.h" | |||
| #include "synthesize.h" | |||
| #include "voice.h" | |||
| #include "spect.h" | |||
| #include "options.h" | |||
| #include "wx/txtstrm.h" | |||
| #include "wx/brush.h" | |||
| #include "wx/datstrm.h" | |||
| @@ -65,33 +63,6 @@ static int default_width[N_PEAKS] = | |||
| static int default_klt_bw[N_PEAKS] = | |||
| {89,90,140,260,260,260,500,500,500}; | |||
| float SpectTilt(int value, int freq) | |||
| {//================================= | |||
| float x; | |||
| float y; | |||
| if((currentcanvas == NULL) || (currentcanvas->spectseq->bass_reduction == 0)) | |||
| return(float(value)); | |||
| y = value*value*2; | |||
| if(freq < 600) | |||
| { | |||
| return(sqrt(y/2.5)); | |||
| } | |||
| else | |||
| if(freq < 1050) | |||
| { | |||
| x = 1.0 + ((1050.0-freq)* 1.5)/450.0; | |||
| return(sqrt(y/x)); | |||
| } | |||
| else | |||
| { | |||
| return(sqrt(y)); | |||
| } | |||
| } | |||
| SpectFrame::SpectFrame(SpectFrame *copy) | |||
| {//===================================== | |||
| @@ -442,34 +413,6 @@ void SpectFrame::ToggleMarker(int n) | |||
| } | |||
| void SpectFrame::ApplyVoiceMods() | |||
| {//============================== | |||
| // apply the modifications to the formants which are defined in the current voice | |||
| int pk; | |||
| char voice_name1[40]; | |||
| strcpy(voice_name1, voice_name2); // remember current voice name | |||
| if(LoadVoice(path_modifiervoice.mb_str(wxConvLocal),0x13) == NULL) | |||
| { | |||
| wxLogError(_T("Can't read voice: ")+path_modifiervoice); | |||
| OnOptions2(MENU_PATH4); | |||
| return; | |||
| } | |||
| wxLogStatus(_T("Convert using voice: ")+path_modifiervoice); | |||
| for(pk=0; pk<N_PEAKS; pk++) | |||
| { | |||
| peaks[pk].pkfreq = (peaks[pk].pkfreq * voice->freq2[pk])/256; | |||
| peaks[pk].pkheight = (peaks[pk].pkheight * voice->height2[pk])/256; | |||
| peaks[pk].pkwidth = (peaks[pk].pkwidth * voice->width2[pk])/256; | |||
| peaks[pk].pkright = (peaks[pk].pkright * voice->width2[pk])/256; | |||
| } | |||
| LoadVoice(voice_name1,1); | |||
| } | |||
| double SpectFrame::GetRms(int seq_amplitude) | |||
| {//========================================= | |||
| @@ -581,130 +524,6 @@ rms = GetRms(seq_amplitude); | |||
| void SpectFrame::Draw(wxDC& dc, int offy, int frame_width, double scalex, double scaley) | |||
| {//===================================================================================== | |||
| int pt; | |||
| int peak; | |||
| peak_t *pk; | |||
| int ix; | |||
| double x0, x1; | |||
| int y0, y1; | |||
| int x, x2, x3; | |||
| double xinc; | |||
| double yf; | |||
| int font_height; | |||
| wxString text; | |||
| if(currentcanvas == NULL) | |||
| return; | |||
| dc.SetFont(*wxSWISS_FONT); | |||
| xinc = dx * scalex; | |||
| x0 = xinc; | |||
| x1 = nx * xinc; | |||
| if(selected) // this frame is selected | |||
| { | |||
| // highlight selected peak by drawing a red triangle | |||
| pk = &peaks[pk_select]; | |||
| x2 = int(pk->pkright * scalex * 0.44); | |||
| x3 = int(pk->pkwidth * scalex * 0.44); | |||
| x = int((pk->pkfreq) * scalex); | |||
| y1 = (pk->pkheight * FRAME_HEIGHT) >> 14; | |||
| if(y1 < 5) y1 = 5; | |||
| wxPoint triangle[3]; | |||
| dc.SetBrush(BRUSH_SELECTED_PEAK); | |||
| dc.SetPen(*wxTRANSPARENT_PEN); | |||
| triangle[0] = wxPoint(0,-y1); | |||
| triangle[1] = wxPoint(x2,0); | |||
| triangle[2] = wxPoint(-x3,0); | |||
| dc.DrawPolygon(3,triangle,x,offy); | |||
| } | |||
| // draw the measured formants | |||
| dc.SetPen(BLUE_PEN); | |||
| for(peak=1; peak<=5; peak++) | |||
| { | |||
| if(formants[peak].freq != 0) | |||
| { | |||
| // set height from linear interpolation of the adjacent | |||
| // points in the spectrum | |||
| pt = (int)(formants[peak].freq / dx); | |||
| y0 = spect[pt-1]; | |||
| y1 = spect[pt]; | |||
| yf = (y1-y0) * (formants[peak].freq - pt*dx)/dx; | |||
| y1 = offy - (int)((y0+yf) * scaley); | |||
| x1 = formants[peak].freq * scalex; | |||
| dc.DrawLine((int)x1,offy,(int)x1,y1); | |||
| } | |||
| } | |||
| // draw the spectrum outline | |||
| if(keyframe) | |||
| dc.SetPen(*wxBLACK_PEN); | |||
| else | |||
| dc.SetPen(*wxMEDIUM_GREY_PEN); | |||
| if(spect != NULL) | |||
| { | |||
| y0 = offy - (int)(spect[0] * scaley); | |||
| for(pt=1; pt<nx; pt++) | |||
| { | |||
| x1 = x0 + xinc; | |||
| y1 = offy - (int)(SpectTilt(spect[pt],int(pt*dx)) * scaley); | |||
| dc.DrawLine((int)x0,y0,(int)x1,y1); | |||
| x0 = x1; | |||
| y0 = y1; | |||
| } | |||
| } | |||
| if(currentcanvas->zoom < 2) | |||
| dc.SetFont(FONT_SMALL); | |||
| else | |||
| dc.SetFont(FONT_MEDIUM); | |||
| // Markers | |||
| x = frame_width - 120 - 32; | |||
| for(ix=0; ix<N_MARKERS; ix++) | |||
| { | |||
| if(markers & 1<<ix) | |||
| { | |||
| dc.SetBrush(BRUSH_MARKER[ix]); | |||
| y0 = offy-FRAME_HEIGHT+22; | |||
| dc.DrawRectangle(x,y0,22,22); | |||
| if(currentcanvas->zoom > 2) | |||
| { | |||
| text.Printf(_T("%d"),ix); | |||
| dc.DrawText(text,x+2,y0); | |||
| } | |||
| x -= 26; | |||
| } | |||
| } | |||
| DrawPeaks(&dc,offy,frame_width,currentcanvas->spectseq->amplitude,scalex); | |||
| font_height = int(15 / currentcanvas->zoomy); | |||
| text.Printf(_T("%3dmS %.1fHz"),int(time*1000),pitch); | |||
| dc.DrawText(text,frame_width-130,offy-FRAME_HEIGHT+20+font_height); | |||
| if(keyframe || rms > 0) | |||
| { | |||
| text.Printf(_T("%3d"),(int)rms); | |||
| dc.DrawText(text,frame_width-130,offy-FRAME_HEIGHT+20+font_height*2); | |||
| } | |||
| dc.SetPen(*wxBLACK_PEN); | |||
| dc.DrawLine(0,offy,frame_width,offy); // base line | |||
| } // end of SpectFrame::Draw | |||
| void SpectFrame::KlattDefaults() | |||
| {//============================ | |||
| // set default values for Klatt parameters | |||
| @@ -66,8 +66,6 @@ | |||
| #define FILEID2_PRAATSEQ 0x51455354 | |||
| class MyFrame; | |||
| typedef struct { | |||
| unsigned short pitch1; | |||
| unsigned short pitch2; | |||
| @@ -137,14 +135,11 @@ public: | |||
| int ImportSPC2(wxInputStream &stream, float &time_acc); | |||
| int Load(wxInputStream &stream, int file_format_type); | |||
| int Save(wxOutputStream &stream, int file_format_type); | |||
| void Draw(wxDC &dc, int offy, int frame_width, double scalex, double scaley); | |||
| void ZeroPeaks(); | |||
| void CopyPeaks(SpectFrame *sf); | |||
| void ToggleMarker(int n); | |||
| void ApplyVoiceMods(); | |||
| void MakeWaveF(int peaks, PitchEnvelope &pitch, int amplitude, int duration); | |||
| void MakeHtab(int numh, int *htab, int pitch); | |||
| double GetRms(int amp); | |||
| void KlattDefaults(); | |||
| @@ -185,18 +180,13 @@ public: | |||
| int ImportSPC2(wxInputStream& stream); | |||
| int Save(wxOutputStream& stream, int selection); | |||
| int Load(wxInputStream& stream); | |||
| void Draw(wxDC &dc, int start_y, int end_y); | |||
| void MakePitchenv(PitchEnvelope &pitch, int start_frame, int end_frame); | |||
| void MakeWave(int start, int end, PitchEnvelope &pitch); | |||
| void InterpolatePeaks(int on); | |||
| void InterpolateAdjacent(void); | |||
| void CopyDown(int frame, int direction); | |||
| void SelectAll(int yes); | |||
| int CountSelected(); | |||
| void DeleteSelected(); | |||
| void ClipboardCopy(); | |||
| int ClipboardInsert(int insert_at); | |||
| float GetFrameLength(int frame, int plus, int *original_mS); | |||
| float GetKeyedLength(); | |||
| void SetFrameLengths(); | |||
| @@ -227,174 +217,3 @@ private: | |||
| double scaley; | |||
| }; | |||
| class SpectDisplay: public wxScrolledWindow | |||
| {//======================================== | |||
| public: | |||
| SpectDisplay(wxWindow *parent, const wxPoint& pos, const wxSize& size, SpectSeq *spect); | |||
| ~SpectDisplay(); | |||
| virtual void OnDraw(wxDC& dc); | |||
| void OnMouse(wxMouseEvent& event); | |||
| void OnKey(wxKeyEvent& event); | |||
| void OnActivate(int active); | |||
| void OnMenu(wxCommandEvent& event); | |||
| void Save(const wxString &path=_T(""),int selection=0); | |||
| void SavePitchenv(PitchEnvelope &pitch); | |||
| void OnZoom(int command); | |||
| SpectSeq *spectseq; | |||
| float zoomx; | |||
| float zoomy; | |||
| int zoom; | |||
| wxString savepath; | |||
| void ReadDialogValues(); | |||
| void WriteDialogValues(); | |||
| void WriteDialogLength(); | |||
| void RefreshDialogValues(int type); | |||
| int ScrollToFrame(int frame, int centre); | |||
| void SelectFrame(int frame); | |||
| private: | |||
| void RefreshFrame(int frame); | |||
| void SetKeyframe(SpectFrame *sf, int yes); | |||
| void SetExtent(); | |||
| int sframe; | |||
| int pk_num; | |||
| DECLARE_EVENT_TABLE() | |||
| }; | |||
| class ByteGraph: public wxScrolledWindow | |||
| {//===================================== | |||
| public: | |||
| ByteGraph(wxWindow *parent, const wxPoint& pos, const wxSize &size); | |||
| virtual void OnDraw(wxDC &dc); | |||
| void SetData(int nx, unsigned char *data); | |||
| void ShowSpectrum(int yes); | |||
| private: | |||
| int npoints; | |||
| unsigned char *graph; | |||
| int show_spectrum; | |||
| double spectrum_scale; | |||
| void DrawSpectrum(wxDC &dc); | |||
| void OnMouse(wxMouseEvent& event); | |||
| DECLARE_EVENT_TABLE() | |||
| }; | |||
| class FormantDlg : public wxPanel | |||
| {//============================== | |||
| public: | |||
| FormantDlg(wxWindow *parent); | |||
| void ShowFrame(SpectSeq *spectseq, int frame, int pk, int field); | |||
| void GetValues(SpectSeq *spectseq, int frame); | |||
| void OnCommand(wxCommandEvent& event); | |||
| void OnSpin(wxSpinEvent& event); | |||
| void HideFields(int synth_type); | |||
| wxCheckBox *usepitchenv; | |||
| wxSpinCtrl *t_amplitude; | |||
| wxSpinCtrl *t_ampframe; | |||
| wxSpinCtrl *t_timeframe; | |||
| wxTextCtrl *tt_timeframe; | |||
| wxSpinCtrl *t_timeseq; | |||
| wxStaticText *t_pitch; | |||
| wxStaticText *t_orig_frame; | |||
| wxStaticText *t_orig_seq; | |||
| wxSpinCtrl *s_klatt[N_KLATTP]; | |||
| wxStaticText *t_klatt[N_KLATTP]; | |||
| private: | |||
| wxStaticText *t_lab[10]; | |||
| wxStaticText *t_labpk[N_PEAKS]; | |||
| wxTextCtrl *t_pkfreq[N_PEAKS]; | |||
| wxTextCtrl *t_pkheight[N_PEAKS]; | |||
| wxTextCtrl *t_pkwidth[N_PEAKS]; | |||
| wxTextCtrl *t_klt_bw[N_PEAKS]; | |||
| wxTextCtrl *t_klt_ap[N_PEAKS]; | |||
| wxTextCtrl *t_klt_bp[N_PEAKS]; | |||
| wxRadioButton *t_select_peak[N_PEAKS]; | |||
| wxButton *t_zoomout; | |||
| wxButton *t_zoomin; | |||
| DECLARE_EVENT_TABLE() | |||
| }; | |||
| class VoiceDlg : public wxPanel | |||
| {//============================= | |||
| public: | |||
| VoiceDlg(wxWindow *parent); | |||
| void ReadParams(); | |||
| void WriteParams(); | |||
| void Save(); | |||
| void Load(); | |||
| void SetFromSpect(SpectSeq *spect); | |||
| voice_t *voice_p; | |||
| PitchEnvelope pitchenv; | |||
| wxSpinCtrl* vd_pitch1; | |||
| wxSpinCtrl* vd_pitch2; | |||
| wxTextCtrl* vd_duration; | |||
| private: | |||
| wxButton *vd_defaults; | |||
| wxButton *vd_load; | |||
| wxButton *vd_save; | |||
| wxStaticText* vd_labpk[N_PEAKS+1]; | |||
| wxSpinCtrl* vd[N_PEAKS+1][3]; | |||
| wxCheckBox* vd_usepitch; | |||
| wxStaticText* vd_lab[3]; | |||
| ByteGraph *vd_pitchgraph; | |||
| wxComboBox *vd_pitchchoice; | |||
| int pitch1; | |||
| int pitch2; | |||
| void OnCommand(wxCommandEvent& event); | |||
| void OnSpin(wxSpinEvent& event); | |||
| DECLARE_EVENT_TABLE() | |||
| }; | |||
| extern SpectSeq *clipboard_spect; | |||
| extern int pk_select; | |||
| extern int samplerate; | |||
| extern unsigned char env_fall[]; | |||
| extern FormantDlg* formantdlg; | |||
| extern VoiceDlg* voicedlg; | |||
| extern wxNotebook* notebook; | |||
| extern ByteGraph* pitchgraph; | |||
| extern SpectDisplay *currentcanvas; | |||
| extern float polint(float xa[],float ya[],int n,float x); | |||
| extern void WavegenInit(int samplerate, int wavemult_fact); | |||
| extern void WavegenInitPkData(int); // initialise envelope data | |||
| extern "C" void SetPitch(int length, unsigned char *env, int pitch1, int pitch2); | |||
| extern void SetSynthHtab(int length_mS, USHORT *ht1, int nh1, float pitch1, USHORT *ht2, int nh2, float pitch2); | |||
| extern void MakeWaveFile(int synthesis_method); | |||
| extern void MakeWaveBuf(int length, UCHAR *buf); | |||
| extern int OpenWaveFile(const char *path, int samplerate); | |||
| extern int OpenWaveFile2(const char *path); | |||
| extern void CloseWaveFile(int rate); | |||
| extern void PlayWavFile(const char *fname); | |||
| extern void SetSpinCtrl(wxSpinCtrl *t, int value); | |||
| extern int GetNumeric(wxTextCtrl *t); | |||
| extern void SetNumeric(wxTextCtrl *t, int value); | |||
| extern int use_spin_controls; | |||
| @@ -28,7 +28,6 @@ | |||
| #include "synthesize.h" | |||
| #include "voice.h" | |||
| #include "spect.h" | |||
| #include "main.h" | |||
| #include "wx/numdlg.h" | |||
| #include "wx/txtstrm.h" | |||
| #include "wx/datstrm.h" | |||
| @@ -107,33 +106,6 @@ static void PeaksZero(peak_t *sp, peak_t *zero) | |||
| void MakeWaveFile(int synthesis_method) | |||
| {//==================================== | |||
| int result=1; | |||
| int resume=0; | |||
| unsigned char wav_outbuf[1024]; | |||
| while(result != 0) | |||
| { | |||
| out_ptr = out_start = wav_outbuf; | |||
| out_end = &wav_outbuf[sizeof(wav_outbuf)]; | |||
| #ifdef INCLUDE_KLATT | |||
| if(synthesis_method == 1) | |||
| result = Wavegen_Klatt(resume); | |||
| else | |||
| #endif | |||
| result = Wavegen(); | |||
| if(f_wave != NULL) | |||
| fwrite(wav_outbuf, 1, out_ptr - wav_outbuf, f_wave); | |||
| resume=1; | |||
| } | |||
| } // end of MakeWaveFile | |||
| SpectSeq::SpectSeq(int n) | |||
| {//====================== | |||
| numframes = n; | |||
| @@ -212,91 +184,6 @@ void SpectSeq::DeleteSelected() | |||
| } // end of SpectSeq::DeleteSelected | |||
| void SpectSeq::ClipboardCopy() | |||
| {//=========================== | |||
| int ix; | |||
| int nframes; | |||
| int count=0; | |||
| nframes = CountSelected(); | |||
| if(nframes == 0) return; | |||
| if(clipboard_spect != NULL) | |||
| delete clipboard_spect; | |||
| if((clipboard_spect = new SpectSeq(nframes))==NULL) return; | |||
| for(ix=0; ix<numframes; ix++) | |||
| { | |||
| if(frames[ix]->selected) | |||
| { | |||
| if((clipboard_spect->frames[count] = new SpectFrame(frames[ix])) == NULL) | |||
| break; | |||
| count++; | |||
| } | |||
| } | |||
| } // end of SpectSeq::ClipboardCopy | |||
| int SpectSeq::ClipboardInsert(int insert_at) | |||
| {//========================================= | |||
| int ix; | |||
| int j; | |||
| int total; | |||
| int result=insert_at; | |||
| float thistime=0; | |||
| float timeinc=0; | |||
| float timeoffset=0; | |||
| SpectFrame **frames2; | |||
| if(clipboard_spect == NULL) return(result); | |||
| if(clipboard_spect->numframes == 0) return(result); | |||
| timeoffset = clipboard_spect->frames[0]->time; | |||
| if(CountSelected() == 0) | |||
| insert_at = -1; | |||
| total = numframes + clipboard_spect->numframes; | |||
| frames2 = new SpectFrame* [total]; | |||
| if(frames2 == NULL) return(result); | |||
| total = 0; | |||
| for(ix=0; ix<numframes; ix++) | |||
| { | |||
| thistime = frames[ix]->time; | |||
| if(ix == insert_at) | |||
| { | |||
| result = total; | |||
| for(j=0; j<clipboard_spect->numframes; j++) | |||
| { | |||
| frames2[total] = new SpectFrame(clipboard_spect->frames[j]); | |||
| frames2[total]->time += (thistime - timeoffset); | |||
| timeinc = frames2[total]->time - thistime + (frames2[total]->length/1000); | |||
| total++; | |||
| } | |||
| } | |||
| frames2[total] = new SpectFrame(frames[ix]); | |||
| frames2[total++]->time += timeinc; | |||
| } | |||
| if(insert_at == -1) | |||
| { | |||
| // insert at the end | |||
| result = total; | |||
| for(j=0; j<clipboard_spect->numframes; j++) | |||
| { | |||
| frames2[total] = new SpectFrame(clipboard_spect->frames[j]); | |||
| frames2[total++]->time += (thistime - timeoffset); | |||
| } | |||
| } | |||
| delete frames; | |||
| frames = frames2; | |||
| numframes = total; | |||
| return(result); | |||
| } // end of SpectSeq::ClipboardInsert | |||
| void SpectSeq::SetFrameLengths() | |||
| {//============================= | |||
| int frame; | |||
| @@ -630,68 +517,6 @@ void SpectSeq::ConstructVowel(void) | |||
| } // end of ConstructVowel | |||
| void SpectSeq::Draw(wxDC& dc, int start_y, int end_y) | |||
| {//================================================== | |||
| int fm; | |||
| int f, f1, f2; | |||
| int x; | |||
| if(end_y < start_y) return; | |||
| if((start_y -= 4) < 0) start_y = 0; | |||
| f1 = start_y / FRAME_HEIGHT; | |||
| f2 = end_y / FRAME_HEIGHT; | |||
| scaley = double(FRAME_HEIGHT) / max_y; | |||
| scalex = double(frame_width) / max_x; | |||
| // scalex = 0.6; | |||
| for(fm=f1; fm <= f2 && fm < numframes; fm++) | |||
| { | |||
| if(frames[fm]->keyframe) | |||
| { | |||
| dc.SetBrush(CREAM_BRUSH); | |||
| dc.SetPen(BORDER_PEN); | |||
| } | |||
| else | |||
| { | |||
| dc.SetBrush(*wxWHITE_BRUSH); | |||
| dc.SetPen(*wxTRANSPARENT_PEN); | |||
| } | |||
| if(frames[fm]->selected) | |||
| dc.SetPen(*wxRED_PEN); | |||
| dc.DrawRectangle(0,FRAME_HEIGHT*fm+2,frame_width, | |||
| FRAME_HEIGHT-2); | |||
| } | |||
| if(grid==1) | |||
| { | |||
| for(f=500; f<=MAX_DISPLAY_FREQ; f+=500) | |||
| { | |||
| x = int(f * scalex); | |||
| if(x > max_x) break; | |||
| if(f==3000 || f==6000 || f==9000) | |||
| dc.SetPen(*wxLIGHT_GREY_PEN); | |||
| else | |||
| dc.SetPen(VLIGHT_GREY_PEN); | |||
| dc.DrawLine(x,start_y,x,numframes*FRAME_HEIGHT); | |||
| } | |||
| } | |||
| for(fm=f1; fm <= f2 && fm < numframes; fm++) | |||
| { | |||
| frames[fm]->Draw(dc,FRAME_HEIGHT*(fm+1),frame_width, | |||
| scalex,scaley); | |||
| } | |||
| } // end of SpectSeq::Draw | |||
| void SpectSeq::InterpolatePeak(int peak) | |||
| {//===================================== | |||
| int f, f1=0, f2; | |||
| @@ -734,69 +559,6 @@ void SpectSeq::InterpolatePeak(int peak) | |||
| } // end of SpectSeq::InterpolatePeak | |||
| void SpectSeq::InterpolateAdjacent(void) | |||
| {//===================================== | |||
| int ix; | |||
| int f1 = -1; | |||
| int select = -1; | |||
| int f2 = -1; | |||
| float ratio; | |||
| peak_t *p = NULL; | |||
| peak_t *p1 = NULL; | |||
| peak_t *p2 = NULL; | |||
| for(ix=0; ix<numframes; ix++) | |||
| { | |||
| if(frames[ix]->selected) | |||
| select = ix; | |||
| else | |||
| if(frames[ix]->keyframe) | |||
| { | |||
| if(select >= 0) | |||
| { | |||
| f2 = ix; | |||
| break; | |||
| } | |||
| else | |||
| f1 = ix; | |||
| } | |||
| } | |||
| if(f1 < 0) | |||
| { | |||
| wxLogError(_T("No previous keyframe")); | |||
| return; | |||
| } | |||
| if(select < 0) | |||
| { | |||
| wxLogError(_T("No selected frame")); | |||
| return; | |||
| } | |||
| if(f2 < 0) | |||
| { | |||
| wxLogError(_T("No subsequent keyframe")); | |||
| return; | |||
| } | |||
| // get ratio | |||
| ix = wxGetNumberFromUser(_T("Interpolate between adjacent frames"),_T("percent"),_T(""),50); | |||
| ratio = (float)ix/100.0; | |||
| for(ix=0; ix<N_PEAKS; ix++) | |||
| { | |||
| p = &frames[select]->peaks[ix]; | |||
| p1 = &frames[f1]->peaks[ix]; | |||
| p2 = &frames[f2]->peaks[ix]; | |||
| p->pkfreq = p1->pkfreq + int((p2->pkfreq - p1->pkfreq)*ratio); | |||
| p->pkheight=p1->pkheight+int((p2->pkheight-p1->pkheight)*ratio); | |||
| p->pkwidth = p1->pkwidth + int((p2->pkwidth - p1->pkwidth)*ratio); | |||
| p->pkright =p1->pkright + int((p2->pkright - p1->pkright)*ratio); | |||
| } | |||
| frames[select]->keyframe = 1; | |||
| formantdlg->ShowFrame(this,select,1,0xff); | |||
| } | |||
| void SpectSeq::InterpolatePeaks(int control) | |||
| {//========================================= | |||
| // 0=turn off 1=turn on | |||
| @@ -1000,209 +762,9 @@ static void SetSynth_mS(int length_mS, SpectFrame *sp1, SpectFrame *sp2, peak_t | |||
| }; | |||
| void SpectSeq::MakeWave(int start, int end, PitchEnvelope &pitch) | |||
| {//============================================================== | |||
| int ix; | |||
| int length; | |||
| int len_samples; | |||
| int total_length; | |||
| float sum_length=0; | |||
| float prev_length=0; | |||
| int first; | |||
| char *fname_speech; | |||
| SpectFrame *sp1 = NULL; | |||
| SpectFrame *sp2; | |||
| double lfactor; | |||
| peak_t peaks0[N_PEAKS]; | |||
| peak_t peaks1[N_PEAKS]; | |||
| peak_t peaks2[N_PEAKS]; | |||
| int synthesizer_type = 0; | |||
| if(voice->klattv[0]) | |||
| { | |||
| synthesizer_type = 1; | |||
| #ifdef INCLUDE_KLATT | |||
| KlattReset(2); | |||
| #endif | |||
| } | |||
| SpeakNextClause(NULL,NULL,2); // stop speaking file | |||
| if(numframes==0) return; | |||
| SetFrameLengths(); | |||
| // find overall length of sequence | |||
| for(ix=0; ix<numframes; ix++) | |||
| { | |||
| if(frames[ix]->keyframe) | |||
| { | |||
| sum_length += prev_length; | |||
| prev_length = frames[ix]->length; | |||
| sp2 = frames[ix]; | |||
| if(sp1 == NULL) | |||
| sp1 = sp2; | |||
| } | |||
| } | |||
| if(sp1 == NULL) | |||
| { | |||
| wxLogError(_T("(No frames have peaks set")); | |||
| return; | |||
| } | |||
| total_length = int(sum_length); | |||
| if((start==end) || (total_length == 0)) | |||
| { | |||
| sp1->MakeWaveF(0,voicedlg->pitchenv,amplitude,duration); | |||
| return; | |||
| } | |||
| if((duration > 0) && (duration < 40000)) | |||
| lfactor = double(duration)/double(total_length); | |||
| else | |||
| { | |||
| duration = total_length; | |||
| lfactor = 1; | |||
| } | |||
| len_samples = int(((total_length * lfactor + 50) * samplerate) / 1000); | |||
| SetPitch(len_samples,pitch.env,9,44); | |||
| fname_speech = WavFileName(); | |||
| OpenWaveFile2(fname_speech); | |||
| first = 0; | |||
| if(start > 0) | |||
| first=1; // a selection, use fade-in | |||
| sp2 = NULL; | |||
| for(ix=start; ix<=end; ix++) | |||
| { | |||
| if(frames[ix]->keyframe) | |||
| { | |||
| sp1 = sp2; | |||
| sp2 = frames[ix]; | |||
| if(sp1 != NULL) | |||
| { | |||
| ApplyAmp_adjust(sp1,peaks1); | |||
| ApplyAmp_adjust(sp2,peaks2); | |||
| if(first) | |||
| { | |||
| PeaksZero(peaks1,peaks0); // fade in | |||
| SetSynth_mS(20,sp1,sp1,peaks0,peaks1,0); | |||
| MakeWaveFile(synthesizer_type); | |||
| first=0; | |||
| } | |||
| length = int(sp1->length * lfactor); | |||
| SetSynth_mS(length,sp1,sp2,peaks1,peaks2,0); | |||
| MakeWaveFile(synthesizer_type); | |||
| } | |||
| } | |||
| } | |||
| PeaksZero(peaks2,peaks0); // fade out | |||
| SetSynth_mS(30,sp2,sp2,peaks2,peaks0,2); | |||
| MakeWaveFile(synthesizer_type); | |||
| CloseWaveFile2(); | |||
| PlayWavFile(fname_speech); | |||
| } // end of SpectSeq::MakeWave | |||
| void SpectFrame::MakeHtab(int numh, int *htab, int pitch) | |||
| {//====================================================== | |||
| // interpolate the spectrum to give a harmonic table for | |||
| // the given pitch (Hz<<12) | |||
| } // end of SpectFrame::MakeHtab | |||
| void SpectFrame::MakeWaveF(int control, PitchEnvelope &pitche, int amplitude, int duration) | |||
| {//====================================================================================== | |||
| // amplitude: percentage adjustment | |||
| int ix; | |||
| int length; // mS | |||
| int len_samples; | |||
| int y; | |||
| peak_t peaks0[N_PEAKS]; | |||
| peak_t peaks1[N_PEAKS]; | |||
| char *fname_speech; | |||
| int synthesizer_type = 0; | |||
| if(voice->klattv[0]) | |||
| { | |||
| synthesizer_type = 1; | |||
| #ifdef INCLUDE_KLATT | |||
| KlattReset(2); | |||
| #endif | |||
| } | |||
| SpeakNextClause(NULL,NULL,2); // stop speaking file | |||
| length = duration; | |||
| if(length==0) | |||
| length = 200; // default length, mS | |||
| len_samples = (length * samplerate) / 1000; | |||
| SetPitch(len_samples + 50,pitche.env,9,44); | |||
| fname_speech = WavFileName(); | |||
| if(OpenWaveFile2(fname_speech) != 0) | |||
| return; | |||
| if(control==0) | |||
| { | |||
| memcpy(peaks1,peaks,sizeof(peaks1)); | |||
| for(ix=0; ix<N_PEAKS; ix++) | |||
| { | |||
| y = peaks1[ix].pkheight * amp_adjust * amplitude; | |||
| peaks1[ix].pkheight = y/10000; | |||
| } | |||
| PeaksZero(peaks1,peaks0); | |||
| SetSynth_mS(20,this,this,peaks0,peaks1,0); | |||
| MakeWaveFile(synthesizer_type); | |||
| SetSynth_mS(length,this,this,peaks1,peaks1,0); | |||
| MakeWaveFile(synthesizer_type); | |||
| SetSynth_mS(30,this,this,peaks1,peaks0,2); | |||
| MakeWaveFile(synthesizer_type); | |||
| } | |||
| else | |||
| { | |||
| #ifdef SPECT_EDITOR | |||
| int maxh; | |||
| USHORT htab0[600]; | |||
| maxh = nx; | |||
| if(maxh >= 600) | |||
| maxh = 600-1; | |||
| for(ix=0; ix<=maxh; ix++) | |||
| htab0[ix] = 0; | |||
| // SetSynthHtab(20,htab0,maxh,dx,spect,maxh,dx); | |||
| SetSynthHtab(20,spect,maxh,dx,spect,maxh,dx); | |||
| MakeWaveFile(0); | |||
| SetSynthHtab(length,spect,maxh,dx,spect,maxh,dx); | |||
| MakeWaveFile(0); | |||
| SetSynthHtab(30,spect,maxh,dx,htab0,maxh,dx); | |||
| MakeWaveFile(0); | |||
| #endif | |||
| } | |||
| CloseWaveFile2(); | |||
| PlayWavFile(fname_speech); | |||
| } // end of SpectFrame::MakeWaveFrame | |||
| @@ -1,478 +0,0 @@ | |||
| /*************************************************************************** | |||
| * Copyright (C) 2005 to 2013 by Jonathan Duddington * | |||
| * email: [email protected] * | |||
| * Copyright (C) 2013 Reece H. Dunn * | |||
| * * | |||
| * This program is free software; you can redistribute it and/or modify * | |||
| * it under the terms of the GNU General Public License as published by * | |||
| * the Free Software Foundation; either version 3 of the License, or * | |||
| * (at your option) any later version. * | |||
| * * | |||
| * This program is distributed in the hope that it will be useful, * | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
| * GNU General Public License for more details. * | |||
| * * | |||
| * You should have received a copy of the GNU General Public License * | |||
| * along with this program; if not, see: * | |||
| * <http://www.gnu.org/licenses/>. * | |||
| ***************************************************************************/ | |||
| #include "wx/wx.h" | |||
| #include "speak_lib.h" | |||
| #include "speech.h" | |||
| #include "phoneme.h" | |||
| #include "main.h" | |||
| #include "synthesize.h" | |||
| #include "voice.h" | |||
| #include "translate.h" | |||
| #include "prosodydisplay.h" | |||
| #ifdef PLATFORM_POSIX | |||
| #include <unistd.h> | |||
| #endif | |||
| #include "wx/font.h" | |||
| #include "wx/textctrl.h" | |||
| #include "wx/button.h" | |||
| #include "wx/checkbox.h" | |||
| #include "wx/filename.h" | |||
| #include "wx/sound.h" | |||
| #define T_SOURCE 501 | |||
| #define T_PHONETIC 502 | |||
| #define T_TRANSLATE 503 | |||
| #define T_PROCESS 504 | |||
| #define T_RULES 505 | |||
| #define T_TRANSLATE_IPA 506 | |||
| TranslDlg *transldlg = NULL; | |||
| extern char *speech_to_phonemes(char *data, char *phout); | |||
| extern ProsodyDisplay *prosodycanvas; | |||
| extern void Write4Bytes(FILE *f, int value); | |||
| BEGIN_EVENT_TABLE(TranslDlg, wxPanel) | |||
| EVT_BUTTON(T_TRANSLATE,TranslDlg::OnCommand) | |||
| EVT_BUTTON(T_PROCESS,TranslDlg::OnCommand) | |||
| EVT_BUTTON(T_RULES,TranslDlg::OnCommand) | |||
| EVT_BUTTON(T_TRANSLATE_IPA,TranslDlg::OnCommand) | |||
| END_EVENT_TABLE() | |||
| FILE *f_wave = NULL; | |||
| wxFont font_phonetic; | |||
| wxTextAttr style_phonetic; | |||
| wxFont font_phonetic_large; | |||
| wxTextAttr style_phonetic_large; | |||
| void PlayWavFile(const char *fname) | |||
| {//================================ | |||
| char command[120]; | |||
| #ifdef PLATFORM_WINDOWS | |||
| wxSound(wxString(fname,wxConvLocal)).Play(wxSOUND_SYNC); | |||
| #else | |||
| // wxSound(wxString(fname,wxConvLocal)).Play(wxSOUND_SYNC); // This gives a click at the start of each play | |||
| sprintf(command,"aplay %s",fname); | |||
| if(system(command) == -1) | |||
| { | |||
| sprintf(command,"play %s",fname); | |||
| if(system(command) == -1) | |||
| { | |||
| wxLogError(_T("Failed to run system command:\n\n"+wxString(command,wxConvLocal))); | |||
| } | |||
| } | |||
| #endif | |||
| } | |||
| char *WavFileName(void) | |||
| {//==================== | |||
| static char f_speech[120]; | |||
| if(!wxDirExists(wxPathOnly(path_speech))) | |||
| { | |||
| path_speech = wxFileSelector(_T("Speech output file"), | |||
| path_phsource,_T("speech.wav"),_T("*"),_T("*"),wxSAVE); | |||
| } | |||
| strcpy(f_speech,path_speech.mb_str(wxConvLocal)); | |||
| return(f_speech); | |||
| } | |||
| int OpenWaveFile2(const char *path) | |||
| /*********************************/ | |||
| { | |||
| // Set the length of 0x7fffffff for --stdout | |||
| // This will be changed to the correct length for -w (write to file) | |||
| static unsigned char wave_hdr[44] = { | |||
| 'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ', | |||
| 0x10,0,0,0,1,0,1,0, 9,0x3d,0,0,0x12,0x7a,0,0, | |||
| 2,0,0x10,0,'d','a','t','a', 0xff,0xff,0xff,0x7f}; | |||
| if(path == NULL) | |||
| return(2); | |||
| if(strcmp(path,"stdout")==0) | |||
| f_wave = stdout; | |||
| else | |||
| f_wave = fopen(path,"wb"); | |||
| if(f_wave != NULL) | |||
| { | |||
| fwrite(wave_hdr,1,24,f_wave); | |||
| Write4Bytes(f_wave,samplerate); | |||
| Write4Bytes(f_wave,samplerate * 2); | |||
| fwrite(&wave_hdr[32],1,12,f_wave); | |||
| return(0); | |||
| } | |||
| wxLogStatus(_T("Can't write to WAV file: '"+wxString(path,wxConvLocal))+_T("'")); | |||
| return(1); | |||
| } // end of OpenWaveFile | |||
| void CloseWaveFile2() | |||
| /******************/ | |||
| { | |||
| unsigned int pos; | |||
| if((f_wave == NULL) || (f_wave == stdout)) | |||
| return; | |||
| fflush(f_wave); | |||
| pos = ftell(f_wave); | |||
| fseek(f_wave,4,SEEK_SET); | |||
| Write4Bytes(f_wave,pos - 8); | |||
| fseek(f_wave,40,SEEK_SET); | |||
| Write4Bytes(f_wave,pos - 44); | |||
| fclose(f_wave); | |||
| f_wave = NULL; | |||
| } // end of CloseWaveFile | |||
| int WavegenFile2(void) | |||
| {//================== | |||
| int finished; | |||
| unsigned char wav_outbuf[1024]; | |||
| out_ptr = out_start = wav_outbuf; | |||
| out_end = wav_outbuf + sizeof(wav_outbuf); | |||
| finished = WavegenFill(0); | |||
| if(f_wave != NULL) | |||
| { | |||
| fwrite(wav_outbuf, 1, out_ptr-wav_outbuf, f_wave); | |||
| } | |||
| return(finished); | |||
| } // end of WavegenFile | |||
| void MakeWave2(PHONEME_LIST *p, int n_phonemes) | |||
| {//============================================ | |||
| int result; | |||
| char *fname_speech; | |||
| int n_ph; | |||
| #ifdef KLATT_TEST | |||
| KlattInit(); | |||
| #endif | |||
| n_ph = n_phonemes; | |||
| fname_speech = WavFileName(); | |||
| OpenWaveFile2(fname_speech); | |||
| Generate(p,&n_ph,0); | |||
| for(;;) | |||
| { | |||
| result = WavegenFile2(); | |||
| if(result != 0) | |||
| break; | |||
| Generate(p,&n_ph,1); | |||
| } | |||
| CloseWaveFile2(); | |||
| PlayWavFile(fname_speech); | |||
| } // end of MakeWave2 | |||
| TranslDlg::TranslDlg(wxWindow *parent) : wxPanel(parent) | |||
| {//===================================================== | |||
| int height; | |||
| int width; | |||
| int x,y; | |||
| int font_size; | |||
| int height_ph = 350; | |||
| wxTextAttr attr; | |||
| wxFont font = wxFont(12,wxFONTFAMILY_ROMAN,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_LIGHT,false,_T(""),wxFONTENCODING_SYSTEM); | |||
| attr.SetFont(font); | |||
| wxClientDisplayRect(&x,&y,&width, &height); | |||
| #ifdef PLATFORM_WINDOWS | |||
| if(height <= 768) | |||
| height_ph = height - 416; | |||
| #else | |||
| if(height <= 800) | |||
| height_ph = 280; | |||
| #endif | |||
| t_source = new wxTextCtrl(this,T_SOURCE,_T(""),wxPoint(0,4), | |||
| wxSize(298,250),wxTE_MULTILINE,wxDefaultValidator,_T("Text input window")); | |||
| t_source->SetDefaultStyle(attr); | |||
| t_phonetic = new wxTextCtrl(this,T_PHONETIC,_T(""),wxPoint(0,262), | |||
| wxSize(298,height_ph),wxTE_MULTILINE | wxTE_READONLY, wxDefaultValidator,_T("Phoneme translation window")); | |||
| style_phonetic = t_phonetic->GetDefaultStyle(); | |||
| font_phonetic = style_phonetic.GetFont(); | |||
| font_size = font_phonetic.GetPointSize(); | |||
| font_phonetic_large = font_phonetic; | |||
| style_phonetic_large = style_phonetic; | |||
| //font_phonetic_large.SetFamily(wxFONTFAMILY_SWISS); | |||
| font_phonetic_large.SetPointSize(font_size+1); | |||
| style_phonetic_large.SetFont(font_phonetic_large); | |||
| y = height_ph + 270; | |||
| t_translate = new wxButton(this,T_TRANSLATE,_T("Translate"),wxPoint(4,y)); | |||
| t_translate = new wxButton(this,T_RULES,_T("Show Rules"),wxPoint(4,y+32)); | |||
| t_translate = new wxButton(this,T_TRANSLATE_IPA,_T("Show IPA"),wxPoint(100,y+32)); | |||
| t_process = new wxButton(this,T_PROCESS,_T("Speak"),wxPoint(100,y)); | |||
| t_source->SetFocus(); | |||
| } // end of TransDlg::TransDlg | |||
| void TranslDlg::SpeakFile(void) | |||
| {//============================ | |||
| wxString file; | |||
| wxFileName fname; | |||
| FILE *f_text; | |||
| char buf[200]; | |||
| fname = wxFileName(path_speaktext); | |||
| file = wxFileSelector(_T("Text file to speak"),fname.GetPath(),fname.GetName(),_T(""),_T("*"),wxOPEN); | |||
| if(file == wxEmptyString) return; | |||
| strcpy(buf,file.mb_str(wxConvLocal)); | |||
| f_text = fopen(buf,"r"); | |||
| if(f_text == NULL) | |||
| { | |||
| wxLogError(_T("Failed to read: ")+file); | |||
| return; | |||
| } | |||
| path_speaktext = file; | |||
| InitText(0); | |||
| SpeakNextClause(f_text,NULL,0); | |||
| return; | |||
| } // end of SpeakFile | |||
| void TranslDlg::ReadVoice(int variant) | |||
| {//=================================== | |||
| wxString path; | |||
| wxString filename; | |||
| char *p; | |||
| char vname[40]; | |||
| char fname[sizeof(path_home)+30]; | |||
| if(variant) | |||
| { | |||
| // remove variant from the previous voice name | |||
| if((p = strchr(voice_name2,'+')) != NULL) | |||
| *p = 0; | |||
| sprintf(fname,"%s/voices/!v",path_home); | |||
| path = wxFileSelector(_T("Load voice variant"),wxString(fname,wxConvLocal),_T(""),_T(""),_T("*"),wxOPEN); | |||
| if(path.IsEmpty()) | |||
| { | |||
| strcpy(fname,voice_name2); | |||
| } | |||
| else | |||
| { | |||
| filename = path.Mid(strlen(fname)+1); | |||
| strcpy(vname,filename.mb_str(wxConvLocal)); | |||
| sprintf(fname,"%s+%s",voice_name2,vname); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| sprintf(fname,"%s/voices",path_home); | |||
| path = wxFileSelector(_T("Load voice"),wxString(fname,wxConvLocal),_T(""),_T(""),_T("*"),wxOPEN); | |||
| if(path.IsEmpty()) | |||
| return; | |||
| filename = path.Mid(strlen(fname)+1); | |||
| strcpy(fname,filename.mb_str(wxConvLocal)); | |||
| } | |||
| if(SetVoiceByName(fname) != EE_OK) | |||
| { | |||
| wxLogError(_T("Failed to load voice data")); | |||
| } | |||
| else | |||
| { | |||
| strcpy(voice_name2,fname); | |||
| } | |||
| WavegenSetVoice(voice); | |||
| } | |||
| void TranslDlg::OnCommand(wxCommandEvent& event) | |||
| {//============================================= | |||
| #define N_PH_LIST N_PHONEME_LIST | |||
| void *vp; | |||
| int translate_text = 0; | |||
| char buf[1000]; | |||
| char phon_out[N_PH_LIST*2]; | |||
| const char *phon_out2; | |||
| int clause_tone; | |||
| int clause_count; | |||
| FILE *f; | |||
| int fd_temp; | |||
| char fname_temp[100]; | |||
| static int n_ph_list; | |||
| static PHONEME_LIST ph_list[N_PH_LIST+1]; | |||
| if(translator==NULL) | |||
| { | |||
| wxLogError(_T("Voice not set")); | |||
| return; | |||
| } | |||
| option_phonemes = 0; | |||
| switch(event.GetId()) | |||
| { | |||
| case T_RULES: | |||
| case MENU_SPEAK_RULES: | |||
| #ifdef PLATFORM_POSIX | |||
| strcpy(fname_temp,"/tmp/espeakXXXXXX"); | |||
| if((fd_temp = mkstemp(fname_temp)) >= 0) | |||
| { | |||
| close(fd_temp); | |||
| if((f = fopen(fname_temp,"w+")) != NULL) | |||
| { | |||
| f_trans = f; // write translation rule trace to a temp file | |||
| } | |||
| } | |||
| #else | |||
| strcpy(fname_temp,tmpnam(NULL)); | |||
| if((f = fopen(fname_temp,"w+")) != NULL) | |||
| { | |||
| f_trans = f; // write translation rule trace to a temp file | |||
| } | |||
| #endif | |||
| t_phonetic->SetDefaultStyle(style_phonetic); | |||
| translate_text = espeakPHONEMES_TRACE; | |||
| break; | |||
| case T_TRANSLATE: | |||
| case MENU_SPEAK_TRANSLATE: | |||
| t_phonetic->SetDefaultStyle(style_phonetic); | |||
| translate_text = espeakPHONEMES_SHOW; | |||
| break; | |||
| case T_TRANSLATE_IPA: | |||
| case MENU_SPEAK_IPA: | |||
| t_phonetic->SetDefaultStyle(style_phonetic_large); | |||
| translate_text = espeakPHONEMES_IPA; | |||
| break; | |||
| case T_PROCESS: | |||
| case MENU_SPEAK_TEXT: | |||
| myframe->OnProsody(event); | |||
| prosodycanvas->LayoutData(ph_list,n_ph_list); | |||
| myframe->Refresh(); | |||
| option_phoneme_events = espeakINITIALIZE_PHONEME_EVENTS; | |||
| option_log_frames = 1; | |||
| MakeWave2(ph_list,n_ph_list); | |||
| option_log_frames = 0; | |||
| break; | |||
| } | |||
| if(translate_text) | |||
| { | |||
| option_phonemes = translate_text; | |||
| option_multibyte = espeakCHARS_AUTO; | |||
| SpeakNextClause(NULL,NULL,2); // stop speaking file | |||
| strncpy0(buf,t_source->GetValue().mb_str(wxConvUTF8),sizeof(buf)); | |||
| phon_out[0] = 0; | |||
| n_ph_list = 0; | |||
| clause_count = 0; | |||
| vp = buf; | |||
| InitText(0); | |||
| while((vp != NULL) && (n_ph_list < N_PH_LIST)) | |||
| { | |||
| vp = TranslateClause(translator,NULL,vp,&clause_tone,NULL); | |||
| CalcPitches(translator,clause_tone); | |||
| CalcLengths(translator); | |||
| phon_out2 = GetTranslatedPhonemeString(option_phonemes); | |||
| if(clause_count++ > 0) | |||
| strcat(phon_out," ||"); | |||
| strcat(phon_out, phon_out2); | |||
| t_phonetic->SetValue(wxString(phon_out2, wxConvUTF8)); | |||
| if((n_ph_list + n_phoneme_list) >= N_PH_LIST) | |||
| { | |||
| n_phoneme_list = N_PH_LIST - n_ph_list; | |||
| } | |||
| memcpy(&ph_list[n_ph_list],phoneme_list,sizeof(PHONEME_LIST)*n_phoneme_list); | |||
| n_ph_list += n_phoneme_list; | |||
| } | |||
| ph_list[N_PH_LIST].ph = NULL; // to recognize overrun off list (in Generate() ) | |||
| t_phonetic->Clear(); | |||
| if(option_phonemes & espeakPHONEMES_TRACE) | |||
| { | |||
| option_phonemes=0; | |||
| rewind(f_trans); | |||
| while(fgets(buf,sizeof(buf),f_trans) != NULL) | |||
| { | |||
| t_phonetic->AppendText(wxString(buf,wxConvUTF8)); | |||
| } | |||
| t_phonetic->AppendText(_T("---\n")); | |||
| if(f_trans != NULL) | |||
| fclose(f_trans); | |||
| remove(fname_temp); | |||
| } | |||
| t_phonetic->AppendText(wxString(phon_out,wxConvUTF8)); | |||
| } | |||
| } // end of TranslDlg::OnCommand | |||
| @@ -1,299 +0,0 @@ | |||
| /*************************************************************************** | |||
| * Copyright (C) 2005 to 2007 by Jonathan Duddington * | |||
| * email: [email protected] * | |||
| * * | |||
| * This program is free software; you can redistribute it and/or modify * | |||
| * it under the terms of the GNU General Public License as published by * | |||
| * the Free Software Foundation; either version 3 of the License, or * | |||
| * (at your option) any later version. * | |||
| * * | |||
| * This program is distributed in the hope that it will be useful, * | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
| * GNU General Public License for more details. * | |||
| * * | |||
| * You should have received a copy of the GNU General Public License * | |||
| * along with this program; if not, write see: * | |||
| * <http://www.gnu.org/licenses/>. * | |||
| ***************************************************************************/ | |||
| #include "wx/wx.h" | |||
| #include "speak_lib.h" | |||
| #include "main.h" | |||
| #include "speech.h" | |||
| #include "phoneme.h" | |||
| #include "synthesize.h" | |||
| #include "voice.h" | |||
| #include "spect.h" | |||
| #include "options.h" | |||
| #include "wx/dialog.h" | |||
| #include "wx/textctrl.h" | |||
| #include "wx/checkbox.h" | |||
| #include "wx/txtstrm.h" | |||
| #include "wx/wfstream.h" | |||
| #include "wx/filename.h" | |||
| VoiceDlg *voicedlg = NULL; | |||
| voice_t voice_data; | |||
| USHORT voice_pcnt[N_PEAKS+1][3]; | |||
| static void VoiceSetup() | |||
| {//===================== | |||
| int pk; | |||
| voice_t *v = &voice_data; | |||
| for(pk=0; pk<N_PEAKS; pk++) | |||
| { | |||
| v->freq[pk] = int(voice_pcnt[pk][0] * 2.56001 * voice_pcnt[N_PEAKS][0] / 100.0); | |||
| v->height[pk] = int(voice_pcnt[pk][1] * 2.56001 * voice_pcnt[N_PEAKS][1] / 100.0); | |||
| v->width[pk] = int(voice_pcnt[pk][2] * 2.56001 * voice_pcnt[N_PEAKS][2] / 100.0); | |||
| } | |||
| } | |||
| static void VoiceInit() | |||
| {//==================== | |||
| int pk, j; | |||
| voice_t *v; | |||
| v = &voice_data; | |||
| v->pitch_base = 71 << 12; | |||
| v->pitch_range = 0x1000; // default = 0x1000 | |||
| for(pk=0; pk<N_PEAKS+1; pk++) | |||
| { | |||
| for(j=0; j<3; j++) | |||
| voice_pcnt[pk][j] = 100; | |||
| } | |||
| VoiceSetup(); | |||
| voice = v; | |||
| } // end of voice_init | |||
| #define VD_DEFAULTS 401 | |||
| #define VD_LOAD 402 | |||
| #define VD_SAVE 403 | |||
| #define VD_PITCHCHOICE 404 | |||
| #define VD_PITCH1 405 | |||
| #define VD_PITCH2 406 | |||
| #define VD_USEPITCH 407 | |||
| wxString pitchchoices[3] = {_T("From spectrum"),_T("Standard"),_T("Monotone")}; | |||
| BEGIN_EVENT_TABLE(VoiceDlg, wxPanel) | |||
| EVT_BUTTON(VD_DEFAULTS,VoiceDlg::OnCommand) | |||
| EVT_BUTTON(VD_LOAD,VoiceDlg::OnCommand) | |||
| EVT_BUTTON(VD_SAVE,VoiceDlg::OnCommand) | |||
| EVT_SPINCTRL(VD_PITCH1,VoiceDlg::OnSpin) | |||
| EVT_SPINCTRL(VD_PITCH2,VoiceDlg::OnSpin) | |||
| EVT_CHECKBOX(VD_USEPITCH,VoiceDlg::OnCommand) | |||
| EVT_COMBOBOX(VD_PITCHCHOICE,VoiceDlg::OnCommand) | |||
| END_EVENT_TABLE() | |||
| VoiceDlg::VoiceDlg(wxWindow *parent) : wxPanel(parent) | |||
| {//========================================================= | |||
| int ix, j; | |||
| int y; | |||
| wxString string; | |||
| voice_t *v; | |||
| wxString captions[3] = {_T("Freq"),_T("Height"),_T("Width")}; | |||
| voice_p = v = &voice_data; | |||
| VoiceInit(); | |||
| pitch1 = 80; | |||
| pitch2 = 120; | |||
| for(j=0; j<3; j++) | |||
| new wxStaticText(this,-1,captions[j],wxPoint(34+j*56,6)); | |||
| y = 26; | |||
| for(ix=0; ix<N_PEAKS+1; ix++) | |||
| { | |||
| if(ix==N_PEAKS) | |||
| { | |||
| string = _T("All"); | |||
| y += 8; | |||
| } | |||
| else | |||
| string.Printf(_T("%2d"),ix); | |||
| vd_labpk[ix] = new wxStaticText(this,-1,string,wxPoint(8,y+2)); | |||
| for(j=0; j<3; j++) | |||
| { | |||
| string.Printf(_T("%d"),voice_pcnt[ix][j]); | |||
| vd[ix][j] = new wxSpinCtrl(this,-1,string, | |||
| wxPoint(32+j*56,y),wxSize(52,22),wxSP_ARROW_KEYS,0,300); | |||
| } | |||
| y += 26; | |||
| } | |||
| for(ix=6; ix<N_PEAKS; ix++) | |||
| vd[ix][2]->Hide(); | |||
| vd_defaults = new wxButton(this,VD_DEFAULTS,_T("Defaults"),wxPoint(32,293)); | |||
| y = 324; | |||
| vd_pitch1 = new wxSpinCtrl(this,VD_PITCH1,_T("80"), | |||
| wxPoint(32,y),wxSize(52,24),wxTE_CENTRE,60,500); | |||
| vd_pitch2 = new wxSpinCtrl(this,VD_PITCH2,_T("120"), | |||
| wxPoint(88,y),wxSize(52,24),wxTE_CENTRE,60,500); | |||
| vd_lab[1] = new wxStaticText(this,-1,_T("Hz"),wxPoint(142,y+2)); | |||
| vd_usepitch = new wxCheckBox(this,VD_USEPITCH,_T("Pitch from spectrum"), | |||
| wxPoint(4,y+24)); | |||
| // vd_load = new wxButton(this,VD_LOAD,_T("Load"),wxPoint(16,y+56)); | |||
| // vd_save = new wxButton(this,VD_SAVE,_T("Save"),wxPoint(106,y+56)); | |||
| y = 422; | |||
| vd_duration = new wxTextCtrl(this,-1,_T(""), | |||
| wxPoint(4,y),wxSize(52,24),wxTE_CENTRE); | |||
| vd_lab[2] = new wxStaticText(this,-1,_T("Duration"),wxPoint(60,y+2)); | |||
| y = 422; | |||
| vd_pitchchoice = new wxComboBox(this,VD_PITCHCHOICE,_T("Standard"), | |||
| wxPoint(4,y+30),wxSize(192,24),3,pitchchoices); | |||
| vd_pitchgraph = new ByteGraph(this,wxPoint(0,y+60),wxSize(200,100)); | |||
| vd_pitchgraph->SetData(128,env_fall); | |||
| vd_pitchgraph->Show(); | |||
| } // end of VoiceDlg::VoiceDlg | |||
| void VoiceDlg::OnCommand(wxCommandEvent& event) | |||
| {//============================================ | |||
| // JSD EVT_COMBOBOX causes GDB lockup if a breakpoint is set | |||
| int id; | |||
| int ix, j; | |||
| switch(id = event.GetId()) | |||
| { | |||
| case VD_DEFAULTS: | |||
| for(ix=0; ix<N_PEAKS+1; ix++) | |||
| { | |||
| for(j=0; j<3; j++) | |||
| { | |||
| voice_pcnt[ix][j] = 100; | |||
| vd[ix][j]->SetValue(_T("100")); | |||
| } | |||
| } | |||
| VoiceSetup(); | |||
| break; | |||
| case VD_LOAD: | |||
| // Load(); | |||
| break; | |||
| case VD_SAVE: | |||
| // Save(); | |||
| break; | |||
| case VD_USEPITCH: | |||
| case VD_PITCHCHOICE: | |||
| if(currentcanvas != NULL) | |||
| SetFromSpect(currentcanvas->spectseq); | |||
| break; | |||
| } | |||
| if(currentcanvas != NULL) currentcanvas->SetFocus(); | |||
| } // end of VoiceDlg::OnCommand | |||
| void VoiceDlg::ReadParams() | |||
| {//======================== | |||
| int ix, j; | |||
| pitchenv.pitch1 = vd_pitch1->GetValue(); | |||
| pitchenv.pitch2 = vd_pitch2->GetValue(); | |||
| voice_data.pitch_base = (pitchenv.pitch1 - 9) << 12; | |||
| voice_data.pitch_range = (pitchenv.pitch2 - pitchenv.pitch1) * 108; | |||
| for(ix=0; ix<N_PEAKS+1; ix++) | |||
| { | |||
| for(j=0; j<3; j++) | |||
| { | |||
| voice_pcnt[ix][j] = vd[ix][j]->GetValue(); | |||
| } | |||
| } | |||
| VoiceSetup(); | |||
| } // end of VoiceDlg::ReadParams | |||
| void VoiceDlg::WriteParams() | |||
| {//======================== | |||
| int ix; | |||
| voice_t *v = voice; | |||
| int val1, val2; | |||
| val1 = (v->pitch_base >> 12) + 9; | |||
| val2 = v->pitch_range/108 + val1; | |||
| vd_pitch1->SetValue(val1); | |||
| vd_pitch2->SetValue(val2); | |||
| for(ix=0; ix<N_PEAKS; ix++) | |||
| { | |||
| vd[ix][0]->SetValue(int(float(v->freq[ix]) / 2.56001 + 0.5)); | |||
| vd[ix][1]->SetValue(int(float(v->height[ix]) / 2.56001 + 0.5)); | |||
| vd[ix][2]->SetValue(int(float(v->width[ix]) / 2.56001 + 0.5)); | |||
| } | |||
| vd[ix][0]->SetValue(100); | |||
| vd[ix][1]->SetValue(100); | |||
| vd[ix][2]->SetValue(100); | |||
| } // end of VoiceDlg::WriteParams | |||
| void VoiceDlg::OnSpin(wxSpinEvent& event) | |||
| {//====================================== | |||
| ReadParams(); | |||
| } | |||
| void VoiceDlg::SetFromSpect(SpectSeq* spect) | |||
| {//========================================= | |||
| if(spect==NULL) return; | |||
| if(vd_pitchchoice->GetValue() == _T("From spectrum")) | |||
| { | |||
| pitchenv = spect->pitchenv; | |||
| } | |||
| else | |||
| if(vd_pitchchoice->GetValue() == _T("Monotone")) | |||
| { | |||
| memset(pitchenv.env,127,128); | |||
| } | |||
| else | |||
| if(vd_pitchchoice->GetValue() == _T("Standard")) | |||
| { | |||
| memcpy(pitchenv.env,env_fall,128); | |||
| } | |||
| vd_pitchgraph->SetData(128,pitchenv.env); | |||
| vd_pitchgraph->Show(); | |||
| if(vd_usepitch->GetValue()) | |||
| { | |||
| SetSpinCtrl(vd_pitch1,spect->pitch1); | |||
| SetSpinCtrl(vd_pitch2,spect->pitch2); | |||
| } | |||
| else | |||
| { | |||
| SetSpinCtrl(vd_pitch1,pitch1); | |||
| SetSpinCtrl(vd_pitch2,pitch2); | |||
| } | |||
| } // end of VoiceDlg::SetFromSpect | |||
| @@ -1,748 +0,0 @@ | |||
| /*************************************************************************** | |||
| * Copyright (C) 2005 to 2013 by Jonathan Duddington * | |||
| * email: [email protected] * | |||
| * Copyright (C) 2013-2015 Reece H. Dunn * | |||
| * * | |||
| * This program is free software; you can redistribute it and/or modify * | |||
| * it under the terms of the GNU General Public License as published by * | |||
| * the Free Software Foundation; either version 3 of the License, or * | |||
| * (at your option) any later version. * | |||
| * * | |||
| * This program is distributed in the hope that it will be useful, * | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
| * GNU General Public License for more details. * | |||
| * * | |||
| * You should have received a copy of the GNU General Public License * | |||
| * along with this program; if not, write see: * | |||
| * <http://www.gnu.org/licenses/>. * | |||
| ***************************************************************************/ | |||
| #include <math.h> | |||
| #include "wx/wx.h" | |||
| #include <wx/dcmemory.h> | |||
| #include <wx/dc.h> | |||
| #include <wx/bitmap.h> | |||
| #include <wx/dirdlg.h> | |||
| #include "wx/filename.h" | |||
| #include "wx/wfstream.h" | |||
| #include "speak_lib.h" | |||
| #include "main.h" | |||
| #include "speech.h" | |||
| #include "phoneme.h" | |||
| #include "synthesize.h" | |||
| #include "voice.h" | |||
| #include "spect.h" | |||
| #include "translate.h" | |||
| #include "options.h" | |||
| /* Read a file of vowel symbols and f1,f2 formants, and produce a vowel diagram | |||
| */ | |||
| extern wxString path_phsource; | |||
| extern char *phondata_ptr; | |||
| extern USHORT *phoneme_index; | |||
| extern int n_phoneme_tables; | |||
| // size of the vowelchart png | |||
| #define WIDTH 1580 | |||
| #define HEIGHT 800 | |||
| #define ROUND(x) ((int) ((x) + 0.5)) | |||
| static int HslValue (double n1, double n2, double hue) | |||
| {//=================================================== | |||
| double value; | |||
| if (hue > 255) | |||
| hue -= 255; | |||
| else if (hue < 0) | |||
| hue += 255; | |||
| if (hue < 42.5) | |||
| value = n1 + (n2 - n1) * (hue / 42.5); | |||
| else if (hue < 127.5) | |||
| value = n2; | |||
| else if (hue < 170) | |||
| value = n1 + (n2 - n1) * ((170 - hue) / 42.5); | |||
| else | |||
| value = n1; | |||
| return ROUND (value * 255.0); | |||
| } | |||
| /** | |||
| * @hue: Hue channel, returns Red channel | |||
| * @saturation: Saturation channel, returns Green channel | |||
| * @lightness: Lightness channel, returns Blue channel | |||
| * | |||
| * The arguments are pointers to int, with the values pointed to in the | |||
| * following ranges: H [0, 360], L [0, 255], S [0, 255]. | |||
| * | |||
| * The function changes the arguments to point to the RGB value | |||
| * corresponding, with the returned values all in the range [0, 255]. | |||
| **/ | |||
| void HslToRgb (int *hue, int *saturation, int *lightness) | |||
| {//====================================================== | |||
| double h, s, l; | |||
| h = (*hue * 256)/360; | |||
| s = *saturation; | |||
| l = *lightness; | |||
| if (s == 0) | |||
| { | |||
| /* achromatic case */ | |||
| *hue = (int)l; | |||
| *lightness = (int)l; | |||
| *saturation = (int)l; | |||
| } | |||
| else | |||
| { | |||
| double m1, m2; | |||
| if (l < 128) | |||
| m2 = (l * (255 + s)) / 65025.0; | |||
| else | |||
| m2 = (l + s - (l * s) / 255.0) / 255.0; | |||
| m1 = (l / 127.5) - m2; | |||
| /* chromatic case */ | |||
| *hue = HslValue (m1, m2, h + 85); | |||
| *saturation = HslValue (m1, m2, h); | |||
| *lightness = HslValue (m1, m2, h - 85); | |||
| } | |||
| } | |||
| static int vowel_posn[N_PHONEME_TAB]; | |||
| static int vowel_posn_ix; | |||
| static double log2a(double x) | |||
| {//======================== | |||
| // log2(x) = log(x) / log(2) | |||
| return(log(x) / 0.693147); | |||
| } | |||
| static int VowelX(int f2) | |||
| {//====================== | |||
| return(WIDTH - int((log2a(f2) - 9.40)*WIDTH/1.9)); | |||
| // return(WIDTH - int((log2a(f2) - 9.49)*WIDTH/1.8)); | |||
| } | |||
| static int VowelY(int f1) | |||
| {//====================== | |||
| return(int((log2a(f1) - 7.85)*HEIGHT/2.15)); | |||
| } | |||
| static int VowelZ(int f3) | |||
| {//====================== | |||
| int z; | |||
| // range 2000-3000Hz, log2= 10.96 to 11.55 | |||
| z = int((log2a(f3) - 11.05)*256/0.50); | |||
| if(z < 0) z = 0; | |||
| if(z > 255) z = 255; | |||
| return(z); | |||
| } | |||
| static void DrawVowel(wxDC *dc, wxString name, int f1, int f2, int f3, int g1, int g2) | |||
| {//================================================================================== | |||
| int ix; | |||
| int posn; | |||
| int collisions; | |||
| int x,y,z,x2,y2; | |||
| int r,g,b; | |||
| wxBrush brush; | |||
| y = VowelY(f1); | |||
| x = VowelX(f2); | |||
| z = VowelZ(f3); | |||
| if(y < 0) y = 0; | |||
| if(y > (HEIGHT-4)) y= (HEIGHT-4); | |||
| if(x < 0) x = 0; | |||
| if(x > (WIDTH-12)) x = (WIDTH-12); | |||
| r = z; | |||
| g = 255; | |||
| b = 100 + z/2; | |||
| HslToRgb(&r,&g,&b); | |||
| brush.SetColour(r,g,b); | |||
| dc->SetBrush(brush); | |||
| dc->DrawCircle(x,y,4); | |||
| // check for a label already at this position | |||
| collisions = 0; | |||
| posn = (x/8)*WIDTH + (y/8); | |||
| for(ix=0; ix<vowel_posn_ix; ix++) | |||
| { | |||
| if(posn == vowel_posn[ix]) | |||
| collisions++; | |||
| } | |||
| vowel_posn[vowel_posn_ix++] = posn; | |||
| dc->DrawText(name,x+4,y+(collisions*10)); | |||
| if(g2 != 0xffff) | |||
| { | |||
| y2 = VowelY(g1); | |||
| x2 = VowelX(g2); | |||
| dc->DrawLine(x,y,x2,y2); | |||
| } | |||
| } | |||
| static int VowelChartDir(wxDC *dc, wxBitmap *bitmap) | |||
| {//================================================= | |||
| int ix; | |||
| int nf; | |||
| int count = 0; | |||
| SpectSeq *spectseq; | |||
| SpectFrame *frame1; | |||
| SpectFrame *frame2=NULL; | |||
| wxFileName filename; | |||
| wxString dir = wxDirSelector(_T("Directory of vowel files"),path_phsource); | |||
| if(dir.IsEmpty()) return(0); | |||
| wxString path = wxFindFirstFile(dir+_T("/*"),wxFILE); | |||
| while (!path.empty()) | |||
| { | |||
| if((spectseq = new SpectSeq) == NULL) break; | |||
| filename = wxFileName(path); | |||
| wxFileInputStream stream(path); | |||
| if(stream.Ok() == FALSE) | |||
| { | |||
| path = wxFindNextFile(); | |||
| delete spectseq; | |||
| continue; | |||
| } | |||
| spectseq->Load(stream); | |||
| nf = 0; | |||
| frame1 = NULL; | |||
| if(spectseq->numframes > 0) | |||
| { | |||
| frame2 = spectseq->frames[0]; | |||
| } | |||
| for(ix=0; ix<spectseq->numframes; ix++) | |||
| { | |||
| if(spectseq->frames[ix]->keyframe) | |||
| { | |||
| nf++; | |||
| frame2 = spectseq->frames[ix]; | |||
| if(frame2->markers & FRFLAG_VOWEL_CENTRE) | |||
| frame1 = frame2; | |||
| } | |||
| } | |||
| if((nf >= 3) && (frame1 != NULL)) | |||
| { | |||
| DrawVowel(dc,wxString(filename.GetName()), | |||
| frame1->peaks[1].pkfreq, frame1->peaks[2].pkfreq, frame1->peaks[3].pkfreq, | |||
| frame2->peaks[1].pkfreq, frame2->peaks[2].pkfreq); | |||
| count++; | |||
| } | |||
| delete spectseq; | |||
| path = wxFindNextFile(); | |||
| } | |||
| filename.SetPath(dir); | |||
| filename.SetFullName(_T("vowelchart.png")); | |||
| bitmap->SaveFile(filename.GetFullPath(),wxBITMAP_TYPE_PNG); | |||
| return(count); | |||
| } | |||
| static int VowelChartList(wxDC *dc, wxBitmap *bitmap, char *fname) | |||
| {//=============================================================== | |||
| // Plot a graph of vowel formants. | |||
| // y-axis is decreasing f1 (closeness) | |||
| // x-axis is decreasing f2 (backness) | |||
| FILE *f_in; | |||
| int ix; | |||
| int f1,f2,f3,g1,g2; | |||
| int colour; | |||
| int count=0; | |||
| wxFileName filename; | |||
| char name[40]; | |||
| char buf[200]; | |||
| wxString path; | |||
| if(fname != NULL) | |||
| { | |||
| path = wxString(fname,wxConvLocal); | |||
| } | |||
| else | |||
| { | |||
| path = wxFileSelector(_T("Read file of vowel formants"),path_phsource, | |||
| _T(""),_T(""),_T("*"),wxOPEN); | |||
| } | |||
| if(path.IsEmpty()) | |||
| { | |||
| return(0); | |||
| } | |||
| filename = wxFileName(path); | |||
| strcpy(buf,path.mb_str(wxConvLocal)); | |||
| f_in = fopen(buf,"r"); | |||
| if(f_in == NULL) | |||
| { | |||
| wxLogError(_T("Can't read file: %s"),buf); | |||
| return(0); | |||
| } | |||
| while(fgets(buf,sizeof(buf),f_in) != NULL) | |||
| { | |||
| g2 = 0xffff; | |||
| ix = sscanf(buf,"%s %d %d %d %d %d %d",name,&colour,&f1,&f2,&f3,&g1,&g2); | |||
| if(ix >= 4) | |||
| { | |||
| if(colour == 1) | |||
| { | |||
| dc->SetPen(*wxMEDIUM_GREY_PEN); | |||
| dc->SetTextForeground(wxColour(100,100,128)); | |||
| } | |||
| else | |||
| { | |||
| dc->SetPen(*wxBLACK_PEN); | |||
| dc->SetTextForeground(*wxBLACK); | |||
| } | |||
| DrawVowel(dc,wxString(name,wxConvLocal), | |||
| f1,f2,f3,g1,g2); | |||
| count++; | |||
| } | |||
| } | |||
| filename.SetExt(_T("png")); | |||
| bitmap->SaveFile(filename.GetFullPath(),wxBITMAP_TYPE_PNG); | |||
| fclose(f_in); | |||
| return(count); | |||
| } | |||
| void VowelChart(int control, char *fname) | |||
| {//====================================== | |||
| // Plot a graph of vowel formants. | |||
| // y-axis is decreasing f1 (closeness) | |||
| // x-axis is decreasing f2 (backness) | |||
| // control=1 from directory of lists | |||
| // control=2 from single list | |||
| // control=3 from directory of phoneme source data files | |||
| int ix; | |||
| int x,y; | |||
| int count; | |||
| wxFileName filename; | |||
| wxBitmap bitmap(WIDTH,HEIGHT); | |||
| // Create a memory DC | |||
| wxMemoryDC dc; | |||
| dc.SelectObject(bitmap); | |||
| dc.SetBrush(*wxWHITE_BRUSH); | |||
| dc.SetFont(*wxSWISS_FONT); | |||
| dc.Clear(); | |||
| // draw grid | |||
| dc.SetPen(*wxLIGHT_GREY_PEN); | |||
| for(ix=200; ix<=1000; ix+=50) | |||
| { | |||
| y = VowelY(ix); | |||
| dc.DrawLine(0,y,WIDTH,y); | |||
| if((ix % 100) == 0) | |||
| dc.DrawText(wxString::Format(_T("%d"),ix),1,y); | |||
| } | |||
| for(ix=700; ix<=2400; ix+=100) | |||
| { | |||
| x = VowelX(ix); | |||
| dc.DrawLine(x,0,x,HEIGHT); | |||
| if((ix % 200)==0) | |||
| dc.DrawText(wxString::Format(_T("%d"),ix),x+1,0); | |||
| } | |||
| dc.SetPen(*wxBLACK_PEN); | |||
| vowel_posn_ix = 0; | |||
| if(control==3) | |||
| count = VowelChartDir(&dc, &bitmap); | |||
| else | |||
| count = VowelChartList(&dc, &bitmap, fname); | |||
| dc.SetTextForeground(*wxBLACK); | |||
| if(control != 1) | |||
| wxLogStatus(_T("Plotted %d vowels"),count); | |||
| } | |||
| void FindPhonemesUsed(void) | |||
| {//======================== | |||
| int hash; | |||
| char *p; | |||
| unsigned int *pw; | |||
| char *next; | |||
| unsigned char c; | |||
| int count = 0; | |||
| int ignore; | |||
| char phonetic[N_WORD_PHONEMES]; | |||
| // look through all the phoneme strings in the **_rules data | |||
| // and mark these phoneme codes as used. | |||
| p = translator->data_dictrules; | |||
| while(*p != 0) | |||
| { | |||
| if(*p == RULE_CONDITION) | |||
| p+=2; | |||
| if(*p == RULE_LINENUM) | |||
| p+=3; | |||
| if(*p == RULE_GROUP_END) | |||
| { | |||
| p++; | |||
| if(*p == 0) break; | |||
| } | |||
| if(*p == RULE_GROUP_START) | |||
| { | |||
| if(p[1] == RULE_REPLACEMENTS) | |||
| { | |||
| p++; | |||
| pw = (unsigned int *)(((long)p+4) & ~3); // advance to next word boundary | |||
| while(pw[0] != 0) | |||
| { | |||
| pw += 2; // find the end of the replacement list, each entry is 2 words. | |||
| } | |||
| p = (char *)(pw+1); | |||
| continue; | |||
| } | |||
| if(p[1] == RULE_LETTERGP2) | |||
| { | |||
| while(*p != RULE_GROUP_END) p++; | |||
| continue; | |||
| } | |||
| p += (strlen(p)+1); | |||
| } | |||
| while((c = *p) != 0) | |||
| { | |||
| if(c == RULE_CONDITION) | |||
| p++; // next byte is the condition number, which may be 3 (= RULE_PHONEMES) | |||
| if(c == RULE_PHONEMES) | |||
| break; | |||
| p++; | |||
| } | |||
| count++; | |||
| if(c == RULE_PHONEMES) | |||
| { | |||
| ignore = 0; | |||
| p++; | |||
| while((c = *p) != 0) | |||
| { | |||
| if(c == phonSWITCH) | |||
| ignore = 1; | |||
| if(ignore == 0) | |||
| phoneme_tab_flags[c] |= 2; | |||
| p++; | |||
| } | |||
| } | |||
| p++; | |||
| } | |||
| // NOTE, we should recognise langopts.textmode and ignore the *_list file (lang=zh) | |||
| for(hash=0; hash<N_HASH_DICT; hash++) | |||
| { | |||
| p = translator->dict_hashtab[hash]; | |||
| if(p == NULL) | |||
| continue; | |||
| while(*p != 0) | |||
| { | |||
| next = p + p[0]; | |||
| if((p[1] & 0x80) == 0) | |||
| { | |||
| p += ((p[1] & 0x3f) + 2); | |||
| strcpy(phonetic,p); | |||
| p += strlen(phonetic) +1; | |||
| // examine flags | |||
| ignore = 0; | |||
| while(p < next) | |||
| { | |||
| if(*p == BITNUM_FLAG_TEXTMODE) | |||
| { | |||
| ignore = 1; | |||
| break; | |||
| } | |||
| p++; | |||
| } | |||
| if(ignore == 0) | |||
| { | |||
| p = phonetic; | |||
| while((c = *p) != 0) | |||
| { | |||
| if(c == phonSWITCH) | |||
| break; | |||
| phoneme_tab_flags[c] |= 2; | |||
| p++; | |||
| } | |||
| } | |||
| } | |||
| p = next; | |||
| } | |||
| } | |||
| } // end of FindPhonemesUsed | |||
| #define N_VOWELFMT_ADDR 20 | |||
| int n_vowelfmt_addr; | |||
| int vowelfmt_addr[N_VOWELFMT_ADDR]; // FMT() statements found in a phoneme definition | |||
| static void FindVowelFmt(int prog_start, int length) | |||
| {//================================================= | |||
| USHORT *prog; | |||
| USHORT instn; | |||
| int prog_end; | |||
| prog_end = prog_start + length; | |||
| n_vowelfmt_addr = 0; | |||
| for(prog = &phoneme_index[prog_start]; prog < &phoneme_index[prog_end]; prog += NumInstnWords(prog)) | |||
| { | |||
| instn = *prog; | |||
| if((instn >> 12) == 11) | |||
| { | |||
| // FMT instruction | |||
| if(n_vowelfmt_addr < N_VOWELFMT_ADDR) | |||
| { | |||
| vowelfmt_addr[n_vowelfmt_addr++] = ((instn & 0xf) << 18) + (prog[1] << 2); | |||
| } | |||
| } | |||
| } | |||
| } // end of FindVowelFmt | |||
| static int prog_log_sorter(PHONEME_PROG_LOG *p1, PHONEME_PROG_LOG *p2) | |||
| {//=================================================================== | |||
| return(p1->addr - p2->addr); | |||
| } | |||
| void MakeVowelLists(void) | |||
| {//====================== | |||
| // For each phoneme table, make a list of its vowels and their | |||
| // formant frequencies (f1,f2,f3) for use by VowelChart() | |||
| int table; | |||
| int ix; | |||
| int phcode; | |||
| PHONEME_TAB *ph; | |||
| FILE *f; | |||
| FILE *f_prog_log; | |||
| SPECT_SEQ *seq; | |||
| SPECT_SEQK *seqk; | |||
| frame_t *frame; | |||
| int n_prog_log; | |||
| int vowelfmt_ix; | |||
| int colour; | |||
| int voice_found; | |||
| PHONEME_PROG_LOG *prog_log_table; | |||
| PHONEME_PROG_LOG *found_prog; | |||
| PHONEME_PROG_LOG this_prog; | |||
| char dirname[sizeof(path_source)+20]; | |||
| char fname[sizeof(dirname)+40]; | |||
| char save_voice_name[80]; | |||
| strcpy(save_voice_name,voice_name2); | |||
| sprintf(fname,"%s%s",path_source,"compile_prog_log"); | |||
| if((f_prog_log = fopen(fname,"rb")) == NULL) | |||
| { | |||
| wxLogError(_T("Can't read 'compile_prog_log;")); | |||
| return; | |||
| } | |||
| ix = GetFileLength(fname); | |||
| prog_log_table = (PHONEME_PROG_LOG *)malloc(ix); | |||
| if(prog_log_table == NULL) | |||
| { | |||
| fclose(f_prog_log); | |||
| return; | |||
| } | |||
| ix = fread(prog_log_table, 1, ix, f_prog_log); | |||
| fclose(f_prog_log); | |||
| n_prog_log = ix / sizeof(PHONEME_PROG_LOG); | |||
| progress = new wxProgressDialog(_T("Vowel charts"),_T(""),n_phoneme_tables); | |||
| sprintf(dirname,"%s%s",path_source,"vowelcharts"); | |||
| mkdir(dirname,S_IRWXU | S_IRGRP | S_IROTH); | |||
| sprintf(fname,"%s/vowel_log",dirname); | |||
| for(table=0; table<n_phoneme_tables; table++) | |||
| { | |||
| sprintf(fname,"%s/%s",dirname,phoneme_tab_list[table].name); | |||
| if((f = fopen(fname,"w"))==NULL) continue; | |||
| progress->Update(table); | |||
| // select the phoneme table by name | |||
| // if(SetVoiceByName(phoneme_tab_list[table].name) != 0) continue; | |||
| if(SelectPhonemeTableName(phoneme_tab_list[table].name) < 0) | |||
| { | |||
| fclose(f); | |||
| continue; | |||
| } | |||
| voice_found = 0; | |||
| if((LoadVoice(phoneme_tab_list[table].name, 0) != NULL) && (translator->data_dictrules != NULL)) | |||
| { | |||
| voice_found = 1; | |||
| FindPhonemesUsed(); | |||
| } | |||
| // phoneme table is terminated by a phoneme with no name (=0) | |||
| for(phcode=1; phcode < n_phoneme_tab; phcode++) | |||
| { | |||
| ph = phoneme_tab[phcode]; | |||
| if((ph==NULL) || (ph->type != phVOWEL) || (ph->program == 0)) | |||
| continue; | |||
| if(voice_found && (phoneme_tab_flags[phcode] & 3) == 0) | |||
| { | |||
| continue; // inherited, and not used | |||
| } | |||
| // find the size of this program | |||
| this_prog.addr = ph->program; | |||
| found_prog = (PHONEME_PROG_LOG *)bsearch((void *)&this_prog, (void *)prog_log_table, n_prog_log, sizeof(PHONEME_PROG_LOG), (int(*)(const void *,const void *))prog_log_sorter); | |||
| FindVowelFmt(ph->program, found_prog->length); | |||
| for(vowelfmt_ix=0; vowelfmt_ix < n_vowelfmt_addr; vowelfmt_ix++) | |||
| { | |||
| ix = vowelfmt_addr[vowelfmt_ix]; | |||
| seq = (SPECT_SEQ *)(&phondata_ptr[ix]); | |||
| seqk = (SPECT_SEQK *)seq; | |||
| if(seq->frame[0].frflags & FRFLAG_KLATT) | |||
| frame = &seqk->frame[1]; | |||
| else | |||
| frame = (frame_t *)&seq->frame[1]; | |||
| if((n_vowelfmt_addr - vowelfmt_ix) == 1) | |||
| colour = 0; | |||
| else | |||
| colour = 1; | |||
| fprintf(f,"%s\t %d %3d %4d %4d",WordToString(ph->mnemonic), colour, | |||
| frame->ffreq[1],frame->ffreq[2],frame->ffreq[3]); | |||
| if(seq->frame[0].frflags & FRFLAG_KLATT) | |||
| frame = &seqk->frame[seqk->n_frames-1]; | |||
| else | |||
| frame = (frame_t *)&seq->frame[seq->n_frames-1]; | |||
| fprintf(f," %3d %4d %4d\n",frame->ffreq[1],frame->ffreq[2],frame->ffreq[3]); | |||
| } | |||
| } | |||
| fclose(f); | |||
| VowelChart(1,fname); // draw the vowel chart | |||
| } | |||
| free(prog_log_table); | |||
| LoadVoice(voice_name2,0); // reset the original phoneme table | |||
| delete progress; | |||
| LoadVoiceVariant(save_voice_name,0); | |||
| } | |||
| #define N_ENVELOPES 30 | |||
| extern int n_envelopes; | |||
| extern char envelope_paths[N_ENVELOPES][80]; | |||
| extern unsigned char envelope_dat[N_ENVELOPES][ENV_LEN]; | |||
| #define HT_ENV 140 | |||
| #define WD_ENV 128*2 | |||
| void DrawEnvelopes() | |||
| {//================ | |||
| int ix_env; | |||
| int y_base; | |||
| int x; | |||
| FILE *f_txt=NULL; | |||
| unsigned char *env; | |||
| char name[200]; | |||
| wxBitmap bitmap(WD_ENV,HT_ENV*n_envelopes); | |||
| // Create a memory DC | |||
| wxMemoryDC dc; | |||
| dc.SelectObject(bitmap); | |||
| dc.SetBrush(*wxWHITE_BRUSH); | |||
| dc.SetFont(*wxSWISS_FONT); | |||
| dc.Clear(); | |||
| sprintf(name,"%s%s",path_source,"envelopes.txt"); | |||
| // f_txt = fopen(name,"w"); | |||
| for(ix_env=0; ix_env<n_envelopes; ix_env++) | |||
| { | |||
| y_base = HT_ENV * ix_env; | |||
| dc.SetPen(*wxLIGHT_GREY_PEN); | |||
| dc.DrawLine(0,y_base+0,256,y_base+0); | |||
| dc.DrawLine(0,y_base+64,256,y_base+64); | |||
| dc.DrawLine(0,y_base+128,256,y_base+128); | |||
| dc.DrawLine(128,y_base+0,128,y_base+128); | |||
| dc.SetPen(*wxBLACK_PEN); | |||
| strncpy0(name,envelope_paths[ix_env],sizeof(name)); | |||
| dc.DrawText(wxString(name,wxConvLocal),1,y_base); | |||
| env = envelope_dat[ix_env]; | |||
| y_base = y_base+128; | |||
| for(x=0; x<127; x++) | |||
| { | |||
| dc.DrawLine(x*2, y_base-env[x]/2, (x+1)*2, y_base-env[x+1]/2); | |||
| } | |||
| if(f_txt != NULL) | |||
| { | |||
| fprintf(f_txt,"%s\n",name); | |||
| for(x=0; x<128; x++) | |||
| { | |||
| fprintf(f_txt," 0x%.2x,",env[x]); | |||
| if((x & 0xf) == 0xf) | |||
| fputc('\n',f_txt); | |||
| } | |||
| fputc('\n',f_txt); | |||
| } | |||
| } | |||
| bitmap.SaveFile(path_phsource+_T("/envelopes.png"),wxBITMAP_TYPE_PNG); | |||
| if(f_txt != NULL) | |||
| fclose(f_txt); | |||
| } | |||