Browse Source

Declare variables at their first point of use

Also use size_t instead of int in some places
where it make sense
master
Fredrik Nyqvist 9 years ago
parent
commit
14a2fb39cf

+ 8
- 16
src/espeak-ng.c View File



void DisplayVoices(FILE *f_out, char *language) void DisplayVoices(FILE *f_out, char *language)
{ {
int ix;
const char *p; const char *p;
int len; int len;
int count; int count;


fprintf(f_out, "Pty Language Age/Gender VoiceName File Other Languages\n"); fprintf(f_out, "Pty Language Age/Gender VoiceName File Other Languages\n");


for (ix = 0; (v = voices[ix]) != NULL; ix++) {
for (int ix = 0; (v = voices[ix]) != NULL; ix++) {
count = 0; count = 0;
p = v->languages; p = v->languages;
while (*p != 0) { while (*p != 0) {
static void Write4Bytes(FILE *f, int value) static void Write4Bytes(FILE *f, int value)
{ {
// Write 4 bytes to a file, least significant first // Write 4 bytes to a file, least significant first
int ix;

for (ix = 0; ix < 4; ix++) {
for (int ix = 0; ix < 4; ix++) {
fputc(value & 0xff, f); fputc(value & 0xff, f);
value = value >> 8; value = value >> 8;
} }


static void CloseWavFile() static void CloseWavFile()
{ {
unsigned int pos;

if ((f_wavfile == NULL) || (f_wavfile == stdout)) if ((f_wavfile == NULL) || (f_wavfile == stdout))
return; return;


fflush(f_wavfile); fflush(f_wavfile);
pos = ftell(f_wavfile);
unsigned int pos = ftell(f_wavfile);


fseek(f_wavfile, 4, SEEK_SET); fseek(f_wavfile, 4, SEEK_SET);
Write4Bytes(f_wavfile, pos - 8); Write4Bytes(f_wavfile, pos - 8);


static int SynthCallback(short *wav, int numsamples, espeak_EVENT *events) static int SynthCallback(short *wav, int numsamples, espeak_EVENT *events)
{ {
char fname[210];

if (quiet) return 0; // -q quiet mode if (quiet) return 0; // -q quiet mode


if (wav == NULL) { if (wav == NULL) {
} }


if (f_wavfile == NULL) { if (f_wavfile == NULL) {
char fname[210];
if (samples_split > 0) { if (samples_split > 0) {
sprintf(fname, "%s_%.2d%s", wavefile, wavefile_count+1, filetype); sprintf(fname, "%s_%.2d%s", wavefile, wavefile_count+1, filetype);
if (OpenWavFile(fname, samplerate) != 0) if (OpenWavFile(fname, samplerate) != 0)


int option_index = 0; int option_index = 0;
int c; int c;
int ix;
char *optarg2; char *optarg2;
int value; int value;
int flag_stdin = 0; int flag_stdin = 0;
optind = 1; optind = 1;
opt_string = ""; opt_string = "";
while (optind < argc) { while (optind < argc) {
int len;
char *p; char *p;


if ((c = *opt_string) == 0) { if ((c = *opt_string) == 0) {
break; // -- means don't interpret further - as commands break; // -- means don't interpret further - as commands


opt_string = ""; opt_string = "";
for (ix = 0;; ix++) {
for (int ix = 0;; ix++) {
if (long_options[ix].name == 0) if (long_options[ix].name == 0)
break; break;
len = strlen(long_options[ix].name);
size_t len = strlen(long_options[ix].name);
if (memcmp(long_options[ix].name, p, len) == 0) { if (memcmp(long_options[ix].name, p, len) == 0) {
c = long_options[ix].val; c = long_options[ix].val;
optarg2 = NULL; optarg2 = NULL;
case 0x103: // --punct case 0x103: // --punct
option_punctuation = 1; option_punctuation = 1;
if (optarg2 != NULL) { if (optarg2 != NULL) {
ix = 0;
int ix = 0;
while ((ix < N_PUNCTLIST) && ((option_punctlist[ix] = optarg2[ix]) != 0)) ix++; while ((ix < N_PUNCTLIST) && ((option_punctlist[ix] = optarg2[ix]) != 0)) ix++;
option_punctlist[N_PUNCTLIST-1] = 0; option_punctlist[N_PUNCTLIST-1] = 0;
option_punctuation = 2; option_punctuation = 2;
} }
} else { } else {
// bulk input on stdin // bulk input on stdin
ix = 0;
int ix = 0;
while (!feof(stdin)) { while (!feof(stdin)) {
p_text[ix++] = fgetc(stdin); p_text[ix++] = fgetc(stdin);
if (ix >= (max-1)) { if (ix >= (max-1)) {

+ 79
- 146
src/libespeak-ng/compiledata.c View File

// Read the phondata-manifest file // Read the phondata-manifest file
FILE *f; FILE *f;
int n_lines = 0; int n_lines = 0;
int ix;
char *p; char *p;
unsigned int value; unsigned int value;
char buf[sizeof(path_home)+40]; char buf[sizeof(path_home)+40];
rewind(f); rewind(f);


if (manifest != NULL) { if (manifest != NULL) {
for (ix = 0; ix < n_manifest; ix++)
for (int ix = 0; ix < n_manifest; ix++)
free(manifest[ix].name); free(manifest[ix].name);
} }


static void DecompilePhoneme(FILE *f_out, PHONEME_TAB *ph, int compile_phoneme) static void DecompilePhoneme(FILE *f_out, PHONEME_TAB *ph, int compile_phoneme)
{ {
USHORT *pc; USHORT *pc;
int instn;
int instn_category;
int address, address2; int address, address2;
int data1;
int type2;
int ix;
int any;
const char *name; const char *name;
char buf[120]; char buf[120];




pc = prog_buf; pc = prog_buf;
while (pc < prog_out) { while (pc < prog_out) {
instn = *pc++;
instn_category = (instn >> 12) & 0xf;
data1 = instn & 0xff;
type2 = (instn >> 8) & 0xf;
int instn = *pc++;
int instn_category = (instn >> 12) & 0xf;
int data1 = instn & 0xff;
int type2 = (instn >> 8) & 0xf;
fprintf(f_out, " %.3x: %.4x %s", (unsigned int)(pc-prog_buf), instn, instn_category_string[instn_category]); fprintf(f_out, " %.3x: %.4x %s", (unsigned int)(pc-prog_buf), instn, instn_category_string[instn_category]);


switch (instn_category) switch (instn_category)
data1 = 0; data1 = 0;
fprintf(f_out, "%s", instn0_string[data1]); fprintf(f_out, "%s", instn0_string[data1]);
} else if (type2 == i_IPA_NAME) { } else if (type2 == i_IPA_NAME) {
int ix;
for (ix = 0; ix < data1; ix += 2) { for (ix = 0; ix < data1; ix += 2) {
instn = *pc++; instn = *pc++;
buf[ix] = instn >> 8; buf[ix] = instn >> 8;
} else if (type2 == 8) { } else if (type2 == 8) {
// list of numbers // list of numbers
fprintf(f_out, " StressLevel("); fprintf(f_out, " StressLevel(");
any = 0;
for (ix = 0; ix < 8; ix++) {
int any = 0;
for (int ix = 0; ix < 8; ix++) {
if (data1 & (1 << ix)) { if (data1 & (1 << ix)) {
if (any) if (any)
fputc(',', f_out); fputc(',', f_out);


static int ref_sorter(char **a, char **b) static int ref_sorter(char **a, char **b)
{ {
int ix;

REF_HASH_TAB *p1 = (REF_HASH_TAB *)(*a); REF_HASH_TAB *p1 = (REF_HASH_TAB *)(*a);
REF_HASH_TAB *p2 = (REF_HASH_TAB *)(*b); REF_HASH_TAB *p2 = (REF_HASH_TAB *)(*b);


ix = strcoll(p1->string, p2->string);
int ix = strcoll(p1->string, p2->string);
if (ix != 0) if (ix != 0)
return ix; return ix;


static void CompileReport(void) static void CompileReport(void)
{ {
int ix; int ix;
int hash;
int n;
REF_HASH_TAB *p; REF_HASH_TAB *p;
REF_HASH_TAB **list; REF_HASH_TAB **list;
const char *data_path; const char *data_path;
int prev_table;
int procedure_num;
int prev_mnemonic;


if (f_report == NULL) if (f_report == NULL)
return; return;


fprintf(f_report, "Data file Used by\n"); fprintf(f_report, "Data file Used by\n");
ix = 0; ix = 0;
for (hash = 0; (hash < 256) && (ix < count_references); hash++) {
for (int hash = 0; (hash < 256) && (ix < count_references); hash++) {
p = ref_hash_tab[hash]; p = ref_hash_tab[hash];
while (p != NULL) { while (p != NULL) {
list[ix++] = p; list[ix++] = p;
p = (REF_HASH_TAB *)(p->link); p = (REF_HASH_TAB *)(p->link);
} }
} }
n = ix;
int n = ix;
qsort((void *)list, n, sizeof(REF_HASH_TAB *), (int (*)(const void *, const void *))ref_sorter); qsort((void *)list, n, sizeof(REF_HASH_TAB *), (int (*)(const void *, const void *))ref_sorter);


data_path = ""; data_path = "";
prev_mnemonic = 0;
prev_table = 0;
int prev_mnemonic = 0;
int prev_table = 0;
for (ix = 0; ix < n; ix++) { for (ix = 0; ix < n; ix++) {
int j = 0; int j = 0;


prev_mnemonic = list[ix]->ph_mnemonic; prev_mnemonic = list[ix]->ph_mnemonic;
if ((prev_mnemonic >> 24) == 'P') { if ((prev_mnemonic >> 24) == 'P') {
// a procedure, not a phoneme // a procedure, not a phoneme
procedure_num = atoi(WordToString(prev_mnemonic));
int procedure_num = atoi(WordToString(prev_mnemonic));
fprintf(f_report, " %s %s", phoneme_tab_list2[prev_table = list[ix]->ph_table].name, proc_names[procedure_num]); fprintf(f_report, " %s %s", phoneme_tab_list2[prev_table = list[ix]->ph_table].name, proc_names[procedure_num]);
} else } else
fprintf(f_report, " [%s] %s", WordToString(prev_mnemonic), phoneme_tab_list2[prev_table = list[ix]->ph_table].name); fprintf(f_report, " [%s] %s", WordToString(prev_mnemonic), phoneme_tab_list2[prev_table = list[ix]->ph_table].name);
static unsigned int StringToWord(const char *string) static unsigned int StringToWord(const char *string)
{ {
// Pack 4 characters into a word // Pack 4 characters into a word
int ix;
unsigned char c; unsigned char c;
unsigned int word;


if (string == NULL) if (string == NULL)
return 0; return 0;


word = 0;
for (ix = 0; ix < 4; ix++) {
unsigned int word = 0;
for (int ix = 0; ix < 4; ix++) {
if (string[ix] == 0) break; if (string[ix] == 0) break;
c = string[ix]; c = string[ix];
word |= (c << (ix*8)); word |= (c << (ix*8));
// control = 1 declare phoneme if not found // control = 1 declare phoneme if not found
// control = 2 start looking after control & stress phonemes // control = 2 start looking after control & stress phonemes


int ix;
int start;
int use;
unsigned int word;

if (strcmp(string, "NULL") == 0) if (strcmp(string, "NULL") == 0)
return 1; return 1;


ix = strlen(string);
int ix = strlen(string);
if ((ix == 0) || (ix > 4)) if ((ix == 0) || (ix > 4))
error("Bad phoneme name '%s'", string); error("Bad phoneme name '%s'", string);
word = StringToWord(string);
unsigned int word = StringToWord(string);


// don't use phoneme number 0, reserved for string terminator // don't use phoneme number 0, reserved for string terminator
start = 1;
int start = 1;


if (control == 2) { if (control == 2) {
// don't look for control and stress phonemes (allows these characters to be // don't look for control and stress phonemes (allows these characters to be
start = 8; start = 8;
} }


use = 0;
int use = 0;
for (ix = start; ix < n_phcodes; ix++) { for (ix = start; ix < n_phcodes; ix++) {
if (phoneme_tab2[ix].mnemonic == word) if (phoneme_tab2[ix].mnemonic == word)
return ix; return ix;


static unsigned int get_char() static unsigned int get_char()
{ {
unsigned int c;
c = fgetc(f_in);
unsigned int c = fgetc(f_in);
if (c == '\n') if (c == '\n')
linenum++; linenum++;
return c; return c;
int acc; int acc;
unsigned char c = 0; unsigned char c = 0;
unsigned char c2; unsigned char c2;
int ix;
int sign;
char *p; char *p;
keywtab_t *pk; keywtab_t *pk;


return -1; return -1;
} }


ix = 0;
int ix = 0;
while (!feof(f_in) && !isspace(c) && (c != '(') && (c != ')') && (c != ',')) { while (!feof(f_in) && !isspace(c) && (c != '(') && (c != ')') && (c != ',')) {
if (c == '\\') if (c == '\\')
c = get_char(); c = get_char();


if ((type == tNUMBER) || (type == tSIGNEDNUMBER)) { if ((type == tNUMBER) || (type == tSIGNEDNUMBER)) {
acc = 0; acc = 0;
sign = 1;
int sign = 1;
p = item_string; p = item_string;


if ((*p == '-') && (type == tSIGNEDNUMBER)) { if ((*p == '-') && (type == tSIGNEDNUMBER)) {
static int NextItemMax(int max) static int NextItemMax(int max)
{ {
// Get a number, but restrict value to max // Get a number, but restrict value to max
int value;
char msg[80]; char msg[80];


value = NextItem(tNUMBER);
int value = NextItem(tNUMBER);
if (value > max) { if (value > max) {
sprintf(msg, "Value %d is greater than maximum %d", value, max); sprintf(msg, "Value %d is greater than maximum %d", value, max);
error(msg, NULL); error(msg, NULL);
// control: bit 0 0= need ( // control: bit 0 0= need (
// bit 1 1= allow comma // bit 1 1= allow comma


int value;

if ((control & 1) == 0) { if ((control & 1) == 0) {
if (!NextItem(tOPENBRACKET)) if (!NextItem(tOPENBRACKET))
error("Expected '('", NULL); error("Expected '('", NULL);
} }


value = NextItem(type);
int value = NextItem(type);
if ((control & 2) && (item_terminator == ',')) if ((control & 2) && (item_terminator == ','))
return value; return value;


int CompileVowelTransition(int which) int CompileVowelTransition(int which)
{ {
// Compile a vowel transition // Compile a vowel transition
int key;
int len = 0; int len = 0;
int rms = 0; int rms = 0;
int f1 = 0; int f1 = 0;
int f3_amp = 0; int f3_amp = 0;
int flags = 0; int flags = 0;
int vcolour = 0; int vcolour = 0;
int x;
int instn = i_VOWELIN; int instn = i_VOWELIN;
int word1;
int word2;


if (which == 1) { if (which == 1) {
len = 50 / 2; // defaults for transition into vowel len = 50 / 2; // defaults for transition into vowel
} }


for (;;) { for (;;) {
key = NextItem(tKEYWORD);
int key = NextItem(tKEYWORD);
if (item_type != tTRANSITION) { if (item_type != tTRANSITION) {
UngetItem(); UngetItem();
break; break;
f2_min = Range(NextItem(tSIGNEDNUMBER), 50, -15, 15) & 0x1f; f2_min = Range(NextItem(tSIGNEDNUMBER), 50, -15, 15) & 0x1f;
f2_max = Range(NextItem(tSIGNEDNUMBER), 50, -15, 15) & 0x1f; f2_max = Range(NextItem(tSIGNEDNUMBER), 50, -15, 15) & 0x1f;
if (f2_min > f2_max) { if (f2_min > f2_max) {
x = f2_min;
int x = f2_min;
f2_min = f2_max; f2_min = f2_max;
f2_max = x; f2_max = x;
} }
break; break;
} }
} }
word1 = len + (rms << 6) + (flags << 12);
word2 = f2 + (f2_min << 6) + (f2_max << 11) + (f3_adj << 16) + (f3_amp << 21) + (f1 << 26) + (vcolour << 29);
int word1 = len + (rms << 6) + (flags << 12);
int word2 = f2 + (f2_min << 6) + (f2_max << 11) + (f3_adj << 16) + (f3_amp << 21) + (f1 << 26) + (vcolour << 29);
prog_out[0] = instn + ((word1 >> 16) & 0xff); prog_out[0] = instn + ((word1 >> 16) & 0xff);
prog_out[1] = word1; prog_out[1] = word1;
prog_out[2] = word2 >> 16; prog_out[2] = word2 >> 16;
int LoadSpect(const char *path, int control) int LoadSpect(const char *path, int control)
{ {
SpectSeq *spectseq; SpectSeq *spectseq;
int peak;
int displ;
int frame;
int n_frames;
int ix; int ix;
int x, x2; int x, x2;
int rms;
float total;
float pkheight; float pkheight;
int marker1_set = 0; int marker1_set = 0;
int frame_vowelbreak = 0; int frame_vowelbreak = 0;
} }


// do we need additional klatt data ? // do we need additional klatt data ?
for (frame = 0; frame < spectseq->numframes; frame++) {
for (int frame = 0; frame < spectseq->numframes; frame++) {
for (ix = 5; ix < N_KLATTP2; ix++) { for (ix = 5; ix < N_KLATTP2; ix++) {
if (spectseq->frames[frame]->klatt_param[ix] != 0) if (spectseq->frames[frame]->klatt_param[ix] != 0)
klatt_flag = FRFLAG_KLATT; klatt_flag = FRFLAG_KLATT;
} }
} }


displ = ftell(f_phdata);
int displ = ftell(f_phdata);


seq_out.n_frames = 0; seq_out.n_frames = 0;
seq_out.sqflags = 0; seq_out.sqflags = 0;
seq_out.length_total = 0; seq_out.length_total = 0;


total = 0;
for (frame = 0; frame < spectseq->numframes; frame++) {
float total = 0.0f;
for (int frame = 0; frame < spectseq->numframes; frame++) {
if (spectseq->frames[frame]->keyframe) { if (spectseq->frames[frame]->keyframe) {
if (seq_out.n_frames == 1) if (seq_out.n_frames == 1)
frame_vowelbreak = frame; frame_vowelbreak = frame;
spectseq->frames[frame_vowelbreak]->markers |= FRFLAG_VOWEL_CENTRE; spectseq->frames[frame_vowelbreak]->markers |= FRFLAG_VOWEL_CENTRE;
} }


n_frames = 0;
for (frame = 0; frame < spectseq->numframes; frame++) {
int n_frames = 0;
for (int frame = 0; frame < spectseq->numframes; frame++) {
fr = spectseq->frames[frame]; fr = spectseq->frames[frame];


if (fr->keyframe) { if (fr->keyframe) {


fr_out->frflags = fr->markers | klatt_flag; fr_out->frflags = fr->markers | klatt_flag;


rms = (int)GetFrameRms(fr, spectseq->amplitude);
int rms = (int)GetFrameRms(fr, spectseq->amplitude);
if (rms > 255) rms = 255; if (rms > 255) rms = 255;
fr_out->rms = rms; fr_out->rms = rms;




// write: peak data // write: peak data
count_frames++; count_frames++;
for (peak = 0; peak < 8; peak++) {
for (int peak = 0; peak < 8; peak++) {
if (peak < 7) if (peak < 7)
fr_out->ffreq[peak] = fr->peaks[peak].pkfreq; fr_out->ffreq[peak] = fr->peaks[peak].pkfreq;


for (ix = 0; ix < 5; ix++) for (ix = 0; ix < 5; ix++)
fr_out->klattp2[ix] = fr->klatt_param[ix+5]; fr_out->klattp2[ix] = fr->klatt_param[ix+5];


for (peak = 0; peak < 7; peak++) {
for (int peak = 0; peak < 7; peak++) {
fr_out->klatt_ap[ix] = fr->peaks[peak].klt_ap; fr_out->klatt_ap[ix] = fr->peaks[peak].klt_ap;


x = fr->peaks[peak].klt_bp / 2; x = fr->peaks[peak].klt_bp / 2;


static int LoadWavefile(FILE *f, const char *fname) static int LoadWavefile(FILE *f, const char *fname)
{ {
int displ;
unsigned char c1; unsigned char c1;
unsigned char c3; unsigned char c3;
int c2; int c2;
int sample; int sample;
int sample2; int sample2;
float x;
int max = 0; int max = 0;
int length;
int sr1, sr2;
int failed; int failed;
int len;
int resample_wav = 0; int resample_wav = 0;
const char *fname2; const char *fname2;
char fname_temp[100]; char fname_temp[100];
int scale_factor = 0; int scale_factor = 0;


fseek(f, 24, SEEK_SET); fseek(f, 24, SEEK_SET);
sr1 = Read4Bytes(f);
sr2 = Read4Bytes(f);
int sr1 = Read4Bytes(f);
int sr2 = Read4Bytes(f);
fseek(f, 40, SEEK_SET); fseek(f, 40, SEEK_SET);


if ((sr1 != samplerate_native) || (sr2 != sr1*2)) { if ((sr1 != samplerate_native) || (sr2 != sr1*2)) {
#endif #endif


fname2 = fname; fname2 = fname;
len = strlen(fname);
size_t len = strlen(fname);
if (strcmp(&fname[len-4], ".wav") == 0) { if (strcmp(&fname[len-4], ".wav") == 0) {
strcpy(msg, fname); strcpy(msg, fname);
msg[len-4] = 0; msg[len-4] = 0;
fseek(f, 40, SEEK_SET); // skip past the WAV header, up to before "data length" fseek(f, 40, SEEK_SET); // skip past the WAV header, up to before "data length"
} }


displ = ftell(f_phdata);
int displ = ftell(f_phdata);


// data contains: 4 bytes of length (n_samples * 2), followed by 2-byte samples (lsb byte first) // data contains: 4 bytes of length (n_samples * 2), followed by 2-byte samples (lsb byte first)
length = Read4Bytes(f);
int length = Read4Bytes(f);


while (!feof(f)) { while (!feof(f)) {
c1 = fgetc(f); c1 = fgetc(f);
fputc(sample & 0xff, f_phdata); fputc(sample & 0xff, f_phdata);
fputc(sample >> 8, f_phdata); fputc(sample >> 8, f_phdata);
} else { } else {
x = ((float)sample / scale_factor) + 0.5;
float x = ((float)sample / scale_factor) + 0.5;
sample2 = (int)x; sample2 = (int)x;
if (sample2 > 127) if (sample2 > 127)
sample2 = 127; sample2 = 127;


static int LoadEnvelope(FILE *f, const char *fname) static int LoadEnvelope(FILE *f, const char *fname)
{ {
int displ;
char buf[128]; char buf[128];


displ = ftell(f_phdata);
int displ = ftell(f_phdata);


fseek(f, 12, SEEK_SET); fseek(f, 12, SEEK_SET);
if (fread(buf, 128, 1, f) == 0) if (fread(buf, 128, 1, f) == 0)


static int LoadEnvelope2(FILE *f, const char *fname) static int LoadEnvelope2(FILE *f, const char *fname)
{ {
int ix, ix2;
int n; int n;
int x, y;
int displ;
int n_points;
double yy;
char line_buf[128]; char line_buf[128];
float env_x[20]; float env_x[20];
float env_y[20]; float env_y[20];
int env_lin[20]; int env_lin[20];
unsigned char env[ENV_LEN]; unsigned char env[ENV_LEN];


n_points = 0;
int n_points = 0;
fgets(line_buf, sizeof(line_buf), f); // skip first line fgets(line_buf, sizeof(line_buf), f); // skip first line

while (!feof(f)) { while (!feof(f)) {
if (fgets(line_buf, sizeof(line_buf), f) == NULL) if (fgets(line_buf, sizeof(line_buf), f) == NULL)
break; break;
env_x[n_points] = env_x[n_points-1]; env_x[n_points] = env_x[n_points-1];
env_y[n_points] = env_y[n_points-1]; env_y[n_points] = env_y[n_points-1];


ix = -1;
ix2 = 0;
for (x = 0; x < ENV_LEN; x++) {
int ix = -1;
int ix2 = 0;
int y = 0;
for (int x = 0; x < ENV_LEN; x++) {
if (x > env_x[ix+4]) if (x > env_x[ix+4])
ix++; ix++;
if (x >= env_x[ix2+1]) if (x >= env_x[ix2+1])
ix2++; ix2++;


if (env_lin[ix2] > 0) { if (env_lin[ix2] > 0) {
yy = env_y[ix2] + (env_y[ix2+1] - env_y[ix2]) * ((float)x - env_x[ix2]) / (env_x[ix2+1] - env_x[ix2]);
double yy = env_y[ix2] + (env_y[ix2+1] - env_y[ix2]) * ((float)x - env_x[ix2]) / (env_x[ix2+1] - env_x[ix2]);
y = (int)(yy * 2.55); y = (int)(yy * 2.55);
} else if (n_points > 3) } else if (n_points > 3)
y = (int)(polint(&env_x[ix], &env_y[ix], 4, x) * 2.55); // convert to range 0-255 y = (int)(polint(&env_x[ix], &env_y[ix], 4, x) * 2.55); // convert to range 0-255
n_envelopes++; n_envelopes++;
} }


displ = ftell(f_phdata);
int displ = ftell(f_phdata);
fwrite(env, 1, 128, f_phdata); fwrite(env, 1, 128, f_phdata);


return displ; return displ;
// return index into spect or sample data area. bit 23=1 if a sample // return index into spect or sample data area. bit 23=1 if a sample


FILE *f; FILE *f;
int id;
int hash;
int addr = 0; int addr = 0;
int type_code = ' '; int type_code = ' ';
REF_HASH_TAB *p, *p2; REF_HASH_TAB *p, *p2;


count_references++; count_references++;


hash = Hash8(path);
int hash = Hash8(path);
p = ref_hash_tab[hash]; p = ref_hash_tab[hash];
while (p != NULL) { while (p != NULL) {
if (strcmp(path, p->string) == 0) { if (strcmp(path, p->string) == 0) {
} }
} }


id = Read4Bytes(f);
int id = Read4Bytes(f);
rewind(f); rewind(f);


if (id == 0x43455053) { if (id == 0x43455053) {


static int CompileToneSpec(void) static int CompileToneSpec(void)
{ {
int pitch1 = 0;
int pitch2 = 0;
int pitch_env = 0; int pitch_env = 0;
int amp_env = 0; int amp_env = 0;


pitch1 = NextItemBrackets(tNUMBER, 2);
pitch2 = NextItemBrackets(tNUMBER, 3);
int pitch1 = NextItemBrackets(tNUMBER, 2);
int pitch2 = NextItemBrackets(tNUMBER, 3);


if (item_terminator == ',') { if (item_terminator == ',') {
NextItemBrackets(tSTRING, 3); NextItemBrackets(tSTRING, 3);


int CompileSound(int keyword, int isvowel) int CompileSound(int keyword, int isvowel)
{ {
int addr;
int value = 0; int value = 0;
char path[N_ITEM_STRING]; char path[N_ITEM_STRING];
static int sound_instns[] = { i_FMT, i_WAV, i_VWLSTART, i_VWLENDING, i_WAVADD }; static int sound_instns[] = { i_FMT, i_WAV, i_VWLSTART, i_VWLENDING, i_WAVADD };
} }
} }
} }
addr = LoadDataFile(path, isvowel);
int addr = LoadDataFile(path, isvowel);
addr = addr / 4; // addr is words not bytes addr = addr / 4; // addr is words not bytes


*prog_out++ = sound_instns[keyword-kFMT] + ((value & 0xff) << 4) + ((addr >> 16) & 0xf); *prog_out++ = sound_instns[keyword-kFMT] + ((value & 0xff) << 4) + ((addr >> 16) & 0xf);
int word = 0; int word = 0;
int word2; int word2;
int data; int data;
int bitmap;
int brackets;
int not_flag; int not_flag;
USHORT *prog_last_if = NULL; USHORT *prog_last_if = NULL;


} }
} else if (item_type == tTEST) { } else if (item_type == tTEST) {
if (key == kTHISSTRESS) { if (key == kTHISSTRESS) {
bitmap = 0;
brackets = 2;
int bitmap = 0;
int brackets = 2;
do { do {
data = NextItemBrackets(tNUMBER, brackets); data = NextItemBrackets(tNUMBER, brackets);
if (data > 7) if (data > 7)
void FillThen(int add) void FillThen(int add)
{ {
USHORT *p; USHORT *p;
int offset;


p = if_stack[if_level].p_then; p = if_stack[if_level].p_then;
if (p != NULL) { if (p != NULL) {
offset = prog_out - p + add;
int offset = prog_out - p + add;


if ((then_count == 1) && (if_level == 1)) { if ((then_count == 1) && (if_level == 1)) {
// The THEN part only contains one statement, we can remove the THEN jump // The THEN part only contains one statement, we can remove the THEN jump


static PHONEME_TAB_LIST *FindPhonemeTable(const char *string) static PHONEME_TAB_LIST *FindPhonemeTable(const char *string)
{ {
int ix;

for (ix = 0; ix < n_phoneme_tabs; ix++) {
for (int ix = 0; ix < n_phoneme_tabs; ix++) {
if (strcmp(phoneme_tab_list2[ix].name, string) == 0) if (strcmp(phoneme_tab_list2[ix].name, string) == 0)
return &phoneme_tab_list2[ix]; return &phoneme_tab_list2[ix];
} }
{ {
PHONEME_TAB_LIST *phtab = NULL; PHONEME_TAB_LIST *phtab = NULL;
int ix; int ix;
unsigned int mnem;
char *phname; char *phname;
char buf[200]; char buf[200];


if (phtab == NULL) if (phtab == NULL)
return NULL; // phoneme table not found return NULL; // phoneme table not found


mnem = StringToWord(phname);
unsigned int mnem = StringToWord(phname);
for (ix = 1; ix < 256; ix++) { for (ix = 1; ix < 256; ix++) {
if (mnem == phtab->phoneme_tab_ptr[ix].mnemonic) if (mnem == phtab->phoneme_tab_ptr[ix].mnemonic)
return &phtab->phoneme_tab_ptr[ix]; return &phtab->phoneme_tab_ptr[ix];


static void ImportPhoneme(void) static void ImportPhoneme(void)
{ {
unsigned int ph_mnem;
unsigned int ph_code;
PHONEME_TAB *ph; PHONEME_TAB *ph;


NextItem(tSTRING); NextItem(tSTRING);
if ((ph = FindPhoneme(item_string)) == NULL) if ((ph = FindPhoneme(item_string)) == NULL)
return; return;


ph_mnem = phoneme_out->mnemonic;
ph_code = phoneme_out->code;
unsigned int ph_mnem = phoneme_out->mnemonic;
unsigned int ph_code = phoneme_out->code;
memcpy(phoneme_out, ph, sizeof(PHONEME_TAB)); memcpy(phoneme_out, ph, sizeof(PHONEME_TAB));
phoneme_out->mnemonic = ph_mnem; phoneme_out->mnemonic = ph_mnem;
phoneme_out->code = ph_code; phoneme_out->code = ph_code;


static void InstnPlusPhoneme(int instn) static void InstnPlusPhoneme(int instn)
{ {
int phcode;

phcode = NextItemBrackets(tPHONEMEMNEM, 0);
int phcode = NextItemBrackets(tPHONEMEMNEM, 0);
*prog_out++ = instn + phcode; *prog_out++ = instn + phcode;
} }


int keyword; int keyword;
int value; int value;
int phcode = 0; int phcode = 0;
int flags;
int ix;
int start;
int count;
int c; int c;
char *p; char *p;
int vowel_length_factor = 100; // for testing int vowel_length_factor = 100; // for testing
strcpy(item_string, " "); strcpy(item_string, " ");


// copy the string, recognize characters in the form U+9999 // copy the string, recognize characters in the form U+9999
flags = 0;
count = 0;
ix = 1;
int flags = 0;
int count = 0;
int ix = 1;


for (p = item_string; *p != 0;) { for (p = item_string; *p != 0;) {
p += utf8_in(&c, p); p += utf8_in(&c, p);
ipa_buf[0] = flags; ipa_buf[0] = flags;
ipa_buf[ix] = 0; ipa_buf[ix] = 0;


start = 1;
int start = 1;
if (flags != 0) if (flags != 0)
start = 0; // only include the flags byte if bits are set start = 0; // only include the flags byte if bits are set
value = strlen(&ipa_buf[start]); // number of UTF-8 bytes value = strlen(&ipa_buf[start]); // number of UTF-8 bytes


static void WritePhonemeTables() static void WritePhonemeTables()
{ {
int ix;
int j;
int n; int n;
int value;
int count; int count;
PHONEME_TAB *p; PHONEME_TAB *p;


value = n_phoneme_tabs;
int value = n_phoneme_tabs;
fputc(value, f_phtab); fputc(value, f_phtab);
fputc(0, f_phtab); fputc(0, f_phtab);
fputc(0, f_phtab); fputc(0, f_phtab);
fputc(0, f_phtab); fputc(0, f_phtab);


for (ix = 0; ix < n_phoneme_tabs; ix++) {
for (int ix = 0; ix < n_phoneme_tabs; ix++) {
p = phoneme_tab_list2[ix].phoneme_tab_ptr; p = phoneme_tab_list2[ix].phoneme_tab_ptr;
n = n_phcodes_list[ix]; n = n_phcodes_list[ix];
p[n].mnemonic = 0; // terminate the phoneme table p[n].mnemonic = 0; // terminate the phoneme table


// count number of locally declared phonemes // count number of locally declared phonemes
count = 0; count = 0;
for (j = 0; j < n; j++) {
for (int j = 0; j < n; j++) {
if (ix == 0) if (ix == 0)
p[j].phflags |= phLOCAL; // write all phonemes in the base phoneme table p[j].phflags |= phLOCAL; // write all phonemes in the base phoneme table




fwrite(phoneme_tab_list2[ix].name, 1, N_PHONEME_TAB_NAME, f_phtab); fwrite(phoneme_tab_list2[ix].name, 1, N_PHONEME_TAB_NAME, f_phtab);


for (j = 0; j < n; j++) {
for (int j = 0; j < n; j++) {
if (p[j].phflags & phLOCAL) { if (p[j].phflags & phLOCAL) {
// this bit is set temporarily to incidate a local phoneme, declared in // this bit is set temporarily to incidate a local phoneme, declared in
// in the current phoneme file // in the current phoneme file
static void StartPhonemeTable(const char *name) static void StartPhonemeTable(const char *name)
{ {
int ix; int ix;
int j;
PHONEME_TAB *p; PHONEME_TAB *p;


fprintf(f_errors, "______________________________\nPhoneme Table: '%s'\n", name); fprintf(f_errors, "______________________________\nPhoneme Table: '%s'\n", name);
n_phcodes = n_phcodes_list[ix]; n_phcodes = n_phcodes_list[ix];


// clear "local phoneme" bit" // clear "local phoneme" bit"
for (j = 0; j < n_phcodes; j++)
for (int j = 0; j < n_phcodes; j++)
phoneme_tab2[j].phflags &= ~phLOCAL; phoneme_tab2[j].phflags &= ~phLOCAL;
break; break;
} }
{ {
// a list of phonemes in another language and the equivalent phoneme strings in this language // a list of phonemes in another language and the equivalent phoneme strings in this language


int ix;
int n_names; int n_names;
int n_bytes; int n_bytes;
int foreign_phoneme; int foreign_phoneme;
if ((p = strstr(line_buf, "//")) != NULL) if ((p = strstr(line_buf, "//")) != NULL)
*p = 0; *p = 0;


for (ix = 0; ix < 6; ix++)
for (int ix = 0; ix < 6; ix++)
names[ix][0] = 0; names[ix][0] = 0;
n_names = sscanf(line_buf, "%s %s %s %s %s %s", names[0], names[1], names[2], names[3], names[4], names[5]); n_names = sscanf(line_buf, "%s %s %s %s %s %s", names[0], names[1], names[2], names[3], names[4], names[5]);
if (n_names < 1) if (n_names < 1)
} }
} }


for (ix = 1; ix < n_names; ix++)
for (int ix = 1; ix < n_names; ix++)
phcode[ix] = LookupPhoneme(names[ix], 1); phcode[ix] = LookupPhoneme(names[ix], 1);


// only write a translation if it has an effect // only write a translation if it has an effect

+ 41
- 64
src/libespeak-ng/compiledict.c View File

void print_dictionary_flags(unsigned int *flags, char *buf, int buf_len) void print_dictionary_flags(unsigned int *flags, char *buf, int buf_len)
{ {
int stress; int stress;
int ix;
const char *name; const char *name;
int len; int len;
int total = 0; int total = 0;
buf += total; buf += total;
} }


for (ix = 8; ix < 64; ix++) {
for (int ix = 8; ix < 64; ix++) {
if (((ix < 30) && (flags[0] & (1 << ix))) || ((ix >= 0x20) && (flags[1] & (1 << (ix-0x20))))) { if (((ix < 30) && (flags[0] & (1 << ix))) || ((ix >= 0x20) && (flags[1] & (1 << (ix-0x20))))) {
name = LookupMnemName(mnem_flags, ix); name = LookupMnemName(mnem_flags, ix);
len = strlen(name) + 1; len = strlen(name) + 1;
unsigned char c; unsigned char c;
char *p; char *p;
char *p_end; char *p_end;
int ix;
int match_type;
int finished = 0; int finished = 0;
int value; int value;
int linenum = 0; int linenum = 0;


static char symbols_lg[] = { 'A', 'B', 'C', 'H', 'F', 'G', 'Y' }; static char symbols_lg[] = { 'A', 'B', 'C', 'H', 'F', 'G', 'Y' };


match_type = 0;
int match_type = 0;
buf_pre[0] = 0; buf_pre[0] = 0;


int ix;
for (ix = 0; ix < group_length; ix++) for (ix = 0; ix < group_length; ix++)
buf[ix] = group_chars[ix]; buf[ix] = group_chars[ix];
buf[ix] = 0; buf[ix] = 0;
char *word; char *word;
char *phonetic; char *phonetic;
unsigned int ix; unsigned int ix;
int step;
unsigned int n_flag_codes = 0; unsigned int n_flag_codes = 0;
int flagnum;
int flag_offset;
int length; int length;
int multiple_words = 0; int multiple_words = 0;
int multiple_numeric_hyphen = 0; int multiple_numeric_hyphen = 0;
char *multiple_string = NULL; char *multiple_string = NULL;
char *multiple_string_end = NULL; char *multiple_string_end = NULL;


int len_word;
int len_phonetic;
int text_not_phonemes; // this word specifies replacement text, not phonemes
unsigned int wc; unsigned int wc;
int all_upper_case;


char *mnemptr; char *mnemptr;
unsigned char flag_codes[100]; unsigned char flag_codes[100];
char encoded_ph[200]; char encoded_ph[200];
char bad_phoneme_str[4];
int bad_phoneme;
static char nullstring[] = { 0 }; static char nullstring[] = { 0 };


text_not_phonemes = 0;
int text_not_phonemes = 0; // this word specifies replacement text, not phonemes
phonetic = word = nullstring; phonetic = word = nullstring;


p = linebuf; p = linebuf;


step = 0;
int step = 0;


c = 0; c = 0;
while (c != '\n') { while (c != '\n') {


if ((c == '?') && (step == 0)) { if ((c == '?') && (step == 0)) {
// conditional rule, allow only if the numbered condition is set for the voice // conditional rule, allow only if the numbered condition is set for the voice
flag_offset = 100;
int flag_offset = 100;


p++; p++;
if (*p == '!') { if (*p == '!') {
while (!isspace2(c = *p)) p++; while (!isspace2(c = *p)) p++;
*p = 0; *p = 0;


flagnum = LookupMnem(mnem_flags, mnemptr);
int flagnum = LookupMnem(mnem_flags, mnemptr);
if (flagnum > 0) { if (flagnum > 0) {
if (flagnum == 200) if (flagnum == 200)
text_mode = 1; text_mode = 1;
// this is replacement text, so don't encode as phonemes. Restrict the length of the replacement word // this is replacement text, so don't encode as phonemes. Restrict the length of the replacement word
strncpy0(encoded_ph, phonetic, N_WORD_BYTES-4); strncpy0(encoded_ph, phonetic, N_WORD_BYTES-4);
} else { } else {
int bad_phoneme;
EncodePhonemes(phonetic, encoded_ph, &bad_phoneme); EncodePhonemes(phonetic, encoded_ph, &bad_phoneme);
if (strchr(encoded_ph, phonSWITCH) != 0) if (strchr(encoded_ph, phonSWITCH) != 0)
flag_codes[n_flag_codes++] = BITNUM_FLAG_ONLY_S; // don't match on suffixes (except 's') when switching languages flag_codes[n_flag_codes++] = BITNUM_FLAG_ONLY_S; // don't match on suffixes (except 's') when switching languages


// check for errors in the phonemes codes // check for errors in the phonemes codes
if (bad_phoneme != 0) { if (bad_phoneme != 0) {
char bad_phoneme_str[4];
// unrecognised phoneme, report error // unrecognised phoneme, report error
bad_phoneme_str[utf8_out(bad_phoneme, bad_phoneme_str)] = 0; bad_phoneme_str[utf8_out(bad_phoneme, bad_phoneme_str)] = 0;
fprintf(f_log, "%5d: Bad phoneme [%s] (U+%x) in: %s %s\n", linenum, bad_phoneme_str, bad_phoneme, word, phonetic); fprintf(f_log, "%5d: Bad phoneme [%s] (U+%x) in: %s %s\n", linenum, bad_phoneme_str, bad_phoneme, word, phonetic);
// convert to lower case, and note if the word is all-capitals // convert to lower case, and note if the word is all-capitals
int c2; int c2;


all_upper_case = 1;
int all_upper_case = 1;
p = word; p = word;
for (p = word;;) { for (p = word;;) {
// this assumes that the lower case char is the same length as the upper case char // this assumes that the lower case char is the same length as the upper case char
flag_codes[n_flag_codes++] = BITNUM_FLAG_ALLCAPS; flag_codes[n_flag_codes++] = BITNUM_FLAG_ALLCAPS;
} }


len_word = strlen(word);
int len_word = strlen(word);


if (translator->transpose_min > 0) if (translator->transpose_min > 0)
len_word = TransposeAlphabet(translator, word); len_word = TransposeAlphabet(translator, word);


*hash = HashDictionary(word); *hash = HashDictionary(word);
len_phonetic = strlen(encoded_ph);
int len_phonetic = strlen(encoded_ph);


dict_line[1] = len_word; // bit 6 indicates whether the word has been compressed dict_line[1] = len_word; // bit 6 indicates whether the word has been compressed
len_word &= 0x3f; len_word &= 0x3f;
static void compile_dictlist_start(void) static void compile_dictlist_start(void)
{ {
// initialise dictionary list // initialise dictionary list
int ix;
char *p; char *p;
char *p2; char *p2;


for (ix = 0; ix < N_HASH_DICT; ix++) {
for (int ix = 0; ix < N_HASH_DICT; ix++) {
p = hash_chains[ix]; p = hash_chains[ix];
while (p != NULL) { while (p != NULL) {
memcpy(&p2, p, sizeof(char *)); memcpy(&p2, p, sizeof(char *));
static void compile_dictlist_end(FILE *f_out) static void compile_dictlist_end(FILE *f_out)
{ {
// Write out the compiled dictionary list // Write out the compiled dictionary list
int hash;
int length; int length;
char *p; char *p;


if (f_log != NULL) { if (f_log != NULL) {
#ifdef OUTPUT_FORMAT #ifdef OUTPUT_FORMAT
for (hash = 0; hash < N_HASH_DICT; hash++) {
for (int hash = 0; hash < N_HASH_DICT; hash++) {
fprintf(f_log, "%8d", hash_counts[hash]); fprintf(f_log, "%8d", hash_counts[hash]);
if ((hash & 7) == 7) if ((hash & 7) == 7)
fputc('\n', f_log); fputc('\n', f_log);
#endif #endif
} }


for (hash = 0; hash < N_HASH_DICT; hash++) {
for (int hash = 0; hash < N_HASH_DICT; hash++) {
p = hash_chains[hash]; p = hash_chains[hash];
hash_counts[hash] = (int)ftell(f_out); hash_counts[hash] = (int)ftell(f_out);


char *p; char *p;
int count = 0; int count = 0;
FILE *f_in; FILE *f_in;
char buf[200];
char fname[sizeof(path_home)+45]; char fname[sizeof(path_home)+45];
char dict_line[128]; char dict_line[128];




linenum = 0; linenum = 0;


char buf[200];
while (fgets(buf, sizeof(buf), f_in) != NULL) { while (fgets(buf, sizeof(buf), f_in) != NULL) {
linenum++; linenum++;


int len; int len;
char c; char c;
int c2, c3; int c2, c3;
int sxflags;
int value; int value;
int literal; int literal;
int hexdigit_input = 0; int hexdigit_input = 0;
rule_phonemes[len++] = ' '; rule_phonemes[len++] = ' ';
output = &rule_phonemes[len]; output = &rule_phonemes[len];
} }
sxflags = 0x808000; // to ensure non-zero bytes

int sxflags = 0x808000; // to ensure non-zero bytes


for (p = string, ix = 0;;) { for (p = string, ix = 0;;) {
literal = 0; literal = 0;
{ {
int ix; int ix;
unsigned char c; unsigned char c;
int wc;
char *p; char *p;
char *prule; char *prule;
int len;
int len_name;
int start;
int state = 2; int state = 2;
int finish = 0; int finish = 0;
char buf[80]; char buf[80];
char output[150]; char output[150];
int bad_phoneme;
char bad_phoneme_str[4];


buf[0] = 0; buf[0] = 0;
rule_cond[0] = 0; rule_cond[0] = 0;
return NULL; return NULL;
} }


int bad_phoneme;
char bad_phoneme_str[4];
EncodePhonemes(rule_phonemes, buf, &bad_phoneme); EncodePhonemes(rule_phonemes, buf, &bad_phoneme);
if (bad_phoneme != 0) { if (bad_phoneme != 0) {
bad_phoneme_str[utf8_out(bad_phoneme, bad_phoneme_str)] = 0; bad_phoneme_str[utf8_out(bad_phoneme, bad_phoneme_str)] = 0;
error_count++; error_count++;
} }
strcpy(output, buf); strcpy(output, buf);
len = strlen(buf)+1;
size_t len = strlen(buf)+1;


len_name = strlen(group_name);
size_t len_name = strlen(group_name);
if ((len_name > 0) && (memcmp(rule_match, group_name, len_name) != 0)) { if ((len_name > 0) && (memcmp(rule_match, group_name, len_name) != 0)) {
int wc;
utf8_in(&wc, rule_match); utf8_in(&wc, rule_match);
if ((group_name[0] == '9') && IsDigit(wc)) { if ((group_name[0] == '9') && IsDigit(wc)) {
// numeric group, rule_match starts with a digit, so OK // numeric group, rule_match starts with a digit, so OK
} }
} }
if (rule_pre[0] != 0) { if (rule_pre[0] != 0) {
start = 0;
int start = 0;
if (rule_pre[0] == RULE_SPACE) { if (rule_pre[0] == RULE_SPACE) {
// omit '_' at the beginning of the pre-string and imply it by using RULE_PRE_ATSTART // omit '_' at the beginning of the pre-string and imply it by using RULE_PRE_ATSTART
c = RULE_PRE_ATSTART; c = RULE_PRE_ATSTART;
static int __cdecl rgroup_sorter(RGROUP *a, RGROUP *b) static int __cdecl rgroup_sorter(RGROUP *a, RGROUP *b)
{ {
// Sort long names before short names // Sort long names before short names
int ix;
ix = strlen(b->name) - strlen(a->name);
int ix = strlen(b->name) - strlen(a->name);
if (ix != 0) return ix; if (ix != 0) return ix;
ix = strcmp(a->name, b->name); ix = strcmp(a->name, b->name);
if (ix != 0) return ix; if (ix != 0) return ix;
#ifdef OUTPUT_FORMAT #ifdef OUTPUT_FORMAT
static void print_rule_group(FILE *f_out, int n_rules, char **rules, char *name) static void print_rule_group(FILE *f_out, int n_rules, char **rules, char *name)
{ {
int rule;
int ix;
unsigned char c; unsigned char c;
int len1; int len1;
int len2; int len2;
int spaces;
char *p; char *p;
char *pout; char *pout;
int condition; int condition;


fprintf(f_out, "\n$group %s\n", name); fprintf(f_out, "\n$group %s\n", name);


for (rule = 0; rule < n_rules; rule++) {
for (int rule = 0; rule < n_rules; rule++) {
p = rules[rule]; p = rules[rule];
len1 = strlen(p) + 1; len1 = strlen(p) + 1;
p = &p[len1]; p = &p[len1];
condition = 0; condition = 0;


pout = rule_match; pout = rule_match;
for (ix = 0; ix < len2; ix++) {
for (int ix = 0; ix < len2; ix++) {
switch (c = p[ix]) switch (c = p[ix])
{ {
case RULE_PRE: case RULE_PRE:
} }
*pout = 0; *pout = 0;


spaces = 12;
int spaces = 12;
if (condition > 0) { if (condition > 0) {
sprintf(buf, "?%d ", condition); sprintf(buf, "?%d ", condition);
spaces -= strlen(buf); spaces -= strlen(buf);


if (rule_pre[0] != 0) { if (rule_pre[0] != 0) {
p = buf; p = buf;
for (ix = strlen(rule_pre)-1; ix >= 0; ix--)
for (int ix = strlen(rule_pre)-1; ix >= 0; ix--)
*p++ = rule_pre[ix]; *p++ = rule_pre[ix];
sprintf(p, ") "); sprintf(p, ") ");
spaces -= strlen(buf); spaces -= strlen(buf);
for (ix = 0; ix < spaces; ix++)
for (int ix = 0; ix < spaces; ix++)
fputc(' ', f_out); fputc(' ', f_out);
fprintf(f_out, "%s", buf); fprintf(f_out, "%s", buf);
spaces = 0; spaces = 0;
} }


for (ix = 0; ix < spaces; ix++)
for (int ix = 0; ix < spaces; ix++)
fputc(' ', f_out); fputc(' ', f_out);


spaces = 14; spaces = 14;
fprintf(f_out, "%s", buf); fprintf(f_out, "%s", buf);
spaces -= strlen(buf); spaces -= strlen(buf);


for (ix = 0; ix < spaces; ix++)
for (int ix = 0; ix < spaces; ix++)
fputc(' ', f_out); fputc(' ', f_out);
DecodePhonemes(rules[rule], buf); DecodePhonemes(rules[rule], buf);
fprintf(f_out, "%s\n", buf); // phonemes fprintf(f_out, "%s\n", buf); // phonemes


static void output_rule_group(FILE *f_out, int n_rules, char **rules, char *name) static void output_rule_group(FILE *f_out, int n_rules, char **rules, char *name)
{ {
int ix;
int len1; int len1;
int len2; int len2;
int len_name;
char *p; char *p;
char *p2, *p3; char *p2, *p3;
const char *common; const char *common;
short nextchar_count[256]; short nextchar_count[256];
memset(nextchar_count, 0, sizeof(nextchar_count)); memset(nextchar_count, 0, sizeof(nextchar_count));


len_name = strlen(name);
int len_name = strlen(name);


#ifdef OUTPUT_FORMAT #ifdef OUTPUT_FORMAT
print_rule_group(f_log, n_rules, rules, name); print_rule_group(f_log, n_rules, rules, name);
if (strcmp(name, "9") == 0) if (strcmp(name, "9") == 0)
len_name = 0; // don't remove characters from numeric match strings len_name = 0; // don't remove characters from numeric match strings


for (ix = 0; ix < n_rules; ix++) {
for (int ix = 0; ix < n_rules; ix++) {
p = rules[ix]; p = rules[ix];
len1 = strlen(p) + 1; // phoneme string len1 = strlen(p) + 1; // phoneme string
p3 = &p[len1]; p3 = &p[len1];
} }


#ifdef LIST_GROUP_INFO #ifdef LIST_GROUP_INFO
for (ix = 32; ix < 256; ix++) {
for (int ix = 32; ix < 256; ix++) {
if (nextchar_count[ix] > 30) if (nextchar_count[ix] > 30)
printf("Group %s %c %d\n", name, ix, nextchar_count[ix]); printf("Group %s %c %d\n", name, ix, nextchar_count[ix]);
} }
{ {
char *p; char *p;
char *p_start; char *p_start;
int group;
int ix;
int n_items;
int length; int length;
int max_length = 0; int max_length = 0;


return 1; return 1;
} }


group = atoi(&p[0]);
int group = atoi(&p[0]);
if (group >= N_LETTER_GROUPS) { if (group >= N_LETTER_GROUPS) {
fprintf(f_log, "%5d: lettergroup out of range (01-%.2d)\n", linenum, N_LETTER_GROUPS-1); fprintf(f_log, "%5d: lettergroup out of range (01-%.2d)\n", linenum, N_LETTER_GROUPS-1);
error_count++; error_count++;
} }
letterGroupsDefined[group] = 1; letterGroupsDefined[group] = 1;


n_items = 0;
int n_items = 0;
while (n_items < N_LETTERGP_ITEMS) { while (n_items < N_LETTERGP_ITEMS) {
while (isspace2(*p)) p++; while (isspace2(*p)) p++;
if (*p == 0) if (*p == 0)


// write out the items, longest first // write out the items, longest first
while (max_length > 1) { while (max_length > 1) {
for (ix = 0; ix < n_items; ix++) {
for (int ix = 0; ix < n_items; ix++) {
if (item_length[ix] == max_length) if (item_length[ix] == max_length)
fwrite(items[ix], 1, max_length, f_out); fwrite(items[ix], 1, max_length, f_out);
} }


FILE *f_in; FILE *f_in;
FILE *f_out; FILE *f_out;
int offset_rules = 0;
int value;
char fname_in[sizeof(path_home)+45]; char fname_in[sizeof(path_home)+45];
char fname_out[sizeof(path_home)+15]; char fname_out[sizeof(path_home)+15];
char fname_temp[sizeof(path_home)+15]; char fname_temp[sizeof(path_home)+15];
} }
sprintf(fname_temp, "%s%ctemp", path_home, PATHSEP); sprintf(fname_temp, "%s%ctemp", path_home, PATHSEP);


value = N_HASH_DICT;
int value = N_HASH_DICT;
int offset_rules = 0;
Write4Bytes(f_out, value); Write4Bytes(f_out, value);
Write4Bytes(f_out, offset_rules); Write4Bytes(f_out, offset_rules);



+ 1
- 2
src/libespeak-ng/compilembrola.c View File

static unsigned int StringToWord(const char *string) static unsigned int StringToWord(const char *string)
{ {
// Pack 4 characters into a word // Pack 4 characters into a word
int ix;
unsigned char c; unsigned char c;
unsigned int word; unsigned int word;


return 0; return 0;


word = 0; word = 0;
for (ix = 0; ix < 4; ix++) {
for (int ix = 0; ix < 4; ix++) {
if (string[ix] == 0) break; if (string[ix] == 0) break;
c = string[ix]; c = string[ix];
word |= (c << (ix*8)); word |= (c << (ix*8));

+ 29
- 57
src/libespeak-ng/dictionary.c View File

{ {
// reverse the order of bytes from little-endian to big-endian // reverse the order of bytes from little-endian to big-endian
#ifdef ARCH_BIG #ifdef ARCH_BIG
int ix;
int word2 = 0; int word2 = 0;


for (ix = 0; ix <= 24; ix += 8) {
for (int ix = 0; ix <= 24; ix += 8) {
word2 = word2 << 8; word2 = word2 << 8;
word2 |= (word >> ix) & 0xff; word2 |= (word >> ix) & 0xff;
} }


int LoadDictionary(Translator *tr, const char *name, int no_error) int LoadDictionary(Translator *tr, const char *name, int no_error)
{ {
int hash;
char *p; char *p;
int *pw; int *pw;
int length;
FILE *f; FILE *f;
unsigned int size;
char fname[sizeof(path_home)+20]; char fname[sizeof(path_home)+20];


strcpy(dictionary_name, name); // currently loaded dictionary name strcpy(dictionary_name, name); // currently loaded dictionary name
// bytes 0-3: offset to rules data // bytes 0-3: offset to rules data
// bytes 4-7: number of hash table entries // bytes 4-7: number of hash table entries
sprintf(fname, "%s%c%s_dict", path_home, PATHSEP, name); sprintf(fname, "%s%c%s_dict", path_home, PATHSEP, name);
size = GetFileLength(fname);
unsigned int size = GetFileLength(fname);


if (tr->data_dictlist != NULL) { if (tr->data_dictlist != NULL) {
Free(tr->data_dictlist); Free(tr->data_dictlist);
fclose(f); fclose(f);


pw = (int *)(tr->data_dictlist); pw = (int *)(tr->data_dictlist);
length = Reverse4Bytes(pw[1]);
int length = Reverse4Bytes(pw[1]);


if (size <= (N_HASH_DICT + sizeof(int)*2)) { if (size <= (N_HASH_DICT + sizeof(int)*2)) {
fprintf(stderr, "Empty _dict file: '%s\n", fname); fprintf(stderr, "Empty _dict file: '%s\n", fname);
// set up hash table for data_dictlist // set up hash table for data_dictlist
p = &(tr->data_dictlist[8]); p = &(tr->data_dictlist[8]);


for (hash = 0; hash < N_HASH_DICT; hash++) {
for (int hash = 0; hash < N_HASH_DICT; hash++) {
tr->dict_hashtab[hash] = p; tr->dict_hashtab[hash] = p;
while ((length = *p) != 0) while ((length = *p) != 0)
p += length; p += length;
*/ */
const char *EncodePhonemes(const char *p, char *outptr, int *bad_phoneme) const char *EncodePhonemes(const char *p, char *outptr, int *bad_phoneme)
{ {
int ix;
unsigned char c; unsigned char c;
int count; // num. of matching characters int count; // num. of matching characters
int max; // highest num. of matching found so far int max; // highest num. of matching found so far
max = -1; max = -1;
max_ph = 0; max_ph = 0;


for (ix = 1; ix < n_phoneme_tab; ix++) {
for (int ix = 1; ix < n_phoneme_tab; ix++) {
if (phoneme_tab[ix] == NULL) if (phoneme_tab[ix] == NULL)
continue; continue;
if (phoneme_tab[ix]->type == phINVALID) if (phoneme_tab[ix]->type == phINVALID)
char *WritePhMnemonic(char *phon_out, PHONEME_TAB *ph, PHONEME_LIST *plist, int use_ipa, int *flags) char *WritePhMnemonic(char *phon_out, PHONEME_TAB *ph, PHONEME_LIST *plist, int use_ipa, int *flags)
{ {
int c; int c;
int mnem;
int len;
int first;
int ix = 0; int ix = 0;
char *p; char *p;
PHONEME_DATA phdata; PHONEME_DATA phdata;
p++; p++;
} }


len = strlen(p);
int len = strlen(p);
if (len > 0) { if (len > 0) {
strcpy(phon_out, p); strcpy(phon_out, p);
phon_out += len; phon_out += len;
} }
} }


first = 1;
for (mnem = ph->mnemonic; (c = mnem & 0xff) != 0; mnem = mnem >> 8) {
int first = 1;
for (int mnem = ph->mnemonic; (c = mnem & 0xff) != 0; mnem = mnem >> 8) {
if ((c == '/') && (option_phoneme_variants == 0)) if ((c == '/') && (option_phoneme_variants == 0))
break; // discard phoneme variant indicator break; // discard phoneme variant indicator




*/ */


int ix;
unsigned int len; unsigned int len;
int phon_out_ix = 0; int phon_out_ix = 0;
int stress; int stress;
use_tie = 0; use_tie = 0;
} }


for (ix = 1; ix < (n_phoneme_list-2); ix++) {
for (int ix = 1; ix < (n_phoneme_list-2); ix++) {
buf = phon_buf; buf = phon_buf;


plist = &phoneme_list[ix]; plist = &phoneme_list[ix];


static int Unpronouncable2(Translator *tr, char *word) static int Unpronouncable2(Translator *tr, char *word)
{ {
int c;
int end_flags;
char ph_buf[N_WORD_PHONEMES]; char ph_buf[N_WORD_PHONEMES];


ph_buf[0] = 0; ph_buf[0] = 0;
c = word[-1];
int c = word[-1];
word[-1] = ' '; // ensure there is a space before the "word" word[-1] = ' '; // ensure there is a space before the "word"
end_flags = TranslateRules(tr, word, ph_buf, sizeof(ph_buf), NULL, FLAG_UNPRON_TEST, NULL);
int end_flags = TranslateRules(tr, word, ph_buf, sizeof(ph_buf), NULL, FLAG_UNPRON_TEST, NULL);
word[-1] = c; word[-1] = c;
if ((end_flags == 0) || (end_flags & SUFX_UNPRON)) if ((end_flags == 0) || (end_flags & SUFX_UNPRON))
return 1; return 1;
int c; int c;
int c1 = 0; int c1 = 0;
int vowel_posn = 9; int vowel_posn = 9;
int index;
int count;
ALPHABET *alphabet; ALPHABET *alphabet;


utf8_in(&c, word); utf8_in(&c, word);
if (((c = *word) == ' ') || (c == 0) || (c == '\'')) if (((c = *word) == ' ') || (c == 0) || (c == '\''))
return 0; return 0;


index = 0;
count = 0;
int index = 0;
int count = 0;
for (;;) { for (;;) {
index += utf8_in(&c, &word[index]); index += utf8_in(&c, &word[index]);
if ((c == 0) || (c == ' ')) if ((c == 0) || (c == ' '))
{ {
int ix; int ix;
unsigned char *p; unsigned char *p;
int max_stress;
int vowel_count; // num of vowels + 1 int vowel_count; // num of vowels + 1
int stressed_syllable = 0; // position of stressed syllable int stressed_syllable = 0; // position of stressed syllable
unsigned char phonetic[N_WORD_PHONEMES]; unsigned char phonetic[N_WORD_PHONEMES];
signed char vowel_stress[N_WORD_PHONEMES/2]; signed char vowel_stress[N_WORD_PHONEMES/2];


strcpy((char *)phonetic, word); strcpy((char *)phonetic, word);
max_stress = GetVowelStress(tr, phonetic, vowel_stress, &vowel_count, &stressed_syllable, 0);
int max_stress = GetVowelStress(tr, phonetic, vowel_stress, &vowel_count, &stressed_syllable, 0);


if (new_stress >= 4) { if (new_stress >= 4) {
// promote to primary stress // promote to primary stress
int mnem; int mnem;
int opt_length; int opt_length;
int done; int done;
int stressflags;
int dflags = 0; int dflags = 0;
int first_primary; int first_primary;
int long_vowel; int long_vowel;
3 secondary stress 3 secondary stress
4 main stress */ 4 main stress */


stressflags = tr->langopts.stress_flags;
int stressflags = tr->langopts.stress_flags;


if (dictionary_flags != NULL) if (dictionary_flags != NULL)
dflags = dictionary_flags[0]; dflags = dictionary_flags[0];
{ {
// apply after the translation is complete // apply after the translation is complete


int ix;
int len;
char *p; char *p;


len = strlen(phonemes);
int len = strlen(phonemes);


if (tr->langopts.param[LOPT_ALT] & 2) { if (tr->langopts.param[LOPT_ALT] & 2) {
for (ix = 0; ix < (len-1); ix++) {
for (int ix = 0; ix < (len-1); ix++) {
if (phonemes[ix] == phonSTRESS_P) { if (phonemes[ix] == phonSTRESS_P) {
p = &phonemes[ix+1]; p = &phonemes[ix+1];
if ((dict_flags & FLAG_ALT2_TRANS) != 0) { if ((dict_flags & FLAG_ALT2_TRANS) != 0) {
int c; int c;
int c2; int c2;
int ix; int ix;
int offset;
int min;
int max;
const char *map; const char *map;
char *p = text; char *p = text;
char *p2; char *p2;
int all_alpha = 1; int all_alpha = 1;
int bits; int bits;
int acc; int acc;
int pairs_start;
const short *pairs_list; const short *pairs_list;
int bufix;
char buf[N_WORD_BYTES+1]; char buf[N_WORD_BYTES+1];


offset = tr->transpose_min - 1;
min = tr->transpose_min;
max = tr->transpose_max;
int offset = tr->transpose_min - 1;
int min = tr->transpose_min;
int max = tr->transpose_max;
map = tr->transpose_map; map = tr->transpose_map;


pairs_start = max - min + 2;
int pairs_start = max - min + 2;


bufix = 0;
int bufix = 0;
do { do {
p += utf8_in(&c, p); p += utf8_in(&c, p);
if (c != 0) { if (c != 0) {
{ {
char *p; char *p;
char *next; char *next;
int hash;
int phoneme_len; int phoneme_len;
int wlen; int wlen;
unsigned char flag; unsigned char flag;
const char *word_end; const char *word_end;
const char *word1; const char *word1;
int wflags = 0; int wflags = 0;
int lookup_symbol;
char word_buf[N_WORD_BYTES+1]; char word_buf[N_WORD_BYTES+1];
char dict_flags_buf[80]; char dict_flags_buf[80];


if (wtab != NULL) if (wtab != NULL)
wflags = wtab->flags; wflags = wtab->flags;


lookup_symbol = flags[1] & FLAG_LOOKUP_SYMBOL;
int lookup_symbol = flags[1] & FLAG_LOOKUP_SYMBOL;
word1 = word; word1 = word;
if (tr->transpose_min > 0) { if (tr->transpose_min > 0) {
strncpy0(word_buf, word, N_WORD_BYTES); strncpy0(word_buf, word, N_WORD_BYTES);
} else } else
wlen = strlen(word); wlen = strlen(word);


hash = HashDictionary(word);
int hash = HashDictionary(word);
p = tr->dict_hashtab[hash]; p = tr->dict_hashtab[hash];


if (p == NULL) { if (p == NULL) {
*/ */
int LookupDictList(Translator *tr, char **wordptr, char *ph_out, unsigned int *flags, int end_flags, WORD_TAB *wtab) int LookupDictList(Translator *tr, char **wordptr, char *ph_out, unsigned int *flags, int end_flags, WORD_TAB *wtab)
{ {
int length;
const char *found; const char *found;
const char *word1; const char *word1;
const char *word2; const char *word2;
char word[N_WORD_BYTES]; char word[N_WORD_BYTES];
static char word_replacement[N_WORD_BYTES]; static char word_replacement[N_WORD_BYTES];


length = 0;
int length = 0;
word2 = word1 = *wordptr; word2 = word1 = *wordptr;


while ((word2[nbytes = utf8_nbytes(word2)] == ' ') && (word2[nbytes+1] == '.')) { while ((word2[nbytes = utf8_nbytes(word2)] == ' ') && (word2[nbytes+1] == '.')) {


int flags0; int flags0;
unsigned int flags[2]; unsigned int flags[2];
int say_as;
char *word1 = (char *)word; char *word1 = (char *)word;
char text[80]; char text[80];


flags0 = flags[0]; flags0 = flags[0];


if (flags[0] & FLAG_TEXTMODE) { if (flags[0] & FLAG_TEXTMODE) {
say_as = option_sayas;
int say_as = option_sayas;
option_sayas = 0; // don't speak replacement word as letter names option_sayas = 0; // don't speak replacement word as letter names
text[0] = 0; text[0] = 0;
strncpy0(&text[1], word1, sizeof(text)); strncpy0(&text[1], word1, sizeof(text));
that were done when the suffix was added to the original word. that were done when the suffix was added to the original word.
*/ */


int i;
char *word_end; char *word_end;
int len_ending;
int end_flags;
const char *p; const char *p;
int len; int len;
char ending[50]; char ending[50];
if (*word_end == REPLACED_E) if (*word_end == REPLACED_E)
*word_end = 'e'; *word_end = 'e';
} }
i = word_end - word;
int i = word_end - word;


if (word_copy != NULL) { if (word_copy != NULL) {
memcpy(word_copy, word, i); memcpy(word_copy, word, i);
} }


// look for multibyte characters to increase the number of bytes to remove // look for multibyte characters to increase the number of bytes to remove
int len_ending;
for (len_ending = i = (end_type & 0x3f); i > 0; i--) { // num.of characters of the suffix for (len_ending = i = (end_type & 0x3f); i > 0; i--) { // num.of characters of the suffix
word_end--; word_end--;
while ((*word_end & 0xc0) == 0x80) { while ((*word_end & 0xc0) == 0x80) {
ending[i] = 0; ending[i] = 0;
word_end--; // now pointing at last character of stem word_end--; // now pointing at last character of stem


end_flags = (end_type & 0xfff0) | FLAG_SUFX;
int end_flags = (end_type & 0xfff0) | FLAG_SUFX;


/* add an 'e' to the stem if appropriate, /* add an 'e' to the stem if appropriate,
if stem ends in vowel+consonant if stem ends in vowel+consonant

+ 3
- 5
src/libespeak-ng/ieee80.c View File

double ConvertFromIeeeExtended(unsigned char *bytes /* LCN */) double ConvertFromIeeeExtended(unsigned char *bytes /* LCN */)
{ {
double f; double f;
int expon;
unsigned long hiMant, loMant;
expon = ((bytes[0] & 0x7F) << 8) | (bytes[1] & 0xFF);
hiMant = ((unsigned long)(bytes[2] & 0xFF) << 24)
int expon = ((bytes[0] & 0x7F) << 8) | (bytes[1] & 0xFF);
int hiMant = ((unsigned long)(bytes[2] & 0xFF) << 24)
| ((unsigned long)(bytes[3] & 0xFF) << 16) | ((unsigned long)(bytes[3] & 0xFF) << 16)
| ((unsigned long)(bytes[4] & 0xFF) << 8) | ((unsigned long)(bytes[4] & 0xFF) << 8)
| ((unsigned long)(bytes[5] & 0xFF)); | ((unsigned long)(bytes[5] & 0xFF));
loMant = ((unsigned long)(bytes[6] & 0xFF) << 24)
int loMant = ((unsigned long)(bytes[6] & 0xFF) << 24)
| ((unsigned long)(bytes[7] & 0xFF) << 16) | ((unsigned long)(bytes[7] & 0xFF) << 16)
| ((unsigned long)(bytes[8] & 0xFF) << 8) | ((unsigned long)(bytes[8] & 0xFF) << 8)
| ((unsigned long)(bytes[9] & 0xFF)); | ((unsigned long)(bytes[9] & 0xFF));

+ 25
- 43
src/libespeak-ng/intonation.c View File



static void count_pitch_vowels(int start, int end, int clause_end) static void count_pitch_vowels(int start, int end, int clause_end)
{ {
int ix;
int stress; int stress;
int max_stress = 0; int max_stress = 0;
int max_stress_posn = 0; // last syllable ot the highest stress int max_stress_posn = 0; // last syllable ot the highest stress
number_tail = 0; // number between tonic syllable and next primary number_tail = 0; // number between tonic syllable and next primary
last_primary = -1; last_primary = -1;


for (ix = start; ix < end; ix++) {
for (int ix = start; ix < end; ix++) {
stress = syllable_tab[ix].stress; // marked stress level stress = syllable_tab[ix].stress; // marked stress level


if (stress >= max_stress) { if (stress >= max_stress) {
// Set the pitch of a vowel in syllable_tab // Set the pitch of a vowel in syllable_tab
static void set_pitch(SYLLABLE *syl, int base, int drop) static void set_pitch(SYLLABLE *syl, int base, int drop)
{ {
int pitch1, pitch2;
int flags = 0; int flags = 0;


if (base < 0) base = 0; if (base < 0) base = 0;


pitch2 = base;
int pitch2 = base;


if (drop < 0) { if (drop < 0) {
flags = SYL_RISE; flags = SYL_RISE;
drop = -drop; drop = -drop;
} }


pitch1 = pitch2 + drop;
int pitch1 = pitch2 + drop;
if (pitch1 < 0) if (pitch1 < 0)
pitch1 = 0; pitch1 = 0;




static int CountUnstressed(int start, int end, int limit) static int CountUnstressed(int start, int end, int limit)
{ {
int ix;

int ix;
for (ix = start; ix <= end; ix++) { for (ix = start; ix <= end; ix++) {
if (syllable_tab[ix].stress >= limit) if (syllable_tab[ix].stress >= limit)
break; break;
int increment = 0; int increment = 0;
int n_steps = 0; int n_steps = 0;
int stage; // onset, head, last int stage; // onset, head, last
int initial;
int overflow_ix = 0; int overflow_ix = 0;
int pitch_range;
int pitch_range_abs;
int *drops; int *drops;
int n_unstressed = 0; int n_unstressed = 0;
int unstressed_ix = 0; int unstressed_ix = 0;
int head_final = end_ix; int head_final = end_ix;
int secondary = 2; int secondary = 2;


pitch_range = (tune->head_end - tune->head_start) << 8;
pitch_range_abs = abs(pitch_range);
int pitch_range = (tune->head_end - tune->head_start) << 8;
int pitch_range_abs = abs(pitch_range);
drops = drops_0; // this should be controled by tune->head_drops drops = drops_0; // this should be controled by tune->head_drops
initial = 1;
int initial = 1;


stage = 0; stage = 0;
if (tune->onset == 255) if (tune->onset == 255)
int initial; int initial;
int overflow = 0; int overflow = 0;
int n_overflow; int n_overflow;
int pitch_range;
int pitch_range_abs;
int *drops; int *drops;
signed char *overflow_tab; signed char *overflow_tab;
SYLLABLE *syl; SYLLABLE *syl;
static signed char continue_tab[5] = { -26, 32, 20, 8, 0 }; static signed char continue_tab[5] = { -26, 32, 20, 8, 0 };


drops = th->body_drops; drops = th->body_drops;
pitch_range = (th->body_end - th->body_start) << 8;
pitch_range_abs = abs(pitch_range);
int pitch_range = (th->body_end - th->body_start) << 8;
int pitch_range_abs = abs(pitch_range);


if (continuing) { if (continuing) {
initial = 0; initial = 0;
// Set a linear pitch change over a number of syllables. // Set a linear pitch change over a number of syllables.
// Used for pre-head, unstressed syllables in the body, and the tail // Used for pre-head, unstressed syllables in the body, and the tail


int ix;
int stress; int stress;
int pitch;
int increment;
int n_increments;
int drop; int drop;
SYLLABLE *syl; SYLLABLE *syl;


increment = (end_pitch - start_pitch) << 8;
n_increments = end_ix - start_ix;
int increment = (end_pitch - start_pitch) << 8;
int n_increments = end_ix - start_ix;


if (n_increments <= 0) if (n_increments <= 0)
return; return;
if (n_increments > 1) if (n_increments > 1)
increment = increment / n_increments; increment = increment / n_increments;


pitch = start_pitch << 8;
int pitch = start_pitch << 8;


for (ix = start_ix; ix < end_ix; ix++) {
for (int ix = start_ix; ix < end_ix; ix++) {
syl = &syllable_tab[ix]; syl = &syllable_tab[ix];
stress = syl->stress; stress = syl->stress;


// Calculate pitch values for the vowels in this tone group // Calculate pitch values for the vowels in this tone group
static int calc_pitches2(int start, int end, int tune_number) static int calc_pitches2(int start, int end, int tune_number)
{ {
int ix;
TUNE *tune; TUNE *tune;
int drop;


tune = &tunes[tune_number]; tune = &tunes[tune_number];
ix = start;
int ix = start;


// vowels before the first primary stress // vowels before the first primary stress




// tonic syllable // tonic syllable


int drop;
if (number_tail == 0) { if (number_tail == 0) {
tone_pitch_env = tune->nucleus0_env; tone_pitch_env = tune->nucleus0_env;
drop = tune->nucleus0_max - tune->nucleus0_min; drop = tune->nucleus0_max - tune->nucleus0_min;
// Calculate pitch values for the vowels in this tone group // Calculate pitch values for the vowels in this tone group
static int calc_pitches(int control, int start, int end, int tune_number) static int calc_pitches(int control, int start, int end, int tune_number)
{ {
int ix;
TONE_HEAD *th; TONE_HEAD *th;
TONE_NUCLEUS *tn; TONE_NUCLEUS *tn;
int drop;
int continuing = 0; int continuing = 0;


if (control == 0) if (control == 0)


th = &tone_head_table[tune_number]; th = &tone_head_table[tune_number];
tn = &tone_nucleus_table[tune_number]; tn = &tone_nucleus_table[tune_number];
ix = start;
int ix = start;


// vowels before the first primary stress // vowels before the first primary stress


if (tn->flags & T_EMPH) if (tn->flags & T_EMPH)
syllable_tab[ix].flags |= SYL_EMPHASIS; syllable_tab[ix].flags |= SYL_EMPHASIS;


int drop;
if (number_tail == 0) { if (number_tail == 0) {
tone_pitch_env = tn->pitch_env0; tone_pitch_env = tn->pitch_env0;
drop = tn->tonic_max0 - tn->tonic_min0; drop = tn->tonic_max0 - tn->tonic_min0;
// clause_tone: 0=. 1=, 2=?, 3=! 4=none // clause_tone: 0=. 1=, 2=?, 3=! 4=none


PHONEME_LIST *p; PHONEME_LIST *p;
int ix;
int count_stressed = 0; int count_stressed = 0;
int final_stressed = 0; int final_stressed = 0;




// count number of stressed syllables // count number of stressed syllables
p = &phoneme_list[0]; p = &phoneme_list[0];
for (ix = 0; ix < n_phoneme_list; ix++, p++) {
for (int ix = 0; ix < n_phoneme_list; ix++, p++) {
if ((p->type == phVOWEL) && (p->stresslevel >= 4)) { if ((p->type == phVOWEL) && (p->stresslevel >= 4)) {
if (count_stressed == 0) if (count_stressed == 0)
final_stressed = ix; final_stressed = ix;
prev_tph = prevw_tph = phoneme_tab[phonPAUSE]; prev_tph = prevw_tph = phoneme_tab[phonPAUSE];


// perform tone sandhi // perform tone sandhi
for (ix = 0; ix < n_phoneme_list; ix++, p++) {
for (int ix = 0; ix < n_phoneme_list; ix++, p++) {
if ((p->type == phPAUSE) && (p->ph->std_length > 50)) { if ((p->type == phPAUSE) && (p->ph->std_length > 50)) {
pause = 1; // there is a pause since the previous vowel pause = 1; // there is a pause since the previous vowel
prevw_tph = phoneme_tab[phonPAUSE]; // forget previous tone prevw_tph = phoneme_tab[phonPAUSE]; // forget previous tone


// convert tone numbers to pitch // convert tone numbers to pitch
p = &phoneme_list[0]; p = &phoneme_list[0];
for (ix = 0; ix < n_phoneme_list; ix++, p++) {
for (int ix = 0; ix < n_phoneme_list; ix++, p++) {
if (p->synthflags & SFLAG_SYLLABLE) { if (p->synthflags & SFLAG_SYLLABLE) {
tone_ph = p->tone_ph; tone_ph = p->tone_ph;


int ix; int ix;
int x; int x;
int st_ix; int st_ix;
int n_st;
int option; int option;
int group_tone; int group_tone;
int group_tone_comma; int group_tone_comma;
int ph_start = 0; int ph_start = 0;
int st_start;
int st_clause_end; int st_clause_end;
int count; int count;
int n_primary;
int count_primary;
PHONEME_TAB *ph; PHONEME_TAB *ph;
int ph_end = n_phoneme_list; int ph_end = n_phoneme_list;


SYLLABLE syllable_tab2[N_PHONEME_LIST]; SYLLABLE syllable_tab2[N_PHONEME_LIST];


syllable_tab = syllable_tab2; // don't use permanent storage. it's only needed during the call of CalcPitches() syllable_tab = syllable_tab2; // don't use permanent storage. it's only needed during the call of CalcPitches()
n_st = 0;
n_primary = 0;
int n_st = 0;
int n_primary = 0;

for (ix = 0; ix < (n_phoneme_list-1); ix++) { for (ix = 0; ix < (n_phoneme_list-1); ix++) {
p = &phoneme_list[ix]; p = &phoneme_list[ix];
if (p->synthflags & SFLAG_SYLLABLE) { if (p->synthflags & SFLAG_SYLLABLE) {
else else
no_tonic = 0; no_tonic = 0;


st_start = 0;
count_primary = 0;
int st_start = 0;
int count_primary = 0;
for (st_ix = 0; st_ix < n_st; st_ix++) { for (st_ix = 0; st_ix < n_st; st_ix++) {
syl = &syllable_tab[st_ix]; syl = &syllable_tab[st_ix];



+ 21
- 45
src/libespeak-ng/klatt.c View File



static double resonator(resonator_ptr r, double input) static double resonator(resonator_ptr r, double input)
{ {
double x;

x = (double)((double)r->a * (double)input + (double)r->b * (double)r->p1 + (double)r->c * (double)r->p2);
double x = (double)((double)r->a * (double)input + (double)r->b * (double)r->p1 + (double)r->c * (double)r->p2);
r->p2 = (double)r->p1; r->p2 = (double)r->p1;
r->p1 = (double)x; r->p1 = (double)x;




static double resonator2(resonator_ptr r, double input) static double resonator2(resonator_ptr r, double input)
{ {
double x;

x = (double)((double)r->a * (double)input + (double)r->b * (double)r->p1 + (double)r->c * (double)r->p2);
double x = (double)((double)r->a * (double)input + (double)r->b * (double)r->p1 + (double)r->c * (double)r->p2);
r->p2 = (double)r->p1; r->p2 = (double)r->p1;
r->p1 = (double)x; r->p1 = (double)x;


static void flutter(klatt_frame_ptr frame) static void flutter(klatt_frame_ptr frame)
{ {
static int time_count; static int time_count;
double delta_f0;
double fla, flb, flc, fld, fle;

fla = (double)kt_globals.f0_flutter / 50;
flb = (double)kt_globals.original_f0 / 100;
flc = sin(PI*12.7*time_count); // because we are calling flutter() more frequently, every 2.9mS
fld = sin(PI*7.1*time_count);
fle = sin(PI*4.7*time_count);
delta_f0 = fla * flb * (flc + fld + fle) * 10;
double fla = (double)kt_globals.f0_flutter / 50;
double flb = (double)kt_globals.original_f0 / 100;
double flc = sin(PI*12.7*time_count); // because we are calling flutter() more frequently, every 2.9mS
double fld = sin(PI*7.1*time_count);
double fle = sin(PI*4.7*time_count);
double delta_f0 = fla * flb * (flc + fld + fle) * 10;
frame->F0hz10 = frame->F0hz10 + (long)delta_f0; frame->F0hz10 = frame->F0hz10 + (long)delta_f0;
time_count++; time_count++;
} }


static double sampled_source(int source_num) static double sampled_source(int source_num)
{ {
int itemp;
double ftemp;
double result; double result;
double diff_value;
int current_value;
int next_value;
double temp_diff;
short *samples; short *samples;


if (source_num == 0) { if (source_num == 0) {
} }


if (kt_globals.T0 != 0) { if (kt_globals.T0 != 0) {
ftemp = (double)kt_globals.nper;
double ftemp = (double)kt_globals.nper;
ftemp = ftemp / kt_globals.T0; ftemp = ftemp / kt_globals.T0;
ftemp = ftemp * kt_globals.num_samples; ftemp = ftemp * kt_globals.num_samples;
itemp = (int)ftemp;
int itemp = (int)ftemp;


temp_diff = ftemp - (double)itemp;
double temp_diff = ftemp - (double)itemp;


current_value = samples[itemp];
next_value = samples[itemp+1];
int current_value = samples[itemp];
int next_value = samples[itemp+1];


diff_value = (double)next_value - (double)current_value;
double diff_value = (double)next_value - (double)current_value;
diff_value = diff_value * temp_diff; diff_value = diff_value * temp_diff;


result = samples[itemp] + diff_value; result = samples[itemp] + diff_value;


static double natural_source() static double natural_source()
{ {
double lgtemp;
static double vwave; static double vwave;


if (kt_globals.nper < kt_globals.nopen) { if (kt_globals.nper < kt_globals.nopen) {
kt_globals.pulse_shape_a -= kt_globals.pulse_shape_b; kt_globals.pulse_shape_a -= kt_globals.pulse_shape_b;
vwave += kt_globals.pulse_shape_a; vwave += kt_globals.pulse_shape_a;
lgtemp = vwave * 0.028;
double lgtemp = vwave * 0.028;


return lgtemp; return lgtemp;
} }


static void setabc(long int f, long int bw, resonator_ptr rp) static void setabc(long int f, long int bw, resonator_ptr rp)
{ {
double r;
double arg;

// Let r = exp(-pi bw t) // Let r = exp(-pi bw t)
arg = kt_globals.minus_pi_t * bw;
r = exp(arg);
double arg = kt_globals.minus_pi_t * bw;
double r = exp(arg);


// Let c = -r**2 // Let c = -r**2
rp->c = -(r * r); rp->c = -(r * r);


static void setzeroabc(long int f, long int bw, resonator_ptr rp) static void setzeroabc(long int f, long int bw, resonator_ptr rp)
{ {
double r;
double arg;

f = -f; f = -f;


// First compute ordinary resonator coefficients // First compute ordinary resonator coefficients
// Let r = exp(-pi bw t) // Let r = exp(-pi bw t)
arg = kt_globals.minus_pi_t * bw;
r = exp(arg);
double arg = kt_globals.minus_pi_t * bw;
double r = exp(arg);


// Let c = -r**2 // Let c = -r**2
rp->c = -(r * r); rp->c = -(r * r);


static double gen_noise(double noise) static double gen_noise(double noise)
{ {
long temp;
static double nlast; static double nlast;


temp = (long)getrandom(-8191, 8191);
long temp = (long)getrandom(-8191, 8191);
kt_globals.nrand = (long)temp; kt_globals.nrand = (long)temp;


noise = kt_globals.nrand + (0.75 * nlast); noise = kt_globals.nrand + (0.75 * nlast);


void KlattInit() void KlattInit()
{ {

static short formant_hz[10] = { 280, 688, 1064, 2806, 3260, 3700, 6500, 7000, 8000, 280 }; static short formant_hz[10] = { 280, 688, 1064, 2806, 3260, 3700, 6500, 7000, 8000, 280 };
static short bandwidth[10] = { 89, 160, 70, 160, 200, 200, 500, 500, 500, 89 }; static short bandwidth[10] = { 89, 160, 70, 160, 200, 200, 500, 500, 500, 89 };
static short parallel_amp[10] = { 0, 59, 59, 59, 59, 59, 59, 0, 0, 0 }; static short parallel_amp[10] = { 0, 59, 59, 59, 59, 59, 59, 0, 0, 0 };
static short parallel_bw[10] = { 59, 59, 89, 149, 200, 200, 500, 0, 0, 0 }; static short parallel_bw[10] = { 59, 59, 89, 149, 200, 200, 500, 0, 0, 0 };


int ix;

sample_count = 0; sample_count = 0;


kt_globals.synthesis_model = CASCADE_PARALLEL; kt_globals.synthesis_model = CASCADE_PARALLEL;
KlattReset(2); KlattReset(2);


// set default values for frame parameters // set default values for frame parameters
for (ix = 0; ix <= 9; ix++) {
for (int ix = 0; ix <= 9; ix++) {
kt_frame.Fhz[ix] = formant_hz[ix]; kt_frame.Fhz[ix] = formant_hz[ix];
kt_frame.Bhz[ix] = bandwidth[ix]; kt_frame.Bhz[ix] = bandwidth[ix];
kt_frame.Ap[ix] = parallel_amp[ix]; kt_frame.Ap[ix] = parallel_amp[ix];

+ 11
- 17
src/libespeak-ng/mbrowrap.c View File



static int start_mbrola(const char *voice_path) static int start_mbrola(const char *voice_path)
{ {
int error, p_stdin[2], p_stdout[2], p_stderr[2];
int p_stdin[2], p_stdout[2], p_stderr[2];
ssize_t written; ssize_t written;
char charbuf[20]; char charbuf[20];


return -1; return -1;
} }


error = create_pipes(p_stdin, p_stdout, p_stderr);
int error = create_pipes(p_stdin, p_stdout, p_stderr);
if (error) if (error)
return -1; return -1;


} }


if (mbr_pid == 0) { if (mbr_pid == 0) {
int i;

if (dup2(p_stdin[0], 0) == -1 || if (dup2(p_stdin[0], 0) == -1 ||
dup2(p_stdout[1], 1) == -1 || dup2(p_stdout[1], 1) == -1 ||
dup2(p_stderr[1], 2) == -1) { dup2(p_stderr[1], 2) == -1) {
(void)written; // suppress 'variable not used' warning (void)written; // suppress 'variable not used' warning
_exit(1); _exit(1);
} }

for (i = p_stderr[1]; i > 2; i--)
for (int i = p_stderr[1]; i > 2; i--)
close(i); close(i);
signal(SIGHUP, SIG_IGN); signal(SIGHUP, SIG_IGN);
signal(SIGINT, SIG_IGN); signal(SIGINT, SIG_IGN);
static int mbrola_died(void) static int mbrola_died(void)
{ {
pid_t pid; pid_t pid;
int status, len;
int status;
const char *msg; const char *msg;
char msgbuf[80]; char msgbuf[80];




log("mbrowrap error: %s", msg); log("mbrowrap error: %s", msg);


len = strlen(mbr_errorbuf);
size_t len = strlen(mbr_errorbuf);
if (!len) if (!len)
snprintf(mbr_errorbuf, sizeof(mbr_errorbuf), "%s", msg); snprintf(mbr_errorbuf, sizeof(mbr_errorbuf), "%s", msg);
else else
static int send_to_mbrola(const char *cmd) static int send_to_mbrola(const char *cmd)
{ {
ssize_t result; ssize_t result;
int len;


if (!mbr_pid) if (!mbr_pid)
return -1; return -1;


len = strlen(cmd);
int len = strlen(cmd);
result = write(mbr_cmd_fd, cmd, len); result = write(mbr_cmd_fd, cmd, len);


if (result == -1) { if (result == -1) {


int init_MBR(const char *voice_path) int init_MBR(const char *voice_path)
{ {
int error, result;
unsigned char wavhdr[45]; unsigned char wavhdr[45];


error = start_mbrola(voice_path);
int error = start_mbrola(voice_path);
if (error) if (error)
return -1; return -1;


result = send_to_mbrola("#\n");
int result = send_to_mbrola("#\n");
if (result != 2) { if (result != 2) {
stop_mbrola(); stop_mbrola();
return -1; return -1;


int reset_MBR() int reset_MBR()
{ {
int result, success = 1;
int success = 1;
char dummybuf[4096]; char dummybuf[4096];


if (mbr_state == MBR_IDLE) if (mbr_state == MBR_IDLE)
if (kill(mbr_pid, SIGUSR1) == -1) if (kill(mbr_pid, SIGUSR1) == -1)
success = 0; success = 0;
free_pending_data(); free_pending_data();
result = write(mbr_cmd_fd, "\n#\n", 3);
int result = write(mbr_cmd_fd, "\n#\n", 3);
if (result != 3) if (result != 3)
success = 0; success = 0;
do { do {


int lastErrorStr_MBR(char *buffer, int bufsize) int lastErrorStr_MBR(char *buffer, int bufsize)
{ {
int result;
if (mbr_pid) if (mbr_pid)
mbrola_has_errors(); mbrola_has_errors();
result = snprintf(buffer, bufsize, "%s", mbr_errorbuf);
int result = snprintf(buffer, bufsize, "%s", mbr_errorbuf);
return result >= bufsize ? (bufsize - 1) : result; return result >= bufsize ? (bufsize - 1) : result;
} }



+ 22
- 45
src/libespeak-ng/numbers.c View File



static int LookupLetter2(Translator *tr, unsigned int letter, char *ph_buf) static int LookupLetter2(Translator *tr, unsigned int letter, char *ph_buf)
{ {
int len;
char single_letter[10]; char single_letter[10];


single_letter[0] = 0; single_letter[0] = 0;
single_letter[1] = '_'; single_letter[1] = '_';
len = utf8_out(letter, &single_letter[2]);
int len = utf8_out(letter, &single_letter[2]);
single_letter[len+2] = ' '; single_letter[len+2] = ' ';
single_letter[len+3] = 0; single_letter[len+3] = 0;


{ {
// control, bit 0: not the first letter of a word // control, bit 0: not the first letter of a word


int len;
static char single_letter[10] = { 0, 0 }; static char single_letter[10] = { 0, 0 };
unsigned int dict_flags[2]; unsigned int dict_flags[2];
char ph_buf3[40]; char ph_buf3[40];


ph_buf1[0] = 0; ph_buf1[0] = 0;
len = utf8_out(letter, &single_letter[2]);
int len = utf8_out(letter, &single_letter[2]);
single_letter[len+2] = ' '; single_letter[len+2] = ' ';


if (next_byte == -1) { if (next_byte == -1) {
int IsSuperscript(int letter) int IsSuperscript(int letter)
{ {
// is this a subscript or superscript letter ? // is this a subscript or superscript letter ?
int ix;
int c; int c;

for (ix = 0; (c = derived_letters[ix]) != 0; ix += 2) {
for (int ix = 0; (c = derived_letters[ix]) != 0; ix += 2) {
if (c > letter) if (c > letter)
break; break;
if (c == letter) if (c == letter)
// bit 1: say 'capital' // bit 1: say 'capital'
// bit 2: say character code for unknown letters // bit 2: say character code for unknown letters


int n_bytes;
int letter; int letter;
int len; int len;
int ix; int ix;
char *pbuf; char *pbuf;
const char *modifier; const char *modifier;
ALPHABET *alphabet; ALPHABET *alphabet;
int al_offset;
int al_flags;
int language; int language;
int number; int number;
int phontab_1;
int speak_letter_number; int speak_letter_number;
char capital[30]; char capital[30];
char ph_buf[80]; char ph_buf[80];
ph_buf[0] = 0; ph_buf[0] = 0;
ph_alphabet[0] = 0; ph_alphabet[0] = 0;
capital[0] = 0; capital[0] = 0;
phontab_1 = translator->phoneme_tab_ix;
int phontab_1 = translator->phoneme_tab_ix;


n_bytes = utf8_in(&letter, word);
int n_bytes = utf8_in(&letter, word);


if ((letter & 0xfff00) == 0x0e000) if ((letter & 0xfff00) == 0x0e000)
letter &= 0xff; // uncode private usage area letter &= 0xff; // uncode private usage area
LookupLetter(tr, number, 0, ph_buf, control & 1); LookupLetter(tr, number, 0, ph_buf, control & 1);
} }


al_offset = 0;
al_flags = 0;
int al_offset = 0;
int al_flags = 0;
if ((alphabet = AlphabetFromChar(letter)) != NULL) { if ((alphabet = AlphabetFromChar(letter)) != NULL) {
al_offset = alphabet->offset; al_offset = alphabet->offset;
al_flags = alphabet->flags; al_flags = alphabet->flags;
unsigned int c; unsigned int c;
int n_stress = 0; int n_stress = 0;
int prev = 0; int prev = 0;
int count;
unsigned char buf[N_WORD_PHONEMES]; unsigned char buf[N_WORD_PHONEMES];


for (ix = 0; (c = phonemes[ix]) != 0; ix++) { for (ix = 0; (c = phonemes[ix]) != 0; ix++) {
} }
buf[ix] = 0; buf[ix] = 0;


count = 0;
int count = 0;
prev = 0; prev = 0;
for (ix = 0; (c = buf[ix]) != 0; ix++) { for (ix = 0; (c = buf[ix]) != 0; ix++) {
if ((c == phonSTRESS_P) && (n_chars > 1) && (prev != phonSWITCH)) { if ((c == phonSTRESS_P) && (n_chars > 1) && (prev != phonSWITCH)) {
int c; int c;
char *p; char *p;
const char *p2; const char *p2;
int acc;
int prev;
int value; int value;
int subtract;
int repeat = 0; int repeat = 0;
int n_digits = 0; int n_digits = 0;
char *word_start; char *word_start;
static const char *roman_numbers = "ixcmvld"; static const char *roman_numbers = "ixcmvld";
static int roman_values[] = { 1, 10, 100, 1000, 5, 50, 500 }; static int roman_values[] = { 1, 10, 100, 1000, 5, 50, 500 };


acc = 0;
prev = 0;
subtract = 0x7fff;
int acc = 0;
int prev = 0;
int subtract = 0x7fff;
ph_out[0] = 0; ph_out[0] = 0;
flags[0] = 0; flags[0] = 0;
flags[1] = 0; flags[1] = 0;
// bit 8 followed by decimal fraction // bit 8 followed by decimal fraction
// bit 9: use #f form for both tens and units (lang=ml) // bit 9: use #f form for both tens and units (lang=ml)


int found;
int ix; int ix;
int units;
int tens;
int is_ordinal;
int used_and = 0; int used_and = 0;
int found_ordinal = 0; int found_ordinal = 0;
int next_phtype; int next_phtype;
char ph_digits[50]; char ph_digits[50];
char ph_and[12]; char ph_and[12];


units = value % 10;
tens = value / 10;
int units = value % 10;
int tens = value / 10;


found = 0;
int found = 0;
ph_ordinal[0] = 0; ph_ordinal[0] = 0;
ph_tens[0] = 0; ph_tens[0] = 0;
ph_digits[0] = 0; ph_digits[0] = 0;
if (control & 0x20) if (control & 0x20)
ord_type = 'q'; ord_type = 'q';


is_ordinal = control & 1;
int is_ordinal = control & 1;


if ((control & 2) && (n_digit_lookup == 2)) { if ((control & 2) && (n_digit_lookup == 2)) {
// pronunciation of the final 2 digits has already been found // pronunciation of the final 2 digits has already been found
// bit 8 followed by decimal fraction // bit 8 followed by decimal fraction


int found; int found;
int hundreds;
int tensunits;
int x; int x;
int ix;
int exact;
int ordinal;
int tplex;
int say_zero_hundred = 0; int say_zero_hundred = 0;
int say_one_hundred;
char string[12]; // for looking up entries in **_list char string[12]; // for looking up entries in **_list
char buf1[100]; char buf1[100];
char buf2[100]; char buf2[100];
char ph_hundred_and[12]; char ph_hundred_and[12];
char ph_thousand_and[12]; char ph_thousand_and[12];


ordinal = control & 0x22;
hundreds = value / 100;
tensunits = value % 100;
int ordinal = control & 0x22;
int hundreds = value / 100;
int tensunits = value % 100;
buf1[0] = 0; buf1[0] = 0;


ph_thousands[0] = 0; ph_thousands[0] = 0;
} else if (hundreds >= 10) { } else if (hundreds >= 10) {
ph_digits[0] = 0; ph_digits[0] = 0;


exact = 0;
int exact = 0;
if ((value % 1000) == 0) if ((value % 1000) == 0)
exact = 1; exact = 1;


tplex = thousandplex+1;
int tplex = thousandplex+1;
if (tr->langopts.numbers2 & NUM2_MYRIADS) if (tr->langopts.numbers2 & NUM2_MYRIADS)
tplex = 0; tplex = 0;


if (found) if (found)
ph_100[0] = 0; ph_100[0] = 0;
else { else {
say_one_hundred = 1;
int say_one_hundred = 1;
if (hundreds == 1) { if (hundreds == 1) {
if ((tr->langopts.numbers & NUM_OMIT_1_HUNDRED) != 0) if ((tr->langopts.numbers & NUM_OMIT_1_HUNDRED) != 0)
say_one_hundred = 0; say_one_hundred = 0;
} }
} else { } else {
if (ph_ordinal2[0] != 0) { if (ph_ordinal2[0] != 0) {
ix = strlen(buf1);
int ix = strlen(buf1);
if ((ix > 0) && (buf1[ix-1] == phonPAUSE_SHORT)) if ((ix > 0) && (buf1[ix-1] == phonPAUSE_SHORT))
buf1[ix-1] = 0; // remove pause before addding ordinal suffix buf1[ix-1] = 0; // remove pause before addding ordinal suffix
strcpy(buf2, ph_ordinal2); strcpy(buf2, ph_ordinal2);

+ 8
- 14
src/libespeak-ng/phonemelist.c View File

{ {
// Copy the phonemes list and perform any substitutions that are required for the // Copy the phonemes list and perform any substitutions that are required for the
// current voice // current voice
int ix;
int k; int k;
int replace_flags; int replace_flags;
int n_plist_out = 0; int n_plist_out = 0;
PHONEME_LIST2 *plist2; PHONEME_LIST2 *plist2;
PHONEME_TAB *next = NULL; PHONEME_TAB *next = NULL;


for (ix = 0; (ix < n_ph_list2) && (n_plist_out < N_PHONEME_LIST); ix++) {
for (int ix = 0; (ix < n_ph_list2) && (n_plist_out < N_PHONEME_LIST); ix++) {
plist2 = &ph_list2[ix]; plist2 = &ph_list2[ix];


// don't do any substitution if the language has been temporarily changed // don't do any substitution if the language has been temporarily changed
PHONEME_TAB *next, *next2; PHONEME_TAB *next, *next2;
int unstress_count = 0; int unstress_count = 0;
int word_stress = 0; int word_stress = 0;
int current_phoneme_tab;
int max_stress;
int voicing; int voicing;
int regression; int regression;
int end_sourceix;
int alternative; int alternative;
int delete_count;
int word_start;
int inserted; int inserted;
int deleted; int deleted;
PHONEME_DATA phdata; PHONEME_DATA phdata;


int n_ph_list3;
PHONEME_LIST *plist3; PHONEME_LIST *plist3;
PHONEME_LIST *plist3_inserted = NULL; PHONEME_LIST *plist3_inserted = NULL;
PHONEME_LIST ph_list3[N_PHONEME_LIST]; PHONEME_LIST ph_list3[N_PHONEME_LIST];
memset(&worddata, 0, sizeof(worddata)); memset(&worddata, 0, sizeof(worddata));
plist2 = ph_list2; plist2 = ph_list2;
phlist = phoneme_list; phlist = phoneme_list;
end_sourceix = plist2[n_ph_list2-1].sourceix;
int end_sourceix = plist2[n_ph_list2-1].sourceix;


// is the last word of the clause unstressed ? // is the last word of the clause unstressed ?
max_stress = 0;
int max_stress = 0;
for (j = n_ph_list2-3; j >= 0; j--) { for (j = n_ph_list2-3; j >= 0; j--) {
// start with the last phoneme (before the terminating pauses) and move backwards // start with the last phoneme (before the terminating pauses) and move backwards
if ((plist2[j].stresslevel & 0x7f) > max_stress) if ((plist2[j].stresslevel & 0x7f) > max_stress)
} }


// look for switch of phoneme tables // look for switch of phoneme tables
delete_count = 0;
current_phoneme_tab = tr->phoneme_tab_ix;
int delete_count = 0;
int current_phoneme_tab = tr->phoneme_tab_ix;
for (j = 0; j < n_ph_list2; j++) { for (j = 0; j < n_ph_list2; j++) {
if (current_phoneme_tab != tr->phoneme_tab_ix) if (current_phoneme_tab != tr->phoneme_tab_ix)
plist2[j].synthflags |= SFLAG_SWITCHED_LANG; plist2[j].synthflags |= SFLAG_SWITCHED_LANG;
} }
} }


n_ph_list3 = SubstitutePhonemes(tr, ph_list3) - 2;
int n_ph_list3 = SubstitutePhonemes(tr, ph_list3) - 2;


for (j = 0; (j < n_ph_list3) && (ix < N_PHONEME_LIST-3);) { for (j = 0; (j < n_ph_list3) && (ix < N_PHONEME_LIST-3);) {
if (ph_list3[j].sourceix) { if (ph_list3[j].sourceix) {
// transfer all the phonemes of the clause into phoneme_list // transfer all the phonemes of the clause into phoneme_list
ph = phoneme_tab[phonPAUSE]; ph = phoneme_tab[phonPAUSE];
ph_list3[0].ph = ph; ph_list3[0].ph = ph;
word_start = 1;
int word_start = 1;


for (j = 0; insert_ph || ((j < n_ph_list3) && (ix < N_PHONEME_LIST-3)); j++) { for (j = 0; insert_ph || ((j < n_ph_list3) && (ix < N_PHONEME_LIST-3)); j++) {
plist3 = &ph_list3[j]; plist3 = &ph_list3[j];

+ 27
- 53
src/libespeak-ng/readclause.c View File

int towlower(int c) int towlower(int c)
{ {
int x; int x;
int ix;


if (c < 0x80) if (c < 0x80)
return tolower(c); return tolower(c);


if (x == 0xfd) { if (x == 0xfd) {
// special cases, lookup translation table // special cases, lookup translation table
for (ix = 0; wchar_tolower[ix] != 0; ix += 2) {
for (int ix = 0; wchar_tolower[ix] != 0; ix += 2) {
if (wchar_tolower[ix] == c) if (wchar_tolower[ix] == c)
return wchar_tolower[ix+1]; return wchar_tolower[ix+1];
} }


int towupper(int c) int towupper(int c)
{ {
int ix;
// check whether a previous character code is the upper-case equivalent of this character // check whether a previous character code is the upper-case equivalent of this character
if (towlower(c-32) == c) if (towlower(c-32) == c)
return c-32; // yes, use it return c-32; // yes, use it
if (towlower(c-1) == c) if (towlower(c-1) == c)
return c-1; return c-1;
for (ix = 0; wchar_toupper[ix] != 0; ix += 2) {
for (int ix = 0; wchar_toupper[ix] != 0; ix += 2) {
if (wchar_toupper[ix] == c) if (wchar_toupper[ix] == c)
return wchar_toupper[ix+1]; return wchar_toupper[ix+1];
} }
int towlower2(unsigned int c) int towlower2(unsigned int c)
{ {
int x; int x;
int ix;


// check for non-standard upper to lower case conversions // check for non-standard upper to lower case conversions
if (c == 'I') { if (c == 'I') {


if (x == 0xfd) { if (x == 0xfd) {
// special cases, lookup translation table // special cases, lookup translation table
for (ix = 0; wchar_tolower[ix] != 0; ix += 2) {
for (int ix = 0; wchar_tolower[ix] != 0; ix += 2) {
if (wchar_tolower[ix] == (int)c) if (wchar_tolower[ix] == (int)c)
return wchar_tolower[ix+1]; return wchar_tolower[ix+1];
} }


int towupper2(unsigned int c) int towupper2(unsigned int c)
{ {
int ix;
if (c > MAX_WALPHA) if (c > MAX_WALPHA)
return towupper(c); return towupper(c);


return c-32; // yes, use it return c-32; // yes, use it
if (towlower2(c-1) == (int)c) if (towlower2(c-1) == (int)c)
return c-1; return c-1;
for (ix = 0; wchar_toupper[ix] != 0; ix += 2) {
for (int ix = 0; wchar_toupper[ix] != 0; ix += 2) {
if (wchar_toupper[ix] == (int)c) if (wchar_toupper[ix] == (int)c)
return wchar_toupper[ix+1]; return wchar_toupper[ix+1];
} }
static int GetC_get(void) static int GetC_get(void)
{ {
unsigned int c; unsigned int c;
unsigned int c2;


if (f_input != NULL) { if (f_input != NULL) {
c = fgetc(f_input); c = fgetc(f_input);
if (feof(f_input)) c = ' '; if (feof(f_input)) c = ' ';


if (option_multibyte == espeakCHARS_16BIT) { if (option_multibyte == espeakCHARS_16BIT) {
c2 = fgetc(f_input);
unsigned int c2 = fgetc(f_input);
if (feof(f_input)) c2 = 0; if (feof(f_input)) c2 = 0;
c = c + (c2 << 8); c = c + (c2 << 8);
} }
// Returns a unicode wide character // Returns a unicode wide character
// Performs UTF8 checking and conversion // Performs UTF8 checking and conversion


int c;
int c1; int c1;
int c2; int c2;
int cbuf[4]; int cbuf[4];
int ix; int ix;
int n_bytes;
static int ungot2 = 0; static int ungot2 = 0;
static const unsigned char mask[4] = { 0xff, 0x1f, 0x0f, 0x07 }; static const unsigned char mask[4] = { 0xff, 0x1f, 0x0f, 0x07 };




if ((option_multibyte < 2) && (c1 & 0x80)) { if ((option_multibyte < 2) && (c1 & 0x80)) {
// multi-byte utf8 encoding, convert to unicode // multi-byte utf8 encoding, convert to unicode
n_bytes = 0;
int n_bytes = 0;


if (((c1 & 0xe0) == 0xc0) && ((c1 & 0x1e) != 0)) if (((c1 & 0xe0) == 0xc0) && ((c1 & 0x1e) != 0))
n_bytes = 1; n_bytes = 1;
n_bytes = 3; n_bytes = 3;


if ((ix = n_bytes) > 0) { if ((ix = n_bytes) > 0) {
c = c1 & mask[ix];
int c = c1 & mask[ix];
while (ix > 0) { while (ix > 0) {
if ((c2 = cbuf[ix] = GetC_get()) == 0) { if ((c2 = cbuf[ix] = GetC_get()) == 0) {
if (option_multibyte == espeakCHARS_AUTO) if (option_multibyte == espeakCHARS_AUTO)
const char *WordToString2(unsigned int word) const char *WordToString2(unsigned int word)
{ {
// Convert a language mnemonic word into a string // Convert a language mnemonic word into a string
int ix;
static char buf[5]; static char buf[5];
char *p; char *p;


p = buf; p = buf;
for (ix = 3; ix >= 0; ix--) {
for (int ix = 3; ix >= 0; ix--) {
if ((*p = word >> (ix*8)) != 0) if ((*p = word >> (ix*8)) != 0)
p++; p++;
} }
// Find the phoneme string (in ascii) to speak the name of character c // Find the phoneme string (in ascii) to speak the name of character c
// Used for punctuation characters and symbols // Used for punctuation characters and symbols


int ix;
unsigned int flags[2]; unsigned int flags[2];
char single_letter[24]; char single_letter[24];
char phonemes[60]; char phonemes[60];
flags[1] = 0; flags[1] = 0;
single_letter[0] = 0; single_letter[0] = 0;
single_letter[1] = '_'; single_letter[1] = '_';
ix = utf8_out(c, &single_letter[2]);
int ix = utf8_out(c, &single_letter[2]);
single_letter[2+ix] = 0; single_letter[2+ix] = 0;


if (only) { if (only) {
FILE *f; FILE *f;
char *p; char *p;
int *ip; int *ip;
int length;
char fname_temp[100]; char fname_temp[100];
char fname2[sizeof(path_home)+13+40]; char fname2[sizeof(path_home)+13+40];


f = NULL; f = NULL;
#ifdef PLATFORM_POSIX #ifdef PLATFORM_POSIX
if ((f = fopen(fname, "rb")) != NULL) { if ((f = fopen(fname, "rb")) != NULL) {
int ix;
int fd_temp; int fd_temp;
int header[3]; int header[3];
char command[sizeof(fname2)+sizeof(fname2)+40]; char command[sizeof(fname2)+sizeof(fname2)+40];


fseek(f, 20, SEEK_SET); fseek(f, 20, SEEK_SET);
for (ix = 0; ix < 3; ix++)
for (int ix = 0; ix < 3; ix++)
header[ix] = Read4Bytes(f); header[ix] = Read4Bytes(f);


// if the sound file is not mono, 16 bit signed, at the correct sample rate, then convert it // if the sound file is not mono, 16 bit signed, at the correct sample rate, then convert it
} }
} }


length = GetFileLength(fname);
int length = GetFileLength(fname);
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);
if ((p = (char *)realloc(soundicon_tab[index].data, length)) == NULL) { if ((p = (char *)realloc(soundicon_tab[index].data, length)) == NULL) {
fclose(f); fclose(f);
static int LookupSoundicon(int c) static int LookupSoundicon(int c)
{ {
// Find the sound icon number for a punctuation chatacter // Find the sound icon number for a punctuation chatacter
int ix;

for (ix = N_SOUNDICON_SLOTS; ix < n_soundicon_tab; ix++) {
for (int ix = N_SOUNDICON_SLOTS; ix < n_soundicon_tab; ix++) {
if (soundicon_tab[ix].name == c) { if (soundicon_tab[ix].name == c) {
if (soundicon_tab[ix].length == 0) { if (soundicon_tab[ix].length == 0) {
if (LoadSoundFile(NULL, ix) != 0) if (LoadSoundFile(NULL, ix) != 0)
// Load a sound file into one of the reserved slots in the sound icon table // Load a sound file into one of the reserved slots in the sound icon table
// (if it'snot already loaded) // (if it'snot already loaded)


int ix;
int ix;
static int slot = -1; static int slot = -1;


for (ix = 0; ix < n_soundicon_tab; ix++) { for (ix = 0; ix < n_soundicon_tab; ix++) {
int soundicon; int soundicon;
int attributes; int attributes;
int short_pause; int short_pause;
int c2;
int len;
int bufix1;
char buf[200]; char buf[200];
char buf2[80]; char buf2[80];
char ph_buf[30]; char ph_buf[30];


c2 = *c2_ptr;
int c2 = *c2_ptr;
buf[0] = 0; buf[0] = 0;


if ((soundicon = LookupSoundicon(c1)) >= 0) { if ((soundicon = LookupSoundicon(c1)) >= 0) {
} }
} }


bufix1 = *bufix;
len = strlen(buf);
int bufix1 = *bufix;
int len = strlen(buf);
strcpy(&output[*bufix], buf); strcpy(&output[*bufix], buf);
*bufix += len; *bufix += len;


// Use the voice properties from the SSML stack to choose a voice, and switch // Use the voice properties from the SSML stack to choose a voice, and switch
// to that voice if it's not the current voice // to that voice if it's not the current voice


int ix;
const char *p; const char *p;
SSML_STACK *sp; SSML_STACK *sp;
const char *v_id; const char *v_id;
voice_select.variant = ssml_stack[0].voice_variant_number; voice_select.variant = ssml_stack[0].voice_variant_number;
voice_select.identifier = NULL; voice_select.identifier = NULL;


for (ix = 0; ix < n_ssml_stack; ix++) {
for (int ix = 0; ix < n_ssml_stack; ix++) {
sp = &ssml_stack[ix]; sp = &ssml_stack[ix];
voice_name_specified = 0; voice_name_specified = 0;


{ {
// Set the speech parameters from the parameter stack // Set the speech parameters from the parameter stack
int param; int param;
int ix;
int value; int value;
char buf[20]; char buf[20];
int new_parameters[N_SPEECH_PARAM]; int new_parameters[N_SPEECH_PARAM];
for (param = 0; param < N_SPEECH_PARAM; param++) for (param = 0; param < N_SPEECH_PARAM; param++)
new_parameters[param] = -1; new_parameters[param] = -1;


for (ix = 0; ix < n_param_stack; ix++) {
for (int ix = 0; ix < n_param_stack; ix++) {
for (param = 0; param < N_SPEECH_PARAM; param++) { for (param = 0; param < N_SPEECH_PARAM; param++) {
if (param_stack[ix].parameter[param] >= 0) if (param_stack[ix].parameter[param] >= 0)
new_parameters[param] = param_stack[ix].parameter[param]; new_parameters[param] = param_stack[ix].parameter[param];


static PARAM_STACK *PushParamStack(int tag_type) static PARAM_STACK *PushParamStack(int tag_type)
{ {
int ix;
PARAM_STACK *sp; PARAM_STACK *sp;


sp = &param_stack[n_param_stack]; sp = &param_stack[n_param_stack];
n_param_stack++; n_param_stack++;


sp->type = tag_type; sp->type = tag_type;
for (ix = 0; ix < N_SPEECH_PARAM; ix++)
for (int ix = 0; ix < N_SPEECH_PARAM; ix++)
sp->parameter[ix] = -1; sp->parameter[ix] = -1;
return sp; return sp;
} }
static void PopParamStack(int tag_type, char *outbuf, int *outix) static void PopParamStack(int tag_type, char *outbuf, int *outix)
{ {
// unwind the stack up to and including the previous tag of this type // unwind the stack up to and including the previous tag of this type
int ix;
int top = 0; int top = 0;


if (tag_type >= SSML_CLOSE) if (tag_type >= SSML_CLOSE)
tag_type -= SSML_CLOSE; tag_type -= SSML_CLOSE;


for (ix = 0; ix < n_param_stack; ix++) {
for (int ix = 0; ix < n_param_stack; ix++) {
if (param_stack[ix].type == tag_type) if (param_stack[ix].type == tag_type)
top = ix; top = ix;
} }


static int attrcmp(const wchar_t *string1, const char *string2) static int attrcmp(const wchar_t *string1, const char *string2)
{ {
int ix;

int ix;
if (string1 == NULL) if (string1 == NULL)
return 1; return 1;


{ {
int sign = 0; int sign = 0;
wchar_t *tail; wchar_t *tail;
double value;


while (iswspace(*pw)) pw++; while (iswspace(*pw)) pw++;
if (*pw == '+') { if (*pw == '+') {
pw++; pw++;
sign = -1; sign = -1;
} }
value = (double)wcstod(pw, &tail);
double value = (double)wcstod(pw, &tail);
if (tail == pw) { if (tail == pw) {
// failed to find a number, return 100% // failed to find a number, return 100%
*value_out = 100; *value_out = 100;
#ifdef PLATFORM_RISCOS #ifdef PLATFORM_RISCOS
*value_out = 100; *value_out = 100;
#else #else
double x;
// convert from semitones to a frequency percentage // convert from semitones to a frequency percentage
x = pow((double)2.0, (double)((value*sign)/12)) * 100;
double x = pow((double)2.0, (double)((value*sign)/12)) * 100;
*value_out = (int)x; *value_out = (int)x;
#endif #endif
return 2; // percentage return 2; // percentage
static void SetProsodyParameter(int param_type, wchar_t *attr1, PARAM_STACK *sp) static void SetProsodyParameter(int param_type, wchar_t *attr1, PARAM_STACK *sp)
{ {
int value; int value;
int sign;


static const MNEM_TAB mnem_volume[] = { static const MNEM_TAB mnem_volume[] = {
{ "default", 100 }, { "default", 100 },
// mnemonic specifies a value as a percentage of the base pitch/range/rate/volume // mnemonic specifies a value as a percentage of the base pitch/range/rate/volume
sp->parameter[param_type] = (param_stack[0].parameter[param_type] * value)/100; sp->parameter[param_type] = (param_stack[0].parameter[param_type] * value)/100;
} else { } else {
sign = attr_prosody_value(param_type, attr1, &value);
int sign = attr_prosody_value(param_type, attr1, &value);


if (sign == 0) if (sign == 0)
sp->parameter[param_type] = value; // absolute value in Hz sp->parameter[param_type] = value; // absolute value in Hz
{ NULL, 0 } { NULL, 0 }
}; };


int ix;
int letter; int letter;
char *p; char *p;


p = &outbuf[index]; p = &outbuf[index];


if ((letter = LookupMnem(keynames, p)) != 0) { if ((letter = LookupMnem(keynames, p)) != 0) {
ix = utf8_out(letter, p);
int ix = utf8_out(letter, p);
*outix = index + ix; *outix = index + ix;
return letter; return letter;
} }


void InitText2(void) void InitText2(void)
{ {
int param;

ungot_char = 0; ungot_char = 0;
ungot_char2 = 0; ungot_char2 = 0;


n_param_stack = 1; n_param_stack = 1;
ssml_stack[0].tag_type = 0; ssml_stack[0].tag_type = 0;


for (param = 0; param < N_SPEECH_PARAM; param++)
for (int param = 0; param < N_SPEECH_PARAM; param++)
speech_parameters[param] = param_stack[0].parameter[param]; // set all speech parameters to defaults speech_parameters[param] = param_stack[0].parameter[param]; // set all speech parameters to defaults


option_punctuation = speech_parameters[espeakPUNCTUATION]; option_punctuation = speech_parameters[espeakPUNCTUATION];

+ 10
- 20
src/libespeak-ng/setlengths.c View File

void SetSpeed(int control) void SetSpeed(int control)
{ {
int x; int x;
int s1;
int wpm;
int wpm2; int wpm2;
int wpm_value;
double sonic;


speed.loud_consonants = 0; speed.loud_consonants = 0;
speed.min_sample_len = 450; speed.min_sample_len = 450;
speed.lenmod2_factor = 100; speed.lenmod2_factor = 100;
speed.min_pause = 5; speed.min_pause = 5;


wpm = embedded_value[EMBED_S];
int wpm = embedded_value[EMBED_S];
if (control == 2) if (control == 2)
wpm = embedded_value[EMBED_S2]; wpm = embedded_value[EMBED_S2];


wpm_value = wpm;
int wpm_value = wpm;


if (voice->speed_percent > 0) if (voice->speed_percent > 0)
wpm = (wpm * voice->speed_percent)/100; wpm = (wpm * voice->speed_percent)/100;
speed3 = (x * voice->speedf3)/256; speed3 = (x * voice->speedf3)/256;
} }
if (control & 2) { if (control & 2) {
sonic = ((double)wpm2)/wpm;
double sonic = ((double)wpm2)/wpm;
DoSonicSpeed((int)(sonic * 1024)); DoSonicSpeed((int)(sonic * 1024));
speed.pause_factor = 85; speed.pause_factor = 85;
speed.clause_pause_factor = 80; speed.clause_pause_factor = 80;
speed.lenmod2_factor = 110 - (wpm - 250)/2; speed.lenmod2_factor = 110 - (wpm - 250)/2;
} }


s1 = (x * voice->speedf1)/256;
int s1 = (x * voice->speedf1)/256;


if (wpm >= 170) if (wpm >= 170)
speed.wav_factor = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds speed.wav_factor = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds
void SetSpeed(int control) void SetSpeed(int control)
{ {
// This is the earlier version of SetSpeed() before sonic speed-up was added // This is the earlier version of SetSpeed() before sonic speed-up was added
int x;
int s1;
int wpm;
int wpm2;


speed.loud_consonants = 0; speed.loud_consonants = 0;
speed.min_sample_len = 450; speed.min_sample_len = 450;
speed.lenmod_factor = 110; // controls the effect of FRFLAG_LEN_MOD reduce length change speed.lenmod_factor = 110; // controls the effect of FRFLAG_LEN_MOD reduce length change
speed.lenmod2_factor = 100; speed.lenmod2_factor = 100;


wpm = embedded_value[EMBED_S];
int wpm = embedded_value[EMBED_S];
if (control == 2) if (control == 2)
wpm = embedded_value[EMBED_S2]; wpm = embedded_value[EMBED_S2];


if (wpm > 360) if (wpm > 360)
speed.loud_consonants = (wpm - 360) / 8; speed.loud_consonants = (wpm - 360) / 8;


wpm2 = wpm;
int wpm2 = wpm;
if (wpm > 359) wpm2 = 359; if (wpm > 359) wpm2 = 359;
if (wpm < 80) wpm2 = 80; if (wpm < 80) wpm2 = 80;
x = speed_lookup[wpm2-80];
int x = speed_lookup[wpm2-80];


if (wpm >= 380) if (wpm >= 380)
x = 7; x = 7;
speed.lenmod2_factor = 110 - (wpm - 250)/2; speed.lenmod2_factor = 110 - (wpm - 250)/2;
} }


s1 = (x * voice->speedf1)/256;
int s1 = (x * voice->speedf1)/256;


if (wpm >= 170) if (wpm >= 170)
speed.wav_factor = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds speed.wav_factor = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds
// relative 0=absolute 1=relative // relative 0=absolute 1=relative


int new_value = value; int new_value = value;
int default_value;


if (relative) { if (relative) {
if (parameter < 5) { if (parameter < 5) {
default_value = param_defaults[parameter];
int default_value = param_defaults[parameter];
new_value = default_value + (default_value * value)/100; new_value = default_value + (default_value * value)/100;
} }
} }


void CalcLengths(Translator *tr) void CalcLengths(Translator *tr)
{ {
int ix;
int ix2; int ix2;
PHONEME_LIST *prev; PHONEME_LIST *prev;
PHONEME_LIST *next; PHONEME_LIST *next;
unsigned char *pitch_env = NULL; unsigned char *pitch_env = NULL;
PHONEME_DATA phdata_tone; PHONEME_DATA phdata_tone;


for (ix = 1; ix < n_phoneme_list; ix++) {
for (int ix = 1; ix < n_phoneme_list; ix++) {
prev = &phoneme_list[ix-1]; prev = &phoneme_list[ix-1];
p = &phoneme_list[ix]; p = &phoneme_list[ix];
stress = p->stresslevel & 0x7; stress = p->stresslevel & 0x7;

+ 6
- 12
src/libespeak-ng/speak_lib.c View File

{ {
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
HKEY RegKey; HKEY RegKey;
unsigned long size;
unsigned long var_type;
char *env; char *env;
unsigned char buf[sizeof(path_home)-13]; unsigned char buf[sizeof(path_home)-13];




buf[0] = 0; buf[0] = 0;
RegOpenKeyExA(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;
unsigned long size = sizeof(buf);
unsigned long var_type = REG_SZ;
RegQueryValueExA(RegKey, "path", 0, &var_type, buf, &size); RegQueryValueExA(RegKey, "path", 0, &var_type, buf, &size);


sprintf(path_home, "%s\\espeak-data", buf); sprintf(path_home, "%s\\espeak-data", buf);


static int initialise(int control) static int initialise(int control)
{ {
int param;
int result; int result;
int srate = 22050; // default sample rate 22050 Hz int srate = 22050; // default sample rate 22050 Hz


SynthesizeInit(); SynthesizeInit();
InitNamedata(); InitNamedata();


for (param = 0; param < N_SPEECH_PARAM; param++)
for (int param = 0; param < N_SPEECH_PARAM; param++)
param_stack[0].parameter[param] = param_defaults[param]; param_stack[0].parameter[param] = param_defaults[param];


return 0; return 0;
// type: 1=word, 2=sentence, 3=named mark, 4=play audio, 5=end, 7=phoneme // type: 1=word, 2=sentence, 3=named mark, 4=play audio, 5=end, 7=phoneme
ENTER("MarkerEvent"); ENTER("MarkerEvent");
espeak_EVENT *ep; espeak_EVENT *ep;
double time;


if ((event_list == NULL) || (event_list_ix >= (n_event_list-2))) if ((event_list == NULL) || (event_list_ix >= (n_event_list-2)))
return; return;
ep->text_position = char_position & 0xffffff; ep->text_position = char_position & 0xffffff;
ep->length = char_position >> 24; ep->length = char_position >> 24;


time = ((double)(count_samples + mbrola_delay + (out_ptr - out_start)/2)*1000.0)/samplerate;
double time = ((double)(count_samples + mbrola_delay + (out_ptr - out_start)/2)*1000.0)/samplerate;
ep->audio_position = (int)time; ep->audio_position = (int)time;
ep->sample = (count_samples + mbrola_delay + (out_ptr - out_start)/2); ep->sample = (count_samples + mbrola_delay + (out_ptr - out_start)/2);


{ {
// symbolic name, symbolicname_character - is there a system resource of symbolic names per language? // symbolic name, symbolicname_character - is there a system resource of symbolic names per language?
int letter; int letter;
int ix;


ix = utf8_in(&letter, key);
int ix = utf8_in(&letter, key);
if (key[ix] == 0) { if (key[ix] == 0) {
// a single character // a single character
sync_espeak_Char(letter); sync_espeak_Char(letter);
ESPEAK_API int espeak_Initialize(espeak_AUDIO_OUTPUT output_type, int buf_length, const char *path, int options) ESPEAK_API int espeak_Initialize(espeak_AUDIO_OUTPUT output_type, int buf_length, const char *path, int options)
{ {
ENTER("espeak_Initialize"); ENTER("espeak_Initialize");
int param;


// It seems that the wctype functions don't work until the locale has been set // It seems that the wctype functions don't work until the locale has been set
// to something other than the default "C". Then, not only Latin1 but also the // to something other than the default "C". Then, not only Latin1 but also the


VoiceReset(0); VoiceReset(0);


for (param = 0; param < N_SPEECH_PARAM; param++)
for (int param = 0; param < N_SPEECH_PARAM; param++)
param_stack[0].parameter[param] = saved_parameters[param] = param_defaults[param]; param_stack[0].parameter[param] = saved_parameters[param] = param_defaults[param];


SetParameter(espeakRATE, 175, 0); SetParameter(espeakRATE, 175, 0);

+ 5
- 8
src/libespeak-ng/spect.c View File

{ {
// General polinomial interpolation routine, xa[1...n] ya[1...n] // General polinomial interpolation routine, xa[1...n] ya[1...n]
int i, m, ns = 1; int i, m, ns = 1;
float den, dif, dift, ho, hp, w;
float den, dift, ho, hp, w;
float y; // result float y; // result
float c[9], d[9]; float c[9], d[9];


dif = fabs(x-xa[1]);
float dif = fabs(x-xa[1]);


for (i = 1; i <= n; i++) { for (i = 1; i <= n; i++) {
if ((dift = fabs(x-xa[i])) < dif) { if ((dift = fabs(x-xa[i])) < dif) {


static SpectFrame *SpectFrameCreate() static SpectFrame *SpectFrameCreate()
{ {
int ix;
SpectFrame *frame; SpectFrame *frame;


frame = malloc(sizeof(SpectFrame)); frame = malloc(sizeof(SpectFrame));
frame->amp_adjust = 100; frame->amp_adjust = 100;
frame->length_adjust = 0; frame->length_adjust = 0;


for (ix = 0; ix < N_PEAKS; ix++) {
for (int ix = 0; ix < N_PEAKS; ix++) {
frame->formants[ix].freq = 0; frame->formants[ix].freq = 0;
frame->peaks[ix].pkfreq = default_freq[ix]; frame->peaks[ix].pkfreq = default_freq[ix];
frame->peaks[ix].pkheight = 0; frame->peaks[ix].pkheight = 0;
{ {
int h; int h;
float total = 0; float total = 0;
int maxh;
int height; int height;
int htab[400]; int htab[400];
wavegen_peaks_t wpeaks[9]; wavegen_peaks_t wpeaks[9];
wpeaks[h].right = frame->peaks[h].pkright << 16; wpeaks[h].right = frame->peaks[h].pkright << 16;
} }


maxh = PeaksToHarmspect(wpeaks, 90<<16, htab, 0);
int maxh = PeaksToHarmspect(wpeaks, 90<<16, htab, 0);
for (h = 1; h < maxh; h++) for (h = 1; h < maxh; h++)
total += ((htab[h] * htab[h]) >> 10); total += ((htab[h] * htab[h]) >> 10);
frame->rms = sqrt(total) / 7.25; frame->rms = sqrt(total) / 7.25;


void SpectSeqDestroy(SpectSeq *spect) void SpectSeqDestroy(SpectSeq *spect)
{ {
int ix;
if (spect->frames != NULL) { if (spect->frames != NULL) {
for (ix = 0; ix < spect->numframes; ix++) {
for (int ix = 0; ix < spect->numframes; ix++) {
if (spect->frames[ix] != NULL) if (spect->frames[ix] != NULL)
SpectFrameDestroy(spect->frames[ix]); SpectFrameDestroy(spect->frames[ix]);
} }

+ 11
- 18
src/libespeak-ng/synth_mbrola.c View File

{ {
// Load a phoneme name translation table from espeak-data/mbrola // Load a phoneme name translation table from espeak-data/mbrola


int size;
int ix;
int *pw; int *pw;
FILE *f_in; FILE *f_in;
char path[sizeof(path_home)+15]; char path[sizeof(path_home)+15];


// read eSpeak's mbrola phoneme translation data, eg. en1_phtrans // read eSpeak's mbrola phoneme translation data, eg. en1_phtrans
sprintf(path, "%s/mbrola_ph/%s", path_home, phtrans); sprintf(path, "%s/mbrola_ph/%s", path_home, phtrans);
size = GetFileLength(path);
int size = GetFileLength(path);
if ((f_in = fopen(path, "rb")) == NULL) { if ((f_in = fopen(path, "rb")) == NULL) {
close_MBR(); close_MBR();
return EE_NOT_FOUND; return EE_NOT_FOUND;


mbrola_control = Read4Bytes(f_in); mbrola_control = Read4Bytes(f_in);
pw = (int *)mbrola_tab; pw = (int *)mbrola_tab;
for (ix = 4; ix < size; ix += 4)
for (int ix = 4; ix < size; ix += 4)
*pw++ = Read4Bytes(f_in); *pw++ = Read4Bytes(f_in);
size = fread(mbrola_tab, 1, size, f_in); size = fread(mbrola_tab, 1, size, f_in);
fclose(f_in); fclose(f_in);
static char *WritePitch(int env, int pitch1, int pitch2, int split, int final) static char *WritePitch(int env, int pitch1, int pitch2, int split, int final)
{ {
// final=1: only give the final pitch value. // final=1: only give the final pitch value.
int x;
int ix;
int pitch_base; int pitch_base;
int pitch_range; int pitch_range;
int p1, p2, p_end;
int p2;
unsigned char *pitch_env; unsigned char *pitch_env;
int max = -1; int max = -1;
int min = 999; int min = 999;
int env100 = 80; // apply the pitch change only over this proportion of the mbrola phoneme(s) int env100 = 80; // apply the pitch change only over this proportion of the mbrola phoneme(s)
int y2; int y2;
int y[4]; int y[4];
int env_split;
char buf[50]; char buf[50];
static char output[50]; static char output[50];




SetPitch2(voice, pitch1, pitch2, &pitch_base, &pitch_range); SetPitch2(voice, pitch1, pitch2, &pitch_base, &pitch_range);


env_split = (split * 128)/100;
int env_split = (split * 128)/100;
if (env_split < 0) if (env_split < 0)
env_split = 0-env_split; env_split = 0-env_split;


// find max and min in the pitch envelope // find max and min in the pitch envelope
for (x = 0; x < 128; x++) {
for (int x = 0; x < 128; x++) {
if (pitch_env[x] > max) { if (pitch_env[x] > max) {
max = pitch_env[x]; max = pitch_env[x];
y_max = x; y_max = x;
y[3] = y[2] + (127 - y[2])/2; y[3] = y[2] + (127 - y[2])/2;


// set initial pitch // set initial pitch
p1 = ((pitch_env[0]*pitch_range)>>8) + pitch_base; // Hz << 12
p_end = ((pitch_env[127]*pitch_range)>>8) + pitch_base;
int p1 = ((pitch_env[0]*pitch_range)>>8) + pitch_base; // Hz << 12
int p_end = ((pitch_env[127]*pitch_range)>>8) + pitch_base;


if (split >= 0) { if (split >= 0) {
sprintf(buf, " 0 %d", p1/4096); sprintf(buf, " 0 %d", p1/4096);


// don't use intermediate pitch points for linear rise and fall // don't use intermediate pitch points for linear rise and fall
if (env > 1) { if (env > 1) {
for (ix = 1; ix < 4; ix++) {
for (int ix = 1; ix < 4; ix++) {
p2 = ((pitch_env[y[ix]]*pitch_range)>>8) + pitch_base; p2 = ((pitch_env[y[ix]]*pitch_range)>>8) + pitch_base;


if (split > 0) if (split > 0)
// Read audio data from Mbrola (length is in millisecs) // Read audio data from Mbrola (length is in millisecs)


static int n_samples; static int n_samples;
int req_samples, result;
int ix;
short value16; short value16;
int value; int value;


if (!resume) if (!resume)
n_samples = samplerate * length / 1000; n_samples = samplerate * length / 1000;


req_samples = (out_end - out_ptr)/2;
int req_samples = (out_end - out_ptr)/2;
if (req_samples > n_samples) if (req_samples > n_samples)
req_samples = n_samples; req_samples = n_samples;
result = read_MBR((short *)out_ptr, req_samples);
int result = read_MBR((short *)out_ptr, req_samples);
if (result <= 0) if (result <= 0)
return 0; return 0;


for (ix = 0; ix < result; ix++) {
for (int ix = 0; ix < result; ix++) {
value16 = out_ptr[0] + (out_ptr[1] << 8); value16 = out_ptr[0] + (out_ptr[1] << 8);
value = value16 * amplitude; value = value16 * amplitude;
value = value / 40; // adjust this constant to give a suitable amplitude for mbrola voices value = value / 40; // adjust this constant to give a suitable amplitude for mbrola voices

+ 21
- 39
src/libespeak-ng/synthdata.c View File

{ {
FILE *f_in; FILE *f_in;
char *p; char *p;
unsigned int length;
char buf[sizeof(path_home)+40]; char buf[sizeof(path_home)+40];


sprintf(buf, "%s%c%s", path_home, PATHSEP, fname); sprintf(buf, "%s%c%s", path_home, PATHSEP, fname);
length = GetFileLength(buf);
unsigned int length = GetFileLength(buf);


if ((f_in = fopen(buf, "rb")) == NULL) { if ((f_in = fopen(buf, "rb")) == NULL) {
fprintf(stderr, "Can't read data file: '%s'\n", buf); fprintf(stderr, "Can't read data file: '%s'\n", buf);
{ {
int ix; int ix;
int n_phonemes; int n_phonemes;
int version;
int result = 1; int result = 1;
int length; int length;
int rate;
unsigned char *p; unsigned char *p;
int *pw; int *pw;


n_tunes = length / sizeof(TUNE); n_tunes = length / sizeof(TUNE);


// read the version number and sample rate from the first 8 bytes of phondata // read the version number and sample rate from the first 8 bytes of phondata
version = 0; // bytes 0-3, version number
rate = 0; // bytes 4-7, sample rate
int version = 0; // bytes 0-3, version number
int rate = 0; // bytes 4-7, sample rate

for (ix = 0; ix < 4; ix++) { for (ix = 0; ix < 4; ix++) {
version += (wavefile_data[ix] << (ix*8)); version += (wavefile_data[ix] << (ix*8));
rate += (wavefile_data[ix+4] << (ix*8)); rate += (wavefile_data[ix+4] << (ix*8));


int PhonemeCode(unsigned int mnem) int PhonemeCode(unsigned int mnem)
{ {
int ix;

for (ix = 0; ix < n_phoneme_tab; ix++) {
for (int ix = 0; ix < n_phoneme_tab; ix++) {
if (phoneme_tab[ix] == NULL) if (phoneme_tab[ix] == NULL)
continue; continue;
if (phoneme_tab[ix]->mnemonic == mnem) if (phoneme_tab[ix]->mnemonic == mnem)


int LookupPhonemeString(const char *string) int LookupPhonemeString(const char *string)
{ {
int ix;
unsigned char c; unsigned char c;
unsigned int mnem;


// Pack up to 4 characters into a word // Pack up to 4 characters into a word
mnem = 0;
for (ix = 0; ix < 4; ix++) {
unsigned int mnem = 0;
for (int ix = 0; ix < 4; ix++) {
if (string[ix] == 0) break; if (string[ix] == 0) break;
c = string[ix]; c = string[ix];
mnem |= (c << (ix*8)); mnem |= (c << (ix*8));
frameref_t *LookupSpect(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, int *n_frames, PHONEME_LIST *plist) frameref_t *LookupSpect(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, int *n_frames, PHONEME_LIST *plist)
{ {
int ix; int ix;
int nf;
int nf1; int nf1;
int seq_break;
frameref_t *frames; frameref_t *frames;
int length1; int length1;
int length_std; int length_std;


seq = (SPECT_SEQ *)(&phondata_ptr[fmt_params->fmt_addr]); seq = (SPECT_SEQ *)(&phondata_ptr[fmt_params->fmt_addr]);
seqk = (SPECT_SEQK *)seq; seqk = (SPECT_SEQK *)seq;
nf = seq->n_frames;
int nf = seq->n_frames;


if (nf >= N_SEQ_FRAMES) if (nf >= N_SEQ_FRAMES)
nf = N_SEQ_FRAMES - 1; nf = N_SEQ_FRAMES - 1;


seq_len_adjust = fmt_params->fmt2_lenadj + fmt_params->fmt_length; seq_len_adjust = fmt_params->fmt2_lenadj + fmt_params->fmt_length;
seq_break = 0;
int seq_break = 0;


for (ix = 0; ix < nf; ix++) { for (ix = 0; ix < nf; ix++) {
if (seq->frame[0].frflags & FRFLAG_KLATT) if (seq->frame[0].frflags & FRFLAG_KLATT)


static void SetUpPhonemeTable(int number, int recursing) static void SetUpPhonemeTable(int number, int recursing)
{ {
int ix;
int includes; int includes;
int ph_code; int ph_code;
PHONEME_TAB *phtab; PHONEME_TAB *phtab;


// now add the phonemes from this table // now add the phonemes from this table
phtab = phoneme_tab_list[number].phoneme_tab_ptr; phtab = phoneme_tab_list[number].phoneme_tab_ptr;
for (ix = 0; ix < phoneme_tab_list[number].n_phonemes; ix++) {
for (int ix = 0; ix < phoneme_tab_list[number].n_phonemes; ix++) {
ph_code = phtab[ix].code; ph_code = phtab[ix].code;
phoneme_tab[ph_code] = &phtab[ix]; phoneme_tab[ph_code] = &phtab[ix];
if (ph_code > n_phoneme_tab) if (ph_code > n_phoneme_tab)
// condition: // condition:
// 0 if diminished, 1 if unstressed, 2 if not stressed, 3 if stressed, 4 if max stress // 0 if diminished, 1 if unstressed, 2 if not stressed, 3 if stressed, 4 if max stress


int stress_level;
PHONEME_LIST *pl; PHONEME_LIST *pl;
static int condition_level[4] = { 1, 2, 4, 15 }; static int condition_level[4] = { 1, 2, 4, 15 };


return false; // no stress elevel for this consonant return false; // no stress elevel for this consonant
} }


stress_level = pl->stresslevel & 0xf;
int stress_level = pl->stresslevel & 0xf;


if (tr != NULL) { if (tr != NULL) {
if ((control & 1) && (plist->synthflags & SFLAG_DICTIONARY) && ((tr->langopts.param[LOPT_REDUCE] & 1) == 0)) { if ((control & 1) && (plist->synthflags & SFLAG_DICTIONARY) && ((tr->langopts.param[LOPT_REDUCE] & 1) == 0)) {
{ {
int which; int which;
int ix; int ix;
unsigned int data;
int instn;
int instn2;
int count; int count;
int check_endtype = 0; int check_endtype = 0;
PHONEME_TAB *ph; PHONEME_TAB *ph;


// bits 8-10 = 7, other conditions // bits 8-10 = 7, other conditions


instn = (*p_prog) & 0xfff;
data = instn & 0xff;
instn2 = instn >> 8;
int instn = (*p_prog) & 0xfff;
unsigned int data = instn & 0xff;
int instn2 = instn >> 8;


if (instn2 < 14) { if (instn2 < 14) {
plist_this = plist; plist_this = plist;
{ {
USHORT *prog; USHORT *prog;
int voweltype; int voweltype;
signed char x;


if (instn_type == 2) { if (instn_type == 2) {
phdata->pd_control |= pd_FORNEXTPH; phdata->pd_control |= pd_FORNEXTPH;
if ((voweltype >= 0) && (voweltype < 6)) { if ((voweltype >= 0) && (voweltype < 6)) {
prog = *p_prog + voweltype*2; prog = *p_prog + voweltype*2;
phdata->sound_addr[instn_type] = (((prog[1] & 0xf) << 16) + prog[2]) * 4; phdata->sound_addr[instn_type] = (((prog[1] & 0xf) << 16) + prog[2]) * 4;
x = (prog[1] >> 4) & 0xff;
signed char x = (prog[1] >> 4) & 0xff;
phdata->sound_param[instn_type] = x; // sign extend phdata->sound_param[instn_type] = x; // sign extend
} }




int NumInstnWords(USHORT *prog) int NumInstnWords(USHORT *prog)
{ {
int instn;
int instn2;
int instn_type;
int n; int n;
int type2;
static const char n_words[16] = { 0, 1, 0, 0, 1, 1, 0, 1, 1, 2, 4, 0, 0, 0, 0, 0 }; static const char n_words[16] = { 0, 1, 0, 0, 1, 1, 0, 1, 1, 2, 4, 0, 0, 0, 0, 0 };


instn = *prog;
instn_type = instn >> 12;
int instn2;
int type2;
int instn = *prog;
int instn_type = instn >> 12;
if ((n = n_words[instn_type]) > 0) if ((n = n_words[instn_type]) > 0)
return n; return n;


bool truth; bool truth;
bool truth2; bool truth2;
int data; int data;
int end_flag;
int ix; int ix;
signed char param_sc; signed char param_sc;


if (ph->program == 0) if (ph->program == 0)
return; return;


end_flag = 0;
int end_flag = 0;


for (prog = &phoneme_index[ph->program]; end_flag != 1; prog++) { for (prog = &phoneme_index[ph->program]; end_flag != 1; prog++) {
instn = *prog; instn = *prog;
void InterpretPhoneme2(int phcode, PHONEME_DATA *phdata) void InterpretPhoneme2(int phcode, PHONEME_DATA *phdata)
{ {
// Examine the program of a single isolated phoneme // Examine the program of a single isolated phoneme
int ix;
PHONEME_LIST plist[4]; PHONEME_LIST plist[4];
memset(plist, 0, sizeof(plist)); memset(plist, 0, sizeof(plist));


for (ix = 0; ix < 4; ix++) {
for (int ix = 0; ix < 4; ix++) {
plist[ix].phcode = phonPAUSE; plist[ix].phcode = phonPAUSE;
plist[ix].ph = phoneme_tab[phonPAUSE]; plist[ix].ph = phoneme_tab[phonPAUSE];
} }

+ 30
- 62
src/libespeak-ng/synthesize.c View File

const char *WordToString(unsigned int word) const char *WordToString(unsigned int word)
{ {
// Convert a phoneme mnemonic word into a string // Convert a phoneme mnemonic word into a string
int ix;
static char buf[5]; static char buf[5];


for (ix = 0; ix < 4; ix++)
for (int ix = 0; ix < 4; ix++)
buf[ix] = word >> (ix*8); buf[ix] = word >> (ix*8);
buf[4] = 0; buf[4] = 0;
return buf; return buf;
// control = 1, less shortening at fast speeds // control = 1, less shortening at fast speeds


unsigned int len; unsigned int len;
int srate2;


if (length == 0) if (length == 0)
len = 0; len = 0;
if (len < 90000) if (len < 90000)
len = (len * samplerate) / 1000; // convert from mS to number of samples len = (len * samplerate) / 1000; // convert from mS to number of samples
else { else {
srate2 = samplerate / 25; // avoid overflow
int srate2 = samplerate / 25; // avoid overflow
len = (len * srate2) / 40; len = (len * srate2) / 40;
} }
} }


static int DoSample2(int index, int which, int std_length, int control, int length_mod, int amp) static int DoSample2(int index, int which, int std_length, int control, int length_mod, int amp)
{ {
int length;
int wav_length;
int wav_scale;
int min_length;
int x; int x;
int len4;
intptr_t *q; intptr_t *q;
unsigned char *p; unsigned char *p;


index = index & 0x7fffff; index = index & 0x7fffff;
p = &wavefile_data[index]; p = &wavefile_data[index];
wav_scale = p[2];
wav_length = (p[1] * 256);
int wav_scale = p[2];
int wav_length = (p[1] * 256);
wav_length += p[0]; // length in bytes wav_length += p[0]; // length in bytes


if (wav_length == 0) if (wav_length == 0)
return 0; return 0;


min_length = speed.min_sample_len;
int min_length = speed.min_sample_len;


if (wav_scale == 0) if (wav_scale == 0)
min_length *= 2; // 16 bit samples min_length *= 2; // 16 bit samples
if (length_mod > 0) if (length_mod > 0)
std_length = (std_length * length_mod)/256; std_length = (std_length * length_mod)/256;


length = (std_length * speed.wav_factor)/256;
int length = (std_length * speed.wav_factor)/256;


if (control & pd_DONTLENGTHEN) { if (control & pd_DONTLENGTHEN) {
// this option is used for Stops, with short noise bursts. // this option is used for Stops, with short noise bursts.
if (amp < 0) if (amp < 0)
return length; return length;


len4 = wav_length / 4;
int len4 = wav_length / 4;


index += 4; index += 4;


// Each frame includes its RMS amplitude value, so to set a new // Each frame includes its RMS amplitude value, so to set a new
// RMS just adjust the formant amplitudes by the appropriate ratio // RMS just adjust the formant amplitudes by the appropriate ratio


int x;
int h;
int ix;

static const short sqrt_tab[200] = { static const short sqrt_tab[200] = {
0, 64, 90, 110, 128, 143, 156, 169, 181, 192, 202, 212, 221, 230, 239, 247, 0, 64, 90, 110, 128, 143, 156, 169, 181, 192, 202, 212, 221, 230, 239, 247,
256, 263, 271, 278, 286, 293, 300, 306, 313, 320, 326, 332, 338, 344, 350, 356, 256, 263, 271, 278, 286, 293, 300, 306, 313, 320, 326, 332, 338, 344, 350, 356,
} }


if (fr->rms == 0) return; // check for divide by zero if (fr->rms == 0) return; // check for divide by zero
x = (new_rms * 64)/fr->rms;
int x = (new_rms * 64)/fr->rms;
if (x >= 200) x = 199; if (x >= 200) x = 199;


x = sqrt_tab[x]; // sqrt(new_rms/fr->rms)*0x200; x = sqrt_tab[x]; // sqrt(new_rms/fr->rms)*0x200;


for (ix = 0; ix < 8; ix++) {
int h;
for (int ix = 0; ix < 8; ix++) {
h = fr->fheight[ix] * x; h = fr->fheight[ix] * x;
fr->fheight[ix] = h/0x200; fr->fheight[ix] = h/0x200;
} }
static void formants_reduce_hf(frame_t *fr, int level) static void formants_reduce_hf(frame_t *fr, int level)
{ {
// change height of peaks 2 to 8, percentage // change height of peaks 2 to 8, percentage
int ix;
int x;


if (voice->klattv[0]) if (voice->klattv[0])
return; return;


for (ix = 2; ix < 8; ix++) {
int x;
for (int ix = 2; ix < 8; ix++) {
x = fr->fheight[ix] * level; x = fr->fheight[ix] * level;
fr->fheight[ix] = x/100; fr->fheight[ix] = x/100;
} }


static void AdjustFormants(frame_t *fr, int target, int min, int max, int f1_adj, int f3_adj, int hf_reduce, int flags) static void AdjustFormants(frame_t *fr, int target, int min, int max, int f1_adj, int f3_adj, int hf_reduce, int flags)
{ {
int x;

target = (target * voice->formant_factor)/256; target = (target * voice->formant_factor)/256;


x = (target - fr->ffreq[2]) / 2;
int x = (target - fr->ffreq[2]) / 2;
if (x > max) x = max; if (x > max) x = max;
if (x < min) x = min; if (x < min) x = min;
fr->ffreq[2] += x; fr->ffreq[2] += x;


int FormantTransition2(frameref_t *seq, int *n_frames, unsigned int data1, unsigned int data2, PHONEME_TAB *other_ph, int which) int FormantTransition2(frameref_t *seq, int *n_frames, unsigned int data1, unsigned int data2, PHONEME_TAB *other_ph, int which)
{ {
int ix;
int formant;
int next_rms;

int len;
int rms;
int f1;
int f2;
int f2_min;
int f2_max;
int f3_adj;
int f3_amp;
int flags;
int vcolour;

#define N_VCOLOUR 2 #define N_VCOLOUR 2
// percentage change for each formant in 256ths // percentage change for each formant in 256ths
static short vcolouring[N_VCOLOUR][5] = { static short vcolouring[N_VCOLOUR][5] = {
if (*n_frames < 2) if (*n_frames < 2)
return 0; return 0;


len = (data1 & 0x3f) * 2;
rms = (data1 >> 6) & 0x3f;
flags = (data1 >> 12);
int len = (data1 & 0x3f) * 2;
int rms = (data1 >> 6) & 0x3f;
int flags = (data1 >> 12);


f2 = (data2 & 0x3f) * 50;
f2_min = (((data2 >> 6) & 0x1f) - 15) * 50;
f2_max = (((data2 >> 11) & 0x1f) - 15) * 50;
f3_adj = (((data2 >> 16) & 0x1f) - 15) * 50;
f3_amp = ((data2 >> 21) & 0x1f) * 8;
f1 = ((data2 >> 26) & 0x7);
vcolour = (data2 >> 29);
int f2 = (data2 & 0x3f) * 50;
int f2_min = (((data2 >> 6) & 0x1f) - 15) * 50;
int f2_max = (((data2 >> 11) & 0x1f) - 15) * 50;
int f3_adj = (((data2 >> 16) & 0x1f) - 15) * 50;
int f3_amp = ((data2 >> 21) & 0x1f) * 8;
int f1 = ((data2 >> 26) & 0x7);
int vcolour = (data2 >> 29);


if ((other_ph != NULL) && (other_ph->mnemonic == '?')) if ((other_ph != NULL) && (other_ph->mnemonic == '?'))
flags |= 8; flags |= 8;
seq[0].frflags |= FRFLAG_LEN_MOD2; // reduce length modification seq[0].frflags |= FRFLAG_LEN_MOD2; // reduce length modification
fr->frflags |= FRFLAG_LEN_MOD2; fr->frflags |= FRFLAG_LEN_MOD2;


next_rms = seq[1].frame->rms;
int next_rms = seq[1].frame->rms;


if (voice->klattv[0]) if (voice->klattv[0])
fr->klattp[KLATT_AV] = seq[1].frame->klattp[KLATT_AV] - 4; fr->klattp[KLATT_AV] = seq[1].frame->klattp[KLATT_AV] - 4;
set_frame_rms(fr, rms); set_frame_rms(fr, rms);


if ((vcolour > 0) && (vcolour <= N_VCOLOUR)) { if ((vcolour > 0) && (vcolour <= N_VCOLOUR)) {
for (ix = 0; ix < *n_frames; ix++) {
for (int ix = 0; ix < *n_frames; ix++) {
fr = CopyFrame(seq[ix].frame, 0); fr = CopyFrame(seq[ix].frame, 0);
seq[ix].frame = fr; seq[ix].frame = fr;


for (formant = 1; formant <= 5; formant++) {
for (int formant = 1; formant <= 5; formant++) {
int x; int x;
x = fr->ffreq[formant] * vcolouring[vcolour-1][formant-1]; x = fr->ffreq[formant] * vcolouring[vcolour-1][formant-1];
fr->ffreq[formant] = x / 256; fr->ffreq[formant] = x / 256;
frame_t *frame2; frame_t *frame2;
frame_t *frame1; frame_t *frame1;
frame_t *frame_centre; frame_t *frame_centre;
int ix;
int len; int len;
int pk; int pk;
int modified; int modified;
frame_centre = (frame_t *)q[2]; frame_centre = (frame_t *)q[2];


// backwards // backwards
ix = syllable_centre -1;
int ix = syllable_centre -1;
frame = frame2 = frame_centre; frame = frame2 = frame_centre;
for (;;) { for (;;) {
if (ix < 0) ix = N_WCMDQ-1; if (ix < 0) ix = N_WCMDQ-1;
int len; int len;
int frame_length; int frame_length;
int length_factor; int length_factor;
int length_mod;
int length_sum;
int length_min;
int total_len = 0; int total_len = 0;
static int wave_flag = 0; static int wave_flag = 0;
int wcmd_spect = WCMD_SPECT; int wcmd_spect = WCMD_SPECT;
if (fmt_params->fmt_addr == 0) if (fmt_params->fmt_addr == 0)
return 0; return 0;


length_mod = plist->length;
int length_mod = plist->length;
if (length_mod == 0) length_mod = 256; if (length_mod == 0) length_mod = 256;


length_min = (samplerate/70); // greater than one cycle at low pitch (Hz)
int length_min = (samplerate/70); // greater than one cycle at low pitch (Hz)
if (which == 2) { if (which == 2) {
if ((translator->langopts.param[LOPT_LONG_VOWEL_THRESHOLD] > 0) && ((this_ph->std_length >= translator->langopts.param[LOPT_LONG_VOWEL_THRESHOLD]) || (plist->synthflags & SFLAG_LENGTHEN) || (this_ph->phflags & phLONG))) if ((translator->langopts.param[LOPT_LONG_VOWEL_THRESHOLD] > 0) && ((this_ph->std_length >= translator->langopts.param[LOPT_LONG_VOWEL_THRESHOLD]) || (plist->synthflags & SFLAG_LENGTHEN) || (this_ph->phflags & phLONG)))
length_min *= 2; // ensure long vowels are longer length_min *= 2; // ensure long vowels are longer
syllable_centre = wcmdq_tail; syllable_centre = wcmdq_tail;
} }


length_sum = 0;
int length_sum = 0;
for (frameix = 1; frameix < n_frames; frameix++) { for (frameix = 1; frameix < n_frames; frameix++) {
length_factor = length_mod; length_factor = length_mod;
if (frames[frameix-1].frflags & FRFLAG_LEN_MOD) // reduce effect of length mod if (frames[frameix-1].frflags & FRFLAG_LEN_MOD) // reduce effect of length mod

+ 6
- 14
src/libespeak-ng/tr_languages.c View File

static void ResetLetterBits(Translator *tr, int groups) static void ResetLetterBits(Translator *tr, int groups)
{ {
// Clear all the specified groups // Clear all the specified groups
unsigned int ix;
unsigned int mask;
unsigned int mask = ~groups;


mask = ~groups;

for (ix = 0; ix < sizeof(tr->letter_bits); ix++)
for (int ix = 0; ix < sizeof(tr->letter_bits); ix++)
tr->letter_bits[ix] &= mask; tr->letter_bits[ix] &= mask;
} }


static void SetLetterBits(Translator *tr, int group, const char *string) static void SetLetterBits(Translator *tr, int group, const char *string)
{ {
int bits;
unsigned char c; unsigned char c;


bits = (1L << group);
int bits = (1L << group);
while ((c = *string++) != 0) while ((c = *string++) != 0)
tr->letter_bits[c] |= bits; tr->letter_bits[c] |= bits;
} }


static void SetLetterBitsRange(Translator *tr, int group, int first, int last) static void SetLetterBitsRange(Translator *tr, int group, int first, int last)
{ {
int bits;
int ix;

bits = (1L << group);
for (ix = first; ix <= last; ix++)
int bits = (1L << group);
for (int ix = first; ix <= last; ix++)
tr->letter_bits[ix] |= bits; tr->letter_bits[ix] |= bits;
} }


static Translator *NewTranslator(void) static Translator *NewTranslator(void)
{ {
Translator *tr; Translator *tr;
int ix;
static const unsigned char stress_amps2[] = { 18, 18, 20, 20, 20, 22, 22, 20 }; static const unsigned char stress_amps2[] = { 18, 18, 20, 20, 20, 22, 22, 20 };
static const short stress_lengths2[8] = { 182, 140, 220, 220, 220, 240, 260, 280 }; static const short stress_lengths2[8] = { 182, 140, 220, 220, 220, 240, 260, 280 };
static const wchar_t empty_wstring[1] = { 0 }; static const wchar_t empty_wstring[1] = { 0 };
tr->punct_within_word = punct_in_word; tr->punct_within_word = punct_in_word;
tr->chars_ignore = chars_ignore_default; tr->chars_ignore = chars_ignore_default;


for (ix = 0; ix < 8; ix++) {
for (int ix = 0; ix < 8; ix++) {
tr->stress_amps[ix] = stress_amps2[ix]; tr->stress_amps[ix] = stress_amps2[ix];
tr->stress_amps_r[ix] = stress_amps2[ix] - 1; tr->stress_amps_r[ix] = stress_amps2[ix] - 1;
tr->stress_lengths[ix] = stress_lengths2[ix]; tr->stress_lengths[ix] = stress_lengths2[ix];

+ 16
- 34
src/libespeak-ng/translate.c View File

int lookupwchar(const unsigned short *list, int c) int lookupwchar(const unsigned short *list, int c)
{ {
// Is the character c in the list ? // Is the character c in the list ?
int ix;


for (ix = 0; list[ix] != 0; ix++) {
for (int ix = 0; list[ix] != 0; ix++) {
if (list[ix] == c) if (list[ix] == c)
return ix+1; return ix+1;
} }
// Replace character c by another character. // Replace character c by another character.
// Returns 0 = not found, 1 = delete character // Returns 0 = not found, 1 = delete character


int ix;

for (ix = 0; list[ix] != 0; ix += 2) {
for (int ix = 0; list[ix] != 0; ix += 2) {
if (list[ix] == c) if (list[ix] == c)
return list[ix+1]; return list[ix+1];
} }
// returns the number of bytes written // returns the number of bytes written


int n_bytes; int n_bytes;
int j;
int shift;
static char unsigned code[4] = { 0, 0xc0, 0xe0, 0xf0 }; static char unsigned code[4] = { 0, 0xc0, 0xe0, 0xf0 };


if (c < 0x80) { if (c < 0x80) {
else else
n_bytes = 3; n_bytes = 3;


shift = 6*n_bytes;
int shift = 6*n_bytes;
buf[0] = code[n_bytes] | (c >> shift); buf[0] = code[n_bytes] | (c >> shift);
for (j = 0; j < n_bytes; j++) {
for (int j = 0; j < n_bytes; j++) {
shift -= 6; shift -= 6;
buf[j+1] = 0x80 + ((c >> shift) & 0x3f); buf[j+1] = 0x80 + ((c >> shift) & 0x3f);
} }
// backwards: set if we are moving backwards through the UTF8 string // backwards: set if we are moving backwards through the UTF8 string


int c1; int c1;
int n_bytes;
int ix;
static const unsigned char mask[4] = { 0xff, 0x1f, 0x0f, 0x07 }; static const unsigned char mask[4] = { 0xff, 0x1f, 0x0f, 0x07 };


// find the start of the next/previous character // find the start of the next/previous character
buf++; buf++;
} }


n_bytes = 0;
int n_bytes = 0;


if ((c1 = *buf++) & 0x80) { if ((c1 = *buf++) & 0x80) {
if ((c1 & 0xe0) == 0xc0) if ((c1 & 0xe0) == 0xc0)
n_bytes = 3; n_bytes = 3;


c1 &= mask[n_bytes]; c1 &= mask[n_bytes];
for (ix = 0; ix < n_bytes; ix++)
for (int ix = 0; ix < n_bytes; ix++)
c1 = (c1 << 6) + (*buf++ & 0x3f); c1 = (c1 << 6) + (*buf++ & 0x3f);
} }
*c = c1; *c = c1;
int count = 0; int count = 0;
int nbytes; int nbytes;
int ok; int ok;
int ix;
char *word; char *word;
char *wbuf; char *wbuf;
char word_buf[80]; char word_buf[80];


word = word1; word = word1;
wbuf = word_buf; wbuf = word_buf;
ix = 0;
int ix = 0;


for (;;) { for (;;) {
ok = 0; ok = 0;
char *eqlist; char *eqlist;
char *p_out; char *p_out;
char *p_in; char *p_in;
int remove_stress = 0;
char phonbuf[N_WORD_PHONEMES]; char phonbuf[N_WORD_PHONEMES];


// has a phoneme equivalence table been specified for this language pair? // has a phoneme equivalence table been specified for this language pair?
len = (pb[2] << 8) + pb[3]; // size of this table in words len = (pb[2] << 8) + pb[3]; // size of this table in words
pb += (len * 4); pb += (len * 4);
} }
remove_stress = pb[1];
int remove_stress = pb[1];


if (option_phonemes & espeakPHONEMES_TRACE) { if (option_phonemes & espeakPHONEMES_TRACE) {
DecodePhonemes(phonemes, phonbuf); DecodePhonemes(phonemes, phonbuf);
// word1 is terminated by space (0x20) character // word1 is terminated by space (0x20) character


char *word1; char *word1;
int word_length;
int ix; int ix;
char *p; char *p;
int pfix; int pfix;
char end_phonemes2[N_WORD_PHONEMES]; char end_phonemes2[N_WORD_PHONEMES];
char word_copy[N_WORD_BYTES]; char word_copy[N_WORD_BYTES];
char word_copy2[N_WORD_BYTES]; char word_copy2[N_WORD_BYTES];
int word_copy_length;
char prefix_chars[0x3f + 2]; char prefix_chars[0x3f + 2];
int found = 0; int found = 0;
int end_flags; int end_flags;
int spell_word; int spell_word;
int stress_bits; int stress_bits;
int emphasize_allcaps = 0; int emphasize_allcaps = 0;
int wflags;
int wmark;
int was_unpronouncable = 0; int was_unpronouncable = 0;
int loopcount; int loopcount;
int add_suffix_phonemes = 0; int add_suffix_phonemes = 0;
memset(wtab_null, 0, sizeof(wtab_null)); memset(wtab_null, 0, sizeof(wtab_null));
wtab = wtab_null; wtab = wtab_null;
} }
wflags = wtab->flags;
wmark = wtab->wmark;
int wflags = wtab->flags;
int wmark = wtab->wmark;


dictionary_flags[0] = 0; dictionary_flags[0] = 0;
dictionary_flags[1] = 0; dictionary_flags[1] = 0;
wordx = word1; wordx = word1;


utf8_in(&first_char, wordx); utf8_in(&first_char, wordx);
word_length = 0;
int word_length = 0;
while ((*wordx != 0) && (*wordx != ' ')) { while ((*wordx != 0) && (*wordx != ' ')) {
wordx += utf8_in(&last_char, wordx); wordx += utf8_in(&last_char, wordx);
word_length++; word_length++;
} }


word_copy_length = wordx - word_start;
int word_copy_length = wordx - word_start;
if (word_copy_length >= N_WORD_BYTES) if (word_copy_length >= N_WORD_BYTES)
word_copy_length = N_WORD_BYTES-1; word_copy_length = N_WORD_BYTES-1;
memcpy(word_copy2, word_start, word_copy_length); memcpy(word_copy2, word_start, word_copy_length);
// word's pronunciation is not given in the dictionary list, although // word's pronunciation is not given in the dictionary list, although
// dictionary_flags may have ben set there // dictionary_flags may have ben set there


int posn;
int non_initial;
int length;

posn = 0;
non_initial = 0;
length = 999;
int posn = 0;
int non_initial = 0;
int length = 999;
wordx = word1; wordx = word1;


while (((length < 3) && (length > 0)) || (word_length > 1 && Unpronouncable(tr, wordx, posn))) { while (((length < 3) && (length > 0)) || (word_length > 1 && Unpronouncable(tr, wordx, posn))) {


int UpperCaseInWord(Translator *tr, char *word, int c) int UpperCaseInWord(Translator *tr, char *word, int c)
{ {
int ix;
int len; int len;
const char *p; const char *p;


if (tr->translator_name == L('g', 'a')) { if (tr->translator_name == L('g', 'a')) {
// Irish // Irish
for (ix = 0;; ix++) {
for (int ix = 0;; ix++) {
if ((p = UCase_ga[ix]) == NULL) if ((p = UCase_ga[ix]) == NULL)
break; break;



+ 15
- 29
src/libespeak-ng/voices.c View File

void ReadTonePoints(char *string, int *tone_pts) void ReadTonePoints(char *string, int *tone_pts)
{ {
// tone_pts[] is int[12] // tone_pts[] is int[12]
int ix;


for (ix = 0; ix < 12; ix++)
for (int ix = 0; ix < 12; ix++)
tone_pts[ix] = -1; tone_pts[ix] = -1;


sscanf(string, "%d %d %d %d %d %d %d %d %d %d", sscanf(string, "%d %d %d %d %d %d %d %d %d %d",
char *p; char *p;
espeak_VOICE *voice_data; espeak_VOICE *voice_data;
int priority; int priority;
int age;
int n_variants = 4; // default, number of variants of this voice before using another voice int n_variants = 4; // default, number of variants of this voice before using another voice
int gender;


#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
char fname_buf[sizeof(path_home)+15]; char fname_buf[sizeof(path_home)+15];


vname[0] = 0; vname[0] = 0;
vgender[0] = 0; vgender[0] = 0;
age = 0;
int age = 0;


while (fgets_strip(linebuf, sizeof(linebuf), f_in) != NULL) { while (fgets_strip(linebuf, sizeof(linebuf), f_in) != NULL) {
if (memcmp(linebuf, "name", 4) == 0) { if (memcmp(linebuf, "name", 4) == 0) {
} }
languages[langix++] = 0; languages[langix++] = 0;


gender = LookupMnem(genders, vgender);
int gender = LookupMnem(genders, vgender);


if (n_languages == 0) if (n_languages == 0)
return NULL; // no language lines in the voice file return NULL; // no language lines in the voice file
{ {
// Set voice to the default values // Set voice to the default values


int pk;
static unsigned char default_heights[N_PEAKS] = { 130, 128, 120, 116, 100, 100, 128, 128, 128 }; // changed for v.1.47 static unsigned char default_heights[N_PEAKS] = { 130, 128, 120, 116, 100, 100, 128, 128, 128 }; // changed for v.1.47
static unsigned char default_widths[N_PEAKS] = { 140, 128, 128, 160, 171, 171, 128, 128, 128 }; static unsigned char default_widths[N_PEAKS] = { 140, 128, 128, 160, 171, 171, 128, 128, 128 };


#endif #endif


InitBreath(); InitBreath();
for (pk = 0; pk < N_PEAKS; pk++) {
for (int pk = 0; pk < N_PEAKS; pk++) {
voice->freq[pk] = 256; voice->freq[pk] = 256;
voice->height[pk] = default_heights[pk]*2; voice->height[pk] = default_heights[pk]*2;
voice->width[pk] = default_widths[pk]*2; voice->width[pk] = default_widths[pk]*2;
static void VoiceFormant(char *p) static void VoiceFormant(char *p)
{ {
// Set parameters for a formant // Set parameters for a formant
int ix;
int formant; int formant;
int freq = 100; int freq = 100;
int height = 100; int height = 100;
int width = 100; int width = 100;
int freqadd = 0; int freqadd = 0;


ix = sscanf(p, "%d %d %d %d %d", &formant, &freq, &height, &width, &freqadd);
int ix = sscanf(p, "%d %d %d %d %d", &formant, &freq, &height, &width, &freqadd);
if (ix < 2) if (ix < 2)
return; return;




static void PhonemeReplacement(int type, char *p) static void PhonemeReplacement(int type, char *p)
{ {
int n;
int phon; int phon;
int flags = 0; int flags = 0;
char phon_string1[12]; char phon_string1[12];
char phon_string2[12]; char phon_string2[12];


strcpy(phon_string2, "NULL"); strcpy(phon_string2, "NULL");
n = sscanf(p, "%d %s %s", &flags, phon_string1, phon_string2);
int n = sscanf(p, "%d %s %s", &flags, phon_string1, phon_string2);
if ((n < 2) || (n_replace_phonemes >= N_REPLACE_PHONEMES)) if ((n < 2) || (n_replace_phonemes >= N_REPLACE_PHONEMES))
return; return;


static unsigned int StringToWord2(const char *string) static unsigned int StringToWord2(const char *string)
{ {
// Convert a language name string to a word such as L('e','n') // Convert a language name string to a word such as L('e','n')
int ix;
int c; int c;
unsigned int value = 0; unsigned int value = 0;


for (ix = 0; (ix < 4) && ((c = string[ix]) != 0); ix++)
for (int ix = 0; (ix < 4) && ((c = string[ix]) != 0); ix++)
value = (value << 8) | (c & 0xff); value = (value << 8) | (c & 0xff);
return value; return value;
} }
static int SetVoiceScores(espeak_VOICE *voice_select, espeak_VOICE **voices, int control) static int SetVoiceScores(espeak_VOICE *voice_select, espeak_VOICE **voices, int control)
{ {
// control: bit0=1 include mbrola voices // control: bit0=1 include mbrola voices
int ix;
int score; int score;
int nv; // number of candidates int nv; // number of candidates
int n_parts = 0; int n_parts = 0;
if ((voice_select->languages != NULL) && (voice_select->languages[0] != 0)) { if ((voice_select->languages != NULL) && (voice_select->languages[0] != 0)) {
n_parts = 1; n_parts = 1;
lang_len = strlen(voice_select->languages); lang_len = strlen(voice_select->languages);
for (ix = 0; (ix <= lang_len) && ((unsigned)ix < sizeof(language)); ix++) {
for (int ix = 0; (ix <= lang_len) && ((unsigned)ix < sizeof(language)); ix++) {
if ((language[ix] = tolower(voice_select->languages[ix])) == '-') if ((language[ix] = tolower(voice_select->languages[ix])) == '-')
n_parts++; n_parts++;
} }


// select those voices which match the specified language // select those voices which match the specified language
nv = 0; nv = 0;
for (ix = 0; ix < n_voices_list; ix++) {
for (int ix = 0; ix < n_voices_list; ix++) {
vp = voices_list[ix]; vp = voices_list[ix];


if (((control & 1) == 0) && (memcmp(vp->identifier, "mb/", 3) == 0)) if (((control & 1) == 0) && (memcmp(vp->identifier, "mb/", 3) == 0))


espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name2) espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name2)
{ {
int ix;
int match_fname = -1; int match_fname = -1;
int match_fname2 = -1; int match_fname2 = -1;
int match_name = -1; int match_name = -1;
const char *id; // this is the filename within espeak-data/voices const char *id; // this is the filename within espeak-data/voices
char *variant_name; char *variant_name;
int last_part_len;
char last_part[41]; char last_part[41];
char name[40]; char name[40];


} }


sprintf(last_part, "%c%s", PATHSEP, name); sprintf(last_part, "%c%s", PATHSEP, name);
last_part_len = strlen(last_part);
int last_part_len = strlen(last_part);


for (ix = 0; voices[ix] != NULL; ix++) {
for (int ix = 0; voices[ix] != NULL; ix++) {
if (strcmp(name, voices[ix]->name) == 0) { if (strcmp(name, voices[ix]->name) == 0) {
match_name = ix; // found matching voice name match_name = ix; // found matching voice name
break; break;
espeak_ERROR SetVoiceByName(const char *name) espeak_ERROR SetVoiceByName(const char *name)
{ {
espeak_VOICE *v; espeak_VOICE *v;
int ix;
espeak_VOICE voice_selector; espeak_VOICE voice_selector;
char *variant_name; char *variant_name;
static char buf[60]; static char buf[60];


variant_name = ExtractVoiceVariantName(buf, 0, 1); variant_name = ExtractVoiceVariantName(buf, 0, 1);


for (ix = 0;; ix++) {
for (int ix = 0;; ix++) {
// convert voice name to lower case (ascii) // convert voice name to lower case (ascii)
if ((buf[ix] = tolower(buf[ix])) == 0) if ((buf[ix] = tolower(buf[ix])) == 0)
break; break;


void FreeVoiceList() void FreeVoiceList()
{ {
int ix;
for (ix = 0; ix < n_voices_list; ix++) {
for (int ix = 0; ix < n_voices_list; ix++) {
if (voices_list[ix] != NULL) { if (voices_list[ix] != NULL) {
free(voices_list[ix]); free(voices_list[ix]);
voices_list[ix] = NULL; voices_list[ix] = NULL;
} }
return (const espeak_VOICE **)voices_list; return (const espeak_VOICE **)voices_list;
#else #else
int ix;
int j;
espeak_VOICE *v; espeak_VOICE *v;
static espeak_VOICE **voices = NULL; static espeak_VOICE **voices = NULL;


SetVoiceScores(voice_spec, voices, 1); SetVoiceScores(voice_spec, voices, 1);
} else { } else {
// list all: omit variant voices and mbrola voices and test voices // list all: omit variant voices and mbrola voices and test voices
j = 0;
for (ix = 0; (v = voices_list[ix]) != NULL; ix++) {
int j = 0;
for (int ix = 0; (v = voices_list[ix]) != NULL; ix++) {
if ((v->languages[0] != 0) && (strcmp(&v->languages[1], "variant") != 0) if ((v->languages[0] != 0) && (strcmp(&v->languages[1], "variant") != 0)
&& (memcmp(v->identifier, "mb/", 3) != 0) && (memcmp(v->identifier, "test/", 5) != 0)) && (memcmp(v->identifier, "mb/", 3) != 0) && (memcmp(v->identifier, "test/", 5) != 0))
voices[j++] = v; voices[j++] = v;

+ 2
- 4
src/libespeak-ng/wave_sada.c View File

char *theMono16BitsWaveBuffer, char *theMono16BitsWaveBuffer,
size_t theSize) size_t theSize)
{ {
size_t num;
ENTER("wave_write"); ENTER("wave_write");
if (my_callback_is_output_enabled && (0 == my_callback_is_output_enabled())) { if (my_callback_is_output_enabled && (0 == my_callback_is_output_enabled())) {
SHOW_TIME("wave_write > my_callback_is_output_enabled: no!"); SHOW_TIME("wave_write > my_callback_is_output_enabled: no!");
} }
#endif #endif


num = write((int)theHandler, theMono16BitsWaveBuffer, theSize);
size_t num = write((int)theHandler, theMono16BitsWaveBuffer, theSize);


// Keep track of the total number of samples sent -- we use this in // Keep track of the total number of samples sent -- we use this in
// wave_get_read_position and also use it to help calculate the // wave_get_read_position and also use it to help calculate the
// //
int wave_close(void *theHandler) int wave_close(void *theHandler)
{ {
int ret;
audio_info_t ainfo; audio_info_t ainfo;
int audio_fd = (int)theHandler; int audio_fd = (int)theHandler;
if (!audio_fd) { if (!audio_fd) {
} }
ENTER("wave_close"); ENTER("wave_close");
// [[[WDW: maybe do a pause/resume ioctl???]]] // [[[WDW: maybe do a pause/resume ioctl???]]]
ret = ioctl(audio_fd, I_FLUSH, FLUSHRW);
int ret = ioctl(audio_fd, I_FLUSH, FLUSHRW);
ioctl(audio_fd, AUDIO_GETINFO, &ainfo); ioctl(audio_fd, AUDIO_GETINFO, &ainfo);


// Calculate the number of samples that won't get // Calculate the number of samples that won't get

+ 34
- 70
src/libespeak-ng/wavegen.c View File



int WcmdqFree() int WcmdqFree()
{ {
int i;
i = wcmdq_head - wcmdq_tail;
int i = wcmdq_head - wcmdq_tail;
if (i <= 0) i += N_WCMDQ; if (i <= 0) i += N_WCMDQ;
return i; return i;
} }
PaStreamCallbackFlags flags, void *userData) PaStreamCallbackFlags flags, void *userData)
#endif #endif
{ {
int ix;
int result;
unsigned char *p; unsigned char *p;
unsigned char *out_buf; unsigned char *out_buf;
unsigned char *out_end2; unsigned char *out_end2;
int pa_size;


pa_size = framesPerBuffer*2;
int pa_size = framesPerBuffer*2;


// make a buffer 3x size of the portaudio output // make a buffer 3x size of the portaudio output
ix = pa_size*3;
int ix = pa_size*3;
if (ix > outbuffer_size) { if (ix > outbuffer_size) {
outbuffer = (unsigned char *)realloc(outbuffer, ix); outbuffer = (unsigned char *)realloc(outbuffer, ix);
if (outbuffer == NULL) { if (outbuffer == NULL) {
event_list_ix = 0; event_list_ix = 0;
#endif #endif


result = WavegenFill(1);
int result = WavegenFill(1);


// copy from the outbut buffer into the portaudio buffer // copy from the outbut buffer into the portaudio buffer
if (result && (out_ptr > out_end2)) if (result && (out_ptr > out_end2))


void WavegenInit(int rate, int wavemult_fact) void WavegenInit(int rate, int wavemult_fact)
{ {
int ix;
double x; double x;


if (wavemult_fact == 0) if (wavemult_fact == 0)
wdata.amplitude = 32; wdata.amplitude = 32;
wdata.amplitude_fmt = 100; wdata.amplitude_fmt = 100;


for (ix = 0; ix < N_EMBEDDED_VALUES; ix++)
for (int ix = 0; ix < N_EMBEDDED_VALUES; ix++)
embedded_value[ix] = embedded_default[ix]; embedded_value[ix] = embedded_default[ix];


// set up window to generate a spread of harmonics from a // set up window to generate a spread of harmonics from a
if (samplerate != 22050) { if (samplerate != 22050) {
// wavemult table has preset values for 22050 Hz, we only need to // wavemult table has preset values for 22050 Hz, we only need to
// recalculate them if we have a different sample rate // recalculate them if we have a different sample rate
for (ix = 0; ix < wavemult_max; ix++) {
for (int ix = 0; ix < wavemult_max; ix++) {
x = 127*(1.0 - cos(PI2*ix/wavemult_max)); x = 127*(1.0 - cos(PI2*ix/wavemult_max));
wavemult[ix] = (int)x; wavemult[ix] = (int)x;
} }


int GetAmplitude(void) int GetAmplitude(void)
{ {
int amp;

// normal, none, reduced, moderate, strong // normal, none, reduced, moderate, strong
static const unsigned char amp_emphasis[5] = { 16, 16, 10, 16, 22 }; static const unsigned char amp_emphasis[5] = { 16, 16, 10, 16, 22 };


amp = (embedded_value[EMBED_A])*55/100;
int amp = (embedded_value[EMBED_A])*55/100;
general_amplitude = amp * amp_emphasis[embedded_value[EMBED_F]] / 16; general_amplitude = amp * amp_emphasis[embedded_value[EMBED_F]] / 16;
return general_amplitude; return general_amplitude;
} }


static void WavegenSetEcho(void) static void WavegenSetEcho(void)
{ {
int delay;
int amp;

voicing = wvoice->voicing; voicing = wvoice->voicing;
delay = wvoice->echo_delay;
amp = wvoice->echo_amp;
int delay = wvoice->echo_delay;
int amp = wvoice->echo_amp;


if (delay >= N_ECHO_BUF) if (delay >= N_ECHO_BUF)
delay = N_ECHO_BUF-1; delay = N_ECHO_BUF-1;
int fp; // centre freq of peak int fp; // centre freq of peak
int fhi; // high freq of peak int fhi; // high freq of peak
int h; // harmonic number int h; // harmonic number
int pk;
int hmax;
int pk;
int hmax_samplerate; // highest harmonic allowed for the samplerate int hmax_samplerate; // highest harmonic allowed for the samplerate
int x; int x;
int ix;
int h1;
int ix;


#ifdef SPECT_EDITOR #ifdef SPECT_EDITOR
if (harm_sqrt_n > 0) if (harm_sqrt_n > 0)
// initialise as much of *out as we will need // initialise as much of *out as we will need
if (wvoice == NULL) if (wvoice == NULL)
return 1; return 1;
hmax = (peaks[wvoice->n_harmonic_peaks].freq + peaks[wvoice->n_harmonic_peaks].right)/pitch;
int hmax = (peaks[wvoice->n_harmonic_peaks].freq + peaks[wvoice->n_harmonic_peaks].right)/pitch;
if (hmax >= MAX_HARMONIC) if (hmax >= MAX_HARMONIC)
hmax = MAX_HARMONIC-1; hmax = MAX_HARMONIC-1;


htab[h++] += pk_shape[(f-fp)/(p->right>>8)] * p->height; htab[h++] += pk_shape[(f-fp)/(p->right>>8)] * p->height;
} }


int y;
int h2;
// increase bass // increase bass
y = peaks[1].height * 10; // addition as a multiple of 1/256s
h2 = (1000<<16)/pitch; // decrease until 1000Hz
int y = peaks[1].height * 10; // addition as a multiple of 1/256s
int h2 = (1000<<16)/pitch; // decrease until 1000Hz
if (h2 > 0) { if (h2 > 0) {
x = y/h2; x = y/h2;
h = 1; h = 1;
} }


// adjust the amplitude of the first harmonic, affects tonal quality // adjust the amplitude of the first harmonic, affects tonal quality
h1 = htab[1] * option_harmonic1;
int h1 = htab[1] * option_harmonic1;
htab[1] = h1/8; htab[1] = h1/8;


// calc intermediate increments of LF harmonics // calc intermediate increments of LF harmonics
{ {
// Called every 64 samples to increment the formant freq, height, and widths // Called every 64 samples to increment the formant freq, height, and widths


int x;
int ix; int ix;
static int Flutter_ix = 0; static int Flutter_ix = 0;


// advance the pitch // advance the pitch
wdata.pitch_ix += wdata.pitch_inc; wdata.pitch_ix += wdata.pitch_inc;
if ((ix = wdata.pitch_ix>>8) > 127) ix = 127; if ((ix = wdata.pitch_ix>>8) > 127) ix = 127;
x = wdata.pitch_env[ix] * wdata.pitch_range;
int x = wdata.pitch_env[ix] * wdata.pitch_range;
wdata.pitch = (x>>8) + wdata.pitch_base; wdata.pitch = (x>>8) + wdata.pitch_base;


amp_ix += amp_inc; amp_ix += amp_inc;
#ifndef PLATFORM_RISCOS #ifndef PLATFORM_RISCOS
static double resonator(RESONATOR *r, double input) static double resonator(RESONATOR *r, double input)
{ {
double x;

x = r->a * input + r->b * r->x1 + r->c * r->x2;
double x = r->a * input + r->b * r->x1 + r->c * r->x2;
r->x2 = r->x1; r->x2 = r->x1;
r->x1 = x; r->x1 = x;


// bwidth Bandwidth of resonator in Hz // bwidth Bandwidth of resonator in Hz
// init Initialize internal data // init Initialize internal data


double x;
double arg;

if (init) { if (init) {
rp->x1 = 0; rp->x1 = 0;
rp->x2 = 0; rp->x2 = 0;
} }


arg = minus_pi_t * bwidth;
x = exp(arg);
double arg = minus_pi_t * bwidth;
double x = exp(arg);


rp->c = -(x * x); rp->c = -(x * x);


void InitBreath(void) void InitBreath(void)
{ {
#ifndef PLATFORM_RISCOS #ifndef PLATFORM_RISCOS
int ix;


minus_pi_t = -PI / samplerate; minus_pi_t = -PI / samplerate;
two_pi_t = -2.0 * minus_pi_t; two_pi_t = -2.0 * minus_pi_t;


for (ix = 0; ix < N_PEAKS; ix++)
for (int ix = 0; ix < N_PEAKS; ix++)
setresonator(&rbreath[ix], 2000, 200, 1); setresonator(&rbreath[ix], 2000, 200, 1);
#endif #endif
} }
static void SetBreath() static void SetBreath()
{ {
#ifndef PLATFORM_RISCOS #ifndef PLATFORM_RISCOS
int pk;


if (wvoice->breath[0] == 0) if (wvoice->breath[0] == 0)
return; return;


for (pk = 1; pk < N_PEAKS; pk++) {
for (int pk = 1; pk < N_PEAKS; pk++) {
if (wvoice->breath[pk] != 0) { if (wvoice->breath[pk] != 0) {
// breath[0] indicates that some breath formants are needed // breath[0] indicates that some breath formants are needed
// set the freq from the current ynthesis formant and the width from the voice data // set the freq from the current ynthesis formant and the width from the voice data
{ {
int value = 0; int value = 0;
#ifndef PLATFORM_RISCOS #ifndef PLATFORM_RISCOS
int noise;
int ix;
int amp; int amp;


// use two random numbers, for alternate formants // use two random numbers, for alternate formants
noise = (rand() & 0x3fff) - 0x2000;
int noise = (rand() & 0x3fff) - 0x2000;


for (ix = 1; ix < N_PEAKS; ix++) {
for (int ix = 1; ix < N_PEAKS; ix++) {
if ((amp = wvoice->breath[ix]) != 0) { if ((amp = wvoice->breath[ix]) != 0) {
amp *= (peaks[ix].height >> 14); amp *= (peaks[ix].height >> 14);
value += (int)resonator(&rbreath[ix], noise) * amp; value += (int)resonator(&rbreath[ix], noise) * amp;


static void SetPitchFormants() static void SetPitchFormants()
{ {
int ix;
int factor = 256; int factor = 256;
int pitch_value; int pitch_value;


factor = 256 + (25 * (pitch_value - 50))/50; factor = 256 + (25 * (pitch_value - 50))/50;
} }


for (ix = 0; ix <= 5; ix++)
for (int ix = 0; ix <= 5; ix++)
wvoice->freq[ix] = (wvoice->freq2[ix] * factor)/256; wvoice->freq[ix] = (wvoice->freq2[ix] * factor)/256;


factor = embedded_value[EMBED_T]*3; factor = embedded_value[EMBED_T]*3;
{ {
// there was an embedded command in the text at this point // there was an embedded command in the text at this point
int sign = 0; int sign = 0;
int command;


command = control & 0x1f;
int command = control & 0x1f;
if ((control & 0x60) == 0x60) if ((control & 0x60) == 0x60)
sign = -1; sign = -1;
else if ((control & 0x60) == 0x40) else if ((control & 0x60) == 0x40)


void SetPitch2(voice_t *voice, int pitch1, int pitch2, int *pitch_base, int *pitch_range) void SetPitch2(voice_t *voice, int pitch1, int pitch2, int *pitch_base, int *pitch_range)
{ {
int x;
int base;
int range;
int pitch_value; int pitch_value;


if (pitch1 > pitch2) { if (pitch1 > pitch2) {
x = pitch1; // swap values
int x = pitch1; // swap values
pitch1 = pitch2; pitch1 = pitch2;
pitch2 = x; pitch2 = x;
} }
if (pitch_value < 0) if (pitch_value < 0)
pitch_value = 0; pitch_value = 0;


base = (voice->pitch_base * pitch_adjust_tab[pitch_value])/128;
range = (voice->pitch_range * embedded_value[EMBED_R])/50;
int base = (voice->pitch_base * pitch_adjust_tab[pitch_value])/128;
int range = (voice->pitch_range * embedded_value[EMBED_R])/50;


// compensate for change in pitch when the range is narrowed or widened // compensate for change in pitch when the range is narrowed or widened
base -= (range - voice->pitch_range)*18; base -= (range - voice->pitch_range)*18;
{ {
int ix; int ix;
DOUBLEX next; DOUBLEX next;
int length2;
int length4;
int qix;
int cmd;
static int glottal_reduce_tab1[4] = { 0x30, 0x30, 0x40, 0x50 }; // vowel before [?], amp * 1/256 static int glottal_reduce_tab1[4] = { 0x30, 0x30, 0x40, 0x50 }; // vowel before [?], amp * 1/256
static int glottal_reduce_tab2[4] = { 0x90, 0xa0, 0xb0, 0xc0 }; // vowel after [?], amp * 1/256 static int glottal_reduce_tab2[4] = { 0x90, 0xa0, 0xb0, 0xc0 }; // vowel after [?], amp * 1/256


glottal_reduce = glottal_reduce_tab2[(modn >> 8) & 3]; glottal_reduce = glottal_reduce_tab2[(modn >> 8) & 3];
} }


for (qix = wcmdq_head+1;; qix++) {
for (int qix = wcmdq_head+1;; qix++) {
if (qix >= N_WCMDQ) qix = 0; if (qix >= N_WCMDQ) qix = 0;
if (qix == wcmdq_tail) break; if (qix == wcmdq_tail) break;


cmd = wcmdq[qix][0];
int cmd = wcmdq[qix][0];
if (cmd == WCMD_SPECT) { if (cmd == WCMD_SPECT) {
end_wave = 0; // next wave generation is from another spectrum end_wave = 0; // next wave generation is from another spectrum
break; break;
} }


// round the length to a multiple of the stepsize // round the length to a multiple of the stepsize
length2 = (length + STEPSIZE/2) & ~0x3f;
int length2 = (length + STEPSIZE/2) & ~0x3f;
if (length2 == 0) if (length2 == 0)
length2 = STEPSIZE; length2 = STEPSIZE;


samplecount_start = samplecount; samplecount_start = samplecount;
nsamples += length2; nsamples += length2;


length4 = length2/4;
int length4 = length2/4;


peaks[7].freq = (7800 * v->freq[7] + v->freqadd[7]*256) << 8; peaks[7].freq = (7800 * v->freq[7] + v->freqadd[7]*256) << 8;
peaks[8].freq = (9000 * v->freq[8] + v->freqadd[8]*256) << 8; peaks[8].freq = (9000 * v->freq[8] + v->freqadd[8]*256) << 8;
void Write4Bytes(FILE *f, int value) void Write4Bytes(FILE *f, int value)
{ {
// Write 4 bytes to a file, least significant first // Write 4 bytes to a file, least significant first
int ix;

for (ix = 0; ix < 4; ix++) {
for (int ix = 0; ix < 4; ix++) {
fputc(value & 0xff, f); fputc(value & 0xff, f);
value = value >> 8; value = value >> 8;
} }
// Call WavegenFill2, and then speed up the output samples. // Call WavegenFill2, and then speed up the output samples.
int WavegenFill(int fill_zeros) int WavegenFill(int fill_zeros)
{ {
int finished;
unsigned char *p_start; unsigned char *p_start;


p_start = out_ptr; p_start = out_ptr;


// fill_zeros is ignored. It is now done in the portaudio callback // fill_zeros is ignored. It is now done in the portaudio callback
finished = WavegenFill2(0);
int finished = WavegenFill2(0);


#if HAVE_SONIC_H #if HAVE_SONIC_H
if (sonicSpeed > 1.0) { if (sonicSpeed > 1.0) {

+ 9
- 17
src/speak-ng.c View File



void DisplayVoices(FILE *f_out, char *language) void DisplayVoices(FILE *f_out, char *language)
{ {
int ix;
const char *p; const char *p;
int len; int len;
int count; int count;


fprintf(f_out, "Pty Language Age/Gender VoiceName File Other Languages\n"); fprintf(f_out, "Pty Language Age/Gender VoiceName File Other Languages\n");


for (ix = 0; (v = voices[ix]) != NULL; ix++) {
for (int ix = 0; (v = voices[ix]) != NULL; ix++) {
count = 0; count = 0;
p = v->languages; p = v->languages;
while (*p != 0) { while (*p != 0) {


static void CloseWaveFile() static void CloseWaveFile()
{ {
unsigned int pos;

if ((f_wave == NULL) || (f_wave == stdout)) if ((f_wave == NULL) || (f_wave == stdout))
return; return;


fflush(f_wave); fflush(f_wave);
pos = ftell(f_wave);
unsigned int pos = ftell(f_wave);


fseek(f_wave, 4, SEEK_SET); fseek(f_wave, 4, SEEK_SET);
Write4Bytes(f_wave, pos - 8); Write4Bytes(f_wave, pos - 8);
fseek(f_wave, 40, SEEK_SET); fseek(f_wave, 40, SEEK_SET);
Write4Bytes(f_wave, pos - 44); Write4Bytes(f_wave, pos - 44);



fclose(f_wave); fclose(f_wave);
f_wave = NULL; f_wave = NULL;
} }


static int WavegenFile(void) static int WavegenFile(void)
{ {
int finished;
unsigned char wav_outbuf[1024]; unsigned char wav_outbuf[1024];
char fname[210]; char fname[210];


out_ptr = out_start = wav_outbuf; out_ptr = out_start = wav_outbuf;
out_end = wav_outbuf + sizeof(wav_outbuf); out_end = wav_outbuf + sizeof(wav_outbuf);


finished = WavegenFill(0);
int finished = WavegenFill(0);


if (quiet) if (quiet)
return finished; return finished;


static int initialise(void) static int initialise(void)
{ {
int param;
int result;
int srate = 22050; // default sample rate int srate = 22050; // default sample rate


// It seems that the wctype functions don't work until the locale has been set // It seems that the wctype functions don't work until the locale has been set
} }
#endif #endif


int result;
if ((result = LoadPhData(&srate)) != 1) { if ((result = LoadPhData(&srate)) != 1) {
if (result == -1) { if (result == -1) {
fprintf(stderr, "Failed to load espeak-data\n"); fprintf(stderr, "Failed to load espeak-data\n");
SetVoiceStack(NULL, ""); SetVoiceStack(NULL, "");
SynthesizeInit(); SynthesizeInit();


for (param = 0; param < N_SPEECH_PARAM; param++)
for (int param = 0; param < N_SPEECH_PARAM; param++)
param_stack[0].parameter[param] = param_defaults[param]; param_stack[0].parameter[param] = param_defaults[param];


return 0; return 0;
int c; int c;
int value; int value;
int speed = 175; int speed = 175;
int ix;
char *optarg2; char *optarg2;
int amp = 100; // default int amp = 100; // default
int wordgap = 0; int wordgap = 0;
optind = 1; optind = 1;
opt_string = ""; opt_string = "";
while (optind < argc) { while (optind < argc) {
int len;
char *p; char *p;


if ((c = *opt_string) == 0) { if ((c = *opt_string) == 0) {
break; // -- means don't interpret further - as commands break; // -- means don't interpret further - as commands


opt_string = ""; opt_string = "";
for (ix = 0;; ix++) {
for (int ix = 0;; ix++) {
if (long_options[ix].name == 0) if (long_options[ix].name == 0)
break; break;
len = strlen(long_options[ix].name);
size_t len = strlen(long_options[ix].name);
if (memcmp(long_options[ix].name, p, len) == 0) { if (memcmp(long_options[ix].name, p, len) == 0) {
c = long_options[ix].val; c = long_options[ix].val;
optarg2 = NULL; optarg2 = NULL;
case 0x103: // --punct case 0x103: // --punct
option_punctuation = 1; option_punctuation = 1;
if (optarg2 != NULL) { if (optarg2 != NULL) {
ix = 0;
int ix = 0;
while ((ix < N_PUNCTLIST) && ((option_punctlist[ix] = optarg2[ix]) != 0)) ix++; while ((ix < N_PUNCTLIST) && ((option_punctlist[ix] = optarg2[ix]) != 0)) ix++;
option_punctlist[N_PUNCTLIST-1] = 0; option_punctlist[N_PUNCTLIST-1] = 0;
option_punctuation = 2; option_punctuation = 2;
InitText(0); InitText(0);
SpeakNextClause(f_text, p_text, 0); SpeakNextClause(f_text, p_text, 0);


ix = 1;
int ix = 1;
for (;;) { for (;;) {
if (WavegenFile() != 0) { if (WavegenFile() != 0) {
if (ix == 0) if (ix == 0)

Loading…
Cancel
Save