/***************************************************************************
* Copyright (C) 2005 to 2007 by Jonathan Duddington *
* email: jonsd@users.sourceforge.net *
* *
* 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();
}
#ifdef deleted
void VoiceDlg::Save()
{//==================
int pk;
wxString filename;
FILE *f;
filename = wxFileSelector(_T("Save voice"),path_voices,_T(""),_T(""),_T("*"),wxSAVE);
if(filename.IsEmpty())
return;
f = fopen(filename.mb_str(wxConvLocal),"w");
if(f == NULL)
{
wxLogError(_T("Failed to open '%s'"),filename.c_str());
return;
}
wxFileName fn(filename);
path_voices = fn.GetPath();
ReadParams();
fprintf(f,"%3d %3d\n",vd_pitch1->GetValue(),vd_pitch2->GetValue());
for(pk=0; pk<N_PEAKS+1; pk++)
{
fprintf(f,"%3d %3d %3d\n",voice_pcnt[pk][0],voice_pcnt[pk][1],voice_pcnt[pk][2]);
}
fclose(f);
} // end of VoiceDlg::Save
void VoiceDlg::Load()
{//===============================
wxString filename;
int pk, j;
filename = wxFileSelector(_T("Load voice"),path_voices,_T(""),_T(""),_T("*"),wxOPEN);
if(filename.IsEmpty()) return;
wxFileInputStream stream(filename);
if(stream.Ok() == FALSE)
{
wxLogError(_T("Failed to open '%s'"),filename.c_str());
return;
}
wxFileName fn(filename);
path_voices = fn.GetPath();
wxTextInputStream s(stream);
s >> pitch1;
s >> pitch2;
for(pk=0; pk<N_PEAKS+1; pk++)
{
for(j=0; j<3; j++)
{
s >> voice_pcnt[pk][j];
SetSpinCtrl(vd[pk][j],voice_pcnt[pk][j]);
}
}
SetSpinCtrl(voicedlg->vd_pitch1,pitch1);
SetSpinCtrl(voicedlg->vd_pitch2,pitch2);
ReadParams();
} // end of VoiceDlg::Load
#endif
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