mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-10-31 21:39:47 +00:00
espeakedit: Change from wxMDI to wxNotebook for prosody and vowel pages. espeakedit: (linux) change to wxWidgets 2.8. git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@292 d46cf337-b52f-0410-862d-fd96e6ae7743
1035 lines
22 KiB
C++
1035 lines
22 KiB
C++
/***************************************************************************
|
|
* 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 "wx/wfstream.h"
|
|
#include "wx/filename.h"
|
|
#include "wx/datstrm.h"
|
|
#include "wx/listimpl.cpp"
|
|
#include "wx/numdlg.h"
|
|
#include "wx/utils.h"
|
|
|
|
#include <ctype.h>
|
|
|
|
#include "speak_lib.h"
|
|
#include "speech.h"
|
|
#include "main.h"
|
|
#include "phoneme.h"
|
|
#include "synthesize.h"
|
|
#include "voice.h"
|
|
#include "translate.h"
|
|
#include "spect.h"
|
|
#include "options.h"
|
|
|
|
extern MyFrame *frame ;
|
|
#define SCROLLUNITS 20
|
|
|
|
SpectSeq *clipboard_spect=NULL;
|
|
wxMenu *menu_spectdisplay=NULL;
|
|
|
|
BEGIN_EVENT_TABLE(SpectDisplay, wxScrolledWindow)
|
|
EVT_LEFT_DOWN(SpectDisplay::OnMouse)
|
|
EVT_RIGHT_DOWN(SpectDisplay::OnMouse)
|
|
EVT_KEY_DOWN(SpectDisplay::OnKey)
|
|
|
|
EVT_MENU(-1, SpectDisplay::OnMenu)
|
|
|
|
END_EVENT_TABLE()
|
|
|
|
// Define a constructor for my canvas
|
|
SpectDisplay::SpectDisplay(wxWindow *parent, const wxPoint& pos, const wxSize& size, SpectSeq *spect)
|
|
: wxScrolledWindow(parent, -1, pos, size,
|
|
wxSUNKEN_BORDER | wxNO_FULL_REPAINT_ON_RESIZE)
|
|
{
|
|
wxString filename;
|
|
|
|
// SetCursor(wxCursor(wxCURSOR_PENCIL));
|
|
SetBackgroundColour(* wxWHITE);
|
|
|
|
zoom = 2;
|
|
zoomx = 0.5;
|
|
zoomy = 0.5;
|
|
|
|
savepath = _T("");
|
|
spectseq = spect;
|
|
sframe = 0;
|
|
pk_num = 1;
|
|
|
|
SetExtent();
|
|
|
|
} // end of SpectDisplay::SpectDisplay
|
|
|
|
|
|
|
|
SpectDisplay::~SpectDisplay()
|
|
{//==========================
|
|
// ?? change currentcanvas
|
|
}
|
|
|
|
|
|
void SpectDisplay::SetExtent()
|
|
{//===========================
|
|
SetScrollbars(SCROLLUNITS,SCROLLUNITS,
|
|
(int)(FRAME_WIDTH*zoomx/SCROLLUNITS)+1,
|
|
(int)(spectseq->numframes*FRAME_HEIGHT*zoomy/SCROLLUNITS)+1);
|
|
Refresh();
|
|
} // end of SpectDisplay::SetExtent
|
|
|
|
|
|
void SpectDisplay::OnDraw(wxDC& dc)
|
|
{//================================
|
|
wxRegion region;
|
|
|
|
dc.SetUserScale(zoomx,zoomy);
|
|
|
|
int f1 = 0x7fffffff, f2 = -1;
|
|
int x1,x2,y1,y2;
|
|
int vX,vY,vW,vH; // Dimensions of client area in pixels
|
|
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);
|
|
CalcUnscrolledPosition(vX+vW,vY+vH,&x2,&y2);
|
|
// Repaint this rectangle
|
|
|
|
if(y1 < f1) f1 = int(y1/zoomy);
|
|
if(y2 > f2) f2 = int(y2/zoomy);
|
|
|
|
upd ++ ;
|
|
}
|
|
|
|
if(spectseq != NULL)
|
|
spectseq->Draw(dc,f1,f2);
|
|
}
|
|
|
|
|
|
void SpectDisplay::OnActivate(int active)
|
|
{//======================================
|
|
if(active)
|
|
{
|
|
currentcanvas = this;
|
|
SetFocus(); // this doesn't seem to work
|
|
|
|
if(sframe >= 0)
|
|
formantdlg->ShowFrame(spectseq,sframe,pk_num,0xff);
|
|
WriteDialogValues();
|
|
|
|
if(wxGetKeyState(WXK_CONTROL))
|
|
{
|
|
ReadDialogValues();
|
|
spectseq->MakeWave(0,spectseq->numframes-1,voicedlg->pitchenv);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
formantdlg->GetValues(spectseq, sframe);
|
|
ReadDialogValues();
|
|
currentcanvas = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
void SetNumeric(wxTextCtrl *t, int value)
|
|
//{=====================================
|
|
{
|
|
wxString string;
|
|
|
|
string.Printf(_T("%d"),value);
|
|
t->SetValue(string);
|
|
}
|
|
|
|
void SetSpinCtrl(wxSpinCtrl *t, int value)
|
|
//{=======================================
|
|
{
|
|
wxString string;
|
|
|
|
string.Printf(_T("%d"),value);
|
|
t->SetValue(string);
|
|
}
|
|
|
|
|
|
|
|
|
|
int GetNumeric(wxTextCtrl *t)
|
|
//{==========================
|
|
{
|
|
return(atoi(t->GetValue().mb_str(wxConvLocal)));
|
|
}
|
|
|
|
|
|
void SpectDisplay::WriteDialogLength()
|
|
{//===================================
|
|
wxString string;
|
|
|
|
string.Printf(_T("%d mS"),int(spectseq->GetKeyedLength()+0.5));
|
|
formantdlg->t_orig_seq->SetLabel(string);
|
|
}
|
|
|
|
|
|
|
|
void SpectDisplay::WriteDialogValues()
|
|
//{===============================
|
|
{
|
|
wxString string;
|
|
|
|
SetSpinCtrl(formantdlg->t_amplitude,spectseq->amplitude);
|
|
|
|
string.Printf(_T("%d - %d Hz %d mS"),
|
|
spectseq->pitch1,spectseq->pitch2,spectseq->duration);
|
|
formantdlg->t_pitch->SetLabel(string);
|
|
|
|
pitchgraph->SetData(128,spectseq->pitchenv.env);
|
|
voicedlg->SetFromSpect(spectseq);
|
|
|
|
WriteDialogLength();
|
|
}
|
|
|
|
|
|
void SpectDisplay::ReadDialogValues()
|
|
//{==================================
|
|
{
|
|
spectseq->amplitude = formantdlg->t_amplitude->GetValue();
|
|
spectseq->duration = GetNumeric(voicedlg->vd_duration);
|
|
voicedlg->ReadParams();
|
|
}
|
|
|
|
|
|
void SpectDisplay::RefreshDialogValues(int type)
|
|
//{=============================================
|
|
{
|
|
int ix;
|
|
long int value;
|
|
SpectFrame *sf;
|
|
|
|
if(spectseq == NULL)
|
|
return;
|
|
|
|
sf = spectseq->frames[sframe];
|
|
|
|
spectseq->amplitude = formantdlg->t_amplitude->GetValue();
|
|
sf->amp_adjust = formantdlg->t_ampframe->GetValue();
|
|
|
|
if(use_spin_controls)
|
|
value = formantdlg->t_timeframe->GetValue();
|
|
else
|
|
formantdlg->tt_timeframe->GetValue().ToLong(&value);
|
|
|
|
sf->length_adjust = value - spectseq->GetFrameLength(sframe,0,NULL);
|
|
|
|
for(ix=0; ix < N_KLATTP; ix++)
|
|
{
|
|
sf->klatt_param[ix] = formantdlg->s_klatt[ix]->GetValue();
|
|
}
|
|
|
|
if(type==0)
|
|
{
|
|
WriteDialogLength();
|
|
Refresh();
|
|
}
|
|
else
|
|
RefreshFrame(sframe); // frame amplitude
|
|
}
|
|
|
|
|
|
void SpectDisplay::RefreshFrame(int frame)
|
|
{//=======================================
|
|
int frame_x, frame_y;
|
|
|
|
CalcScrolledPosition(0,int(frame*FRAME_HEIGHT*zoomy),
|
|
&frame_x,&frame_y);
|
|
|
|
RefreshRect(wxRect(0,frame_y,int(1000*zoomx),int(FRAME_HEIGHT*zoomy)));
|
|
}
|
|
|
|
|
|
|
|
int SpectDisplay::ScrollToFrame(int frame, int centre)
|
|
{//===================================================
|
|
int scrollx, scrolly;
|
|
int x, y;
|
|
int scrolled = 0;
|
|
|
|
GetClientSize(&x,&y);
|
|
GetViewStart(&scrollx,&scrolly);
|
|
scrolly *= SCROLLUNITS;
|
|
|
|
if(centre)
|
|
{
|
|
Scroll(-1, int(((frame+0.5)*FRAME_HEIGHT*zoomy - y/2) /SCROLLUNITS));
|
|
return(1);
|
|
}
|
|
|
|
if(scrolly > frame * FRAME_HEIGHT * zoomy)
|
|
{
|
|
Scroll(-1, int((frame * FRAME_HEIGHT * zoomy) / SCROLLUNITS));
|
|
scrolled = 1;
|
|
}
|
|
else
|
|
{
|
|
if(((frame+1) * FRAME_HEIGHT * zoomy) > (scrolly + y))
|
|
{
|
|
Scroll(-1, int(((frame+1)*FRAME_HEIGHT*zoomy - y) /SCROLLUNITS)+1);
|
|
scrolled = 1;
|
|
}
|
|
}
|
|
return(scrolled);
|
|
} // end of SpectDisplay::ScrollToFrame
|
|
|
|
|
|
void SpectDisplay::SelectFrame(int frame)
|
|
{//======================================
|
|
sframe = frame;
|
|
spectseq->SelectAll(0);
|
|
spectseq->frames[frame]->selected = 1;
|
|
formantdlg->ShowFrame(spectseq,frame,1,0xff);
|
|
ScrollToFrame(frame,1);
|
|
Refresh();
|
|
SetFocus();
|
|
} // end of SpectDisplay::SelectFrame
|
|
|
|
|
|
void SpectDisplay::OnZoom(int command)
|
|
{//===============================
|
|
static float zoomtab[] = {0.25,0.3536,0.5,0.7071,1,1.14142};
|
|
int f1, f2, frame;
|
|
int x,y;
|
|
int height,width;
|
|
|
|
GetClientSize(&width,&height);
|
|
CalcScrolledPosition(0,0,&x,&y);
|
|
|
|
// centre on a visible selected frame, or if none keep the centred frame centred
|
|
f1 = int(-y/(FRAME_HEIGHT*zoomy));
|
|
f2 = int((-y+height)/(FRAME_HEIGHT*zoomy));
|
|
for(frame=f1; frame<=f2 && frame<spectseq->numframes; frame++)
|
|
{
|
|
if(spectseq->frames[frame]->selected) break;
|
|
}
|
|
if(frame > f2)
|
|
frame = int((-y+height/2)/(FRAME_HEIGHT*zoomy)); // keep centred frame
|
|
|
|
switch(command)
|
|
{
|
|
case T_ZOOMIN:
|
|
if(zoom < 5) zoom++;
|
|
break;
|
|
case T_ZOOMOUT:
|
|
if(zoom > 0) zoom--;
|
|
break;
|
|
}
|
|
|
|
zoomx = zoomy = zoomtab[zoom];
|
|
SetExtent();
|
|
ScrollToFrame(frame,1);
|
|
Refresh();
|
|
} // end of OnZoom
|
|
|
|
|
|
|
|
void SpectDisplay::Save(const wxString &path, int selection)
|
|
{//=========================================================
|
|
wxString filename;
|
|
wxFrame *parent;
|
|
wxString msg;
|
|
wxString fname = _T("");
|
|
wxFileName f;
|
|
|
|
if(selection)
|
|
msg = _T("Save selected frames");
|
|
else
|
|
{
|
|
msg = _T("Save spectrum sequence");
|
|
fname = spectseq->name;
|
|
}
|
|
|
|
if(path.empty())
|
|
{
|
|
filename = wxFileSelector(msg,wxFileName(savepath).GetPath(),fname,_T(""),_T("*"),wxSAVE);
|
|
}
|
|
else
|
|
filename = path;
|
|
|
|
if(filename.IsEmpty())
|
|
return;
|
|
|
|
wxFileOutputStream stream(filename);
|
|
|
|
if(stream.Ok() == FALSE)
|
|
{
|
|
wxLogError(_T("Failed to write '%s'"),filename.c_str());
|
|
return;
|
|
}
|
|
spectseq->Save(stream,selection);
|
|
savepath = filename;
|
|
if((parent = (wxFrame *)GetParent()) != NULL)
|
|
{
|
|
f = wxFileName(filename);
|
|
parent->SetTitle(f.GetName());
|
|
spectseq->name = f.GetName();
|
|
}
|
|
Refresh(); // Shouldn't need this, but redraw problem
|
|
|
|
if(path.empty())
|
|
{
|
|
wxFileName p(filename);
|
|
}
|
|
} // end of Save
|
|
|
|
|
|
void SpectDisplay::SavePitchenv(PitchEnvelope &pitch)
|
|
{//==================================================
|
|
// save the pitch envelope
|
|
|
|
int ix;
|
|
FILE *f_env;
|
|
wxString filename;
|
|
char fname[200];
|
|
|
|
filename = wxFileSelector(_T("(Save pitch envelope"),path_pitches,_T(""),_T(""),_T("*"),wxSAVE);
|
|
if(filename.IsEmpty())
|
|
return;
|
|
|
|
strcpy(fname, filename.mb_str(wxConvLocal));
|
|
f_env = fopen(fname,"w");
|
|
if(f_env == NULL)
|
|
{
|
|
wxLogError(_T("Failed to write ")+filename);
|
|
return;
|
|
}
|
|
|
|
for(ix=0; ix<128; ix++)
|
|
{
|
|
fprintf(f_env," 0x%.2x,",pitch.env[ix]);
|
|
if((ix & 0xf) == 0xf)
|
|
fprintf(f_env,"\n");
|
|
}
|
|
fclose(f_env);
|
|
} // end of SpectDisplay::SavePitchenv
|
|
|
|
|
|
|
|
|
|
void SpectDisplay::PlayChild(int number, PitchEnvelope pitchenv)
|
|
{//=========================================================
|
|
#ifdef deleted
|
|
SpectSeq *seq;
|
|
|
|
if(number >= canvaslistix) return;
|
|
|
|
if((seq = canvaslist[number]->spectseq) == NULL)
|
|
return;
|
|
|
|
ReadDialogValues();
|
|
seq->MakeWave(0,seq->numframes-1,pitchenv);
|
|
#endif
|
|
} // end of PlayChild
|
|
|
|
|
|
void SpectDisplay::SetKeyframe(SpectFrame *sf, int yes)
|
|
{//====================================================
|
|
if(sf->keyframe == yes) return; // already done
|
|
|
|
sf->keyframe = yes;
|
|
pitchgraph->Refresh();
|
|
|
|
WriteDialogLength();
|
|
}
|
|
|
|
|
|
|
|
void SpectDisplay::OnMenu(wxCommandEvent& event)
|
|
{//=============================================
|
|
int id;
|
|
int code;
|
|
wxKeyEvent keyevent;
|
|
SpectFrame *sf;
|
|
static int key[] = {0x1044,0x3044,0x104e,0x1047,0x105a,0x1051,0x3051,WXK_F1,WXK_F2,0x1049,WXK_F10,0x104b};
|
|
|
|
id = event.GetId();
|
|
|
|
if(id >= 300)
|
|
{
|
|
sf = spectseq->frames[sframe];
|
|
sf->ToggleMarker(id-300);
|
|
Refresh();
|
|
return;
|
|
}
|
|
|
|
// simulate a KeyEvent that corresponds to this menu entry
|
|
code = key[id - 201];
|
|
keyevent.m_keyCode = code & 0xfff;
|
|
if(code & 0x1000)
|
|
keyevent.m_controlDown = TRUE;
|
|
else
|
|
keyevent.m_controlDown = FALSE;
|
|
if(code & 0x2000)
|
|
keyevent.m_shiftDown = TRUE;
|
|
else
|
|
keyevent.m_shiftDown = FALSE;
|
|
OnKey(keyevent);
|
|
}
|
|
|
|
|
|
|
|
void SpectDisplay::OnKey(wxKeyEvent& event)
|
|
{//====================================
|
|
int key;
|
|
int display=0; // 1=change one peak 2=one frame, 3=all
|
|
int direction=0;
|
|
int x_inc;
|
|
int y_inc;
|
|
int i;
|
|
int field=0xff;
|
|
int keyfr;
|
|
int control;
|
|
int number;
|
|
SpectFrame *sf;
|
|
peak_t *pk;
|
|
// static short pk_inc1[N_PEAKS] = {2,2,2,5,5,5,5,5,5};
|
|
static short pk_inc1[N_PEAKS] = {4,4,4,8,8,8,8,8,8};
|
|
static short pk_inc2[N_PEAKS] = {8,8,20,20,20,20,25,25,25};
|
|
|
|
sf = spectseq->frames[sframe];
|
|
pk = &sf->peaks[pk_num];
|
|
key = event.GetKeyCode();
|
|
control = event.ControlDown();
|
|
if(control && isalnum(key)) key |= 0x1000;
|
|
|
|
if(event.ShiftDown())
|
|
{
|
|
x_inc = pk_inc1[pk_num];
|
|
y_inc = 0x40;
|
|
}
|
|
else
|
|
{
|
|
x_inc = pk_inc2[pk_num];
|
|
y_inc = 0x100;
|
|
}
|
|
|
|
switch(key)
|
|
{
|
|
case WXK_NEXT:
|
|
if(sframe < spectseq->numframes-1)
|
|
{
|
|
formantdlg->GetValues(spectseq, sframe);
|
|
spectseq->SelectAll(0);
|
|
sframe++;
|
|
spectseq->frames[sframe]->selected = 1;
|
|
display = 3;
|
|
}
|
|
break;
|
|
|
|
case WXK_PRIOR:
|
|
if(sframe > 0)
|
|
{
|
|
formantdlg->GetValues(spectseq, sframe);
|
|
spectseq->SelectAll(0);
|
|
sframe--;
|
|
spectseq->frames[sframe]->selected = 1;
|
|
display = 3;
|
|
}
|
|
break;
|
|
|
|
|
|
case 'Z':
|
|
if(pk_num > 0)
|
|
{
|
|
pk_num--;
|
|
display = 2;
|
|
}
|
|
break;
|
|
|
|
case 'X':
|
|
if(pk_num < N_PEAKS-1)
|
|
{
|
|
pk_num++;
|
|
display = 2;
|
|
}
|
|
break;
|
|
|
|
case WXK_RIGHT:
|
|
pk->pkfreq = pk->pkfreq - (pk->pkfreq % x_inc) + x_inc;
|
|
if(pk->pkfreq >= MAX_DISPLAY_FREQ)
|
|
pk->pkfreq = MAX_DISPLAY_FREQ;
|
|
display = 1;
|
|
direction = 1;
|
|
field = 1;
|
|
break;
|
|
|
|
case WXK_LEFT:
|
|
pk->pkfreq = pk->pkfreq - (pk->pkfreq % x_inc) - x_inc;
|
|
if(pk->pkfreq < 50)
|
|
pk->pkfreq = 50;
|
|
display = 1;
|
|
direction = -1;
|
|
field = 1;
|
|
break;
|
|
|
|
case WXK_UP:
|
|
pk->pkheight = pk->pkheight - (pk->pkheight % y_inc) + y_inc;
|
|
if(pk->pkheight >= 0x7fff)
|
|
pk->pkheight = 0x7fff;
|
|
display = 1;
|
|
field = 2;
|
|
SetKeyframe(sf,1);
|
|
break;
|
|
|
|
case WXK_DOWN:
|
|
pk->pkheight = pk->pkheight - (pk->pkheight % y_inc) - y_inc;
|
|
if(pk->pkheight <= 0)
|
|
{
|
|
pk->pkheight = 0;
|
|
keyfr = 0; // but only if all the other peaks are zero
|
|
for(i=0; i<N_PEAKS; i++)
|
|
{
|
|
if(sf->peaks[i].pkheight > 0)
|
|
keyfr = 1;
|
|
}
|
|
SetKeyframe(sf,keyfr);
|
|
}
|
|
|
|
display = 1;
|
|
field = 2;
|
|
break;
|
|
|
|
case ',': // width--
|
|
if(event.ControlDown())
|
|
{
|
|
// CTRL, rotate, make right slope steeper
|
|
if(pk_num < 3)
|
|
{
|
|
pk->pkright-= 5;
|
|
pk->pkwidth += 5;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pk->pkright -= 10;
|
|
pk->pkwidth -= 10;
|
|
if(pk->pkright < 0)
|
|
pk->pkright = 0;
|
|
if(pk->pkwidth < 0)
|
|
pk->pkwidth = 0;
|
|
}
|
|
field = 4;
|
|
display = 1;
|
|
break;
|
|
|
|
case '.': // width++
|
|
if(event.ControlDown())
|
|
{
|
|
// CTRL: rotate, make left slope steeper
|
|
if(pk_num < 3)
|
|
{
|
|
pk->pkright += 5;
|
|
pk->pkwidth -= 5;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pk->pkright += 10;
|
|
pk->pkwidth += 10;
|
|
}
|
|
field = 4;
|
|
display = 1;
|
|
break;
|
|
|
|
case '<': // width--
|
|
pk->pkright -= 2;
|
|
pk->pkwidth -= 2;
|
|
if(pk->pkwidth < 0)
|
|
pk->pkwidth = 0;
|
|
display = 1;
|
|
field = 4;
|
|
break;
|
|
|
|
case '>': // width++
|
|
pk->pkright += 2;
|
|
pk->pkwidth += 2;
|
|
display = 1;
|
|
field = 4;
|
|
break;
|
|
|
|
case '[': // width--
|
|
pk->pkright -= 1;
|
|
if(pk->pkright < 0)
|
|
pk->pkright = 0;
|
|
display = 1;
|
|
field = 4;
|
|
break;
|
|
|
|
case ']': // width++
|
|
pk->pkright += 1;
|
|
display = 1;
|
|
field = 4;
|
|
break;
|
|
|
|
case '/': // make left=right
|
|
i = pk->pkwidth + pk->pkright;
|
|
pk->pkwidth = pk->pkright = i/2;
|
|
display = 1;
|
|
field = 4;
|
|
break;
|
|
|
|
case 0x1041: // CTRL-A
|
|
spectseq->SelectAll(1);
|
|
Refresh();
|
|
break;
|
|
|
|
case 0x1042: // CTRL-B
|
|
// toggle bass reduction
|
|
spectseq->bass_reduction ^= 1;
|
|
Refresh();
|
|
break;
|
|
|
|
case 0x1043: // CTRL-C
|
|
spectseq->ClipboardCopy();
|
|
break;
|
|
|
|
case 0x1044: // CTRL-D
|
|
// copy peaks down from previous/next keyframe
|
|
if(event.ShiftDown())
|
|
spectseq->CopyDown(sframe,1);
|
|
else
|
|
spectseq->CopyDown(sframe,-1);
|
|
SetKeyframe(sf,1);
|
|
display = 2;
|
|
break;
|
|
|
|
case 0x1047: // CTRL-G toggle grid
|
|
spectseq->grid ^= 1;
|
|
Refresh();
|
|
break;
|
|
|
|
case 0x1049: // CTRL-I interpolate between two frames
|
|
spectseq->InterpolateAdjacent();
|
|
display = 2;
|
|
break;
|
|
|
|
case 0x104b: // CTRL-K
|
|
// spectseq->SetKlattDefaults();
|
|
// display = 3;
|
|
break;
|
|
|
|
case 0x104d: // CTRL-M
|
|
sf->ToggleMarker(1);
|
|
display = 2;
|
|
break;
|
|
|
|
case 0x104e: // CTRL-N
|
|
number = wxGetNumberFromUser(_T("Toggle Marker"),_T("Marker"),_T(""),1,0,7);
|
|
sf->ToggleMarker(number);
|
|
display = 2;
|
|
break;
|
|
|
|
case 0x104f: // CTRL-O
|
|
spectseq->ConstructVowel();
|
|
break;
|
|
|
|
case 0x1051: // CTRL-Q
|
|
if(event.ShiftDown())
|
|
spectseq->InterpolatePeaks(0); // remove interpolation
|
|
else
|
|
spectseq->InterpolatePeaks(1); // show interpolation
|
|
display = 3;
|
|
break;
|
|
|
|
case 0x1053: // CTRL-S
|
|
Save(savepath);
|
|
break;
|
|
|
|
case 0x1056: // CTRL-V
|
|
if(event.ShiftDown())
|
|
{
|
|
// insert frames from the clipboard
|
|
sframe = spectseq->ClipboardInsert(sframe);
|
|
SetExtent();
|
|
display = 3;
|
|
pitchgraph->Refresh();
|
|
break;
|
|
}
|
|
|
|
// overwrite just the peaks
|
|
if(clipboard_spect == NULL)
|
|
break;
|
|
i = 0;
|
|
while((i < clipboard_spect->numframes) && ((sframe+i) < spectseq->numframes))
|
|
{
|
|
spectseq->frames[sframe+i]->CopyPeaks(clipboard_spect->frames[i]);
|
|
i++;
|
|
}
|
|
display = 3;
|
|
break;
|
|
|
|
case 0x1058: // CTRL-X
|
|
spectseq->ClipboardCopy();
|
|
spectseq->DeleteSelected();
|
|
SetExtent();
|
|
sframe = 0;
|
|
display = 3;
|
|
pitchgraph->Refresh();
|
|
break;
|
|
|
|
case 0x105a: // CTRK-Z
|
|
sf->ZeroPeaks();
|
|
SetKeyframe(sf,0);
|
|
display = 2;
|
|
break;
|
|
|
|
case WXK_F10:
|
|
sf->ApplyVoiceMods();
|
|
display = 2;
|
|
break;
|
|
|
|
case WXK_F2:
|
|
// make and play sequence
|
|
ReadDialogValues();
|
|
spectseq->MakeWave(0,spectseq->numframes-1,voicedlg->pitchenv);
|
|
break;
|
|
|
|
case WXK_F1:
|
|
// make and play selected
|
|
ReadDialogValues();
|
|
sf->MakeWaveF(0,voicedlg->pitchenv,spectseq->amplitude,spectseq->duration);
|
|
break;
|
|
case WXK_F3:
|
|
// make and play selected
|
|
ReadDialogValues();
|
|
sf->MakeWaveF(1,voicedlg->pitchenv,spectseq->amplitude,spectseq->duration);
|
|
break;
|
|
|
|
default:
|
|
if(key>='0' && key<='9')
|
|
{
|
|
i = key-'0';
|
|
if(event.ControlDown())
|
|
{
|
|
if(i==0) i=10;
|
|
PlayChild(i-1,voicedlg->pitchenv);
|
|
}
|
|
else
|
|
{
|
|
// select peak number
|
|
if((pk_num = i) >= N_PEAKS) pk_num = N_PEAKS-1;
|
|
}
|
|
display=2;
|
|
}
|
|
event.Skip();
|
|
break;
|
|
}
|
|
|
|
if(display)
|
|
{
|
|
pk_select = pk_num;
|
|
sf = spectseq->frames[sframe];
|
|
pk = &sf->peaks[pk_num];
|
|
|
|
if(pk->pkwidth < 50) pk->pkwidth = 50; // min. width
|
|
if(pk->pkright < 50) pk->pkright = 50;
|
|
|
|
// ensure minimum separation between peaks & prevent crossover
|
|
if(direction > 0)
|
|
{
|
|
for(i=pk_num+1; i<N_PEAKS; i++)
|
|
{
|
|
if(sf->peaks[i].pkfreq < sf->peaks[i-1].pkfreq + 100)
|
|
sf->peaks[i].pkfreq = sf->peaks[i-1].pkfreq + 100;
|
|
}
|
|
}
|
|
else
|
|
if(direction < 0)
|
|
{
|
|
for(i=pk_num-1; i>=0; i--)
|
|
{
|
|
if(sf->peaks[i].pkfreq > sf->peaks[i+1].pkfreq - 100)
|
|
sf->peaks[i].pkfreq = sf->peaks[i+1].pkfreq - 100;
|
|
}
|
|
}
|
|
|
|
if(display==3)
|
|
{
|
|
formantdlg->ShowFrame(spectseq,sframe,pk_num,0xff);
|
|
Refresh();
|
|
}
|
|
else
|
|
{
|
|
// only one frame needs to be redrawn
|
|
formantdlg->ShowFrame(spectseq,sframe,pk_num,field);
|
|
RefreshFrame(sframe);
|
|
}
|
|
|
|
if(sframe >= 0)
|
|
{
|
|
if(ScrollToFrame(sframe,0))
|
|
Refresh(); // shouldn't need this, but we have redraw problems
|
|
}
|
|
|
|
}
|
|
} // end of SpectDisplay::OnKey
|
|
|
|
|
|
void SpectDisplay::OnMouse(wxMouseEvent& event)
|
|
{//========================================
|
|
int frame;
|
|
int ix;
|
|
|
|
SetFocus();
|
|
if(event.RightDown())
|
|
{
|
|
PopupMenu(menu_spectdisplay);
|
|
return;
|
|
}
|
|
|
|
wxClientDC dc(this);
|
|
PrepareDC(dc);
|
|
|
|
wxPoint pt(event.GetLogicalPosition(dc));
|
|
|
|
if(spectseq->numframes==0) return;
|
|
|
|
frame = (int)(pt.y/(FRAME_HEIGHT*zoomy));
|
|
|
|
if(!event.ControlDown())
|
|
spectseq->SelectAll(0);
|
|
|
|
if(event.ShiftDown())
|
|
{
|
|
if(sframe >= 0)
|
|
{
|
|
if(frame < sframe)
|
|
for(ix=frame; ix<=sframe; ix++)
|
|
spectseq->frames[ix]->selected =1;
|
|
else
|
|
for(ix=sframe; ix<=frame && ix<spectseq->numframes; ix++)
|
|
spectseq->frames[ix]->selected =1;
|
|
Refresh();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(frame < spectseq->numframes)
|
|
spectseq->frames[frame]->selected ^= 1;
|
|
Refresh();
|
|
}
|
|
|
|
if(frame < spectseq->numframes)
|
|
{
|
|
formantdlg->GetValues(spectseq,sframe);
|
|
if(sframe != frame)
|
|
formantdlg->ShowFrame(spectseq,frame,pk_num,0xff);
|
|
|
|
sframe = frame;
|
|
}
|
|
} // end of SpectDisplay::OnMouse
|
|
|
|
|
|
void MyFrame::OnNewWindow(wxCommandEvent& event)
|
|
{//=============================================
|
|
SpectSeq *spectseq;
|
|
wxString leaf;
|
|
wxString pathload;
|
|
int width, height;
|
|
|
|
if(event.GetId() == MENU_SPECTRUM)
|
|
pathload = path_spectload;
|
|
else
|
|
pathload = path_spectload2;
|
|
|
|
wxString filename = wxFileSelector(_T("Read spectrum or praat data"),pathload,
|
|
_T(""),_T(""),_T("*"),wxOPEN);
|
|
if(filename.IsEmpty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
// create SpectSeq and import data
|
|
spectseq = new SpectSeq;
|
|
if(spectseq == NULL)
|
|
{
|
|
wxLogError(_T("Failed to create SpectSeq"));
|
|
return;
|
|
}
|
|
|
|
wxFileInputStream stream(filename);
|
|
if(stream.Ok() == FALSE)
|
|
{
|
|
wxLogError(_T("Failed to open '%s'"),filename.c_str());
|
|
return;
|
|
}
|
|
wxFileName path = wxFileName(filename);
|
|
leaf = path.GetName();
|
|
|
|
setlocale(LC_NUMERIC,"C"); // read numbers in the form 1.23456
|
|
spectseq->Load(stream);
|
|
spectseq->name = leaf;
|
|
spectseq->MakePitchenv(spectseq->pitchenv,0,spectseq->numframes-1);
|
|
|
|
if(event.GetId() == MENU_SPECTRUM)
|
|
path_spectload = path.GetPath();
|
|
else
|
|
path_spectload2 = path.GetPath();
|
|
|
|
|
|
|
|
GetClientSize(&width, &height);
|
|
SpectDisplay *canvas = new SpectDisplay(screenpages, wxDefaultPosition, wxSize(width, height), spectseq);
|
|
screenpages->AddPage(canvas, leaf, true);
|
|
canvas->savepath = filename;
|
|
currentcanvas = canvas;
|
|
}
|
|
|
|
|
|
void InitSpectrumDisplay()
|
|
{//=======================
|
|
wxMenu *menu_markers = new wxMenu;
|
|
menu_spectdisplay = new wxMenu;
|
|
|
|
menu_markers->Append(301,_T("1 Vowel break point"));
|
|
menu_markers->Append(302,_T("2 Reduce length changes"));
|
|
menu_markers->Append(303,_T("3 Break F0 to F2"));
|
|
menu_markers->Append(304,_T("4 Break. All formants"));
|
|
menu_markers->Append(305,_T("5 Allow greater rate of formant change"));
|
|
menu_markers->Append(306,_T("6 Trill"));
|
|
menu_markers->Append(307,_T("7 Defer wav mixing"));
|
|
|
|
menu_spectdisplay->Append(201,_T("Copy Peaks Down CTRL+D"));
|
|
menu_spectdisplay->Append(202,_T("Copy Peaks Up SHIFT+CTRL+D"));
|
|
menu_spectdisplay->Append(204,_T("Grid (toggle) CTRL+G"));
|
|
menu_spectdisplay->Append(210,_T("Interpolate (percentage) CTRL+I"));
|
|
menu_spectdisplay->Append(212,_T("Convert sequence to Klatt format CTRL+K"));
|
|
menu_spectdisplay->Append(203,_T("Marker (toggle) CTRL+N"));
|
|
menu_spectdisplay->Append(206,_T("Show Interpolation CTRL+Q"));
|
|
menu_spectdisplay->Append(207,_T("Hide Interpolation CTRL+SHIFT+Q"));
|
|
menu_spectdisplay->Append(205,_T("Zero Peaks CTRL+Z"));
|
|
menu_spectdisplay->Append(210,_T("Toggle Marker"),menu_markers);
|
|
menu_spectdisplay->Append(211,_T("Apply the formant adjustments from a voice file"));
|
|
menu_spectdisplay->AppendSeparator();
|
|
menu_spectdisplay->Append(208,_T("Play Selected Frame F1"));
|
|
menu_spectdisplay->Append(209,_T("Play All F2"));
|
|
|
|
}
|