[1.39.28]

Added experimental Klatt synthesizer.
Klatt phonemes use a new format of phoneme data.
espeakedit, new dialog fields and layout for Klatt phonemes.
Added Klatt versions of English phonemes.

Fixed some compilation warnings on Windows.
Fixed bug in Lettergroups > L10

Increased amplitude of harmonics below F1 peak, to increase bass.
Allow 5 (up from 4) pairs of values in "tone" command in voice files.
Default to slightly wider pk_shape1.

If words are separated by hyphens, don't add word-gap, and don't pass new-word flag onto phoneme processing.


git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@203 d46cf337-b52f-0410-862d-fd96e6ae7743
This commit is contained in:
jonsd
2008-11-22 22:25:29 +00:00
parent a7501374b2
commit 1150d1d8da
52 changed files with 2687 additions and 399 deletions
+78 -36
View File
@@ -597,17 +597,21 @@ int Compile::LoadSpect(const char *path, int control)
int peak;
int displ;
int frame;
int n_frames;
int ix;
int x;
int x, x2;
int rms;
float total;
float pkheight;
int marker1_set=0;
int frame_vowelbreak=0;
int klatt_flag=0;
SpectFrame *fr;
frame_t *fr_out;
wxString path_sep = _T("/");
SPECT_SEQ seq_out;
SPECT_SEQK seqk_out;
// create SpectSeq and import data
spectseq = new SpectSeq;
@@ -627,11 +631,14 @@ int Compile::LoadSpect(const char *path, int control)
}
spectseq->Load(stream);
if(spectseq->synthesizer_type == 1)
klatt_flag = FRFLAG_KLATT;
displ = ftell(f_phdata);
seq_out.n_frames=0;
seq_out.flags=0;
seq_out.length=0;
seq_out.length_total=0;
total = 0;
for(frame=0; frame < spectseq->numframes; frame++)
@@ -669,7 +676,7 @@ for(ix=0; ix<8; ix++)
total += spectseq->frames[frame-1]->length;
}
}
seq_out.length = int(total);
seq_out.length_total = int(total);
if((control & 1) && (marker1_set == 0))
{
@@ -678,68 +685,103 @@ for(ix=0; ix<8; ix++)
spectseq->frames[frame_vowelbreak]->markers |= FRFLAG_VOWEL_CENTRE;
}
ix = 0;
n_frames = 0;
for(frame=0; frame < spectseq->numframes; frame++)
{
fr = spectseq->frames[frame];
if(fr->keyframe)
{
if(klatt_flag)
fr_out = &seqk_out.frame[n_frames];
else
fr_out = (frame_t *)&seq_out.frame[n_frames];
x = int(fr->length + 0.5); // round to nearest mS
if(x > 255) x = 255;
seq_out.frame[ix].length = x;
fr_out->length = x;
fr_out->frflags = fr->markers | klatt_flag;
seq_out.frame[ix].frflags = fr->markers;
rms = int(fr->GetRms(spectseq->amplitude));
if(rms > 255) rms = 255;
seq_out.frame[ix].rms = rms;
fr_out->rms = rms;
if(n_frames == (seq_out.n_frames-1))
fr_out->length = 0; // give last frame zero length
if(ix == (seq_out.n_frames-1))
seq_out.frame[ix].length = 0; // give last frame zero length
// write: peak data
count_frames++;
for(peak=0; peak<N_PEAKS; peak++)
{
seq_out.frame[ix].ffreq[peak] = fr->peaks[peak].pkfreq;
pkheight = spectseq->amplitude * fr->amp_adjust * fr->peaks[peak].pkheight;
pkheight = pkheight/640000;
if(pkheight > 255) pkheight = 255;
seq_out.frame[ix].fheight[peak] = int(pkheight);
fr_out->ffreq[peak] = fr->peaks[peak].pkfreq;
if(klatt_flag)
{
pkheight = fr->peaks[peak].pkheight / 128;
}
else
{
pkheight = spectseq->amplitude * fr->amp_adjust * fr->peaks[peak].pkheight;
pkheight = pkheight/640000;
if(pkheight > 255) pkheight = 255;
}
fr_out->fheight[peak] = int(pkheight);
if(peak < 6)
{
x = fr->peaks[peak].pkwidth/4;
x = fr->peaks[peak].pkwidth/2;
x2 = fr->peaks[peak].pkright;
if(klatt_flag == 0)
{
x /= 2;
x2 /= 4;
}
if(x > 255) x = 255;
seq_out.frame[ix].fwidth[peak] = x;
fr_out->fwidth[peak] = x;
x = fr->peaks[peak].pkright/4;
if(x > 255) x = 255;
seq_out.frame[ix].fright[peak] = x;
if(x2 > 255) x2 = 255;
fr_out->fright[peak] = x2;
}
}
#ifdef LOG_DETAIL
fprintf(f_errors,"Frame %d %3dmS rms=%3d flags=%2d pk=%4d %4d %4d",ix,seq_out.frame[ix].length,
seq_out.frame[ix].rms,seq_out.frame[ix].flags,
seq_out.frame[ix].peaks[1].pkfreq,seq_out.frame[ix].peaks[2].pkfreq,seq_out.frame[ix].peaks[3].pkfreq);
if(klatt_flag)
{
if(fr->klatt_param[KLATT_Kopen] == 0)
{
Error("Klatt_Kopen has value 0");
}
if(fr->markers != 0)
{
fprintf(f_errors," [%x]",fr->markers);
}
fputc('\n',f_errors);
#endif
ix++;
// additional fields
for(ix=0; ix<N_KLATTP; ix++)
{
fr_out->klattp[ix] = fr->klatt_param[ix];
}
fr_out->fwidth6 = fr->peaks[6].pkwidth/2;
fr_out->fright6 = fr->peaks[6].pkright;
}
n_frames++;
}
}
ix = (char *)(&seq_out.frame[seq_out.n_frames]) - (char *)(&seq_out);
ix = (ix+3) & 0xfffc; // round up to multiple of 4 bytes
if(klatt_flag)
{
seqk_out.n_frames = seq_out.n_frames;
seqk_out.flags = seq_out.flags;
seqk_out.length_total = seq_out.length_total;
ix = (char *)(&seqk_out.frame[seqk_out.n_frames]) - (char *)(&seqk_out);
ix = (ix+3) & 0xfffc; // round up to multiple of 4 bytes
fwrite(&seqk_out,ix,1,f_phdata);
}
else
{
ix = (char *)(&seq_out.frame[seq_out.n_frames]) - (char *)(&seq_out);
ix = (ix+3) & 0xfffc; // round up to multiple of 4 bytes
fwrite(&seq_out,ix,1,f_phdata);
}
fwrite(&seq_out,ix,1,f_phdata);
delete spectseq;
return(displ);
} // end of Compile::LoadSpect
+1 -1
View File
@@ -1268,7 +1268,7 @@ static int compile_lettergroup(char *input, FILE *f_out)
group = atoi(&p[0]);
if(group >= N_LETTER_GROUPS)
{
fprintf(f_log,"%5d: lettergroup out of range (01-%.2d)\n",linenum,N_LETTER_GROUPS);
fprintf(f_log,"%5d: lettergroup out of range (01-%.2d)\n",linenum,N_LETTER_GROUPS-1);
error_count++;
return(1);
}
+1 -1
View File
@@ -232,7 +232,7 @@ wxSashLayoutWindow *win;
win = new wxSashLayoutWindow(this, ID_WINDOW_LEFT2,
wxDefaultPosition, wxSize(200, 30),
wxNO_BORDER | wxSW_3D | wxCLIP_CHILDREN);
win->SetDefaultSize(wxSize(208, 1000));
win->SetDefaultSize(wxSize(212, 1000));
win->SetOrientation(wxLAYOUT_VERTICAL);
win->SetAlignment(wxLAYOUT_LEFT);
// win->SetBackgroundColour(wxColour(0, 255, 255));
+117 -32
View File
@@ -43,10 +43,10 @@ ByteGraph *pitchgraph=NULL;
BEGIN_EVENT_TABLE(FormantDlg, wxPanel)
EVT_BUTTON(T_ZOOMOUT,FormantDlg::OnCommand)
EVT_BUTTON(T_ZOOMIN,FormantDlg::OnCommand)
EVT_SPINCTRL(T_AMPLITUDE,FormantDlg::OnSpin)
EVT_SPINCTRL(T_TIMESEQ,FormantDlg::OnSpin)
EVT_SPINCTRL(T_AMPFRAME,FormantDlg::OnSpin)
EVT_SPINCTRL(T_TIMEFRAME,FormantDlg::OnSpin)
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()
@@ -79,21 +79,19 @@ void FormantDlg::OnSpin(wxSpinEvent& event)
switch(id = event.GetId())
{
case T_AMPLITUDE:
case T_TIMESEQ:
case T_TIMEFRAME:
currentcanvas->RefreshDialogValues(0);
break;
case T_AMPFRAME:
currentcanvas->RefreshDialogValues(1);
break;
default:
currentcanvas->RefreshDialogValues(0);
break;
}
currentcanvas->SetFocus();
}
FormantDlg::FormantDlg(wxWindow *parent) : wxPanel(parent,-1,wxDefaultPosition,wxSize(400,1000))
{//==========================================================================
{//=============================================================================================
int ix;
int y;
int xplace;
@@ -104,6 +102,7 @@ FormantDlg::FormantDlg(wxWindow *parent) : wxPanel(parent,-1,wxDefaultPosition,w
xplace = 28;
id = 201;
new wxStaticText(this,-1,_T("Formants"),wxPoint(4,5));
t_lab[4] = new wxStaticText(this,-1,_T(" BW BWp Ap"),wxPoint(78,5),wxSize(300,20));
for(ix=0; ix<N_PEAKS; ix++)
{
@@ -115,48 +114,124 @@ FormantDlg::FormantDlg(wxWindow *parent) : wxPanel(parent,-1,wxDefaultPosition,w
wxPoint(xplace,y+24*ix),wxSize(48,20),
wxTE_CENTRE+wxTE_READONLY);
t_pkheight[ix] = new wxTextCtrl(this,id++,_T(""),
wxPoint(xplace+52,y+24*ix),wxSize(36,20),
wxPoint(xplace+50,y+24*ix),wxSize(36,20),
wxTE_CENTRE+wxTE_READONLY);
t_pkwidth[ix] = new wxTextCtrl(this,id++,_T(""),
wxPoint(xplace+92,y+24*ix),wxSize(48,20),
wxPoint(xplace+88,y+24*ix),wxSize(48,20),
wxTE_CENTRE+wxTE_READONLY);
#ifdef WIDTH2
t_pkright[ix] = new wxTextCtrl(this,id++,_T(""),
wxPoint(xplace+132,y+24*ix),wxSize(36,20),
wxPoint(xplace+138,y+24*ix),wxSize(36,20),
wxTE_CENTRE+wxTE_READONLY);
#endif
if(ix>5) t_pkwidth[ix]->Hide();
}
t_ampframe = new wxSpinCtrl(this,T_AMPFRAME,_T(""),
wxPoint(6,244),wxSize(52,24),wxTE_CENTRE,0,500);
t_lab[3] = new wxStaticText(this,-1,_T("% amp - Frame"),wxPoint(61,248));
t_timeframe = new wxSpinCtrl(this,T_TIMEFRAME,_T(""),
wxPoint(6,272),wxSize(52,24),wxTE_CENTRE,0,500);
t_orig_frame = new wxStaticText(this,-1,_T("mS"),wxPoint(61,276));
y=240;
t_timeframe = new wxSpinCtrl(this,T_TIMEFRAME,_T(""), wxPoint(6,y+0), wxSize(52,24), wxTE_CENTRE,0,500);
t_orig_frame = new wxStaticText(this,-1,_T("mS"),wxPoint(57,y+8));
t_ampframe = new wxSpinCtrl(this,T_AMPFRAME,_T(""), wxPoint(100,y+0), wxSize(52,24), wxTE_CENTRE,0,500);
t_lab[3] = new wxStaticText(this,-1,_T("% amp - Frame"),wxPoint(151,y+8));
t_zoomout = new wxButton(this,T_ZOOMOUT,_T("Zoom-"),wxPoint(16,310));
t_zoomin = new wxButton(this,T_ZOOMIN,_T("Zoom+"),wxPoint(106,310));
s_klatt[KLATT_AV] = new wxSpinCtrl(this,T_AV,_T(""), wxPoint(6,y+32), wxSize(52,24), wxTE_CENTRE,0,500);
t_klatt[KLATT_AV] = new wxStaticText(this,-1,_T("AV"),wxPoint(61,y+36));
s_klatt[KLATT_AVp] = new wxSpinCtrl(this,T_AVP,_T(""), wxPoint(100,y+32), wxSize(52,24), wxTE_CENTRE,0,500);
t_klatt[KLATT_AVp] = new wxStaticText(this,-1,_T("AVp"),wxPoint(155,y+36));
s_klatt[KLATT_Fric] = new wxSpinCtrl(this,T_FRIC,_T(""), wxPoint(6,y+60), wxSize(52,24), wxTE_CENTRE,0,500);
t_klatt[KLATT_Fric] = new wxStaticText(this,-1,_T("Fric"),wxPoint(61,y+64));
s_klatt[KLATT_FricBP] = new wxSpinCtrl(this,T_FRICBP,_T(""), wxPoint(100,y+60), wxSize(52,24), wxTE_CENTRE,0,500);
t_klatt[KLATT_FricBP] = new wxStaticText(this,-1,_T("FricBP"),wxPoint(155,y+64));
s_klatt[KLATT_Aspr] = new wxSpinCtrl(this,T_ASPR,_T(""), wxPoint(6,y+88), wxSize(52,24), wxTE_CENTRE,0,500);
t_klatt[KLATT_Aspr] = new wxStaticText(this,-1,_T("Aspr"),wxPoint(61,y+92));
s_klatt[KLATT_Turb] = new wxSpinCtrl(this,T_TURB,_T(""), wxPoint(100,y+88), wxSize(52,24), wxTE_CENTRE,0,500);
t_klatt[KLATT_Turb] = new wxStaticText(this,-1,_T("Turb"),wxPoint(155,y+92));
s_klatt[KLATT_Skew] = new wxSpinCtrl(this,T_SKEW,_T(""), wxPoint(6,y+116), wxSize(52,24), wxTE_CENTRE,0,500);
t_klatt[KLATT_Skew] = new wxStaticText(this,-1,_T("Skew"),wxPoint(61,y+120));
s_klatt[KLATT_Tilt] = new wxSpinCtrl(this,T_TILT,_T(""), wxPoint(100,y+116), wxSize(52,24), wxTE_CENTRE,0,500);
t_klatt[KLATT_Tilt] = new wxStaticText(this,-1,_T("Tilt"),wxPoint(155,y+120));
s_klatt[KLATT_Kopen] = new wxSpinCtrl(this,T_KOPEN,_T(""), wxPoint(6,y+144), wxSize(52,24), wxTE_CENTRE,0,500);
t_klatt[KLATT_Kopen] = new wxStaticText(this,-1,_T("kopen"),wxPoint(61,y+148));
// usepitchenv = new wxCheckBox(this,T_USEPITCHENV,_T("???"),wxPoint(20,320));
t_zoomout = new wxButton(this,T_ZOOMOUT,_T("Zoom-"),wxPoint(16,420));
t_zoomin = new wxButton(this,T_ZOOMIN,_T("Zoom+"),wxPoint(106,420));
y=468;
t_amplitude = new wxSpinCtrl(this,T_AMPLITUDE,_T(""),
wxPoint(6,370),wxSize(52,24),wxTE_CENTRE,0,500);
t_lab[2] = new wxStaticText(this,-1,_T("% amp - Sequence"),wxPoint(61,374));
wxPoint(6,y),wxSize(52,24),wxTE_CENTRE,0,y+130);
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,404));
t_orig_seq = new wxStaticText(this,-1,_T("mS"),wxPoint(61,y+30));
t_pitch = new wxStaticText(this,-1,_T(""),wxPoint(4,440),wxSize(192,24));
t_pitch = new wxStaticText(this,-1,_T(""),wxPoint(4,520),wxSize(192,24));
pitchgraph = new ByteGraph(this,wxPoint(0,460),wxSize(200,140));
pitchgraph = new ByteGraph(this,wxPoint(0,538),wxSize(200,140));
pitchgraph->SetData(128,env_fall);
pitchgraph->ShowSpectrum(1);
pitchgraph->Show();
}
void FormantDlg::HideFields(int synth_type)
{//=======================================
int ix;
static int prev_synth_type = -1;
if(synth_type == prev_synth_type)
return; // no change
if(synth_type == 0)
{
for(ix=0; ix<9; ix++)
{
s_klatt[ix]->Hide();
t_klatt[ix]->Hide();
}
for(ix=6; ix<9; ix++)
{
t_pkfreq[ix]->Show();
t_pkheight[ix]->Show();
t_pkwidth[ix]->Hide();
t_pkright[ix]->Hide();
}
t_ampframe->Show();
t_amplitude->Show();
t_lab[2]->Show();
t_lab[3]->Show();
t_labpk[7]->Show();
t_labpk[8]->Show();
t_lab[4]->Hide();
}
else
{
for(ix=0; ix<9; ix++)
{
s_klatt[ix]->Show();
t_klatt[ix]->Show();
}
for(ix=7; ix<9; ix++)
{
t_pkfreq[ix]->Hide();
t_pkheight[ix]->Hide();
t_pkwidth[ix]->Hide();
t_pkright[ix]->Hide();
}
t_pkwidth[6]->Show(1);
t_pkright[6]->Show(1);
t_ampframe->Hide();
t_amplitude->Hide();
t_lab[2]->Hide();
t_lab[3]->Hide();
t_labpk[7]->Hide();
t_labpk[8]->Hide();
t_lab[4]->Show();
}
prev_synth_type = synth_type;
}
void FormantDlg::ShowFrame(SpectSeq *spectseq, int frame, int pk, int field)
{//==============================================================
@@ -169,6 +244,8 @@ void FormantDlg::ShowFrame(SpectSeq *spectseq, int frame, int pk, int field)
return;
sf = spectseq->frames[frame];
HideFields(spectseq->synthesizer_type);
if(field == 0xff)
{
// indicate the selected peak
@@ -203,10 +280,8 @@ void FormantDlg::ShowFrame(SpectSeq *spectseq, int frame, int pk, int field)
{
value.Printf(_T("%3d"),sf->peaks[ix].pkwidth);
t_pkwidth[ix]->SetValue(value);
#ifdef WIDTH2
value.Printf(_T("%3d"),sf->peaks[ix].pkright);
t_pkright[ix]->SetValue(value);
#endif
}
}
@@ -216,6 +291,16 @@ void FormantDlg::ShowFrame(SpectSeq *spectseq, int frame, int pk, int field)
t_orig_frame->SetLabel(value);
value.Printf(_T("%3d"),sf->amp_adjust);
t_ampframe->SetValue(value);
if(spectseq->synthesizer_type == 1)
{
for(ix=0; ix<9; ix++)
{
SetSpinCtrl(s_klatt[ix], sf->klatt_param[ix]);
}
}
} // end of FormantDlg::ShowFrame
+1282
View File
File diff suppressed because it is too large Load Diff
+138
View File
@@ -0,0 +1,138 @@
#define CASCADE_PARALLEL 1 /* Type of synthesis model */
#define ALL_PARALLEL 2
#define IMPULSIVE 1 /* Type of voicing source */
#define NATURAL 2
#define SAMPLED 3
#define PI 3.1415927
/* typedef's that need to be exported */
typedef long flag;
/* Resonator Structure */
typedef struct
{
double a;
double b;
double c;
double p1;
double p2;
double a_inc;
double b_inc;
double c_inc;
} resonator_t, *resonator_ptr;
/* Structure for Klatt Globals */
typedef struct
{
flag synthesis_model; /* cascade-parallel or all-parallel */
flag outsl; /* Output waveform selector */
long samrate; /* Number of output samples per second */
long FLPhz ; /* Frequeny of glottal downsample low-pass filter */
long BLPhz ; /* Bandwidth of glottal downsample low-pass filter */
flag glsource; /* Type of glottal source */
int f0_flutter; /* Percentage of f0 flutter 0-100 */
long nspfr; /* number of samples per frame */
long nper; /* Counter for number of samples in a pitch period */
long ns;
long T0; /* Fundamental period in output samples times 4 */
long nopen; /* Number of samples in open phase of period */
long nmod; /* Position in period to begin noise amp. modul */
long nrand; /* Varible used by random number generator */
double pulse_shape_a; /* Makes waveshape of glottal pulse when open */
double pulse_shape_b; /* Makes waveshape of glottal pulse when open */
double minus_pi_t;
double two_pi_t;
double onemd;
double decay;
double amp_bypas; /* AB converted to linear gain */
double amp_voice; /* AVdb converted to linear gain */
double par_amp_voice; /* AVpdb converted to linear gain */
double amp_aspir; /* AP converted to linear gain */
double amp_frica; /* AF converted to linear gain */
double amp_breth; /* ATURB converted to linear gain */
double amp_gain0; /* G0 converted to linear gain */
int num_samples; /* number of glottal samples */
double sample_factor; /* multiplication factor for glottal samples */
short *natural_samples; /* pointer to an array of glottal samples */
long original_f0; /* original value of f0 not modified by flutter */
int fadeout; // set to 64 to cause fadeout over 64 samples
int scale_wav; // depends on the voicing source
#define N_RSN 20
#define Rnpc 0
#define R1c 1
#define R2c 2
#define R3c 3
#define R4c 4
#define R5c 5
#define R6c 6
#define R7c 7
#define R8c 8
#define Rnz 9
#define Rparallel 10
#define Rnpp 10
#define R1p 11
#define R2p 12
#define R3p 13
#define R4p 14
#define R5p 15
#define R6p 16
#define RGL 17
#define RLP 18
#define Rout 19
resonator_t rsn[N_RSN]; // internal storage for resonators
resonator_t rsn_next[N_RSN];
} klatt_global_t, *klatt_global_ptr;
/* Structure for Klatt Parameters */
#define F_NP 0 // nasal zero formant
#define F1 1
#define F2 2
#define F3 3
#define F4 4
#define F5 5
#define F6 6
#define F_NZ 9 // nasal pole formant
typedef struct
{
long F0hz10; /* Voicing fund freq in Hz */
long AVdb; /* Amp of voicing in dB, 0 to 70 */
int Fhz[10]; // formant Hz, F_NZ to F6 to F_NP
int Bhz[10];
int Ap[10]; /* Amp of parallel formants in dB, 0 to 80 */
int Bphz[10]; /* Parallel formants bw in Hz, 40 to 1000 */
long ASP; /* Amp of aspiration in dB, 0 to 70 */
long Kopen; /* # of samples in open period, 10 to 65 */
long Aturb; /* Breathiness in voicing, 0 to 80 */
long TLTdb; /* Voicing spectral tilt in dB, 0 to 24 */
long AF; /* Amp of frication in dB, 0 to 80 */
long Kskew; /* Skewness of alternate periods, 0 to 40 in sample#/2 */
long AB; /* Amp of bypass fric. in dB, 0 to 80 */
long AVpdb; /* Amp of voicing, par in dB, 0 to 70 */
long Gain0; /* Overall gain, 60 dB is unity, 0 to 60 */
long AVdb_tmp; //copy of AVdb, which is changed within parwave()
int Fhz_next[10]; // Fhz for the next chunk, so we can do interpolation of resonator (a,b,c) parameters
int Bhz_next[10];
} klatt_frame_t, *klatt_frame_ptr;
+1 -1
View File
@@ -1186,7 +1186,7 @@ static int attr_prosody_value(int param_type, const wchar_t *pw, int *value_out)
pw++;
sign = -1;
}
value = wcstod(pw,&tail);
value = (float)wcstod(pw,&tail);
if(tail == pw)
{
// failed to find a number, return 100%
+2 -2
View File
@@ -300,10 +300,10 @@ static void init_path(const char *path)
}
buf[0] = 0;
RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Speech\\Voices\\Tokens\\eSpeak", 0, KEY_READ, &RegKey);
RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Speech\\Voices\\Tokens\\eSpeak", 0, KEY_READ, &RegKey);
size = sizeof(buf);
var_type = REG_SZ;
RegQueryValueEx(RegKey, "path", 0, &var_type, buf, &size);
RegQueryValueExA(RegKey, "path", 0, &var_type, buf, &size);
sprintf(path_home,"%s\\espeak-data",buf);
+113 -8
View File
@@ -137,7 +137,8 @@ int SpectFrame::Import(wxInputStream& stream1)
double x;
unsigned short *spect_data;
wxTextInputStream stream(stream1);
synthesizer_type = 0;
wxTextInputStream stream(stream1);
stream >> time;
stream >> pitch;
@@ -273,12 +274,13 @@ int SpectFrame::ImportSPC2(wxInputStream& stream, float &time_acc)
int SpectFrame::Load(wxInputStream& stream)
{//========================================
int SpectFrame::Load(wxInputStream& stream, int synth_type)
{//========================================================
int ix;
int x;
unsigned short *spect_data;
synthesizer_type = synth_type;
wxDataInputStream s(stream);
time = s.ReadDouble();
@@ -300,6 +302,14 @@ int SpectFrame::Load(wxInputStream& stream)
peaks[ix].pkright = s.Read16();
}
if(synthesizer_type == 1)
{
for(ix=0; ix<N_KLATTP; ix++)
{
klatt_param[ix] = s.Read16();
}
}
spect_data = new USHORT[nx];
if(spect_data == NULL)
@@ -324,7 +334,7 @@ int SpectFrame::Save(wxOutputStream& stream)
{//=========================================
int ix;
wxDataOutputStream s(stream);
wxDataOutputStream s(stream);
s.WriteDouble(time);
s.WriteDouble(pitch);
@@ -345,6 +355,14 @@ int SpectFrame::Save(wxOutputStream& stream)
s.Write16(peaks[ix].pkright);
}
if(synthesizer_type == 1)
{
for(ix=0; ix<N_KLATTP; ix++)
{
s.Write16(klatt_param[ix]);
}
}
for(ix=0; ix<nx; ix++)
{
s.Write16(spect[ix]);
@@ -367,6 +385,7 @@ void SpectFrame::ZeroPeaks()
void SpectFrame::CopyPeaks(SpectFrame *sf)
{//=======================================
memcpy(peaks,sf->peaks,sizeof(peaks));
memcpy(klatt_param, sf->klatt_param, sizeof(klatt_param));
keyframe = sf->keyframe;
}
@@ -448,6 +467,9 @@ void SpectFrame::DrawPeaks(wxDC *dc, int offy, int frame_width, int seq_amplitud
int y1, y2;
double yy;
int max_ix;
int height;
int pkright;
int pkwidth;
int buf[DRAWPEAKWIDTH*2];
max_ix = int(9000 * scale_x);
@@ -459,9 +481,24 @@ void SpectFrame::DrawPeaks(wxDC *dc, int offy, int frame_width, int seq_amplitud
if((pk->pkfreq == 0) || (pk->pkheight==0)) continue;
if(synthesizer_type==1)
{
if(peak==0) continue;
height = pk->pkheight + (64 * 64);
height = (500000/height) * 100;
pkright = pkwidth = pk->pkheight / 16;
}
else
{
height = pk->pkheight;
pkright = pk->pkright;
pkwidth = pk->pkwidth;
}
x1 = (int)(pk->pkfreq*scale_x);
x2 = (int)((pk->pkfreq + pk->pkright)*scale_x);
x3 = (int)((pk->pkfreq - pk->pkwidth)*scale_x);
x2 = (int)((pk->pkfreq + pkright)*scale_x);
x3 = (int)((pk->pkfreq - pkwidth)*scale_x);
if(x3 >= DRAWPEAKWIDTH)
continue; // whole peak is off the scale
@@ -469,7 +506,7 @@ void SpectFrame::DrawPeaks(wxDC *dc, int offy, int frame_width, int seq_amplitud
if((width = x2-x1) <= 0) continue;
for(ix=0; ix<width; ix++)
{
buf[x1+ix] += pk->pkheight * pk_shape1[(ix*PEAKSHAPEW)/width];
buf[x1+ix] += height * pk_shape1[(ix*PEAKSHAPEW)/width];
}
if((width = x1-x3) <= 0) continue;
@@ -477,7 +514,7 @@ void SpectFrame::DrawPeaks(wxDC *dc, int offy, int frame_width, int seq_amplitud
{
if(x3+ix >= 0)
{
buf[x3+ix] += pk->pkheight * pk_shape1[((width-ix)*PEAKSHAPEW)/width];
buf[x3+ix] += height * pk_shape1[((width-ix)*PEAKSHAPEW)/width];
}
}
}
@@ -633,3 +670,71 @@ void SpectFrame::Draw(wxDC& dc, int offy, int frame_width, double scalex, double
} // end of SpectFrame::Draw
void SpectFrame::KlattDefaults()
{//============================
// set default values for Klatt parameters
int pk;
int bw;
int bw3;
synthesizer_type = 1;
klatt_param[KLATT_AV] = 59;
klatt_param[KLATT_AVp] = 0;
klatt_param[KLATT_Fric] = 0;
klatt_param[KLATT_FricBP] = 0;
klatt_param[KLATT_Aspr] = 0;
klatt_param[KLATT_Turb] = 0;
klatt_param[KLATT_Skew] = 0;
klatt_param[KLATT_Tilt] = 0;
klatt_param[KLATT_Kopen] = 40;
klatt_param[KLATT_spare1] = 0;
bw = 60;
if(peaks[1].pkfreq < 400)
bw = 55;
if(peaks[1].pkfreq > 600)
bw = 70;
if(peaks[1].pkfreq > 650)
bw = 80;
if(peaks[1].pkfreq > 750)
bw = 90;
peaks[1].pkwidth = bw;
bw = 90;
bw3 = 150;
if(peaks[2].pkfreq < 1000)
{
bw = 80;
bw3 = 120;
}
if(peaks[2].pkfreq > 1600)
{
bw = 100;
bw3 = 200;
}
if(peaks[2].pkfreq > 2000)
{
bw = 110;
bw3 = 250;
}
peaks[2].pkwidth = bw;
peaks[3].pkwidth = bw3;
peaks[4].pkwidth = 200;
peaks[5].pkwidth = 200;
peaks[6].pkwidth = 500;
peaks[0].pkfreq = 280; // FNP
peaks[0].pkwidth = 280; // FNZ
peaks[7].pkfreq = 7800;
peaks[7].pkwidth = 0;
peaks[8].pkfreq = 9000;
peaks[8].pkwidth = 0;
for(pk=0; pk<=8; pk++)
{
peaks[pk].pkheight = peaks[pk].pkwidth << 6;
peaks[pk].pkright = 0;
}
}
+29 -6
View File
@@ -39,8 +39,20 @@
#define T_TIMEFRAME 310
#define T_TIMESEQ 311
#define T_AV 312
#define T_AVP 313
#define T_FRIC 314
#define T_FRICBP 315
#define T_ASPR 316
#define T_TURB 317
#define T_SKEW 318
#define T_TILT 319
#define T_KOPEN 320
#define FILEID1_SPECTSEQ 0x43455053
#define FILEID2_SPECTSEQ 0x51455354
#define FILEID2_SPECTSEQ 0x51455354 // for eSpeak sequence
#define FILEID2_SPECTSEK 0x4b455354 // for Klatt sequence
#define FILEID1_SPC2 0x32435053 // an old format for spectrum files
@@ -110,7 +122,7 @@ public:
~SpectFrame();
int Import(wxInputStream &stream);
int ImportSPC2(wxInputStream &stream, float &time_acc);
int Load(wxInputStream &stream);
int Load(wxInputStream &stream, int synthesizer_type);
int Save(wxOutputStream &stream);
void Draw(wxDC &dc, int offy, int frame_width, double scalex, double scaley);
@@ -122,6 +134,7 @@ public:
void MakeWave(int peaks, PitchEnvelope &pitch, int amplitude, int duration);
void MakeHtab(int numh, int *htab, int pitch);
double GetRms(int amp);
void KlattDefaults();
int selected;
int keyframe;
@@ -136,8 +149,11 @@ public:
int nx;
int markers;
int max_y;
int synthesizer_type; // 0=eSpeak, 1=Klatt
USHORT *spect; // sqrt of harmonic amplitudes, 1-nx at 'pitch'
short klatt_param[N_KLATTP];
formant_t formants[N_PEAKS]; // this is just the estimate given by Praat
peak_t peaks[N_PEAKS];
@@ -171,7 +187,8 @@ public:
float GetKeyedLength();
void SetFrameLengths();
void ConstructVowel(void);
void SetKlattDefaults(void);
int numframes;
int amplitude;
int spare;
@@ -186,6 +203,8 @@ public:
int bass_reduction;
int max_x;
int max_y;
int synthesizer_type;
private:
void Load2(wxInputStream& stream, int import, int n);
@@ -262,8 +281,9 @@ class FormantDlg : public wxPanel
public:
FormantDlg(wxWindow *parent);
void ShowFrame(SpectSeq *spectseq, int frame, int pk, int field);
void OnCommand(wxCommandEvent& event);
void OnSpin(wxSpinEvent& event);
void OnCommand(wxCommandEvent& event);
void OnSpin(wxSpinEvent& event);
void HideFields(int synth_type);
wxCheckBox *usepitchenv;
@@ -275,6 +295,9 @@ class FormantDlg : public wxPanel
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];
@@ -346,7 +369,7 @@ extern void WavegenInit(int samplerate, int wavemult_fact);
extern void WavegenInitPkData(int); // initialise envelope data
extern 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();
extern void MakeWaveFile(int synthesis_method);
extern void MakeWaveBuf(int length, UCHAR *buf);
extern int OpenWaveFile(const char *path, int samplerate);
+69 -25
View File
@@ -244,10 +244,19 @@ void SpectDisplay::ReadDialogValues()
void SpectDisplay::RefreshDialogValues(int type)
//{=============================================
{
int ix;
SpectFrame *sf;
sf = spectseq->frames[sframe];
spectseq->amplitude = formantdlg->t_amplitude->GetValue();
spectseq->frames[sframe]->amp_adjust = formantdlg->t_ampframe->GetValue();
spectseq->frames[sframe]->length_adjust =
formantdlg->t_timeframe->GetValue() - spectseq->GetFrameLength(sframe,0,NULL);
sf->amp_adjust = formantdlg->t_ampframe->GetValue();
sf->length_adjust = formantdlg->t_timeframe->GetValue() - spectseq->GetFrameLength(sframe,0,NULL);
for(ix=0; ix<9; ix++)
{
sf->klatt_param[ix] = formantdlg->s_klatt[ix]->GetValue();
}
if(type==0)
{
@@ -472,7 +481,7 @@ void SpectDisplay::OnMenu(wxCommandEvent& event)
int code;
wxKeyEvent keyevent;
SpectFrame *sf;
static int key[] = {0x1044,0x3044,0x104e,0x1047,0x105a,0x1051,0x3051,WXK_F1,WXK_F2,0x1049,WXK_F10};
static int key[] = {0x1044,0x3044,0x104e,0x1047,0x105a,0x1051,0x3051,WXK_F1,WXK_F2,0x1049,WXK_F10,0x104b};
id = event.GetId();
@@ -624,13 +633,19 @@ void SpectDisplay::OnKey(wxKeyEvent& event)
if(event.ControlDown())
{
// CTRL, rotate, make right slope steeper
pk->pkright-= 5;
if(spectseq->synthesizer_type==0)
pk->pkright-= 5;
pk->pkwidth += 5;
}
else
{
pk->pkright -= 10;
if(spectseq->synthesizer_type==0)
pk->pkright -= 10;
pk->pkwidth -= 10;
if(pk->pkright < 0)
pk->pkright = 0;
if(pk->pkwidth < 0)
pk->pkwidth = 0;
}
field = 4;
display = 1;
@@ -640,12 +655,14 @@ void SpectDisplay::OnKey(wxKeyEvent& event)
if(event.ControlDown())
{
// CTRL: rotate, make left slope steeper
pk->pkright += 5;
if(spectseq->synthesizer_type==0)
pk->pkright += 5;
pk->pkwidth -= 5;
}
else
{
pk->pkright += 10;
if(spectseq->synthesizer_type==0)
pk->pkright += 10;
pk->pkwidth += 10;
}
field = 4;
@@ -653,19 +670,37 @@ void SpectDisplay::OnKey(wxKeyEvent& event)
break;
case '<': // width--
pk->pkright -= 2;
if(spectseq->synthesizer_type==0)
pk->pkright -= 2;
pk->pkwidth -= 2;
if(pk->pkwidth < 0)
pk->pkwidth = 0;
display = 1;
field = 4;
break;
case '>': // width++
pk->pkright += 2;
if(spectseq->synthesizer_type==0)
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;
@@ -708,6 +743,11 @@ void SpectDisplay::OnKey(wxKeyEvent& event)
display = 2;
break;
case 0x104b: // CTRL-K
spectseq->SetKlattDefaults();
display = 3;
break;
case 0x104d: // CTRL-M
sf->ToggleMarker(1);
display = 2;
@@ -825,25 +865,28 @@ void SpectDisplay::OnKey(wxKeyEvent& event)
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;
if(spectseq->synthesizer_type==0)
{
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++)
// ensure minimum separation between peaks & prevent crossover
if(direction > 0)
{
if(sf->peaks[i].pkfreq < sf->peaks[i-1].pkfreq + 100)
sf->peaks[i].pkfreq = sf->peaks[i-1].pkfreq + 100;
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--)
else
if(direction < 0)
{
if(sf->peaks[i].pkfreq > sf->peaks[i+1].pkfreq - 100)
sf->peaks[i].pkfreq = sf->peaks[i+1].pkfreq - 100;
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;
}
}
}
@@ -1008,6 +1051,7 @@ void InitSpectrumDisplay()
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"));
+160 -46
View File
@@ -34,8 +34,12 @@
#define MAX_HARMONIC 400 // 400 * 50Hz = 20 kHz, more than enough
int SpeakNextClause(FILE *f_text, const void *text_in, int control);
extern void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2);
#define KLATT_TEST
extern void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v, int control);
extern int Wavegen_Klatt(int resume);
extern void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v);
extern int Wavegen();
extern void CloseWaveFile2();
extern FILE *f_wave;
@@ -100,18 +104,27 @@ static void PeaksZero(peak_t *sp, peak_t *zero)
void MakeWaveFile()
{//================
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)];
result = Wavegen();
#ifdef KLATT_TEST
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
@@ -135,6 +148,7 @@ SpectSeq::SpectSeq(int n)
max_x = 3000;
max_y = 1;
synthesizer_type = 0;
}
SpectSeq::~SpectSeq()
@@ -378,7 +392,7 @@ void SpectSeq::Load2(wxInputStream& stream, int import, int n)
}
else
{
if(frame->Load(stream) != 0) break;
if(frame->Load(stream, synthesizer_type) != 0) break;
}
frames[numframes++] = frame;
@@ -493,8 +507,19 @@ int SpectSeq::Load(wxInputStream & stream)
stream.SeekI(4);
return(ImportSPC2(stream));
}
if(id1 != FILEID1_SPECTSEQ || id2 != FILEID2_SPECTSEQ)
else
if((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSEQ))
{
synthesizer_type = 0; // eSpeak formants
}
else
if((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSEK))
{
synthesizer_type = 1; // formants for Klatt synthesizer
}
else
{
// Praat analysis data
stream.SeekI(0);
return(Import(stream));
}
@@ -530,7 +555,10 @@ int SpectSeq::Save(wxOutputStream &stream, int selection)
wxDataOutputStream s(stream);
s.Write32(FILEID1_SPECTSEQ);
s.Write32(FILEID2_SPECTSEQ);
if(synthesizer_type == 1)
s.Write32(FILEID2_SPECTSEK);
else
s.Write32(FILEID2_SPECTSEQ);
s.WriteString(name);
s.Write16(count);
@@ -549,6 +577,23 @@ int SpectSeq::Save(wxOutputStream &stream, int selection)
void SpectSeq::SetKlattDefaults(void)
{//==================================
int ix;
synthesizer_type = 1;
for(ix=0; ix<numframes; ix++)
{
if(frames[ix]->keyframe)
{
frames[ix]->KlattDefaults();
}
frames[ix]->synthesizer_type = 1;
}
}
void SpectSeq::ConstructVowel(void)
{//================================
@@ -785,6 +830,7 @@ void SpectSeq::CopyDown(int frame, int direction)
frames[frame]->peaks[pk].pkwidth = frames[f1]->peaks[pk].pkwidth;
frames[frame]->peaks[pk].pkright = frames[f1]->peaks[pk].pkright;
}
memcpy(frames[frame]->klatt_param, frames[f1]->klatt_param, sizeof(frames[frame]->klatt_param));
break;
}
}
@@ -878,46 +924,88 @@ void SpectSeq::ApplyAmp_adjust(SpectFrame *sp, peak_t *peaks)
int y;
memcpy(peaks,sp->peaks,sizeof(*peaks)*N_PEAKS);
for(ix=0; ix<N_PEAKS; ix++)
if(synthesizer_type == 0)
{
y = peaks[ix].pkheight * sp->amp_adjust * amplitude;
peaks[ix].pkheight = y / 10000;
for(ix=0; ix<N_PEAKS; ix++)
{
y = peaks[ix].pkheight * sp->amp_adjust * amplitude;
peaks[ix].pkheight = y / 10000;
}
}
} // end of ApplyAmp_adjust
void PeaksToFrame(peak_t *pks, frame_t *fr)
{//========================================
void PeaksToFrame(SpectFrame *sp1, peak_t *pks, frame_t *fr)
{//=========================================================
int ix;
int x;
int x, x2;
for(ix=0; ix<N_PEAKS; ix++)
{
fr->ffreq[ix] = pks[ix].pkfreq;
fr->fheight[ix] = pks[ix].pkheight >> 6;
if(sp1->synthesizer_type==0)
{
x = pks[ix].pkheight >> 6;
}
else
{
x = pks[ix].pkheight >> 7;
fr->fwidth6 = pks[6].pkwidth >> 1;
fr->fright6 = pks[6].pkright;
}
if(x > 255)
x = 255;
fr->fheight[ix] = x;
if(ix < 6)
{
if((x = (pks[ix].pkwidth >> 2)) > 255)
x = pks[ix].pkwidth/2;
x2 = pks[ix].pkright;
if(sp1->synthesizer_type == 0)
{
x /= 2;
x2 /= 4;
}
if(x > 255)
x = 255;
fr->fwidth[ix] = x;
if((x = (pks[ix].pkright >> 2)) > 255)
x = 255;
fr->fright[ix] = x;
if(x2 > 255)
x2 = 255;
fr->fright[ix] = x2;
}
}
for(ix=0; ix<N_KLATTP; ix++)
{
fr->klattp[ix] = sp1->klatt_param[ix];
}
}
static void SetSynth_mS(int length_mS, peak_t *sp1, peak_t *sp2)
{//=============================================================
static void SetSynth_mS(int length_mS, SpectFrame *sp1, SpectFrame *sp2, peak_t *pks1, peak_t *pks2, int control)
{//==============================================================================================================
static frame_t fr1, fr2;
PeaksToFrame(sp1,&fr1);
PeaksToFrame(sp2,&fr2);
PeaksToFrame(sp1,pks1,&fr1);
PeaksToFrame(sp2,pks2,&fr2);
#ifdef KLATT_TEST
if(sp1->synthesizer_type == 1)
{
SetSynth_Klatt((length_mS * samplerate) / 1000, 0, &fr1, &fr2, voice, control); // convert mS to samples
}
else
#endif
{
SetSynth((length_mS * samplerate) / 1000, 0, &fr1, &fr2, voice); // convert mS to samples
}
};
SetSynth((length_mS * samplerate) / 1000, 0, &fr1, &fr2); // convert mS to samples
}
@@ -939,6 +1027,7 @@ void SpectSeq::MakeWave(int start, int end, PitchEnvelope &pitch)
peak_t peaks1[N_PEAKS];
peak_t peaks2[N_PEAKS];
KlattInit();
SpeakNextClause(NULL,NULL,2); // stop speaking file
if(numframes==0) return;
@@ -1007,23 +1096,39 @@ void SpectSeq::MakeWave(int start, int end, PitchEnvelope &pitch)
{
ApplyAmp_adjust(sp1,peaks1);
ApplyAmp_adjust(sp2,peaks2);
if(first)
{
PeaksZero(peaks1,peaks0); // fade in
SetSynth_mS(20,peaks0,peaks1);
MakeWaveFile();
if(synthesizer_type == 1)
{
memcpy(peaks0,peaks1,sizeof(peaks0));
}
else
{
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,peaks1,peaks2);
MakeWaveFile();
SetSynth_mS(length,sp1,sp2,peaks1,peaks2,0);
MakeWaveFile(synthesizer_type);
}
}
}
PeaksZero(peaks2,peaks0); // fade out
SetSynth_mS(30,peaks2,peaks0);
MakeWaveFile();
if(synthesizer_type == 1)
{
memcpy(peaks0,peaks2,sizeof(peaks0));
}
else
{
PeaksZero(peaks2,peaks0); // fade out
}
SetSynth_mS(30,sp2,sp2,peaks2,peaks0,2);
MakeWaveFile(synthesizer_type);
CloseWaveFile2();
PlayWavFile(fname_speech);
@@ -1054,6 +1159,7 @@ void SpectFrame::MakeWave(int control, PitchEnvelope &pitche, int amplitude, int
char *fname_speech;
// USHORT htab0[600];
KlattInit();
SpeakNextClause(NULL,NULL,2); // stop speaking file
length = duration;
@@ -1069,23 +1175,31 @@ void SpectFrame::MakeWave(int control, PitchEnvelope &pitche, int amplitude, int
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,peaks0,peaks1);
MakeWaveFile();
SetSynth_mS(length,peaks1,peaks1);
MakeWaveFile();
SetSynth_mS(30,peaks1,peaks0);
MakeWaveFile();
if(synthesizer_type == 0)
{
for(ix=0; ix<N_PEAKS; ix++)
{
y = peaks1[ix].pkheight * amp_adjust * amplitude;
peaks1[ix].pkheight = y/10000;
}
PeaksZero(peaks1,peaks0);
}
else
{
memcpy(peaks0,peaks1,sizeof(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
{
+1
View File
@@ -21,6 +21,7 @@
#include <sys/types.h>
// conditional compilation options
#define INCLUDE_KLATT
#if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN
#define ARCH_BIG
+2 -2
View File
@@ -77,7 +77,7 @@ BOOL load_MBR()
if(hinstDllMBR != NULL)
return TRUE; // already loaded
if (!(hinstDllMBR=LoadLibrary("mbrola.dll")))
if (!(hinstDllMBR=LoadLibraryA("mbrola.dll")))
return FALSE;
init_MBR =(PROCIC) GetProcAddress(hinstDllMBR,"init_MBR");
write_MBR =(PROCIC) GetProcAddress(hinstDllMBR,"write_MBR");
@@ -179,7 +179,7 @@ espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int
#ifdef USE_MBROLA_LIB
#ifdef PLATFORM_WINDOWS
setVolumeRatio_MBR((float)(mbrola_control & 0xff) /16.0);
setVolumeRatio_MBR((float)(mbrola_control & 0xff) /16.0f);
#else
mbrolib_get_parameter(mb_handle,&m_parameters);
m_parameters.ignore_error = 1;
+26 -10
View File
@@ -35,7 +35,7 @@
#include "translate.h"
#include "wave.h"
const char *version_string = "1.39.26 15.Nov.08";
const char *version_string = "1.39.28 22.Nov.08";
const int version_phdata = 0x013900;
int option_device_number = -1;
@@ -375,9 +375,10 @@ frameref_t *LookupSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB
int length1;
int length_std;
int length_factor;
SPECT_SEQ *seq;
SPECT_SEQ *seq2;
SPECT_SEQ *seq, *seq2;
SPECT_SEQK *seqk, *seqk2;
PHONEME_TAB *next2_ph;
frame_t *frame;
static frameref_t frames_buf[N_SEQ_FRAMES];
PHONEME_TAB *other_ph;
@@ -389,6 +390,7 @@ frameref_t *LookupSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB
if((ix = LookupSound(this_ph,other_ph,which,match_level,0)) < 4)
return(NULL);
seq = (SPECT_SEQ *)(&spects_data[ix]);
seqk = (SPECT_SEQK *)seq;
nf = seq->n_frames;
@@ -397,15 +399,20 @@ frameref_t *LookupSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB
seq_break = 0;
length1 = 0;
for(ix=0; ix<nf; ix++)
{
frames_buf[ix].frame = &seq->frame[ix];
frames_buf[ix].frflags = seq->frame[ix].frflags;
frames_buf[ix].length = seq->frame[ix].length;
if(seq->frame[ix].frflags & FRFLAG_VOWEL_CENTRE)
if(seq->frame[0].frflags & FRFLAG_KLATT)
frame = &seqk->frame[ix];
else
frame = (frame_t *)&seq->frame[ix];
frames_buf[ix].frame = frame;
frames_buf[ix].frflags = frame->frflags;
frames_buf[ix].length = frame->length;
if(frame->frflags & FRFLAG_VOWEL_CENTRE)
seq_break = ix;
}
frames = &frames_buf[0];
if(seq_break > 0)
{
@@ -462,14 +469,23 @@ frameref_t *LookupSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB
// a secondary reference has been returned, which is not a wavefile
// add these spectra to the main sequence
seq2 = (SPECT_SEQ *)(&spects_data[wavefile_ix]);
seqk2 = (SPECT_SEQK *)seq2;
// first frame of the addition just sets the length of the last frame of the main seq
nf--;
for(ix=0; ix<seq2->n_frames; ix++)
{
frames[nf].length = seq2->frame[ix].length;
if(seq2->frame[0].frflags & FRFLAG_KLATT)
frame = &seqk2->frame[ix];
else
frame = (frame_t *)&seq2->frame[ix];
frames[nf].length = frame->length;
if(ix > 0)
frames[nf].frame = &seq2->frame[ix];
{
frames[nf].frame = frame;
frames[nf].frflags = frame->frflags;
}
nf++;
}
wavefile_ix = 0;
+31 -5
View File
@@ -354,6 +354,15 @@ static void set_frame_rms(frame_t *fr, int new_rms)
849,851,853,856,858,861,863,865,868,870,872,875,877,879,882,884,
886,889,891,893,896,898,900,902};
if(fr->frflags & FRFLAG_KLATT)
{
if(new_rms == -1)
{
fr->klattp[KLATT_AV] = 50;
}
return;
}
if(fr->rms == 0) return; // check for divide by zero
x = (new_rms * 64)/fr->rms;
if(x >= 200) x = 199;
@@ -375,6 +384,9 @@ static void formants_reduce_hf(frame_t *fr, int level)
int ix;
int x;
if(fr->frflags & FRFLAG_KLATT)
return;
for(ix=2; ix<N_PEAKS; ix++)
{
x = fr->fheight[ix] * level;
@@ -540,6 +552,10 @@ static short vcolouring[N_VCOLOUR][5] = {
next_rms = seq[1].frame->rms;
if(fr->frflags & FRFLAG_KLATT)
{
fr->klattp[KLATT_AV] = 53; // reduce the amplituide of the start of a vowel
}
if(f2 != 0)
{
if(rms & 0x20)
@@ -661,6 +677,9 @@ static void SmoothSpect(void)
q = wcmdq[syllable_centre];
frame_centre = (frame_t *)q[2];
//if(frame_centre->frflags & FRFLAG_KLATT)
// return; // TESTING
// backwards
ix = syllable_centre -1;
frame = frame2 = frame_centre;
@@ -672,7 +691,7 @@ static void SmoothSpect(void)
if(q[0] == WCMD_PAUSE || q[0] == WCMD_WAVE)
break;
if(q[0] == WCMD_SPECT || q[0] == WCMD_SPECT2)
if(q[0] <= WCMD_SPECT2)
{
len = q[1] & 0xffff;
@@ -759,7 +778,7 @@ static void SmoothSpect(void)
if(q[0] == WCMD_PAUSE || q[0] == WCMD_WAVE)
break;
if(q[0] == WCMD_SPECT || q[0] == WCMD_SPECT2)
if(q[0] <= WCMD_SPECT2)
{
len = q[1] & 0xffff;
@@ -834,7 +853,7 @@ static void SmoothSpect(void)
}
syllable_start = syllable_end;
}
} // end of SmoothSpect
static void StartSyllable(void)
@@ -891,22 +910,29 @@ if(which==1)
if(frames == NULL)
return(0); // not found
frame1 = frames[0].frame;
frame1_length = frames[0].length;
if(frame1->frflags & FRFLAG_KLATT)
wcmd_spect = WCMD_KLATT;
if(wavefile_ix == 0)
{
if(wave_flag)
{
// cancel any wavefile that was playing previously
wcmd_spect = WCMD_SPECT2;
if(frame1->frflags & FRFLAG_KLATT)
wcmd_spect = WCMD_KLATT2;
wave_flag = 0;
}
else
{
wcmd_spect = WCMD_SPECT;
if(frame1->frflags & FRFLAG_KLATT)
wcmd_spect = WCMD_KLATT;
}
}
frame1 = frames[0].frame;
frame1_length = frames[0].length;
if(last_frame != NULL)
{
if(((last_frame->length < 2) || (last_frame->frflags & FRFLAG_VOWEL_CENTRE))
+66 -7
View File
@@ -22,11 +22,13 @@
#define MAX_HARMONIC 400 // 400 * 50Hz = 20 kHz, more than enough
#define N_SEQ_FRAMES 25 // max frames in a spectrum sequence (real max is ablut 8)
#define STEPSIZE 64 // 2.9mS at 22 kHz sample rate
#define PITCHfall 0
#define PITCHrise 1
// flags set for frames within a spectrum sequence
#define FRFLAG_KLATT 0x01 // this frame includes extra data for Klatt synthesizer
#define FRFLAG_VOWEL_CENTRE 0x02 // centre point of vowel
#define FRFLAG_LEN_MOD 0x04 // reduce effect of length adjustment
#define FRFLAG_BREAK_LF 0x08 // but keep f3 upwards
@@ -75,6 +77,18 @@ typedef struct {
short pkright;
} peak_t;
#define N_KLATTP 10 // this affects the phoneme data file format
#define KLATT_AV 0
#define KLATT_Kopen 1
#define KLATT_Skew 2
#define KLATT_Tilt 3
#define KLATT_Turb 4
#define KLATT_Aspr 5
#define KLATT_AVp 6 // this is after the parameters which can be change by the Voice
#define KLATT_Fric 7
#define KLATT_FricBP 8
#define KLATT_spare1 9
typedef struct {
short frflags;
unsigned char length;
@@ -83,8 +97,20 @@ typedef struct {
unsigned char fheight[9];
unsigned char fwidth[6]; // width/4
unsigned char fright[6]; // width/4
unsigned char fwidth6, fright6;
unsigned char klattp[N_KLATTP];
} frame_t;
typedef struct {
short frflags;
unsigned char length;
unsigned char rms;
short ffreq[9];
unsigned char fheight[9];
unsigned char fwidth[6]; // width/4
unsigned char fright[6]; // width/4
} frame_t2; // the original, without Klatt additions, used for file "phondata"
// formant data used by wavegen
@@ -103,6 +129,26 @@ typedef struct {
DOUBLEX right_inc;
} wavegen_peaks_t;
typedef struct {
unsigned char *pitch_env;
int pitch; // pitch Hz*256
int pitch_ix; // index into pitch envelope (*256)
int pitch_inc; // increment to pitch_ix
int pitch_base; // Hz*256 low, before modified by envelope
int pitch_range; // Hz*256 range of envelope
unsigned char *mix_wavefile; // wave file to be added to synthesis
int n_mix_wavefile; // length in bytes
int mix_wave_scale; // 0=2 byte samples
int mix_wave_amp;
int mix_wavefile_ix;
int amplitude;
int amplitude_v;
int prev_was_synth; // previous sound was synthesized (not a played wave or pause)
} WGEN_DATA;
typedef struct {
double a;
double b;
@@ -113,11 +159,19 @@ typedef struct {
typedef struct {
short length;
short length_total; // not used
unsigned char n_frames;
unsigned char flags;
frame_t2 frame[N_SEQ_FRAMES]; // max. frames in a spectrum sequence
} SPECT_SEQ; // sequence of espeak formant frames
typedef struct {
short length_total; // not used
unsigned char n_frames;
unsigned char flags;
frame_t frame[N_SEQ_FRAMES]; // max. frames in a spectrum sequence
} SPECT_SEQ;
} SPECT_SEQK; // sequence of klatt formants frames
typedef struct {
short length;
@@ -176,16 +230,18 @@ extern unsigned char env_frise[128];
extern unsigned char pitch_adjust_tab[MAX_PITCH_VALUE+1];
// queue of commands for wavegen
#define WCMD_AMPLITUDE 1
#define WCMD_PITCH 2
#define WCMD_KLATT 1
#define WCMD_KLATT2 2
#define WCMD_SPECT 3
#define WCMD_SPECT2 4
#define WCMD_PAUSE 5
#define WCMD_WAVE 6
#define WCMD_WAVE2 7
#define WCMD_MARKER 8
#define WCMD_VOICE 9
#define WCMD_EMBEDDED 10
#define WCMD_AMPLITUDE 8
#define WCMD_PITCH 9
#define WCMD_MARKER 10
#define WCMD_VOICE 11
#define WCMD_EMBEDDED 12
#define N_WCMDQ 160
@@ -278,3 +334,6 @@ int PauseLength(int pause, int control);
int LookupPhonemeTable(const char *name);
void InitBreath(void);
void KlattInit();
int Wavegen_Klatt2(int length, int modulation, int resume, frame_t *fr1, frame_t *fr2);
+3 -1
View File
@@ -515,6 +515,7 @@ SetLengthMods(tr,3); // all equal
tr->langopts.param[LOPT_SONORANT_MIN] = 130; // limit the shortening of sonorants before short vowels
tr->langopts.param[LOPT_REDUCE] = 1; // reduce vowels even if phonemes are specified in it_list
tr->langopts.numbers = 0x2709 + NUM_ROMAN;
tr->langopts.accents = 2; // Say "Capital" after the letter.
}
break;
@@ -769,8 +770,9 @@ SetLengthMods(tr,3); // all equal
static const unsigned char stress_amps_sq[8] = {17,12, 17,17, 20,20, 24,22 };
tr = new Translator();
SetupTranslator(tr,stress_lengths_sq,stress_amps_sq);
tr->langopts.stress_flags = 0x4;
tr->langopts.stress_flags = 0x4 + 0x10;
SetLetterVowel(tr,'y');
tr->langopts.numbers = 0x69 + 0x8000;
}
break;
+5 -1
View File
@@ -1747,7 +1747,11 @@ int Translator::TranslateWord2(char *word, WORD_TAB *wtab, int pre_pause, int ne
first_phoneme = 0;
}
}
plist2->sourceix = source_ix; // ????
// don't set new-word if there is a hyphen before it
if((word_flags & FLAG_HYPHEN) == 0)
{
plist2->sourceix = source_ix;
}
end_stressed_vowel = 0;
if((stress >= 4) && (phoneme_tab[ph_list2[n_ph_list2-1].phcode]->type == phVOWEL))
+1 -1
View File
@@ -29,7 +29,7 @@
#define N_RULE_GROUP2 120 // max num of two-letter rule chains
#define N_HASH_DICT 1024
#define N_CHARSETS 20
#define N_LETTER_GROUPS 25
#define N_LETTER_GROUPS 26
/* dictionary flags, word 1 */
+3 -2
View File
@@ -249,6 +249,7 @@ void MakeWave2(PHONEME_LIST *p, int n_phonemes)
char *fname_speech;
int n_ph;
KlattInit();
n_ph = n_phonemes;
fname_speech = WavFileName();
OpenWaveFile2(fname_speech);
@@ -275,9 +276,9 @@ TranslDlg::TranslDlg(wxWindow *parent) : wxPanel(parent)
{//=====================================================
t_source = new wxTextCtrl(this,T_SOURCE,_T(""),wxPoint(0,4),
wxSize(200,250),wxTE_MULTILINE);
wxSize(204,250),wxTE_MULTILINE);
t_phonetic = new wxTextCtrl(this,T_PHONETIC,_T(""),wxPoint(0,262),
wxSize(200,350),wxTE_MULTILINE);
wxSize(204,350),wxTE_MULTILINE);
t_translate = new wxButton(this,T_TRANSLATE,_T("Translate"),wxPoint(4,620));
t_translate = new wxButton(this,T_RULES,_T("Show Rules"),wxPoint(4,652));
+2 -1
View File
@@ -40,6 +40,7 @@ typedef struct {
int formant_factor; // adjust nominal formant frequencies by this because of the voice's pitch (256ths)
int consonant_amp; // amplitude of unvoiced consonants
int consonant_ampv; // amplitude of the noise component of voiced consonants
int klatt[8];
// parameters used by Wavegen
short freq[N_PEAKS]; // 100% = 256
@@ -68,7 +69,7 @@ extern USHORT voice_pcnt[N_PEAKS+1][3];
extern voice_t *voice;
extern int tone_points[10];
extern int tone_points[12];
const char *SelectVoice(espeak_VOICE *voice_select);
espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name);
+24 -15
View File
@@ -49,8 +49,8 @@ MNEM_TAB genders [] = {
{"female", 2},
{NULL, 0 }};
//int tone_points[10] = {250,140, 1200,110, -1,0, -1,0, -1,0};
int tone_points[10] = {600,170, 1200,135, 2000,110, 3000,110, -1,0};
int tone_points[12] = {600,170, 1200,135, 2000,110, 3000,110, -1,0};
//int tone_points[12] = {250,200, 400,170, 600,170, 1200,135, 2000,110, -1,0};
// limit the rate of change for each formant number
//static int formant_rate_22050[9] = {50, 104, 165, 230, 220, 220, 220, 220, 220}; // values for 22kHz sample rate
@@ -101,11 +101,13 @@ espeak_VOICE voice_selected;
#define V_NUMBERS 25
#define V_OPTION 26
#define V_MBROLA 27
#define V_MBROLA 27
#define V_KLATT 28
// these need a phoneme table to have been specified
#define V_REPLACE 28
#define V_CONSONANTS 29
#define V_REPLACE 29
#define V_CONSONANTS 30
typedef struct {
@@ -144,6 +146,7 @@ static keywtab_t keyword_tab[] = {
{"option", V_OPTION},
{"mbrola", V_MBROLA},
{"consonants", V_CONSONANTS},
{"klatt", V_KLATT},
// these just set a value in langopts.param[]
{"l_dieresis", 0x100+LOPT_DIERESES},
@@ -195,7 +198,7 @@ void SetToneAdjust(voice_t *voice, int *tone_pts)
int height2;
double rate;
for(pt=0; pt<10; pt+=2)
for(pt=0; pt<12; pt+=2)
{
if(tone_pts[pt] == -1)
{
@@ -225,15 +228,16 @@ void SetToneAdjust(voice_t *voice, int *tone_pts)
void ReadTonePoints(char *string, int *tone_pts)
{//=============================================
// tone_pts[] is int[10]
// tone_pts[] is int[12]
int ix;
for(ix=0; ix<10; ix++)
for(ix=0; ix<12; ix++)
tone_pts[ix] = -1;
sscanf(string,"%d %d %d %d %d %d %d %d",
sscanf(string,"%d %d %d %d %d %d %d %d %d %d",
&tone_pts[0],&tone_pts[1],&tone_pts[2],&tone_pts[3],
&tone_pts[4],&tone_pts[5],&tone_pts[6],&tone_pts[7]);
&tone_pts[4],&tone_pts[5],&tone_pts[6],&tone_pts[7],
&tone_pts[8],&tone_pts[9]);
}
@@ -369,10 +373,11 @@ void VoiceReset(int tone_only)
voice->echo_amp = 0;
voice->flutter = 64;
voice->n_harmonic_peaks = 5;
voice->peak_shape = 1;
voice->peak_shape = 0;
voice->voicing = 64;
voice->consonant_amp = 100;
voice->consonant_ampv = 100;
memset(voice->klatt,0,sizeof(voice->klatt));
#ifdef PLATFORM_RISCOS
voice->roughness = 1;
@@ -864,6 +869,11 @@ voice_t *LoadVoice(const char *vname, int control)
}
break;
case V_KLATT:
Read8Numbers(p,voice->klatt);
voice->klatt[KLATT_Kopen] -= 40;
break;
default:
if((key & 0xff00) == 0x100)
{
@@ -1493,13 +1503,12 @@ void GetVoices(const char *path)
}
#else
#ifdef PLATFORM_WINDOWS
WIN32_FIND_DATA FindFileData;
WIN32_FIND_DATAA FindFileData;
HANDLE hFind = INVALID_HANDLE_VALUE;
DWORD dwError;
#undef UNICODE // we need FindFirstFileA() which takes an 8-bit c-string
sprintf(fname,"%s\\*",path);
hFind = FindFirstFile(fname, &FindFileData);
hFind = FindFirstFileA(fname, &FindFileData);
if(hFind == INVALID_HANDLE_VALUE)
return;
@@ -1529,7 +1538,7 @@ void GetVoices(const char *path)
voices_list[n_voices_list++] = voice_data;
}
}
} while(FindNextFile(hFind, &FindFileData) != 0);
} while(FindNextFileA(hFind, &FindFileData) != 0);
FindClose(hFind);
#else
+13 -2
View File
@@ -510,6 +510,7 @@ void MakeVowelLists(void)
PHONEME_TAB *ph;
FILE *f;
SPECT_SEQ *seq;
SPECT_SEQK *seqk;
frame_t *frame;
int match_level;
char dirname[sizeof(path_source)+20];
@@ -547,10 +548,20 @@ void MakeVowelLists(void)
continue;
seq = (SPECT_SEQ *)(&spects_data[ix]);
frame = &seq->frame[1];
seqk = (SPECT_SEQK *)seq;
if(seq->frame[0].frflags & FRFLAG_KLATT)
frame = &seqk->frame[1];
else
frame = (frame_t *)&seq->frame[1];
fprintf(f,"%s\t %3d %4d %4d",WordToString(ph->mnemonic),
frame->ffreq[1],frame->ffreq[2],frame->ffreq[3]);
frame = &seq->frame[seq->n_frames-1];
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);
+81 -68
View File
@@ -34,6 +34,8 @@
#include "synthesize.h"
#include "voice.h"
//#undef INCLUDE_KLATT
#ifdef USE_PORTAUDIO
#include "portaudio.h"
#undef USE_PORTAUDIO
@@ -51,10 +53,9 @@
#define PI 3.1415927
#define PI2 6.283185307
#define STEPSIZE 64 // 2.9mS at 22 kHz sample rate
#define N_WAV_BUF 10
static voice_t *wvoice;
voice_t *wvoice;
FILE *f_log = NULL;
int option_waveout = 0;
@@ -98,24 +99,13 @@ static int hspect[2][MAX_HARMONIC]; // 2 copies, we interpolate between
static int max_hval=0;
static int nsamples=0; // number to do
static int amplitude = 32;
static int amplitude_v = 0;
static int modulation_type = 0;
static int glottal_flag = 0;
static int glottal_reduce = 0;
static unsigned char *mix_wavefile = NULL; // wave file to be added to synthesis
static int n_mix_wavefile = 0; // length in bytes
static int mix_wave_scale = 0; // 0=2 byte samples
static int mix_wave_amp = 32;
static int mix_wavefile_ix = 0;
static int pitch; // pitch Hz*256
static int pitch_ix; // index into pitch envelope (*256)
static int pitch_inc; // increment to pitch_ix
static unsigned char *pitch_env=NULL;
static int pitch_base; // Hz*256 low, before modified by envelope
static int pitch_range; // Hz*256 range of envelope
WGEN_DATA wdata;
static int amp_ix;
static int amp_inc;
static unsigned char *amplitude_env = NULL;
@@ -385,8 +375,8 @@ static void WcmdqIncHead()
// data points from which to make the presets for pk_shape1 and pk_shape2
#define PEAKSHAPEW 256
static const float pk_shape_x[2][8] = {
{0,-0.6, 0.0, 0.6, 1.4, 2.5, 4.5, 5.5},
{0,-0.6, 0.0, 0.6, 1.4, 2.0, 4.5, 5.5 }};
{0,-0.6f, 0.0f, 0.6f, 1.4f, 2.5f, 4.5f, 5.5f},
{0,-0.6f, 0.0f, 0.6f, 1.4f, 2.0f, 4.5f, 5.5f }};
static const float pk_shape_y[2][8] = {
{0, 67, 81, 67, 31, 14, 0, -6} ,
{0, 77, 81, 77, 31, 7, 0, -6 }};
@@ -737,6 +727,7 @@ void WavegenInit(int rate, int wavemult_fact)
if(wavemult_fact == 0)
wavemult_fact=60; // default
wvoice = NULL;
samplerate = samplerate_native = rate;
PHASE_INC_FACTOR = 0x8000000 / samplerate; // assumes pitch is Hz*32
Flutter_inc = (64 * samplerate)/rate;
@@ -745,6 +736,9 @@ void WavegenInit(int rate, int wavemult_fact)
wavephase = 0x7fffffff;
max_hval = 0;
wdata.amplitude = 32;
wdata.prev_was_synth = 0;
for(ix=0; ix<N_EMBEDDED_VALUES; ix++)
embedded_value[ix] = embedded_default[ix];
@@ -769,7 +763,11 @@ void WavegenInit(int rate, int wavemult_fact)
WavegenInitPkData(1);
WavegenInitPkData(0);
pk_shape = pk_shape2; // ph_shape2
pk_shape = pk_shape2; // pk_shape2
#ifdef INCLUDE_KLATT
KlattInit();
#endif
#ifdef LOG_FRAMES
remove("log-espeakedit");
@@ -784,7 +782,7 @@ int GetAmplitude(void)
// normal, none, reduced, moderate, strong
static const unsigned char amp_emphasis[5] = {16, 16, 10, 16, 22};
amp = (embedded_value[EMBED_A])*60/100;
amp = (embedded_value[EMBED_A])*55/100;
general_amplitude = amp * amp_emphasis[embedded_value[EMBED_F]] / 16;
return(general_amplitude);
}
@@ -903,6 +901,13 @@ int PeaksToHarmspect(wavegen_peaks_t *peaks, int pitch, int *htab, int control)
}
}
// increase bass, up to the F1 peak
h=1;
for(f=pitch; f<peaks[1].freq; f+=pitch)
{
htab[h++] += (peaks[1].height * 16);
}
// find the nearest harmonic for HF peaks where we don't use shape
for(; pk<N_PEAKS; pk++)
{
@@ -961,10 +966,10 @@ static void AdvanceParameters()
static int Flutter_ix = 0;
// advance the pitch
pitch_ix += pitch_inc;
if((ix = pitch_ix>>8) > 127) ix = 127;
x = pitch_env[ix] * pitch_range;
pitch = (x>>8) + pitch_base;
wdata.pitch_ix += wdata.pitch_inc;
if((ix = wdata.pitch_ix>>8) > 127) ix = 127;
x = wdata.pitch_env[ix] * wdata.pitch_range;
wdata.pitch = (x>>8) + wdata.pitch_base;
amp_ix += amp_inc;
@@ -973,9 +978,9 @@ static void AdvanceParameters()
Flutter_ix = 0;
x = ((int)(Flutter_tab[Flutter_ix >> 6])-0x80) * flutter_amp;
Flutter_ix += Flutter_inc;
pitch += x;
if(pitch < 102400)
pitch = 102400; // min pitch, 25 Hz (25 << 12)
wdata.pitch += x;
if(wdata.pitch < 102400)
wdata.pitch = 102400; // min pitch, 25 Hz (25 << 12)
if(samplecount == samplecount_start)
return;
@@ -1159,26 +1164,26 @@ int Wavegen()
{
hswitch = 0;
harmspect = hspect[0];
maxh2 = PeaksToHarmspect(peaks,pitch<<4,hspect[0],0);
maxh2 = PeaksToHarmspect(peaks, wdata.pitch<<4, hspect[0], 0);
// adjust amplitude to compensate for fewer harmonics at higher pitch
amplitude2 = (amplitude * pitch)/(100 << 11);
amplitude2 = (wdata.amplitude * wdata.pitch)/(100 << 11);
// switch sign of harmonics above about 900Hz, to reduce max peak amplitude
h_switch_sign = 890 / (pitch >> 12);
h_switch_sign = 890 / (wdata.pitch >> 12);
}
else
AdvanceParameters();
// pitch is Hz<<12
phaseinc = (pitch>>7) * PHASE_INC_FACTOR;
cycle_samples = samplerate/(pitch >> 12); // sr/(pitch*2)
hf_factor = pitch >> 11;
phaseinc = (wdata.pitch>>7) * PHASE_INC_FACTOR;
cycle_samples = samplerate/(wdata.pitch >> 12); // sr/(pitch*2)
hf_factor = wdata.pitch >> 11;
maxh = maxh2;
harmspect = hspect[hswitch];
hswitch ^= 1;
maxh2 = PeaksToHarmspect(peaks,pitch<<4,hspect[hswitch],1);
maxh2 = PeaksToHarmspect(peaks, wdata.pitch<<4, hspect[hswitch], 1);
SetBreath();
}
@@ -1211,11 +1216,11 @@ int Wavegen()
for(pk=wvoice->n_harmonic_peaks+1; pk<N_PEAKS; pk++)
{
// find the nearest harmonic for HF peaks where we don't use shape
peak_harmonic[pk] = peaks[pk].freq / (pitch*16);
peak_harmonic[pk] = peaks[pk].freq / (wdata.pitch*16);
}
// adjust amplitude to compensate for fewer harmonics at higher pitch
amplitude2 = (amplitude * pitch)/(100 << 11);
amplitude2 = (wdata.amplitude * wdata.pitch)/(100 << 11);
if(glottal_flag > 0)
{
@@ -1337,22 +1342,22 @@ int Wavegen()
// mix with sampled wave if required
z2 = 0;
if(mix_wavefile_ix < n_mix_wavefile)
if(wdata.mix_wavefile_ix < wdata.n_mix_wavefile)
{
if(mix_wave_scale == 0)
if(wdata.mix_wave_scale == 0)
{
// a 16 bit sample
c = mix_wavefile[mix_wavefile_ix+1];
sample = mix_wavefile[mix_wavefile_ix] + (c * 256);
mix_wavefile_ix += 2;
c = wdata.mix_wavefile[wdata.mix_wavefile_ix+1];
sample = wdata.mix_wavefile[wdata.mix_wavefile_ix] + (c * 256);
wdata.mix_wavefile_ix += 2;
}
else
{
// a 8 bit sample, scaled
sample = (signed char)mix_wavefile[mix_wavefile_ix++] * mix_wave_scale;
sample = (signed char)wdata.mix_wavefile[wdata.mix_wavefile_ix++] * wdata.mix_wave_scale;
}
z2 = (sample * amplitude_v) >> 10;
z2 = (z2 * mix_wave_amp)/32;
z2 = (sample * wdata.amplitude_v) >> 10;
z2 = (z2 * wdata.mix_wave_amp)/32;
}
z1 = z2 + (((total>>8) * amplitude2) >> 13);
@@ -1587,8 +1592,8 @@ static void SetAmplitude(int length, unsigned char *amp_env, int value)
else
amp_inc = (256 * ENV_LEN * STEPSIZE)/length;
amplitude = (value * general_amplitude)/16;
amplitude_v = (amplitude * wvoice->consonant_ampv * 15)/100; // for wave mixed with voiced sounds
wdata.amplitude = (value * general_amplitude)/16;
wdata.amplitude_v = (wdata.amplitude * wvoice->consonant_ampv * 15)/100; // for wave mixed with voiced sounds
amplitude_env = amp_env;
}
@@ -1641,18 +1646,18 @@ if(option_log_frames)
}
}
#endif
if((pitch_env = env)==NULL)
pitch_env = env_fall; // default
if((wdata.pitch_env = env)==NULL)
wdata.pitch_env = env_fall; // default
pitch_ix = 0;
wdata.pitch_ix = 0;
if(length==0)
pitch_inc = 0;
wdata.pitch_inc = 0;
else
pitch_inc = (256 * ENV_LEN * STEPSIZE)/length;
wdata.pitch_inc = (256 * ENV_LEN * STEPSIZE)/length;
SetPitch2(wvoice, pitch1, pitch2, &pitch_base, &pitch_range);
SetPitch2(wvoice, pitch1, pitch2, &wdata.pitch_base, &wdata.pitch_range);
// set initial pitch
pitch = ((pitch_env[0]*pitch_range)>>8) + pitch_base; // Hz << 12
wdata.pitch = ((wdata.pitch_env[0] * wdata.pitch_range) >>8) + wdata.pitch_base; // Hz << 12
flutter_amp = wvoice->flutter;
@@ -1662,15 +1667,14 @@ if(option_log_frames)
void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2)
{//============================================================
void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v)
{//========================================================================
int ix;
DOUBLEX next;
int length2;
int length4;
int qix;
int cmd;
voice_t *v;
static int glottal_reduce_tab1[4] = {0x30, 0x30, 0x40, 0x50}; // vowel before [?], amp * 1/256
// static int glottal_reduce_tab1[4] = {0x30, 0x40, 0x50, 0x60}; // vowel before [?], amp * 1/256
static int glottal_reduce_tab2[4] = {0x90, 0xa0, 0xb0, 0xc0}; // vowel after [?], amp * 1/256
@@ -1724,8 +1728,6 @@ if(option_log_frames)
break; // next is not from spectrum, so continue until end of wave cycle
}
v = wvoice;
// round the length to a multiple of the stepsize
length2 = (length + STEPSIZE/2) & ~0x3f;
if(length2 == 0)
@@ -1767,7 +1769,7 @@ if(option_log_frames)
static int Wavegen2(int length, int modulation, int resume, frame_t *fr1, frame_t *fr2)
{//====================================================================================
if(resume==0)
SetSynth(length,modulation,fr1,fr2);
SetSynth(length, modulation, fr1, fr2, wvoice);
return(Wavegen());
}
@@ -1839,35 +1841,46 @@ int WavegenFill(int fill_zeros)
{
echo_complete -= length;
}
n_mix_wavefile = 0;
wdata.n_mix_wavefile = 0;
wdata.prev_was_synth = 0;
result = PlaySilence(length,resume);
break;
case WCMD_WAVE:
echo_complete = echo_length;
n_mix_wavefile = 0;
wdata.n_mix_wavefile = 0;
wdata.prev_was_synth = 0;
result = PlayWave(length,resume,(unsigned char*)q[2], q[3] & 0xff, q[3] >> 8);
break;
case WCMD_WAVE2:
// wave file to be played at the same time as synthesis
mix_wave_amp = q[3] >> 8;
mix_wave_scale = q[3] & 0xff;
if(mix_wave_scale == 0)
n_mix_wavefile = length*2;
wdata.mix_wave_amp = q[3] >> 8;
wdata.mix_wave_scale = q[3] & 0xff;
if(wdata.mix_wave_scale == 0)
wdata.n_mix_wavefile = length*2;
else
n_mix_wavefile = length;
mix_wavefile_ix = 0;
mix_wavefile = (unsigned char *)q[2];
wdata.n_mix_wavefile = length;
wdata.mix_wavefile_ix = 0;
wdata.mix_wavefile = (unsigned char *)q[2];
break;
case WCMD_SPECT2: // as WCMD_SPECT but stop any concurrent wave file
n_mix_wavefile = 0; // ... and drop through to WCMD_SPECT case
wdata.n_mix_wavefile = 0; // ... and drop through to WCMD_SPECT case
case WCMD_SPECT:
echo_complete = echo_length;
result = Wavegen2(length & 0xffff,q[1] >> 16,resume,(frame_t *)q[2],(frame_t *)q[3]);
break;
#ifdef INCLUDE_KLATT
case WCMD_KLATT2: // as WCMD_SPECT but stop any concurrent wave file
wdata.n_mix_wavefile = 0; // ... and drop through to WCMD_SPECT case
case WCMD_KLATT:
echo_complete = echo_length;
result = Wavegen_Klatt2(length & 0xffff,q[1] >> 16,resume,(frame_t *)q[2],(frame_t *)q[3]);
break;
#endif
case WCMD_MARKER:
MarkerEvent(q[1],q[2],q[3],out_ptr);
#ifdef LOG_FRAMES