[1.43.57]

Indicate language changes in IPA phoneme output.

Phoneme definitions FMT(), second parameter is amplitude percentage.

Phoneme definitions CALL(),  If phoneme type is not defined, copy the static attributes from the called phoneme.

Unpronouncable word check: stop when an apostrophe is reached.


git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@250 d46cf337-b52f-0410-862d-fd96e6ae7743
This commit is contained in:
jonsd
2010-07-18 22:43:04 +00:00
parent 3bf61040b9
commit ebf0535e6d
85 changed files with 2294 additions and 1945 deletions
+69 -7
View File
@@ -21,6 +21,7 @@
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <time.h>
#include "wx/wx.h"
#include "wx/wfstream.h"
@@ -359,6 +360,8 @@ static PHONEME_TAB *phoneme_out;
static int n_phcodes_list[N_PHONEME_TABS];
static PHONEME_TAB_LIST phoneme_tab_list2[N_PHONEME_TABS];
static PHONEME_TAB *phoneme_tab2;
static int phoneme_flags;
static int place_articulation;
#define N_PROCS 50
int n_procs;
@@ -838,16 +841,41 @@ static int ph_sorter(char **a, char **b)
static void PrintPhonemesUsed(FILE *f, const char *dictname)
{//=========================================================
static void PrintPhonemesUsed(FILE *f, const char *dsource, const char *dictname)
{//==============================================================================
int ix;
PHONEME_TAB *ph;
PHONEME_TAB *ph_tab[N_PHONEME_TAB];
int count = 0;
int n_ph = 0;
int section = 0;
time_t mod_time;
char fname[sizeof(path_home)+45];
struct stat statbuf;
char time_string[20];
const char *files[] = {"rules","list","listx"};
fprintf(f,"\n\nDictionary %s_dict\n",dictname);
// find the date-stamp of the dictionary source files
mod_time = 0;
for(ix=0; ix<3; ix++)
{
sprintf(fname,"%s%s_%s",dsource, dictname, files[ix]);
if(stat(fname,&statbuf) == 0)
{
if(statbuf.st_mtime > mod_time)
mod_time = statbuf.st_mtime;
}
}
if(mod_time > 0)
{
strftime(time_string, sizeof(time_string), "%F", localtime(&mod_time));
fprintf(f,"\n\nDictionary %s_dict %s\n",dictname, time_string);
}
else
{
fprintf(f,"\n\nDictionary %s_dict\n",dictname);
}
fflush(f);
for(ix=0; (ix<N_PHONEME_TAB) && (phoneme_tab[ix] != NULL); ix++)
@@ -1003,7 +1031,7 @@ static wxString CompileAllDictionaries()
{
memset(phoneme_tab_flags,0,sizeof(phoneme_tab_flags));
FindPhonemesUsed();
PrintPhonemesUsed(f_phused,dictname);
PrintPhonemesUsed(f_phused, path_dsource, dictname);
}
cont = dir.GetNext(&filename);
@@ -2160,7 +2188,29 @@ int CompileSound(int keyword, int isvowel)
strcpy(path, item_string);
if(item_terminator == ',')
{
value = NextItemBrackets(tSIGNEDNUMBER,1);
if((keyword == kVOWELSTART) || (keyword == kVOWELENDING))
{
value = NextItemBrackets(tSIGNEDNUMBER,1);
if(value > 127)
{
value = 127;
error("Parameter > 127",NULL);
}
if(value < -128)
{
value = -128;
error("Parameter < -128",NULL);
}
}
else
{
value = NextItemBrackets(tNUMBER,1);
if(value > 255)
{
value = 255;
error("Parameter > 255",NULL);
}
}
}
addr = LoadDataFile(path, isvowel);
addr = addr / 4; // addr is words not bytes
@@ -2525,6 +2575,18 @@ static void CallPhoneme(void)
if((ph = FindPhoneme(item_string)) == NULL)
return;
addr = ph->program;
if(phoneme_out->type == phINVALID)
{
// Phoneme type has not been set. Copy it from the called phoneme
phoneme_out->type = ph->type;
phoneme_flags = ph->phflags & ~phARTICULATION;
place_articulation = (ph->phflags & phARTICULATION) >> 16;
phoneme_out->start_type = ph->start_type;
phoneme_out->end_type = ph->end_type;
phoneme_out->std_length = ph->std_length;
phoneme_out->length_mod = ph->length_mod;
}
}
*prog_out++ = i_CALLPH + (addr >> 16);
@@ -2551,8 +2613,6 @@ static void InstnPlusPhoneme(int instn)
int CompilePhoneme(int compile_phoneme)
{//====================================
int endphoneme = 0;
int phoneme_flags = 0;
int place_articulation = 0;
int keyword;
int value;
int phcode = 0;
@@ -2568,6 +2628,8 @@ int CompilePhoneme(int compile_phoneme)
if_level = 0;
if_stack[0].returned = 0;
after_if = 0;
phoneme_flags = 0;
place_articulation = 0;
NextItem(tSTRING);
if(compile_phoneme)
+3
View File
@@ -1118,6 +1118,9 @@ static void copy_rule_string(char *string, int &state)
case 'b':
sxflags |= SUFX_B;
break;
case 'a':
sxflags |= SUFX_A;
break;
default:
if(isdigit(c))
value = (value*10) + (c - '0');
+36 -29
View File
@@ -245,6 +245,7 @@ int LoadDictionary(Translator *tr, const char *name, int no_error)
char fname[sizeof(path_home)+20];
strcpy(dictionary_name,name); // currently loaded dictionary name
strcpy(tr->dictionary_name, name);
// Load a pronunciation data file into memory
// bytes 0-3: offset to rules data
@@ -634,32 +635,32 @@ void GetTranslatedPhonemeString(char *phon_out, int n_phon_out)
}
}
}
WritePhMnemonic(phon_out, &phon_out_ix, plist->ph, plist);
if(plist->synthflags & SFLAG_LENGTHEN)
{
WritePhMnemonic(phon_out, &phon_out_ix, phoneme_tab[phonLENGTHEN], NULL);
}
if((plist->synthflags & SFLAG_SYLLABLE) && (plist->type != phVOWEL))
{
// syllablic consonant
WritePhMnemonic(phon_out, &phon_out_ix, phoneme_tab[phonSYLLABIC], NULL);
}
if(plist->ph->code == phonSWITCH)
{
// the tone_ph field contains a phoneme table number
p = phoneme_tab_list[plist->tone_ph].name;
while((c = *p++) != 0)
{
if(option_phonemes != 3)
phon_out[phon_out_ix++] = c;
}
phon_out[phon_out_ix++] = ' ';
sprintf(&phon_out[phon_out_ix], "(%s)", p);
phon_out_ix += (strlen(p) + 2);
}
else
if(plist->tone_ph > 0)
{
WritePhMnemonic(phon_out, &phon_out_ix, phoneme_tab[plist->tone_ph], NULL);
WritePhMnemonic(phon_out, &phon_out_ix, plist->ph, plist);
if(plist->synthflags & SFLAG_LENGTHEN)
{
WritePhMnemonic(phon_out, &phon_out_ix, phoneme_tab[phonLENGTHEN], NULL);
}
if((plist->synthflags & SFLAG_SYLLABLE) && (plist->type != phVOWEL))
{
// syllablic consonant
WritePhMnemonic(phon_out, &phon_out_ix, phoneme_tab[phonSYLLABIC], NULL);
}
if(plist->tone_ph > 0)
{
WritePhMnemonic(phon_out, &phon_out_ix, phoneme_tab[plist->tone_ph], NULL);
}
}
}
@@ -810,7 +811,7 @@ static int Unpronouncable_en(Translator *tr, char *word)
index += utf8_in(&c,&word[index]);
count++;
if((c==0) || (c==' '))
if((c==0) || (c==' ') || (c == '\''))
break;
if(IsVowel(tr, c) || (c == 'y'))
@@ -890,7 +891,7 @@ int Unpronouncable(Translator *tr, char *word)
if(tr->langopts.param[LOPT_UNPRONOUNCABLE] == 1)
return(0);
if((*word == ' ') || (*word == 0))
if(((c = *word) == ' ') || (c == 0) || (c == '\''))
return(0);
index = 0;
@@ -898,7 +899,7 @@ int Unpronouncable(Translator *tr, char *word)
for(;;)
{
index += utf8_in(&c,&word[index]);
if((c==0) || (c==' '))
if((c==0) || (c==' ') || (c == '\''))
break;
if(count==0)
@@ -925,7 +926,7 @@ int Unpronouncable(Translator *tr, char *word)
vowel_posn--; // disregard this as the initial letter when counting
if(vowel_posn > (tr->langopts.max_initial_consonants+1))
return(1); // no vowel, or no vowel in first four letters
return(1); // no vowel, or no vowel in first few letters
return(0);
@@ -1167,6 +1168,7 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags,
int opt_length;
int done;
int stressflags;
int dflags = 0;
signed char vowel_stress[N_WORD_PHONEMES/2];
char syllable_weight[N_WORD_PHONEMES/2];
@@ -1185,6 +1187,9 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags,
stressflags = tr->langopts.stress_flags;
if(dictionary_flags != NULL)
dflags = dictionary_flags[0];
/* copy input string into internal buffer */
for(ix=0; ix<N_WORD_PHONEMES; ix++)
{
@@ -1202,16 +1207,16 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags,
max_output = output + (N_WORD_PHONEMES-3); /* check for overrun */
// any stress position marked in the xx_list dictionary ?
stressed_syllable = dictionary_flags[0] & 0x7;
if(dictionary_flags[0] & 0x8)
stressed_syllable = dflags & 0x7;
if(dflags & 0x8)
{
// this indicates a word without a primary stress
stressed_syllable = dictionary_flags[0] & 0x3;
stressed_syllable = dflags & 0x3;
unstressed_word = 1;
}
max_stress = GetVowelStress(tr, phonetic, vowel_stress, vowel_count, stressed_syllable, 1);
if(max_stress < 0)
if((max_stress < 0) && dictionary_flags)
{
if((tr->langopts.stress_flags & 1) && (vowel_count == 2))
{
@@ -1994,13 +1999,15 @@ static void MatchRule(Translator *tr, char *word[], char *word_start, int group_
break;
case RULE_NOTVOWEL:
if(!IsLetter(tr, letter_w,0))
if(IsLetter(tr, letter_w, 0) || ((letter_w == ' ') && (word_flags & FLAG_SUFFIX_VOWEL)))
{
failed = 1;
}
else
{
add_points = (20-distance_right);
post_ptr += letter_xbytes;
}
else
failed = 1;
break;
case RULE_DIGIT:
+35 -50
View File
@@ -178,7 +178,7 @@ if(argc > 1)
// Make a menubar
myframe->SetMenuBar(MakeMenu(0));
myframe->SetMenuBar(MakeMenu(0, voice_name2));
myframe->CreateStatusBar();
myframe->SetVoiceTitle(voice_name2);
@@ -240,7 +240,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxMDIParentFrame)
EVT_TIMER(1, MyFrame::OnTimer)
EVT_SIZE(MyFrame::OnSize)
EVT_SASH_DRAGGED_RANGE(ID_WINDOW_TOP, ID_WINDOW_BOTTOM, MyFrame::OnSashDrag)
EVT_SASH_DRAGGED(ID_WINDOW_LEFT, MyFrame::OnSashDrag)
END_EVENT_TABLE()
@@ -260,22 +260,16 @@ MyFrame::MyFrame(wxWindow *parent, const wxWindowID id, const wxString& title, c
int result;
int param;
// Create some dummy layout windows
wxSashLayoutWindow *win;
// Another window to the left of the client window
win = new wxSashLayoutWindow(this, ID_WINDOW_LEFT2,
m_leftWindow = new wxSashLayoutWindow(this, ID_WINDOW_LEFT,
wxDefaultPosition, wxSize(298, 30),
wxNO_BORDER | wxSW_3D | wxCLIP_CHILDREN);
win->SetDefaultSize(wxSize(310, 1000));
win->SetOrientation(wxLAYOUT_VERTICAL);
win->SetAlignment(wxLAYOUT_LEFT);
// win->SetBackgroundColour(wxColour(0, 255, 255));
win->SetSashVisible(wxSASH_RIGHT, TRUE);
m_leftWindow->SetDefaultSize(wxSize(310, 1000));
m_leftWindow->SetOrientation(wxLAYOUT_VERTICAL);
m_leftWindow->SetAlignment(wxLAYOUT_LEFT);
m_leftWindow->SetSashVisible(wxSASH_RIGHT, TRUE);
m_leftWindow2 = win;
notebook = new wxNotebook(m_leftWindow2,-1);
notebook = new wxNotebook(m_leftWindow,-1);
// notebook->AddPage(voicedlg,_T("Voice"),FALSE);
formantdlg = new FormantDlg(notebook);
notebook->AddPage(formantdlg,_T(" Spect"),FALSE);
@@ -336,12 +330,14 @@ void MyFrame::SetVoiceTitle(char *voice_name)
{//==========================================
char buf[100];
SetTitle(AppName + _T(" - ") + wxString(voice_name,wxConvLocal) + _T(" voice"));
if(data_menu != NULL)
if((data_menu != NULL) && (translator != NULL))
{
sprintf(buf,"Compile &dictionary '%s'",dictionary_name);
sprintf(buf,"Compile &dictionary '%s'",translator->dictionary_name);
data_menu->SetLabel(MENU_COMPILE_DICT, wxString(buf,wxConvLocal));
sprintf(buf,"&Layout '%s_rules' file",dictionary_name);
sprintf(buf,"&Layout '%s_rules' file",translator->dictionary_name);
data_menu->SetLabel(MENU_FORMAT_DICTIONARY, wxString(buf,wxConvLocal));
sprintf(buf,"&Sort '%s_rules' file",translator->dictionary_name);
data_menu->SetLabel(MENU_SORT_DICTIONARY, wxString(buf,wxConvLocal));
}
}
@@ -563,8 +559,8 @@ void DisplayErrorFile(const char *fname)
len = GetFileLength(fname);
if(len > 0)
{
if(len > 2000)
len = 2000; // restrict length to pppppevent crash in wxLogMessage()
if(len > 1500)
len = 1500; // restrict length to pppppevent crash in wxLogMessage()
msg = (char *)malloc(len+1);
if(msg != NULL)
{
@@ -633,8 +629,8 @@ void MyFrame::OnTools(wxCommandEvent& event)
sprintf(fname_log,"%s%s",path_dsource,"dict_log");
log = fopen(fname_log,"w");
LoadDictionary(translator, dictionary_name, 0);
if((err = CompileDictionary(path_dsource,dictionary_name,log,err_fname,debug_flag)) < 0)
LoadDictionary(translator, translator->dictionary_name, 0);
if((err = CompileDictionary(path_dsource,translator->dictionary_name,log,err_fname,debug_flag)) < 0)
{
wxLogError(_T("Can't access file:\n")+wxString(err_fname,wxConvLocal));
@@ -729,37 +725,26 @@ void MyFrame::OnSpeak(wxCommandEvent& event)
void MyFrame::OnSashDrag(wxSashEvent& event)
{
if (event.GetDragStatus() == wxSASH_STATUS_OUT_OF_RANGE)
return;
int w, h;
switch (event.GetId())
{
case ID_WINDOW_TOP:
{
m_topWindow->SetDefaultSize(wxSize(1000, event.GetDragRect().height));
break;
}
case ID_WINDOW_LEFT1:
{
m_leftWindow1->SetDefaultSize(wxSize(event.GetDragRect().width, 1000));
break;
}
case ID_WINDOW_LEFT2:
{
m_leftWindow2->SetDefaultSize(wxSize(event.GetDragRect().width, 1000));
break;
}
case ID_WINDOW_BOTTOM:
{
m_bottomWindow->SetDefaultSize(wxSize(1000, event.GetDragRect().height));
break;
}
}
wxLayoutAlgorithm layout;
layout.LayoutMDIFrame(this);
if (event.GetDragStatus() == wxSASH_STATUS_OUT_OF_RANGE)
return;
// Leaves bits of itself behind sometimes
GetClientWindow()->Refresh();
GetClientSize(&w, &h);
switch (event.GetId())
{
case ID_WINDOW_LEFT:
{
m_leftWindow->SetDefaultSize(wxSize(event.GetDragRect().width, h));
break;
}
}
wxLayoutAlgorithm layout;
layout.LayoutMDIFrame(this);
// Leaves bits of itself behind sometimes
GetClientWindow()->Refresh();
}
+1 -1
View File
@@ -421,7 +421,7 @@ if(option_log_frames)
#endif
out = resonator(&(kt_globals.rsn[Rout]),out);
temp = (out * wdata.amplitude * kt_globals.amp_gain0) ; /* Convert back to integer */
temp = (int)(out * wdata.amplitude * kt_globals.amp_gain0) ; /* Convert back to integer */
// mix with a recorded WAV if required for this phoneme
+3 -9
View File
@@ -8,7 +8,7 @@ typedef unsigned char UCHAR;
extern wxMenuBar *MakeMenu(int type);
extern wxMenuBar *MakeMenu(int type, const char *dict_name);
extern wxString path_phsource;
extern wxString path_speaktext;
@@ -56,10 +56,7 @@ class MyFrame: public wxMDIParentFrame
protected:
wxSashLayoutWindow* m_topWindow;
wxSashLayoutWindow* m_leftWindow1;
wxSashLayoutWindow* m_leftWindow2;
wxSashLayoutWindow* m_bottomWindow;
wxSashLayoutWindow* m_leftWindow;
wxTimer m_timer;
DECLARE_EVENT_TABLE()
@@ -177,10 +174,7 @@ enum {
SPECTSEQ_VOICEDLG
};
#define ID_WINDOW_TOP 100
#define ID_WINDOW_LEFT1 101
#define ID_WINDOW_LEFT2 102
#define ID_WINDOW_BOTTOM 103
#define ID_WINDOW_LEFT 101
+1 -1
View File
@@ -19,7 +19,7 @@
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>
#include <poll.h>
+10 -4
View File
@@ -22,13 +22,12 @@
#include "main.h"
wxMenu *speak_menu;
wxMenu *data_menu = NULL;
wxMenuBar *MakeMenu(int type)
{//==========================
wxMenuBar *MakeMenu(int type, const char *dict_name)
{//=================================================
char buf[100];
wxMenu *file_menu;
wxMenu *help_menu;
wxMenu *option_menu = NULL;
@@ -95,6 +94,13 @@ wxMenuBar *MakeMenu(int type)
data_menu->Append(MENU_FORMAT_DICTIONARY, _("&Layout *_rules file"));
data_menu->Append(MENU_SORT_DICTIONARY, _("&Sort *_rules file"));
sprintf(buf,"Compile &dictionary '%s'",dict_name);
data_menu->SetLabel(MENU_COMPILE_DICT, wxString(buf,wxConvLocal));
sprintf(buf,"&Layout '%s_rules' file",dict_name);
data_menu->SetLabel(MENU_FORMAT_DICTIONARY, wxString(buf,wxConvLocal));
sprintf(buf,"&Sort '%s_rules' file",dict_name);
data_menu->SetLabel(MENU_SORT_DICTIONARY, wxString(buf,wxConvLocal));
// OPTIONS MENU
paths_menu = new wxMenu;
paths_menu->Append(MENU_PATH0, _("Master phonemes file..."));
+1 -1
View File
@@ -36,6 +36,7 @@
// phoneme properties
// bits 16-19 give place of articulation
#define phARTICULATION 0xf0000
#define phWAVE 0x01
#define phUNSTRESSED 0x02
#define phFORTIS 0x08
@@ -50,7 +51,6 @@
#define phBRKAFTER 0x4000 // [*] add a post-pause
#define phBEFOREPAUSE 0x8000 // replace with the link_out phoneme if the next phoneme is a pause
#define phNONSYLLABIC 0x100000 // don't count this vowel as a syllable when finding the stress position
#define phLONG 0x200000
#define phLENGTHENSTOP 0x400000 // make the pre-pause slightly longer
+6 -2
View File
@@ -591,6 +591,8 @@ void MyFrame::OnProsody(wxCommandEvent& WXUNUSED(event))
// Open the Prosody display window
// Make another frame, containing a canvas
int h, w, w2;
if(prosodyframe != NULL)
{
// The Prosody window is already open
@@ -598,8 +600,10 @@ void MyFrame::OnProsody(wxCommandEvent& WXUNUSED(event))
return;
}
m_leftWindow->GetSize(&w2, &h);
GetClientSize(&w, &h);
prosodyframe = new ChildFrProsody(myframe, _T(""),
wxPoint(10, 200), wxSize(1000, 300),
wxPoint(0, 100), wxSize(w-w2, 420),
wxDEFAULT_FRAME_STYLE |
wxNO_FULL_REPAINT_ON_RESIZE);
@@ -622,7 +626,7 @@ void MyFrame::OnProsody(wxCommandEvent& WXUNUSED(event))
prosodycanvas = canvas;
// Associate the menu bar with the frame
prosodyframe->SetMenuBar(MakeMenu(2));
prosodyframe->SetMenuBar(MakeMenu(2,translator->dictionary_name));
prosodyframe->prosodycanvas = canvas;
prosodyframe->Show(TRUE);
+7 -5
View File
@@ -35,6 +35,7 @@
#include "phoneme.h"
#include "synthesize.h"
#include "voice.h"
#include "translate.h"
#include "spect.h"
#include "options.h"
@@ -981,6 +982,7 @@ void MyFrame::OnNewWindow(wxCommandEvent& event)
SpectSeq *spectseq;
wxString leaf;
wxString pathload;
int width, height;
if(event.GetId() == MENU_SPECTRUM)
pathload = path_spectload;
@@ -1021,10 +1023,11 @@ void MyFrame::OnNewWindow(wxCommandEvent& event)
else
path_spectload2 = path.GetPath();
// Make another frame, containing a canvas
// Make another frame, containing a canvas
GetClientSize(&width, &height);
MyChild *subframe = new MyChild(myframe, _T("Spectrum"),
wxPoint(10, 10), wxSize(300, 300),
wxDEFAULT_FRAME_STYLE | wxMAXIMIZE |
wxPoint(10, 0), wxSize(500, height),
wxDEFAULT_FRAME_STYLE |
wxNO_FULL_REPAINT_ON_RESIZE);
subframe->SetTitle(leaf);
@@ -1032,14 +1035,13 @@ void MyFrame::OnNewWindow(wxCommandEvent& event)
// Give it a status line
subframe->CreateStatusBar();
int width, height;
subframe->GetClientSize(&width, &height);
SpectDisplay *canvas = new SpectDisplay(subframe, wxPoint(0, 0), wxSize(width, height), spectseq);
canvas->savepath = filename;
currentcanvas = canvas;
// Associate the menu bar with the frame
subframe->SetMenuBar(MakeMenu(1));
subframe->SetMenuBar(MakeMenu(1,translator->dictionary_name));
subframe->canvas = canvas;
subframe->Show(TRUE);
-1
View File
@@ -522,7 +522,6 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr
memset(&fmtp, 0, sizeof(fmtp));
InterpretPhoneme(NULL, 0, p, &phdata);
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
fmtp.fmt_length = phdata.sound_param[pd_FMT];
len = DoSpect2(p->ph, 0, &fmtp, p, -1);
// len = DoSpect(p->ph,prev->ph,phoneme_tab[phonPAUSE],2,p,-1);
len = (len * 1000)/samplerate;
+5 -5
View File
@@ -35,8 +35,8 @@
#include "translate.h"
#include "wave.h"
const char *version_string = "1.43.52 04.Jul.10";
const int version_phdata = 0x014351;
const char *version_string = "1.43.57 18.Jul.10";
const int version_phdata = 0x014354;
int option_device_number = -1;
FILE *f_logespeak = NULL;
@@ -1041,15 +1041,15 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_
}
}
else
if(instn2 == 4)
if(instn2 ==pd_ADDWAV)
{
// addWav(), return if previous instruction was FMT() or WAV()
end_flag--;
}
if((instn2 != 1) && (instn2 != 4))
if((instn2 == pd_VWLSTART) || (instn2 == pd_VWLEND))
{
// FMT, VowelStart or VowelEnding.
// VowelStart or VowelEnding.
phdata->sound_param[instn2] = param_sc; // sign extend
}
}
+36 -8
View File
@@ -54,6 +54,7 @@ static int last_wcmdq;
static int pitch_length;
static int amp_length;
static int modn_flags;
static int fmt_amplitude=0;
static int syllable_start;
static int syllable_end;
@@ -223,6 +224,13 @@ static void DoPause(int length, int control)
wcmdq[wcmdq_tail][1] = len;
WcmdqInc();
last_frame = NULL;
if(fmt_amplitude != 0)
{
wcmdq[wcmdq_tail][0] = WCMD_FMT_AMPLITUDE;
wcmdq[wcmdq_tail][1] = fmt_amplitude = 0;
WcmdqInc();
}
} // end of DoPause
@@ -972,7 +980,7 @@ static void StartSyllable(void)
int DoSpect2(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, PHONEME_LIST *plist, int modulation)
{//========================================================================================================
// which 0 not a vowel, 1 start of vowel, 2 body and end of vowel
// which: 0 not a vowel, 1 start of vowel, 2 body and end of vowel
// length_mod: 256 = 100%
// modulation: -1 = don't write to wcmdq
@@ -1025,6 +1033,15 @@ if(which==1)
if(frames == NULL)
return(0); // not found
if(fmt_params->fmt_amp != fmt_amplitude)
{
// an amplitude adjustment is specified for this sequence
q = wcmdq[wcmdq_tail];
q[0] = WCMD_FMT_AMPLITUDE;
q[1] = fmt_amplitude = fmt_params->fmt_amp;
WcmdqInc();
}
frame1 = frames[0].frame;
if(voice->klattv[0])
wcmd_spect = WCMD_KLATT;
@@ -1166,6 +1183,16 @@ if(which==1)
total_len += len;
}
}
if((which != 1) && (fmt_amplitude != 0))
{
q = wcmdq[wcmdq_tail];
q[0] = WCMD_FMT_AMPLITUDE;
q[1] = fmt_amplitude = 0;
WcmdqInc();
}
return(total_len);
} // end of DoSpect
@@ -1429,7 +1456,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
// a period of voicing before the release
InterpretPhoneme(NULL, 0x01, p, &phdata);
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
fmtp.fmt_length = phdata.sound_param[pd_FMT];
fmtp.fmt_amp = phdata.sound_param[pd_FMT];
DoSpect2(ph, 0, &fmtp, p, 0);
if(p->synthflags & SFLAG_LENGTHEN)
@@ -1457,7 +1484,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
}
InterpretPhoneme(NULL,0, p, &phdata);
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
fmtp.fmt_length = phdata.sound_param[pd_FMT];
fmtp.fmt_amp = phdata.sound_param[pd_FMT];
fmtp.wav_addr = phdata.sound_addr[pd_ADDWAV];
fmtp.wav_amp = phdata.sound_param[pd_ADDWAV];
DoSpect2(ph, 0, &fmtp, p, 0);
@@ -1504,7 +1531,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
memset(&fmtp, 0, sizeof(fmtp));
fmtp.std_length = phdata.pd_param[i_SET_LENGTH]*2;
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
fmtp.fmt_length = phdata.sound_param[pd_FMT];
fmtp.fmt_amp = phdata.sound_param[pd_FMT];
fmtp.wav_addr = phdata.sound_addr[pd_ADDWAV];
fmtp.wav_amp = phdata.sound_param[pd_ADDWAV];
@@ -1529,7 +1556,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
InterpretPhoneme(NULL,0, p, &phdata);
fmtp.std_length = phdata.pd_param[i_SET_LENGTH]*2;
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
fmtp.fmt_length = phdata.sound_param[pd_FMT];
fmtp.fmt_amp = phdata.sound_param[pd_FMT];
if(next->type==phVOWEL)
{
@@ -1578,7 +1605,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
InterpretPhoneme(NULL, 0, p, &phdata);
fmtp.std_length = phdata.pd_param[i_SET_LENGTH]*2;
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
fmtp.fmt_length = phdata.sound_param[pd_FMT];
fmtp.fmt_amp = phdata.sound_param[pd_FMT];
fmtp.wav_addr = phdata.sound_addr[pd_ADDWAV];
fmtp.wav_amp = phdata.sound_param[pd_ADDWAV];
DoSpect2(p->ph, 0, &fmtp, p, modulation);
@@ -1619,9 +1646,10 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
fmtp.use_vowelin = 1;
fmtp.fmt_control = 1;
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
// fmtp.fmt_length = phdata.sound_param[pd_FMT];
}
fmtp.fmt_amp = phdata.sound_param[pd_FMT];
pitch_env = envelope_data[p->env];
amp_env = NULL;
if(p->tone_ph != 0)
@@ -1670,7 +1698,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
}
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
fmtp.fmt_length = phdata.sound_param[pd_FMT];
fmtp.fmt_amp = phdata.sound_param[pd_FMT];
fmtp.transition0 = 0;
fmtp.transition1 = 0;
+4
View File
@@ -177,6 +177,7 @@ int mix_wavefile_offset;
int amplitude;
int amplitude_v;
int amplitude_fmt; // percentage amplitude adjustment for formant synthesis
} WGEN_DATA;
@@ -275,6 +276,7 @@ typedef struct {
int use_vowelin;
int fmt_addr;
int fmt_length;
int fmt_amp;
int fmt2_addr;
int fmt2_lenadj;
int wav_addr;
@@ -466,6 +468,8 @@ extern unsigned char pitch_adjust_tab[MAX_PITCH_VALUE+1];
#define WCMD_VOICE 11
#define WCMD_EMBEDDED 12
#define WCMD_MBROLA_DATA 13
#define WCMD_FMT_AMPLITUDE 14
#define N_WCMDQ 160
+2 -4
View File
@@ -60,8 +60,6 @@ static void Translator_Russian(Translator *tr);
static void SetLetterVowel(Translator *tr, int c)
{//==============================================
tr->letter_bits[c] = (tr->letter_bits[c] & 0x40) | 0x81; // keep value for group 6 (front vowels e,i,y)
@@ -618,7 +616,7 @@ Translator *SelectTranslator(const char *name)
tr->langopts.accents = 2; // Say "Capital" after the letter.
tr->langopts.vowel_pause = 0;
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_OMIT_1_HUNDRED | NUM_NOPAUSE | NUM_ROMAN | NUM_VIGESIMAL | NUM_DFRACTION_4;
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_OMIT_1_HUNDRED | NUM_NOPAUSE | NUM_ROMAN | NUM_ROMAN_CAPITALS | NUM_ROMAN_AFTER | NUM_VIGESIMAL | NUM_DFRACTION_4;
SetLetterVowel(tr,'y');
}
break;
@@ -670,7 +668,7 @@ Translator *SelectTranslator(const char *name)
tr->langopts.spelling_stress = 1;
tr->langopts.accents = 1;
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_HUNDRED_AND | NUM_OMIT_1_HUNDRED | NUM_DECIMAL_COMMA | NUM_THOUS_SPACE | NUM_DFRACTION_2 | NUM_ROMAN_UC;
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_HUNDRED_AND | NUM_OMIT_1_HUNDRED | NUM_DECIMAL_COMMA | NUM_THOUS_SPACE | NUM_DFRACTION_2 | NUM_ROMAN_CAPITALS;
tr->langopts.numbers2 = 0x4a; // variant numbers before thousands,milliards
tr->langopts.replace_chars = replace_cyrillic_latin;
+12 -6
View File
@@ -862,7 +862,7 @@ if((wmark > 0) && (wmark < 8))
{
// either all upper or all lower case
if((tr->langopts.numbers & NUM_ROMAN) || ((tr->langopts.numbers & NUM_ROMAN_UC) && (wflags & FLAG_ALL_UPPER)))
if((tr->langopts.numbers & NUM_ROMAN) || ((tr->langopts.numbers & NUM_ROMAN_CAPITALS) && (wflags & FLAG_ALL_UPPER)))
{
if((found = TranslateRoman(tr, word1, phonemes, wtab)) != 0)
dictionary_flags[0] |= FLAG_ABBREV; // prevent emphasis if capitals
@@ -920,6 +920,9 @@ if((wmark > 0) && (wmark < 8))
// find a remainder that we can pronounce.
emphasize_allcaps = 0;
if(wordx[0] == '\'')
break;
if(posn > 0)
non_initial = 1;
@@ -934,6 +937,7 @@ if((wmark > 0) && (wmark < 8))
return(0);
}
#ifdef deleted
p = &wordx[word_length-3]; // this looks wrong. Doesn't consider multi-byte chars.
if(memcmp(p,"'s ",3) == 0)
{
@@ -943,7 +947,7 @@ if((wmark > 0) && (wmark < 8))
p[1] = ' ';
last_char = p[-1];
}
#endif
length=0;
while(wordx[length] != ' ') length++;
}
@@ -952,7 +956,7 @@ if((wmark > 0) && (wmark < 8))
// anything left ?
if(*wordx != ' ')
{
if(unpron_phonemes[0] != 0)
if((unpron_phonemes[0] != 0) && (wordx[0] != '\''))
{
// letters which have been spoken individually from affecting the pronunciation of the pronuncable part
wordx[-1] = ' ';
@@ -1163,9 +1167,11 @@ strcpy(phonemes2,phonemes);
else
{
if(end_flags & FLAG_SUFX)
TranslateRules(tr, wordx, phonemes, N_WORD_PHONEMES, NULL,wflags | FLAG_SUFFIX_REMOVED, dictionary_flags);
else
TranslateRules(tr, wordx, phonemes, N_WORD_PHONEMES, NULL,wflags,dictionary_flags);
wflags |= FLAG_SUFFIX_REMOVED;
if(end_type & SUFX_A)
wflags |= FLAG_SUFFIX_VOWEL;
TranslateRules(tr, wordx, phonemes, N_WORD_PHONEMES, NULL, wflags, dictionary_flags);
if(phonemes[0] == phonSWITCH)
{
+25 -20
View File
@@ -109,6 +109,7 @@
#define FLAG_COMMA_AFTER 0x20000 // comma after this word
#define FLAG_MULTIPLE_SPACES 0x40000 // word is preceded by multiple spaces, newline, or tab
#define FLAG_SUFFIX_VOWEL 0x08000000 // remember an initial vowel from the suffix
#define FLAG_NO_TRACE 0x10000000 // passed to TranslateRules() to suppress dictionary lookup printout
#define FLAG_NO_PREFIX 0x20000000
@@ -122,6 +123,8 @@
#define SUFX_Q 0x4000 // don't retranslate
#define SUFX_T 0x10000 // don't affect the stress position in the stem
#define SUFX_B 0x20000 // break, this character breaks the word into stem and suffix (used with SUFX_P)
#define SUFX_A 0x40000 // remember that the suffix starts with a vowel
#define FLAG_ALLOW_TEXTMODE 0x02 // allow dictionary to translate to text rather than phonemes
#define FLAG_SUFX 0x04
@@ -380,16 +383,16 @@ typedef struct {
#define NUM_DFRACTION_3 0x6000
#define NUM_DFRACTION_4 0x8000
#define NUM_DFRACTION_5 0xa000
#define NUM_ORDINAL_DOT 0x10000
#define NUM_ROMAN 0x20000
#define NUM_ROMAN_UC 0x40000
#define NUM_NOPAUSE 0x80000
#define NUM_AND_HUNDRED 0x100000
#define NUM_ROMAN_AFTER 0x200000
#define NUM_VIGESIMAL 0x400000
#define NUM_ROMAN_ORDINAL 0x800000
#define NUM_ROMAN_CAPITALS 0x1000000
#define NUM_THOUSAND_AND 0x2000000
#define NUM_ORDINAL_DOT 0x10000
#define NUM_NOPAUSE 0x20000
#define NUM_AND_HUNDRED 0x40000
#define NUM_THOUSAND_AND 0x80000
#define NUM_VIGESIMAL 0x100000
#define NUM_ROMAN 0x1000000
#define NUM_ROMAN_CAPITALS 0x2000000
#define NUM_ROMAN_AFTER 0x4000000
#define NUM_ROMAN_ORDINAL 0x8000000
// bits0-1=which numbers routine to use.
// bit2= thousands separator must be space
@@ -404,16 +407,17 @@ typedef struct {
// bit11=say 19** as nineteen hundred
// bit12=allow space as thousands separator (in addition to langopts.thousands_sep)
// bits13-15 post-decimal-digits 0=single digits, 1=(LANG=it) 2=(LANG=pl) 3=(LANG=ro)
// bit16=dot after number indicates ordinal
// bit17=recognize roman numbers
// bit18=Roman numbers only if upper case
// bit19=don't add pause after a number
// bit20='and' before hundreds
// bit21= say "roman" after the number, not before
// bit22= vigesimal number, if tens are not found
// bit23=Roman numbers are ordinal numbers
// bit24=Roman numbers must be capital letters
// bit25='and' after thousands if there are no hundreds
// bit16= dot after number indicates ordinal
// bit17= don't add pause after a number
// bit18= 'and' before hundreds
// bit19= 'and' after thousands if there are no hundreds
// bit20= vigesimal number, if tens are not found
// bit24= recognize roman numbers
// bit25= Roman numbers only if upper case
// bit26= say "roman" after the number, not before
// bit27= Roman numbers are ordinal numbers
int numbers;
// bits 1-4 use variant form of numbers before thousands,millions,etc.
@@ -476,6 +480,7 @@ typedef struct
int translator_name;
int transpose_max;
int transpose_min;
char dictionary_name[40];
char phon_out[300];
char phonemes_repeat[20];
+2 -1
View File
@@ -292,13 +292,14 @@ TranslDlg::TranslDlg(wxWindow *parent) : wxPanel(parent)
t_phonetic = new wxTextCtrl(this,T_PHONETIC,_T(""),wxPoint(0,262),
wxSize(298,height_ph),wxTE_MULTILINE | wxTE_READONLY,wxDefaultValidator,_T("Phoneme translation window"));
wxSize(298,height_ph),wxTE_MULTILINE | wxTE_READONLY, wxDefaultValidator,_T("Phoneme translation window"));
style_phonetic = t_phonetic->GetDefaultStyle();
font_phonetic = style_phonetic.GetFont();
font_size = font_phonetic.GetPointSize();
font_phonetic_large = font_phonetic;
style_phonetic_large = style_phonetic;
//font_phonetic_large.SetFamily(wxFONTFAMILY_SWISS);
font_phonetic_large.SetPointSize(font_size+1);
style_phonetic_large.SetFont(font_phonetic_large);
+12 -3
View File
@@ -693,6 +693,7 @@ void WavegenInit(int rate, int wavemult_fact)
max_hval = 0;
wdata.amplitude = 32;
wdata.amplitude_fmt = 100;
for(ix=0; ix<N_EMBEDDED_VALUES; ix++)
embedded_value[ix] = embedded_default[ix];
@@ -1147,7 +1148,8 @@ int Wavegen()
maxh2 = PeaksToHarmspect(peaks, wdata.pitch<<4, hspect[0], 0);
// adjust amplitude to compensate for fewer harmonics at higher pitch
amplitude2 = (wdata.amplitude * wdata.pitch)/(100 << 11);
// amplitude2 = (wdata.amplitude * wdata.pitch)/(100 << 11);
amplitude2 = (wdata.amplitude * (wdata.pitch >> 8) * wdata.amplitude_fmt)/(10000 << 3);
// switch sign of harmonics above about 900Hz, to reduce max peak amplitude
h_switch_sign = 890 / (wdata.pitch >> 12);
@@ -1200,7 +1202,8 @@ int Wavegen()
}
// adjust amplitude to compensate for fewer harmonics at higher pitch
amplitude2 = (wdata.amplitude * wdata.pitch)/(100 << 11);
// amplitude2 = (wdata.amplitude * wdata.pitch)/(100 << 11);
amplitude2 = (wdata.amplitude * (wdata.pitch >> 8) * wdata.amplitude_fmt)/(10000 << 3);
if(glottal_flag > 0)
{
@@ -1535,7 +1538,7 @@ void SetEmbedded(int control, int value)
general_amplitude = GetAmplitude();
break;
case EMBED_F: // emphasiis
case EMBED_F: // emphasis
general_amplitude = GetAmplitude();
break;
@@ -1837,6 +1840,7 @@ int WavegenFill(int fill_zeros)
echo_complete -= length;
}
wdata.n_mix_wavefile = 0;
wdata.amplitude_fmt = 100;
KlattReset(1);
result = PlaySilence(length,resume);
break;
@@ -1907,6 +1911,11 @@ int WavegenFill(int fill_zeros)
case WCMD_MBROLA_DATA:
result = MbrolaFill(length, resume);
break;
case WCMD_FMT_AMPLITUDE:
if((wdata.amplitude_fmt = q[1]) == 0)
wdata.amplitude_fmt = 100; // percentage, but value=0 means 100%
break;
}
if(result==0)