Browse Source

Remove extra newlines from the files to provide consistent spacing.

master
Reece H. Dunn 9 years ago
parent
commit
f0c2c4cca2

+ 0
- 55
src/espeak-ng.c View File

// This version of the command-line speak program uses the // This version of the command-line speak program uses the
// libespeak.so.1 library // libespeak.so.1 library




static const char *help_text = static const char *help_text =
"\nespeak-ng [options] [\"<words>\"]\n\n" "\nespeak-ng [options] [\"<words>\"]\n\n"
"-f <text file> Text file to speak\n" "-f <text file> Text file to speak\n"
"\t List the available voices for the specified language.\n" "\t List the available voices for the specified language.\n"
"\t If <language> is omitted, then list all voices.\n"; "\t If <language> is omitted, then list all voices.\n";





int samplerate; int samplerate;
int quiet = 0; int quiet = 0;
unsigned int samples_total = 0; unsigned int samples_total = 0;
char filetype[5]; char filetype[5];
char wavefile[200]; char wavefile[200];



void DisplayVoices(FILE *f_out, char *language) void DisplayVoices(FILE *f_out, char *language)
{ {
int ix; int ix;
} }
} }





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 OpenWavFile(char *path, int rate) int OpenWavFile(char *path, int rate)
{ {
static unsigned char wave_hdr[44] = { static unsigned char wave_hdr[44] = {
return 1; return 1;
} }



fwrite(wave_hdr, 1, 24, f_wavfile); fwrite(wave_hdr, 1, 24, f_wavfile);
Write4Bytes(f_wavfile, rate); Write4Bytes(f_wavfile, rate);
Write4Bytes(f_wavfile, rate * 2); Write4Bytes(f_wavfile, rate * 2);
return 0; return 0;
} }




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


} }



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



static void PrintVersion() static void PrintVersion()
{ {
const char *version; const char *version;
printf("eSpeak text-to-speech: %s Data at: %s\n", version, path_data); printf("eSpeak text-to-speech: %s Data at: %s\n", version, path_data);
} }




#ifdef NEED_GETOPT #ifdef NEED_GETOPT
struct option { struct option {
char *name; char *name;


static const char *err_load = "Failed to read "; static const char *err_load = "Failed to read ";



FILE *f_text = NULL; FILE *f_text = NULL;
char *p_text = NULL; char *p_text = NULL;
FILE *f_phonemes_out = stdout; FILE *f_phonemes_out = stdout;
else else
synth_flags |= espeakCHARS_8BIT; synth_flags |= espeakCHARS_8BIT;
break; break;

case 'h': case 'h':
printf("\n"); printf("\n");
PrintVersion(); PrintVersion();
printf("%s", help_text); printf("%s", help_text);
exit(0); exit(0);
break; break;

case 'k': case 'k':
option_capitals = atoi(optarg2); option_capitals = atoi(optarg2);
break; break;

case 'x': case 'x':
phoneme_options |= espeakPHONEMES_SHOW; phoneme_options |= espeakPHONEMES_SHOW;
break; break;

case 'X': case 'X':
phoneme_options |= espeakPHONEMES_TRACE; phoneme_options |= espeakPHONEMES_TRACE;
break; break;

case 'm': case 'm':
synth_flags |= espeakSSML; synth_flags |= espeakSSML;
break; break;

case 'p': case 'p':
pitch = atoi(optarg2); pitch = atoi(optarg2);
break; break;

case 'q': case 'q':
quiet = 1; quiet = 1;
break; break;

case 'f': case 'f':
strncpy0(filename, optarg2, sizeof(filename)); strncpy0(filename, optarg2, sizeof(filename));
break; break;

case 'l': case 'l':
option_linelength = atoi(optarg2); option_linelength = atoi(optarg2);
break; break;

case 'a': case 'a':
volume = atoi(optarg2); volume = atoi(optarg2);
break; break;

case 's': case 's':
speed = atoi(optarg2); speed = atoi(optarg2);
break; break;

case 'g': case 'g':
wordgap = atoi(optarg2); wordgap = atoi(optarg2);
break; break;

case 'v': case 'v':
strncpy0(voicename, optarg2, sizeof(voicename)); strncpy0(voicename, optarg2, sizeof(voicename));
break; break;

case 'w': case 'w':
option_waveout = 1; option_waveout = 1;
strncpy0(wavefile, optarg2, sizeof(filename)); strncpy0(wavefile, optarg2, sizeof(filename));
break; break;

case 'z': // remove pause from the end of a sentence case 'z': // remove pause from the end of a sentence
synth_flags &= ~espeakENDPAUSE; synth_flags &= ~espeakENDPAUSE;
break; break;

case 0x100: // --stdin case 0x100: // --stdin
flag_stdin = 1; flag_stdin = 1;
break; break;

case 0x105: // --stdout case 0x105: // --stdout
option_waveout = 1; option_waveout = 1;
strcpy(wavefile, "stdout"); strcpy(wavefile, "stdout");
break; break;

case 0x101: // --compile-debug case 0x101: // --compile-debug
case 0x102: // --compile case 0x102: // --compile
strncpy0(voicename, optarg2, sizeof(voicename)); strncpy0(voicename, optarg2, sizeof(voicename));
flag_compile = c; flag_compile = c;
quiet = 1; quiet = 1;
break; break;

case 0x103: // --punct case 0x103: // --punct
option_punctuation = 1; option_punctuation = 1;
if (optarg2 != NULL) { if (optarg2 != NULL) {
option_punctuation = 2; option_punctuation = 2;
} }
break; break;

case 0x104: // --voices case 0x104: // --voices
espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, 0, data_path, 0); espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, 0, data_path, 0);
DisplayVoices(stdout, optarg2); DisplayVoices(stdout, optarg2);
exit(0); exit(0);

case 0x106: // -- split case 0x106: // -- split
if (optarg2 == NULL) if (optarg2 == NULL)
samples_split_seconds = 30 * 60; // default 30 minutes samples_split_seconds = 30 * 60; // default 30 minutes
else else
samples_split_seconds = atoi(optarg2) * 60; samples_split_seconds = atoi(optarg2) * 60;
break; break;

case 0x107: // --path case 0x107: // --path
data_path = optarg2; data_path = optarg2;
break; break;

case 0x108: // --phonout case 0x108: // --phonout
if ((f_phonemes_out = fopen(optarg2, "w")) == NULL) if ((f_phonemes_out = fopen(optarg2, "w")) == NULL)
fprintf(stderr, "Can't write to: %s\n", optarg2); fprintf(stderr, "Can't write to: %s\n", optarg2);
break; break;

case 0x109: // --pho case 0x109: // --pho
phoneme_options |= espeakPHONEMES_MBROLA; phoneme_options |= espeakPHONEMES_MBROLA;
break; break;

case 0x10a: // --ipa case 0x10a: // --ipa
phoneme_options |= espeakPHONEMES_IPA; phoneme_options |= espeakPHONEMES_IPA;
if (optarg2 != NULL) { if (optarg2 != NULL) {


} }
break; break;

case 0x10b: // --version case 0x10b: // --version
PrintVersion(); PrintVersion();
exit(0); exit(0);

case 0x10c: // --sep case 0x10c: // --sep
phoneme_options |= espeakPHONEMES_SHOW; phoneme_options |= espeakPHONEMES_SHOW;
if (optarg2 == 0) if (optarg2 == 0)
if (phonemes_separator == 'z') if (phonemes_separator == 'z')
phonemes_separator = 0x200c; // ZWNJ phonemes_separator = 0x200c; // ZWNJ
break; break;

case 0x10d: // --tie case 0x10d: // --tie
phoneme_options |= (espeakPHONEMES_SHOW | espeakPHONEMES_TIE); phoneme_options |= (espeakPHONEMES_SHOW | espeakPHONEMES_TIE);
if (optarg2 == 0) if (optarg2 == 0)
if (phonemes_separator == 'z') if (phonemes_separator == 'z')
phonemes_separator = 0x200d; // ZWJ phonemes_separator = 0x200d; // ZWJ
break; break;

case 0x10e: // --compile-mbrola case 0x10e: // --compile-mbrola
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, 0); samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, 0);
espeak_ng_CompileMbrolaVoice(optarg2, stdout); espeak_ng_CompileMbrolaVoice(optarg2, stdout);
exit(0); exit(0);

case 0x10f: // --compile-intonations case 0x10f: // --compile-intonations
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, espeakINITIALIZE_PATH_ONLY); samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, espeakINITIALIZE_PATH_ONLY);
espeak_ng_CompileIntonation(stdout); espeak_ng_CompileIntonation(stdout);
exit(0); exit(0);

case 0x110: // --compile-phonemes case 0x110: // --compile-phonemes
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, espeakINITIALIZE_PATH_ONLY); samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, espeakINITIALIZE_PATH_ONLY);
espeak_ng_CompilePhonemeData(22050, stdout); espeak_ng_CompilePhonemeData(22050, stdout);
exit(0); exit(0);

default: default:
exit(0); exit(0);
} }
} }



if (option_waveout || quiet) { if (option_waveout || quiet) {
// writing to a file (or no output), we can use synchronous mode // writing to a file (or no output), we can use synchronous mode
samplerate = espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, 0, data_path, 0); samplerate = espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, 0, data_path, 0);
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, 0); samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, 0);
} }



if (voicename[0] == 0) if (voicename[0] == 0)
strcpy(voicename, "default"); strcpy(voicename, "default");


if (option_punctuation == 2) if (option_punctuation == 2)
espeak_SetPunctuationList(option_punctlist); espeak_SetPunctuationList(option_punctlist);



espeak_SetPhonemeTrace(phoneme_options | (phonemes_separator << 8), f_phonemes_out); espeak_SetPhonemeTrace(phoneme_options | (phonemes_separator << 8), f_phonemes_out);


if (filename[0] == 0) { if (filename[0] == 0) {
exit(1); exit(1);
} }



if (p_text != NULL) { if (p_text != NULL) {
int size; int size;
size = strlen(p_text); size = strlen(p_text);

+ 2
- 144
src/libespeak-ng/compiledata.c View File

{ NULL, 0, 0 } { NULL, 0, 0 }
}; };




static keywtab_t k_properties[] = { static keywtab_t k_properties[] = {
{ "isPause", 0, phPAUSE }, { "isPause", 0, phPAUSE },
{ "isVowel", 0, phVOWEL }, { "isVowel", 0, phVOWEL },
{ "afr", tPHONEME_TYPE, phSTOP }, // treat as stop { "afr", tPHONEME_TYPE, phSTOP }, // treat as stop
{ "apr", tPHONEME_TYPE, phFRICATIVE }, // [h] voiceless approximant { "apr", tPHONEME_TYPE, phFRICATIVE }, // [h] voiceless approximant



// keywords // keywords
{ "phonemenumber", tSTATEMENT, kPHONEMENUMBER }, { "phonemenumber", tSTATEMENT, kPHONEMENUMBER },
{ "phonemetable", tSTATEMENT, kPHONEMETABLE }, { "phonemetable", tSTATEMENT, kPHONEMETABLE },
{ "endtype", tSTATEMENT, kENDTYPE }, { "endtype", tSTATEMENT, kENDTYPE },
{ "voicingswitch", tSTATEMENT, kVOICINGSWITCH }, { "voicingswitch", tSTATEMENT, kVOICINGSWITCH },



{ "IF", tSTATEMENT, kIF }, { "IF", tSTATEMENT, kIF },
{ "ELSE", tSTATEMENT, kELSE }, { "ELSE", tSTATEMENT, kELSE },
{ "ELIF", tSTATEMENT, kELIF }, { "ELIF", tSTATEMENT, kELIF },
{ "VowelEnding", tSTATEMENT, kVOWELENDING }, { "VowelEnding", tSTATEMENT, kVOWELENDING },
{ "addWav", tSTATEMENT, kANDWAV }, { "addWav", tSTATEMENT, kANDWAV },



{ "Vowelin", tSTATEMENT, kVOWELIN }, { "Vowelin", tSTATEMENT, kVOWELIN },
{ "Vowelout", tSTATEMENT, kVOWELOUT }, { "Vowelout", tSTATEMENT, kVOWELOUT },
{ "Continue", tSTATEMENT, kCONTINUE }, { "Continue", tSTATEMENT, kCONTINUE },
{ NULL, 0, -1 } { NULL, 0, -1 }
}; };



static keywtab_t *keyword_tabs[] = { static keywtab_t *keyword_tabs[] = {
keywords, k_conditions, k_properties, k_intonation keywords, k_conditions, k_properties, k_intonation
}; };



static PHONEME_TAB *phoneme_out; static PHONEME_TAB *phoneme_out;


static int n_phcodes_list[N_PHONEME_TABS]; static int n_phcodes_list[N_PHONEME_TABS];
static char *p_equivalence; static char *p_equivalence;
static char equivalence_buf[20000]; static char equivalence_buf[20000];



#define N_PROCS 50 #define N_PROCS 50
int n_procs; int n_procs;
int proc_addr[N_PROCS]; int proc_addr[N_PROCS];
fprintf(f_out, ")"); fprintf(f_out, ")");
} }
break; break;

case 2: case 2:
case 3: case 3:
if (type2 < 12) { if (type2 < 12) {
} }
fprintf(f_out, ")"); fprintf(f_out, ")");
break; break;

case 6: case 6:
fprintf(f_out, "%s", instn_jumps[(instn >> 9) & 7]); fprintf(f_out, "%s", instn_jumps[(instn >> 9) & 7]);
fprintf(f_out, " %d", instn & 0x1ff); fprintf(f_out, " %d", instn & 0x1ff);
break; break;

case 9: case 9:
address = ((data1 & 0xf) << 4) + *pc++; address = ((data1 & 0xf) << 4) + *pc++;
fprintf(f_out, "CALL %.5x", address); fprintf(f_out, "CALL %.5x", address);
break; break;

case 10: case 10:
fprintf(f_out, "%s", instn10_string[type2]); fprintf(f_out, "%s", instn10_string[type2]);
switch (type2) switch (type2)
break; break;
} }
break; break;

case 11: case 11:
case 12: case 12:
case 13: case 13:
} }
} }






static int n_phoneme_tabs; static int n_phoneme_tabs;
static int n_phcodes; static int n_phcodes;


static FILE *f_prog_log = NULL; static FILE *f_prog_log = NULL;
static FILE *f_report; static FILE *f_report;



static FILE *f_in; static FILE *f_in;
static int f_in_linenum; static int f_in_linenum;
static int f_in_displ; static int f_in_displ;



static int linenum; static int linenum;
static int count_references = 0; static int count_references = 0;
static int duplicate_references = 0; static int duplicate_references = 0;


static REF_HASH_TAB *ref_hash_tab[256]; static REF_HASH_TAB *ref_hash_tab[256];



#define N_ENVELOPES 30 #define N_ENVELOPES 30
int n_envelopes = 0; int n_envelopes = 0;
char envelope_paths[N_ENVELOPES][80]; char envelope_paths[N_ENVELOPES][80];
unsigned char envelope_dat[N_ENVELOPES][ENV_LEN]; unsigned char envelope_dat[N_ENVELOPES][ENV_LEN];



typedef struct { typedef struct {
FILE *file; FILE *file;
int linenum; int linenum;
} IF_STACK; } IF_STACK;
IF_STACK if_stack[N_IF_STACK]; IF_STACK if_stack[N_IF_STACK];



enum { enum {
tENDFILE = 1, tENDFILE = 1,
tSTRING, tSTRING,
#define N_ITEM_STRING 256 #define N_ITEM_STRING 256
char item_string[N_ITEM_STRING]; char item_string[N_ITEM_STRING];




static int ref_sorter(char **a, char **b) static int ref_sorter(char **a, char **b)
{ {
int ix; int ix;
return p1->ph_mnemonic - p2->ph_mnemonic; return p1->ph_mnemonic - p2->ph_mnemonic;
} }




static void CompileReport(void) static void CompileReport(void)
{ {
int ix; int ix;
fclose(f_report); fclose(f_report);
} }



static void error(const char *format, const char *string) static void error(const char *format, const char *string)
{ {
if (string == NULL) if (string == NULL)
return f; return f;
} }



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
return word; return word;
} }



static MNEM_TAB reserved_phonemes[] = { static MNEM_TAB reserved_phonemes[] = {
{ "_\001", phonCONTROL }, // NOT USED { "_\001", phonCONTROL }, // NOT USED
{ "%", phonSTRESS_U }, { "%", phonSTRESS_U },
{ NULL, 0 } { NULL, 0 }
}; };



static void ReservePhCodes() static void ReservePhCodes()
{ {
// Reserve phoneme codes which have fixed numbers so that they can be // Reserve phoneme codes which have fixed numbers so that they can be
} }
} }



static int LookupPhoneme(const char *string, int control) static int LookupPhoneme(const char *string, int control)
{ {
// control = 0 explicit declaration // control = 0 explicit declaration
return use; return use;
} }




static unsigned int get_char() static unsigned int get_char()
{ {
unsigned int c; unsigned int c;
linenum--; linenum--;
} }



int CheckNextChar() int CheckNextChar()
{ {
int c; int c;
return c; return c;
} }



static int NextItem(int type) static int NextItem(int type)
{ {
int acc; int acc;
return acc * sign; return acc * sign;
} }



if ((type >= tKEYWORD) && (type <= tINTONATION)) { if ((type >= tKEYWORD) && (type <= tINTONATION)) {
pk = keyword_tabs[type-tKEYWORD]; pk = keyword_tabs[type-tKEYWORD];
while (pk->mnem != NULL) { while (pk->mnem != NULL) {
return -1; return -1;
} }




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
return value; return value;
} }




static int NextItemBrackets(int type, int control) static int NextItemBrackets(int type, int control)
{ {
// Expect a parameter inside parantheses // Expect a parameter inside parantheses
if (item_terminator != ')') if (item_terminator != ')')
error("Expected ')'", NULL); error("Expected ')'", NULL);
return value; return value;

} }



static void UngetItem() static void UngetItem()
{ {
fseek(f_in, f_in_displ, SEEK_SET); fseek(f_in, f_in_displ, SEEK_SET);
linenum = f_in_linenum; linenum = f_in_linenum;
} }





static int Range(int value, int divide, int min, int max) static int Range(int value, int divide, int min, int max)
{ {
if (value < 0) if (value < 0)
return value - min; return value - min;
} }



int CompileVowelTransition(int which) int CompileVowelTransition(int which)
{ {
// Compile a vowel transition // Compile a vowel transition
return 0; return 0;
} }




int LoadSpect(const char *path, int control) int LoadSpect(const char *path, int control)
{ {
SpectSeq *spectseq; SpectSeq *spectseq;
return displ; return displ;
} }




static int LoadWavefile(FILE *f, const char *fname) static int LoadWavefile(FILE *f, const char *fname)
{ {
int displ; int displ;
if (system(command) != 0) if (system(command) != 0)
failed = 1; failed = 1;



if (failed || (GetFileLength(fname_temp) <= 0)) { if (failed || (GetFileLength(fname_temp) <= 0)) {
if (resample_fails < 2) if (resample_fails < 2)
error("Resample command failed: %s", command); error("Resample command failed: %s", command);
max = sample; max = sample;
else if (sample < -max) else if (sample < -max)
max = -sample; max = -sample;

} }


scale_factor = (max / 127) + 1; scale_factor = (max / 127) + 1;
return displ | 0x800000; // set bit 23 to indicate a wave file rather than a spectrum return displ | 0x800000; // set bit 23 to indicate a wave file rather than a spectrum
} }




static int LoadEnvelope(FILE *f, const char *fname) static int LoadEnvelope(FILE *f, const char *fname)
{ {
int displ; int displ;
return displ; return displ;
} }




/* Generate a hash code from the specified string */ /* Generate a hash code from the specified string */
static int Hash8(const char *string) static int Hash8(const char *string)
{ {
return (hash+chars) & 0xff; return (hash+chars) & 0xff;
} }




static int LoadEnvelope2(FILE *f, const char *fname) static int LoadEnvelope2(FILE *f, const char *fname)
{ {
int ix, ix2; int ix, ix2;
env[x] = y; env[x] = y;
} }



if (n_envelopes < N_ENVELOPES) { if (n_envelopes < N_ENVELOPES) {
strncpy0(envelope_paths[n_envelopes], fname, sizeof(envelope_paths[0])); strncpy0(envelope_paths[n_envelopes], fname, sizeof(envelope_paths[0]));
memcpy(envelope_dat[n_envelopes], env, ENV_LEN); memcpy(envelope_dat[n_envelopes], env, ENV_LEN);
return addr; return addr;
} }



static int CompileToneSpec(void) static int CompileToneSpec(void)
{ {
int pitch1 = 0; int pitch1 = 0;
return 0; return 0;
} }




/* /*
Condition Condition
bits 14,15 1 bits 14,15 1
=8 data = stress bitmap =8 data = stress bitmap
=9 special tests =9 special tests
*/ */

int CompileIf(int elif) int CompileIf(int elif)
{ {
int key; int key;
return 0; return 0;
} }



void FillThen(int add) void FillThen(int add)
{ {
USHORT *p; USHORT *p;
then_count = 0; then_count = 0;
} }



int CompileElse(void) int CompileElse(void)
{ {
USHORT *ref; USHORT *ref;
return 0; return 0;
} }



int CompileElif(void) int CompileElif(void)
{ {
if (if_level < 1) { if (if_level < 1) {
return 0; return 0;
} }



int CompileEndif(void) int CompileEndif(void)
{ {
USHORT *p; USHORT *p;
return 0; return 0;
} }



static int CompileSwitch(int type) static int CompileSwitch(int type)
{ {
// Type 0: EndSwitch // Type 0: EndSwitch
return 0; return 0;
} }




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




static PHONEME_TAB *FindPhoneme(const char *string) static PHONEME_TAB *FindPhoneme(const char *string)
{ {
PHONEME_TAB_LIST *phtab = NULL; PHONEME_TAB_LIST *phtab = NULL;
return NULL; return NULL;
} }



static void ImportPhoneme(void) static void ImportPhoneme(void)
{ {
unsigned int ph_mnem; unsigned int ph_mnem;
if (phoneme_out->type != phVOWEL) { if (phoneme_out->type != phVOWEL) {
phoneme_out->end_type = 0; // voicingswitch, this must be set later to refer to a local phoneme phoneme_out->end_type = 0; // voicingswitch, this must be set later to refer to a local phoneme
} }

} }



static void CallPhoneme(void) static void CallPhoneme(void)
{ {
PHONEME_TAB *ph; PHONEME_TAB *ph;
*prog_out++ = addr; *prog_out++ = addr;
} }



static void DecThenCount() static void DecThenCount()
{ {
if (then_count > 0) if (then_count > 0)
*prog_out++ = instn + phcode; *prog_out++ = instn + phcode;
} }



int CompilePhoneme(int compile_phoneme) int CompilePhoneme(int compile_phoneme)
{ {
int endphoneme = 0; int endphoneme = 0;
error("More than one phoneme type: %s", item_string); error("More than one phoneme type: %s", item_string);
phoneme_out->type = keyword; phoneme_out->type = keyword;
break; break;

case tPLACE: case tPLACE:
if (place_articulation > 0) if (place_articulation > 0)
error("Place of articulation has already been given: %s", item_string); error("Place of articulation has already been given: %s", item_string);
place_articulation = keyword; place_articulation = keyword;
break; break;

case tPHONEME_FLAG: case tPHONEME_FLAG:
phoneme_flags |= keyword; phoneme_flags |= keyword;
break; break;

case tINSTRN1: case tINSTRN1:
// instruction group 0, with 8 bit operands which set data in PHONEME_DATA // instruction group 0, with 8 bit operands which set data in PHONEME_DATA
switch (keyword) switch (keyword)
InstnPlusPhoneme(keyword << 8); InstnPlusPhoneme(keyword << 8);
DecThenCount(); DecThenCount();
break; break;

case i_PAUSE_BEFORE: case i_PAUSE_BEFORE:
value = NextItemMax(255); value = NextItemMax(255);
*prog_out++ = (i_PAUSE_BEFORE << 8) + value; *prog_out++ = (i_PAUSE_BEFORE << 8) + value;
DecThenCount(); DecThenCount();
break; break;

case i_PAUSE_AFTER: case i_PAUSE_AFTER:
value = NextItemMax(255); value = NextItemMax(255);
*prog_out++ = (i_PAUSE_AFTER << 8) + value; *prog_out++ = (i_PAUSE_AFTER << 8) + value;
DecThenCount(); DecThenCount();
break; break;

case i_SET_LENGTH: case i_SET_LENGTH:
value = NextItemMax(511); value = NextItemMax(511);
if (phoneme_out->type == phVOWEL) if (phoneme_out->type == phVOWEL)
DecThenCount(); DecThenCount();
} }
break; break;

case i_ADD_LENGTH: case i_ADD_LENGTH:
value = NextItem(tSIGNEDNUMBER) / 2; value = NextItem(tSIGNEDNUMBER) / 2;
*prog_out++ = (i_ADD_LENGTH << 8) + (value & 0xff); *prog_out++ = (i_ADD_LENGTH << 8) + (value & 0xff);
DecThenCount(); DecThenCount();
break; break;

case i_LENGTH_MOD: case i_LENGTH_MOD:
value = NextItem(tNUMBER); value = NextItem(tNUMBER);
phoneme_out->length_mod = value; phoneme_out->length_mod = value;
break; break;

case i_IPA_NAME: case i_IPA_NAME:
NextItem(tSTRING); NextItem(tSTRING);


break; break;
} }
break; break;

case tSTATEMENT: case tSTATEMENT:
switch (keyword) switch (keyword)
{ {
ImportPhoneme(); ImportPhoneme();
phoneme_flags = phoneme_out->phflags; phoneme_flags = phoneme_out->phflags;
break; break;

case kSTARTTYPE: case kSTARTTYPE:
phcode = NextItem(tPHONEMEMNEM); phcode = NextItem(tPHONEMEMNEM);
if (phcode == -1) if (phcode == -1)
phcode = LookupPhoneme(item_string, 1); phcode = LookupPhoneme(item_string, 1);
phoneme_out->start_type = phcode; phoneme_out->start_type = phcode;
break; break;

case kENDTYPE: case kENDTYPE:
phcode = NextItem(tPHONEMEMNEM); phcode = NextItem(tPHONEMEMNEM);
if (phcode == -1) if (phcode == -1)
else if (phcode != phoneme_out->start_type) else if (phcode != phoneme_out->start_type)
error("endtype must equal starttype for consonants", NULL); error("endtype must equal starttype for consonants", NULL);
break; break;

case kVOICINGSWITCH: case kVOICINGSWITCH:
phcode = NextItem(tPHONEMEMNEM); phcode = NextItem(tPHONEMEMNEM);
if (phcode == -1) if (phcode == -1)
phcode = LookupPhoneme(item_string, 1); phcode = LookupPhoneme(item_string, 1);
phoneme_out->end_type = phcode; // use end_type field for consonants as voicing_switch phoneme_out->end_type = phcode; // use end_type field for consonants as voicing_switch
break; break;

case kSTRESSTYPE: case kSTRESSTYPE:
value = NextItem(tNUMBER); value = NextItem(tNUMBER);
phoneme_out->std_length = value; phoneme_out->std_length = value;
prog_out = prog_buf; prog_out = prog_buf;
} }
break; break;

case kIF: case kIF:
endphoneme = CompileIf(0); endphoneme = CompileIf(0);
break; break;

case kELSE: case kELSE:
endphoneme = CompileElse(); endphoneme = CompileElse();
break; break;

case kELIF: case kELIF:
endphoneme = CompileElif(); endphoneme = CompileElif();
break; break;

case kENDIF: case kENDIF:
endphoneme = CompileEndif(); endphoneme = CompileEndif();
break; break;

case kENDSWITCH: case kENDSWITCH:
break; break;

case kSWITCH_PREVVOWEL: case kSWITCH_PREVVOWEL:
endphoneme = CompileSwitch(1); endphoneme = CompileSwitch(1);
break; break;

case kSWITCH_NEXTVOWEL: case kSWITCH_NEXTVOWEL:
endphoneme = CompileSwitch(2); endphoneme = CompileSwitch(2);
break; break;

case kCALLPH: case kCALLPH:
CallPhoneme(); CallPhoneme();
DecThenCount(); DecThenCount();
break; break;

case kFMT: case kFMT:
if_stack[if_level].returned = 1; if_stack[if_level].returned = 1;
DecThenCount(); DecThenCount();
else else
endphoneme = CompileSound(keyword, 0); endphoneme = CompileSound(keyword, 0);
break; break;

case kWAV: case kWAV:
if_stack[if_level].returned = 1; if_stack[if_level].returned = 1;
// fallthrough:
case kVOWELSTART: case kVOWELSTART:
case kVOWELENDING: case kVOWELENDING:
case kANDWAV: case kANDWAV:
DecThenCount(); DecThenCount();
endphoneme = CompileSound(keyword, 0); endphoneme = CompileSound(keyword, 0);
break; break;

case kVOWELIN: case kVOWELIN:
DecThenCount(); DecThenCount();
endphoneme = CompileVowelTransition(1); endphoneme = CompileVowelTransition(1);
break; break;

case kVOWELOUT: case kVOWELOUT:
DecThenCount(); DecThenCount();
endphoneme = CompileVowelTransition(2); endphoneme = CompileVowelTransition(2);
break; break;

case kTONESPEC: case kTONESPEC:
DecThenCount(); DecThenCount();
endphoneme = CompileToneSpec(); endphoneme = CompileToneSpec();
break; break;

case kCONTINUE: case kCONTINUE:
*prog_out++ = i_CONTINUE; *prog_out++ = i_CONTINUE;
DecThenCount(); DecThenCount();
break; break;

case kRETURN: case kRETURN:
*prog_out++ = i_RETURN; *prog_out++ = i_RETURN;
DecThenCount(); DecThenCount();
break; break;

case kINCLUDE: case kINCLUDE:
case kPHONEMENUMBER: case kPHONEMENUMBER:
case kPHONEMETABLE: case kPHONEMETABLE:
error("Missing 'endphoneme' before '%s'", item_string); // drop through to endphoneme error("Missing 'endphoneme' before '%s'", item_string); // drop through to endphoneme
// fallthrough:
case kENDPHONEME: case kENDPHONEME:
case kENDPROCEDURE: case kENDPROCEDURE:
endphoneme = 1; endphoneme = 1;
*prog_out++ = i_RETURN; *prog_out++ = i_RETURN;
break; break;
} }

break; break;
} }
} }
return 0; return 0;
} }






static void WritePhonemeTables() static void WritePhonemeTables()
{ {
int ix; int ix;
} }
} }



static void EndPhonemeTable() static void EndPhonemeTable()
{ {
int ix; int ix;
} }
} }



static void StartPhonemeTable(const char *name) static void StartPhonemeTable(const char *name)
{ {
int ix; int ix;
n_phoneme_tabs++; n_phoneme_tabs++;
} }



static void CompileEquivalents() static void CompileEquivalents()
{ {
// 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
p_start[3] = n_bytes; p_start[3] = n_bytes;
} }




static void CompilePhonemeFiles() static void CompilePhonemeFiles()
{ {
int item; int item;
{ {
case kUTF8_BOM: case kUTF8_BOM:
break; // ignore bytes 0xef 0xbb 0xbf break; // ignore bytes 0xef 0xbb 0xbf

case kINCLUDE: case kINCLUDE:
NextItem(tSTRING); NextItem(tSTRING);
sprintf(buf, "%s/../phsource/%s", path_home, item_string); sprintf(buf, "%s/../phsource/%s", path_home, item_string);
f_in = f; f_in = f;
strncpy0(current_fname, item_string, sizeof(current_fname)); strncpy0(current_fname, item_string, sizeof(current_fname));
linenum = 1; linenum = 1;

} else } else
error("Missing file: %s", item_string); error("Missing file: %s", item_string);
break; break;

case kPHONEMETABLE: case kPHONEMETABLE:
EndPhonemeTable(); EndPhonemeTable();
NextItem(tSTRING); // name of the new phoneme table NextItem(tSTRING); // name of the new phoneme table
StartPhonemeTable(item_string); StartPhonemeTable(item_string);
break; break;

case kPHONEMESTART: case kPHONEMESTART:
if (n_phoneme_tabs == 0) { if (n_phoneme_tabs == 0) {
Error("phonemetable is missing"); Error("phonemetable is missing");
} }
CompilePhoneme(1); CompilePhoneme(1);
break; break;

case kPROCEDURE: case kPROCEDURE:
CompilePhoneme(0); CompilePhoneme(0);
break; break;

case kEQUIVALENTS: case kEQUIVALENTS:
CompileEquivalents(); CompileEquivalents();
break; break;

default: default:
if (!feof(f_in)) if (!feof(f_in))
Error("Keyword 'phoneme' expected"); Error("Keyword 'phoneme' expected");
phoneme_tab2[n_phcodes+1].mnemonic = 0; // terminator phoneme_tab2[n_phcodes+1].mnemonic = 0; // terminator
} }




static espeak_ng_STATUS CompilePhonemeData2(const char *source, FILE *log) static espeak_ng_STATUS CompilePhonemeData2(const char *source, FILE *log)
{ {
char fname[sizeof(path_home)+40]; char fname[sizeof(path_home)+40];
"# Address Data file\n" "# Address Data file\n"
"# ------- ---------\n"); "# ------- ---------\n");



fprintf(f_errors, "Source data path = '%s/../phsource'\n", path_home); fprintf(f_errors, "Source data path = '%s/../phsource'\n", path_home);
fprintf(f_errors, "Master phonemes file = '%s/../phsource/phonemes'\n", path_home); fprintf(f_errors, "Master phonemes file = '%s/../phsource/phonemes'\n", path_home);
fprintf(f_errors, "Output to '%s/'\n\n", path_home); fprintf(f_errors, "Output to '%s/'\n\n", path_home);
return ENS_OK; return ENS_OK;
} }



static const char *preset_tune_names[] = { static const char *preset_tune_names[] = {
"s1", "c1", "q1", "e1", NULL "s1", "c1", "q1", "e1", NULL
}; };
return LookupMnem(envelope_names, name); return LookupMnem(envelope_names, name);
} }



#pragma GCC visibility push(default) #pragma GCC visibility push(default)


espeak_ng_STATUS espeak_ng_CompileIntonation(FILE *log) espeak_ng_STATUS espeak_ng_CompileIntonation(FILE *log)
TUNE *tune_data; TUNE *tune_data;
TUNE new_tune; TUNE new_tune;



char name[12]; char name[12];
char tune_names[N_TUNE_NAMES][12]; char tune_names[N_TUNE_NAMES][12];
char buf[sizeof(path_home)+150]; char buf[sizeof(path_home)+150];
} }
} }



for (ix = 0; preset_tune_names[ix] != NULL; ix++) { for (ix = 0; preset_tune_names[ix] != NULL; ix++) {
strcpy(tune_names[ix], preset_tune_names[ix]); strcpy(tune_names[ix], preset_tune_names[ix]);
} }
if (found == 0) if (found == 0)
error("Bad tune name: '%s;", new_tune.name); error("Bad tune name: '%s;", new_tune.name);
break; break;

case kENDTUNE: case kENDTUNE:
compiling_tune = 0; compiling_tune = 0;


} }
memcpy(&tune_data[tune_number], &new_tune, sizeof(TUNE)); memcpy(&tune_data[tune_number], &new_tune, sizeof(TUNE));
break; break;

case kTUNE_PREHEAD: case kTUNE_PREHEAD:
new_tune.prehead_start = NextItem(tNUMBER); new_tune.prehead_start = NextItem(tNUMBER);
new_tune.prehead_end = NextItem(tNUMBER); new_tune.prehead_end = NextItem(tNUMBER);
break; break;

case kTUNE_ONSET: case kTUNE_ONSET:
new_tune.onset = NextItem(tNUMBER); new_tune.onset = NextItem(tNUMBER);
new_tune.unstr_start[0] = NextItem(tSIGNEDNUMBER); new_tune.unstr_start[0] = NextItem(tSIGNEDNUMBER);
new_tune.unstr_end[0] = NextItem(tSIGNEDNUMBER); new_tune.unstr_end[0] = NextItem(tSIGNEDNUMBER);
done_onset = 1; done_onset = 1;
break; break;

case kTUNE_HEADLAST: case kTUNE_HEADLAST:
new_tune.head_last = NextItem(tNUMBER); new_tune.head_last = NextItem(tNUMBER);
new_tune.unstr_start[2] = NextItem(tSIGNEDNUMBER); new_tune.unstr_start[2] = NextItem(tSIGNEDNUMBER);
new_tune.unstr_end[2] = NextItem(tSIGNEDNUMBER); new_tune.unstr_end[2] = NextItem(tSIGNEDNUMBER);
done_last = 1; done_last = 1;
break; break;

case kTUNE_HEADENV: case kTUNE_HEADENV:
NextItem(tSTRING); NextItem(tSTRING);
if ((ix = LookupEnvelopeName(item_string)) < 0) if ((ix = LookupEnvelopeName(item_string)) < 0)
new_tune.stressed_env = ix; new_tune.stressed_env = ix;
new_tune.stressed_drop = NextItem(tNUMBER); new_tune.stressed_drop = NextItem(tNUMBER);
break; break;

case kTUNE_HEAD: case kTUNE_HEAD:
new_tune.head_max_steps = NextItem(tNUMBER); new_tune.head_max_steps = NextItem(tNUMBER);
new_tune.head_start = NextItem(tNUMBER); new_tune.head_start = NextItem(tNUMBER);
new_tune.unstr_start[1] = NextItem(tSIGNEDNUMBER); new_tune.unstr_start[1] = NextItem(tSIGNEDNUMBER);
new_tune.unstr_end[1] = NextItem(tSIGNEDNUMBER); new_tune.unstr_end[1] = NextItem(tSIGNEDNUMBER);
break; break;

case kTUNE_HEADEXTEND: case kTUNE_HEADEXTEND:
// up to 8 numbers // up to 8 numbers
for (ix = 0; ix < (int)(sizeof(new_tune.head_extend)); ix++) { for (ix = 0; ix < (int)(sizeof(new_tune.head_extend)); ix++) {
} }
new_tune.n_head_extend = ix; // number of values new_tune.n_head_extend = ix; // number of values
break; break;

case kTUNE_NUCLEUS0: case kTUNE_NUCLEUS0:
NextItem(tSTRING); NextItem(tSTRING);
if ((ix = LookupEnvelopeName(item_string)) < 0) { if ((ix = LookupEnvelopeName(item_string)) < 0) {
new_tune.nucleus0_max = NextItem(tNUMBER); new_tune.nucleus0_max = NextItem(tNUMBER);
new_tune.nucleus0_min = NextItem(tNUMBER); new_tune.nucleus0_min = NextItem(tNUMBER);
break; break;

case kTUNE_NUCLEUS1: case kTUNE_NUCLEUS1:
NextItem(tSTRING); NextItem(tSTRING);
if ((ix = LookupEnvelopeName(item_string)) < 0) { if ((ix = LookupEnvelopeName(item_string)) < 0) {
new_tune.split_tail_end = new_tune.tail_end; new_tune.split_tail_end = new_tune.tail_end;
} }
break; break;

case kTUNE_SPLIT: case kTUNE_SPLIT:
NextItem(tSTRING); NextItem(tSTRING);
if ((ix = LookupEnvelopeName(item_string)) < 0) { if ((ix = LookupEnvelopeName(item_string)) < 0) {
else else
new_tune.split_tune = ix; new_tune.split_tune = ix;
break; break;

default: default:
error("Unexpected: '%s'", item_string); error("Unexpected: '%s'", item_string);
break; break;
return error_count > 0 ? ENE_COMPILE_ERRORS : ENS_OK; return error_count > 0 ? ENE_COMPILE_ERRORS : ENS_OK;
} }




espeak_ng_STATUS espeak_ng_CompilePhonemeData(long rate, FILE *log) espeak_ng_STATUS espeak_ng_CompilePhonemeData(long rate, FILE *log)
{ {
if (!log) log = stderr; if (!log) log = stderr;

+ 1
- 48
src/libespeak-ng/compiledict.c View File

{ "$u2+", 0x4e }, { "$u2+", 0x4e },
{ "$u3+", 0x4f }, { "$u3+", 0x4f },



// these set the corresponding numbered bit if dictionary_flags // these set the corresponding numbered bit if dictionary_flags
{ "$pause", 8 }, // ensure pause before this word { "$pause", 8 }, // ensure pause before this word
{ "$strend", 9 }, // full stress if at end of clause { "$strend", 9 }, // full stress if at end of clause
{ NULL, -1 } { NULL, -1 }
}; };



#define LEN_GROUP_NAME 12 #define LEN_GROUP_NAME 12


typedef struct { typedef struct {
int group3_ix; int group3_ix;
} RGROUP; } RGROUP;



int isspace2(unsigned int c) int isspace2(unsigned int c)
{ {
// can't use isspace() because on Windows, isspace(0xe1) gives TRUE ! // can't use isspace() because on Windows, isspace(0xe1) gives TRUE !
return 1; return 1;
} }




static FILE *fopen_log(const char *fname, const char *access) static FILE *fopen_log(const char *fname, const char *access)
{ {
// performs fopen, but produces error message to f_log if it fails // performs fopen, but produces error message to f_log if it fails
return f; return f;
} }



/* Lookup a mnemonic string in a table, return its name */ /* Lookup a mnemonic string in a table, return its name */
const char *LookupMnemName(MNEM_TAB *table, const int value) const char *LookupMnemName(MNEM_TAB *table, const int value)
{ {
return ""; /* not found */ return ""; /* not found */
} }



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;
} }
} }





char *DecodeRule(const char *group_chars, int group_length, char *rule, int control) char *DecodeRule(const char *group_chars, int group_length, char *rule, int control)
{ {
/* Convert compiled match template to ascii */ /* Convert compiled match template to ascii */
return output; return output;
} }





static int compile_line(char *linebuf, char *dict_line, int *hash) static int compile_line(char *linebuf, char *dict_line, int *hash)
{ {
// Compile a line in the language_list file // Compile a line in the language_list file
step = 1; step = 1;
} }
break; break;

case 1: case 1:
if ((c == '-') && multiple_words) { if ((c == '-') && multiple_words) {
if (IsDigit09(word[0])) if (IsDigit09(word[0]))
} }
} }
break; break;

case 2: case 2:
if (isspace2(c)) if (isspace2(c))
multiple_words++; multiple_words++;
step = 3; step = 3;
} }
break; break;

case 3: case 3:
if (!isspace2(c)) { if (!isspace2(c)) {
phonetic = p; phonetic = p;
step = 4; step = 4;
} }
break; break;

case 4: case 4:
if (isspace2(c)) { if (isspace2(c)) {
p[0] = 0; /* terminate phonetic */ p[0] = 0; /* terminate phonetic */
step = 5; step = 5;
} }
break; break;

case 5: case 5:
break; break;
} }
} }
dict_line[0] = length; dict_line[0] = length;



return length; return length;
} }




static void compile_dictlist_start(void) static void compile_dictlist_start(void)
{ {
// initialise dictionary list // initialise dictionary list
} }
} }



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
} }
} }




static int compile_dictlist_file(const char *path, const char *filename) static int compile_dictlist_file(const char *path, const char *filename)
{ {
int length; int length;
return 0; return 0;
} }




static char rule_cond[80]; static char rule_cond[80];
static char rule_pre[80]; static char rule_pre[80];
static char rule_post[80]; static char rule_post[80];


#define N_RULES 3000 // max rules for each group #define N_RULES 3000 // max rules for each group




int isHexDigit(int c) int isHexDigit(int c)
{ {
if ((c >= '0') && (c <= '9')) if ((c >= '0') && (c <= '9'))
return -1; return -1;
} }



static void copy_rule_string(char *string, int *state_out) static void copy_rule_string(char *string, int *state_out)
{ {
// state 0: conditional, 1=pre, 2=match, 3=post, 4=phonemes // state 0: conditional, 1=pre, 2=match, 3=post, 4=phonemes
} else } else
output[ix++] = RULE_LETTERGP2; output[ix++] = RULE_LETTERGP2;
break; break;

case '$': case '$':
value = 0; value = 0;
mr = mnem_rules; mr = mnem_rules;
error_count++; error_count++;
} }
break; break;

case 'P': case 'P':
sxflags |= SUFX_P; // Prefix, now drop through to Suffix sxflags |= SUFX_P; // Prefix, now drop through to Suffix
// fallthrough
case 'S': case 'S':
output[ix++] = RULE_ENDING; output[ix++] = RULE_ENDING;
value = 0; value = 0;
*state_out = next_state[state]; *state_out = next_state[state];
} }




static char *compile_rule(char *input) static char *compile_rule(char *input)
{ {
int ix; int ix;
copy_rule_string(buf, &state); copy_rule_string(buf, &state);
p = buf; p = buf;
break; break;

case '(': // start of suffix section case '(': // start of suffix section
*p = 0; *p = 0;
state = 2; state = 2;
error_count++; error_count++;
} }
break; break;

case '\n': // end of line case '\n': // end of line
case '\r': case '\r':
case 0: // end of line case 0: // end of line
copy_rule_string(buf, &state); copy_rule_string(buf, &state);
finish = 1; finish = 1;
break; break;

case '\t': // end of section section case '\t': // end of section section
case ' ': case ' ':
*p = 0; *p = 0;
copy_rule_string(buf, &state); copy_rule_string(buf, &state);
p = buf; p = buf;
break; break;

case '?': case '?':
if (state == 2) if (state == 2)
state = 0; state = 0;
else else
*p++ = c; *p++ = c;
break; break;

default: default:
*p++ = c; *p++ = c;
break; break;
return prule; return prule;
} }



int __cdecl string_sorter(char **a, char **b) int __cdecl string_sorter(char **a, char **b)
{ {
char *pa, *pb; char *pa, *pb;
return strcmp(pa, pb); return strcmp(pa, pb);
} }



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
return a->start-b->start; return a->start-b->start;
} }



#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)
{ {
} }
#endif #endif



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 ix;
#endif #endif
} }




static int compile_lettergroup(char *input, FILE *f_out) static int compile_lettergroup(char *input, FILE *f_out)
{ {
char *p; char *p;
return 0; return 0;
} }



static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp)
{ {
char *prule; char *prule;


} }
break; break;

case 2: // .replace case 2: // .replace
{ {
int replace1; int replace1;
return 0; return 0;
} }




int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *fname_err, int flags) int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *fname_err, int flags)
{ {
// fname: space to write the filename in case of error // fname: space to write the filename in case of error

+ 7
- 121
src/libespeak-ng/dictionary.c View File

#include "synthesize.h" #include "synthesize.h"
#include "translate.h" #include "translate.h"



int dictionary_skipwords; int dictionary_skipwords;
char dictionary_name[40]; char dictionary_name[40];


'a', 'a', 'a', 'b', 'o', 'c', 'd', 'd', 'e', 'e', 'e', 'e', 'e', 'e' 'a', 'a', 'a', 'b', 'o', 'c', 'd', 'd', 'e', 'e', 'e', 'e', 'e', 'e'
}; };






#pragma GCC visibility push(default) #pragma GCC visibility push(default)
void strncpy0(char *to, const char *from, int size) void strncpy0(char *to, const char *from, int size)
{ {
} }
#pragma GCC visibility pop #pragma GCC visibility pop



int Reverse4Bytes(int word) int Reverse4Bytes(int word)
{ {
// reverse the order of bytes from little-endian to big-endian // reverse the order of bytes from little-endian to big-endian
#endif #endif
} }



int LookupMnem(MNEM_TAB *table, const char *string) int LookupMnem(MNEM_TAB *table, const char *string)
{ {
while (table->mnem != NULL) { while (table->mnem != NULL) {
return table->value; return table->value;
} }



static void InitGroups(Translator *tr) static void InitGroups(Translator *tr)
{ {
// Called after dictionary 1 is loaded, to set up table of entry points for translation rule chains // Called after dictionary 1 is loaded, to set up table of entry points for translation rule chains
// for single-letters and two-letter combinations // for single-letters and two-letter combinations



int ix; int ix;
char *p; char *p;
char *p_name; char *p_name;
p += (strlen(p) + 1); p += (strlen(p) + 1);
p++; p++;
} }

} }




int LoadDictionary(Translator *tr, const char *name, int no_error) int LoadDictionary(Translator *tr, const char *name, int no_error)
{ {
int hash; int hash;
size = fread(tr->data_dictlist, 1, size, f); size = fread(tr->data_dictlist, 1, size, f);
fclose(f); fclose(f);



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


return 0; return 0;
} }



/* Generate a hash code from the specified string /* Generate a hash code from the specified string
This is used to access the dictionary_2 word-lookup dictionary This is used to access the dictionary_2 word-lookup dictionary
*/ */
return (hash+chars) & 0x3ff; // a 10 bit hash code return (hash+chars) & 0x3ff; // a 10 bit hash code
} }




/* Translate a phoneme string from ascii mnemonics to internal phoneme numbers, /* Translate a phoneme string from ascii mnemonics to internal phoneme numbers,
from 'p' up to next blank . from 'p' up to next blank .
Returns advanced 'p' Returns advanced 'p'
p++; p++;
break; break;
} }

default: default:
// lookup the phoneme mnemonic, find the phoneme with the highest number of // lookup the phoneme mnemonic, find the phoneme with the highest number of
// matching characters // matching characters
return p; return p;
} }




void DecodePhonemes(const char *inptr, char *outptr) void DecodePhonemes(const char *inptr, char *outptr)
{ {
// Translate from internal phoneme codes into phoneme mnemonics // Translate from internal phoneme codes into phoneme mnemonics
*outptr = 0; /* string terminator */ *outptr = 0; /* string terminator */
} }



// using Kirschenbaum to IPA translation, ascii 0x20 to 0x7f // using Kirschenbaum to IPA translation, ascii 0x20 to 0x7f
unsigned short ipa1[96] = { unsigned short ipa1[96] = {
0x20, 0x21, 0x22, 0x2b0, 0x24, 0x25, 0x0e6, 0x2c8, 0x28, 0x29, 0x27e, 0x2b, 0x2cc, 0x2d, 0x2e, 0x2f, 0x20, 0x21, 0x22, 0x2b0, 0x24, 0x25, 0x0e6, 0x2c8, 0x28, 0x29, 0x27e, 0x2b, 0x2cc, 0x2d, 0x2e, 0x2f,
static char *phon_out_buf = NULL; // passes the result of GetTranslatedPhonemeString() static char *phon_out_buf = NULL; // passes the result of GetTranslatedPhonemeString()
static unsigned int phon_out_size = 0; static unsigned int phon_out_size = 0;



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;
return phon_out; return phon_out;
} }




const char *GetTranslatedPhonemeString(int phoneme_mode) const char *GetTranslatedPhonemeString(int phoneme_mode)
{ {
/* Called after a clause has been translated into phonemes, in order /* Called after a clause has been translated into phonemes, in order
use_tie = 0; use_tie = 0;
} }



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


return phon_out_buf; return phon_out_buf;
} }




static int IsLetterGroup(Translator *tr, char *word, int group, int pre) static int IsLetterGroup(Translator *tr, char *word, int group, int pre)
{ {
// match the word against a list of utf-8 strings // match the word against a list of utf-8 strings
return 0; return 0;
} }



static int IsLetter(Translator *tr, int letter, int group) static int IsLetter(Translator *tr, int letter, int group)
{ {
int letter2; int letter2;
return 0; return 0;
} }



int IsVowel(Translator *tr, int letter) int IsVowel(Translator *tr, int letter)
{ {
return IsLetter(tr, letter, LETTERGP_VOWEL2); return IsLetter(tr, letter, LETTERGP_VOWEL2);
} }





static int Unpronouncable2(Translator *tr, char *word) static int Unpronouncable2(Translator *tr, char *word)
{ {
int c; int c;
return 0; return 0;
} }



int Unpronouncable(Translator *tr, char *word, int posn) int Unpronouncable(Translator *tr, char *word, int posn)
{ {
/* Determines whether a word in 'unpronouncable', i.e. whether it should /* Determines whether a word in 'unpronouncable', i.e. whether it should
return 1; // no vowel, or no vowel in first few letters return 1; // no vowel, or no vowel in first few letters


return 0; return 0;

} }




static int GetVowelStress(Translator *tr, unsigned char *phonemes, signed char *vowel_stress, int *vowel_count, int *stressed_syllable, int control) static int GetVowelStress(Translator *tr, unsigned char *phonemes, signed char *vowel_stress, int *vowel_count, int *stressed_syllable, int control)
{ {
// control = 1, set stress to 1 for forced unstressed vowels // control = 1, set stress to 1 for forced unstressed vowels
return max_stress; return max_stress;
} }




static char stress_phonemes[] = { phonSTRESS_D, phonSTRESS_U, phonSTRESS_2, phonSTRESS_3, static char stress_phonemes[] = { phonSTRESS_D, phonSTRESS_U, phonSTRESS_2, phonSTRESS_3,
phonSTRESS_P, phonSTRESS_P2, phonSTRESS_TONIC }; phonSTRESS_P, phonSTRESS_P2, phonSTRESS_TONIC };



void ChangeWordStress(Translator *tr, char *word, int new_stress) void ChangeWordStress(Translator *tr, char *word, int new_stress)
{ {
int ix; int ix;
*word = 0; *word = 0;
} }




void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags, int tonic, int control) void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags, int tonic, int control)
{ {
/* Guess stress pattern of word. This is language specific /* Guess stress pattern of word. This is language specific


static char consonant_types[16] = { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 }; static char consonant_types[16] = { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 };



/* stress numbers STRESS_BASE + /* stress numbers STRESS_BASE +
0 diminished, unstressed within a word 0 diminished, unstressed within a word
1 unstressed, weak 1 unstressed, weak
} }
} }



switch (tr->langopts.stress_rule) switch (tr->langopts.stress_rule)
{ {
case 8: case 8:
// stress on first syllable, unless it is a light syllable followed by a heavy syllable // stress on first syllable, unless it is a light syllable followed by a heavy syllable
if ((syllable_weight[1] > 0) || (syllable_weight[2] == 0)) if ((syllable_weight[1] > 0) || (syllable_weight[2] == 0))
break; break;
// else drop through to case 1
// fallthrough
case 1: case 1:
// stress on second syllable // stress on second syllable
if ((stressed_syllable == 0) && (vowel_count > 2)) { if ((stressed_syllable == 0) && (vowel_count > 2)) {
max_stress = 4; max_stress = 4;
} }
break; break;

case 10: // penultimate, but final if only 1 or 2 syllables case 10: // penultimate, but final if only 1 or 2 syllables
if (stressed_syllable == 0) { if (stressed_syllable == 0) {
if (vowel_count < 4) { if (vowel_count < 4) {
break; break;
} }
} }
// drop through to next case
// fallthrough
case 2: case 2:
// a language with stress on penultimate vowel // a language with stress on penultimate vowel


} }
} }
break; break;

case 3: case 3:
// stress on last vowel // stress on last vowel
if (stressed_syllable == 0) { if (stressed_syllable == 0) {
max_stress = 4; max_stress = 4;
} }
break; break;

case 4: // stress on antipenultimate vowel case 4: // stress on antipenultimate vowel
if (stressed_syllable == 0) { if (stressed_syllable == 0) {
stressed_syllable = vowel_count - 3; stressed_syllable = vowel_count - 3;
max_stress = 4; max_stress = 4;
} }
break; break;

case 5: case 5:
// LANG=Russian // LANG=Russian
if (stressed_syllable == 0) { if (stressed_syllable == 0) {
max_stress = 4; max_stress = 4;
} }
break; break;

case 6: // LANG=hi stress on the last heaviest syllable case 6: // LANG=hi stress on the last heaviest syllable
if (stressed_syllable == 0) { if (stressed_syllable == 0) {
int wt; int wt;
max_stress = 4; max_stress = 4;
} }
break; break;

case 7: // LANG=tr, the last syllable for any vowel marked explicitly as unstressed case 7: // LANG=tr, the last syllable for any vowel marked explicitly as unstressed
if (stressed_syllable == 0) { if (stressed_syllable == 0) {
stressed_syllable = vowel_count - 1; stressed_syllable = vowel_count - 1;
max_stress = 4; max_stress = 4;
} }
break; break;

case 9: // mark all as stressed case 9: // mark all as stressed
for (ix = 1; ix < vowel_count; ix++) { for (ix = 1; ix < vowel_count; ix++) {
if (vowel_stress[ix] < 0) if (vowel_stress[ix] < 0)
vowel_stress[ix] = 4; vowel_stress[ix] = 4;
} }
break; break;

case 12: // LANG=kl (Greenlandic) case 12: // LANG=kl (Greenlandic)
long_vowel = 0; long_vowel = 0;
for (ix = 1; ix < vowel_count; ix++) { for (ix = 1; ix < vowel_count; ix++) {
vowel_stress[stressed_syllable] = 4; vowel_stress[stressed_syllable] = 4;
max_stress = 4; max_stress = 4;
break; break;

case 13: // LANG=ml, 1st unless 1st vowel is short and 2nd is long case 13: // LANG=ml, 1st unless 1st vowel is short and 2nd is long
if (stressed_syllable == 0) { if (stressed_syllable == 0) {
stressed_syllable = 1; stressed_syllable = 1;
else else
stress = 3; stress = 3;



if (unstressed_word == 0) { if (unstressed_word == 0) {
if ((stressflags & S_2_SYL_2) && (vowel_count == 3)) { if ((stressflags & S_2_SYL_2) && (vowel_count == 3)) {
// Two syllable word, if one syllable has primary stress, then give the other secondary stress // Two syllable word, if one syllable has primary stress, then give the other secondary stress
max_stress = tonic; max_stress = tonic;
} }



/* produce output phoneme string */ /* produce output phoneme string */
p = phonetic; p = phonetic;
v = 1; v = 1;


if (!(control & 1) && ((ph = phoneme_tab[*p]) != NULL)) { if (!(control & 1) && ((ph = phoneme_tab[*p]) != NULL)) {

while ((ph->type == phSTRESS) || (*p == phonEND_WORD)) { while ((ph->type == phSTRESS) || (*p == phonEND_WORD)) {
p++; p++;
ph = phoneme_tab[p[0]]; ph = phoneme_tab[p[0]];
return; return;
} }




void AppendPhonemes(Translator *tr, char *string, int size, const char *ph) void AppendPhonemes(Translator *tr, char *string, int size, const char *ph)
{ {
/* Add new phoneme string "ph" to "string" /* Add new phoneme string "ph" to "string"
strcat(string, ph); strcat(string, ph);
} }




static void MatchRule(Translator *tr, char *word[], char *word_start, int group_length, char *rule, MatchRecord *match_out, int word_flags, int dict_flags) static void MatchRule(Translator *tr, char *word[], char *word_start, int group_length, char *rule, MatchRecord *match_out, int word_flags, int dict_flags)
{ {
/* Checks a specified word against dictionary rules. /* Checks a specified word against dictionary rules.
return; return;
} }



total_consumed = 0; total_consumed = 0;
common_phonemes = NULL; common_phonemes = NULL;
match_type = 0; match_type = 0;
rule--; // so we are still pointing at the 0 rule--; // so we are still pointing at the 0
failed = 2; // matched OK failed = 2; // matched OK
break; break;

case RULE_PRE_ATSTART: // pre rule with implied 'start of word' case RULE_PRE_ATSTART: // pre rule with implied 'start of word'
check_atstart = 1; check_atstart = 1;
unpron_ignore = 0; unpron_ignore = 0;
match_type = RULE_PRE; match_type = RULE_PRE;
break; break;

case RULE_PRE: case RULE_PRE:
match_type = RULE_PRE; match_type = RULE_PRE;
if (word_flags & FLAG_UNPRON_TEST) { if (word_flags & FLAG_UNPRON_TEST) {
failed = 1; failed = 1;
} }
break; break;

case RULE_POST: case RULE_POST:
match_type = RULE_POST; match_type = RULE_POST;
break; break;
} else } else
failed = 1; failed = 1;
break; break;


case RULE_POST: case RULE_POST:
/* continue moving fowards */ /* continue moving fowards */
distance_right += 6; distance_right += 6;
} else } else
failed = 1; failed = 1;
break; break;

case RULE_LETTERGP2: // match against a list of utf-8 strings case RULE_LETTERGP2: // match against a list of utf-8 strings
letter_group = *rule++ - 'A'; letter_group = *rule++ - 'A';
if ((n_bytes = IsLetterGroup(tr, post_ptr-1, letter_group, 0)) > 0) { if ((n_bytes = IsLetterGroup(tr, post_ptr-1, letter_group, 0)) > 0) {
} else } else
failed = 1; failed = 1;
break; break;

case RULE_NOTVOWEL: case RULE_NOTVOWEL:
if (IsLetter(tr, letter_w, 0) || ((letter_w == ' ') && (word_flags & FLAG_SUFFIX_VOWEL))) if (IsLetter(tr, letter_w, 0) || ((letter_w == ' ') && (word_flags & FLAG_SUFFIX_VOWEL)))
failed = 1; failed = 1;
post_ptr += letter_xbytes; post_ptr += letter_xbytes;
} }
break; break;

case RULE_DIGIT: case RULE_DIGIT:
if (IsDigit(letter_w)) { if (IsDigit(letter_w)) {
add_points = (20-distance_right); add_points = (20-distance_right);
} else } else
failed = 1; failed = 1;
break; break;

case RULE_NONALPHA: case RULE_NONALPHA:
if (!iswalpha2(letter_w)) { if (!iswalpha2(letter_w)) {
add_points = (21-distance_right); add_points = (21-distance_right);
} else } else
failed = 1; failed = 1;
break; break;

case RULE_DOUBLE: case RULE_DOUBLE:
if (letter == last_letter) if (letter == last_letter)
add_points = (21-distance_right); add_points = (21-distance_right);
else else
failed = 1; failed = 1;
break; break;

case RULE_DOLLAR: case RULE_DOLLAR:
command = *rule++; command = *rule++;
if (command == DOLLAR_UNPR) if (command == DOLLAR_UNPR)
failed = 1; failed = 1;
} }
break; break;

case '-': case '-':
if ((letter == '-') || ((letter == ' ') && (word_flags & FLAG_HYPHEN_AFTER))) if ((letter == '-') || ((letter == ' ') && (word_flags & FLAG_HYPHEN_AFTER)))
add_points = (22-distance_right); // one point more than match against space add_points = (22-distance_right); // one point more than match against space
else else
failed = 1; failed = 1;
break; break;

case RULE_SYLLABLE: case RULE_SYLLABLE:
{ {
/* more than specified number of vowel letters to the right */ /* more than specified number of vowel letters to the right */
else else
failed = 1; failed = 1;
} }
break;

break;
case RULE_NOVOWELS: case RULE_NOVOWELS:
{ {
char *p = post_ptr + letter_xbytes; char *p = post_ptr + letter_xbytes;
if (!failed) if (!failed)
add_points = (19-distance_right); add_points = (19-distance_right);
} }
break;

break;
case RULE_SKIPCHARS: case RULE_SKIPCHARS:
{ {
// Used for lang=Tamil, used to match on the next word after an unknown word ending // Used for lang=Tamil, used to match on the next word after an unknown word ending
if (letter_w == rule_w) if (letter_w == rule_w)
post_ptr = p2; post_ptr = p2;
} }
break;

break;
case RULE_INC_SCORE: case RULE_INC_SCORE:
add_points = 20; // force an increase in points add_points = 20; // force an increase in points
break; break;

case RULE_DEL_FWD: case RULE_DEL_FWD:
// find the next 'e' in the word and replace by 'E' // find the next 'e' in the word and replace by 'E'
for (p = *word + group_length; p < post_ptr; p++) { for (p = *word + group_length; p < post_ptr; p++) {
} }
} }
break; break;

case RULE_ENDING: case RULE_ENDING:
{ {
int end_type; int end_type;
rule += 3; rule += 3;
} }
} }
break;

break;
case RULE_NO_SUFFIX: case RULE_NO_SUFFIX:
if (word_flags & FLAG_SUFFIX_REMOVED) if (word_flags & FLAG_SUFFIX_REMOVED)
failed = 1; // a suffix has been removed failed = 1; // a suffix has been removed
else else
add_points = 1; add_points = 1;
break; break;

default: default:
if (letter == rb) { if (letter == rb) {
if ((letter & 0xc0) != 0x80) { if ((letter & 0xc0) != 0x80) {
break; break;
} }
break; break;


case RULE_PRE: case RULE_PRE:
/* match backwards from start of current group */ /* match backwards from start of current group */
distance_left += 2; distance_left += 2;
} else } else
failed = 1; failed = 1;
break; break;

case RULE_LETTERGP2: // match against a list of utf-8 strings case RULE_LETTERGP2: // match against a list of utf-8 strings
letter_group = *rule++ - 'A'; letter_group = *rule++ - 'A';
if ((n_bytes = IsLetterGroup(tr, pre_ptr, letter_group, 1)) > 0) { if ((n_bytes = IsLetterGroup(tr, pre_ptr, letter_group, 1)) > 0) {
} else } else
failed = 1; failed = 1;
break; break;

case RULE_NOTVOWEL: case RULE_NOTVOWEL:
if (!IsLetter(tr, letter_w, 0)) { if (!IsLetter(tr, letter_w, 0)) {
add_points = (20-distance_left); add_points = (20-distance_left);
} else } else
failed = 1; failed = 1;
break; break;

case RULE_DOUBLE: case RULE_DOUBLE:
if (letter == last_letter) if (letter == last_letter)
add_points = (21-distance_left); add_points = (21-distance_left);
else else
failed = 1; failed = 1;
break; break;

case RULE_DIGIT: case RULE_DIGIT:
if (IsDigit(letter_w)) { if (IsDigit(letter_w)) {
add_points = (21-distance_left); add_points = (21-distance_left);
} else } else
failed = 1; failed = 1;
break; break;

case RULE_NONALPHA: case RULE_NONALPHA:
if (!iswalpha2(letter_w)) { if (!iswalpha2(letter_w)) {
add_points = (21-distance_right); add_points = (21-distance_right);
} else } else
failed = 1; failed = 1;
break; break;

case RULE_DOLLAR: case RULE_DOLLAR:
command = *rule++; command = *rule++;
if ((command == DOLLAR_LIST) || ((command & 0xf0) == 0x20)) { if ((command == DOLLAR_LIST) || ((command & 0xf0) == 0x20)) {
failed = 1; failed = 1;
} }
break; break;

case RULE_SYLLABLE: case RULE_SYLLABLE:
/* more than specified number of vowels to the left */ /* more than specified number of vowels to the left */
syllable_count = 1; syllable_count = 1;
else else
failed = 1; failed = 1;
break; break;

case RULE_STRESSED: case RULE_STRESSED:
if (tr->word_stressed_count > 0) if (tr->word_stressed_count > 0)
add_points = 19; add_points = 19;
else else
failed = 1; failed = 1;
break; break;

case RULE_NOVOWELS: case RULE_NOVOWELS:
{ {
char *p = pre_ptr - letter_xbytes - 1; char *p = pre_ptr - letter_xbytes - 1;
if (!failed) if (!failed)
add_points = 3; add_points = 3;
} }
break;

break;
case RULE_IFVERB: case RULE_IFVERB:
if (tr->expect_verb) if (tr->expect_verb)
add_points = 1; add_points = 1;
else else
failed = 1; failed = 1;
break; break;

case RULE_CAPITAL: case RULE_CAPITAL:
if (word_flags & FLAG_FIRST_UPPER) if (word_flags & FLAG_FIRST_UPPER)
add_points = 1; add_points = 1;
else else
failed = 1; failed = 1;
break; break;

case '.': case '.':
// dot in pre- section, match on any dot before this point in the word // dot in pre- section, match on any dot before this point in the word
for (p = pre_ptr; *p != ' '; p--) { for (p = pre_ptr; *p != ' '; p--) {
if (*p == ' ') if (*p == ' ')
failed = 1; failed = 1;
break; break;

case '-': case '-':
if ((letter == '-') || ((letter == ' ') && (word_flags & FLAG_HYPHEN))) if ((letter == '-') || ((letter == ' ') && (word_flags & FLAG_HYPHEN)))
add_points = (22-distance_right); // one point more than match against space add_points = (22-distance_right); // one point more than match against space
else else
failed = 1; failed = 1;
break; break;

default: default:
if (letter == rb) { if (letter == rb) {
if (letter == RULE_SPACE) if (letter == RULE_SPACE)
memcpy(match_out, &best, sizeof(MatchRecord)); memcpy(match_out, &best, sizeof(MatchRecord));
} }





int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, char *end_phonemes, int word_flags, unsigned int *dict_flags) int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, char *end_phonemes, int word_flags, unsigned int *dict_flags)
{ {
/* Translate a word bounded by space characters /* Translate a word bounded by space characters
} }
word_copy[ix] = 0; word_copy[ix] = 0;



if ((option_phonemes & espeakPHONEMES_TRACE) && ((word_flags & FLAG_NO_TRACE) == 0)) { if ((option_phonemes & espeakPHONEMES_TRACE) && ((word_flags & FLAG_NO_TRACE) == 0)) {
char wordbuf[120]; char wordbuf[120];
unsigned int ix; unsigned int ix;
return 0; return 0;
} }



void ApplySpecialAttribute2(Translator *tr, char *phonemes, int dict_flags) void ApplySpecialAttribute2(Translator *tr, char *phonemes, int dict_flags)
{ {
// apply after the translation is complete // apply after the translation is complete
} }
} }




int TransposeAlphabet(Translator *tr, char *text) int TransposeAlphabet(Translator *tr, char *text)
{ {
// transpose cyrillic alphabet (for example) into ascii (single byte) character codes // transpose cyrillic alphabet (for example) into ascii (single byte) character codes
int bufix; int bufix;
char buf[N_WORD_BYTES+1]; char buf[N_WORD_BYTES+1];



offset = tr->transpose_min - 1; offset = tr->transpose_min - 1;
min = tr->transpose_min; min = tr->transpose_min;
max = tr->transpose_max; max = tr->transpose_max;
return strlen(text); return strlen(text);
} }





/* Find an entry in the word_dict file for a specified word. /* Find an entry in the word_dict file for a specified word.
Returns NULL if no match, else returns 'word_end' Returns NULL if no match, else returns 'word_end'


return 0; return 0;
} }




/* Lookup a specified word in the word dictionary. /* Lookup a specified word in the word dictionary.
Returns phonetic data in 'phonetic' and bits in 'flags' Returns phonetic data in 'phonetic' and bits in 'flags'




found = LookupDict2(tr, word, word1, ph_out, flags, end_flags, wtab); found = LookupDict2(tr, word, word1, ph_out, flags, end_flags, wtab);



if (flags[0] & FLAG_MAX3) { if (flags[0] & FLAG_MAX3) {
if (strcmp(ph_out, tr->phonemes_repeat) == 0) { if (strcmp(ph_out, tr->phonemes_repeat) == 0) {
tr->phonemes_repeat_count++; tr->phonemes_repeat_count++;
} else } else
tr->phonemes_repeat_count = 0; tr->phonemes_repeat_count = 0;



if ((found == 0) && (flags[1] & FLAG_ACCENT)) { if ((found == 0) && (flags[1] & FLAG_ACCENT)) {
int letter; int letter;
word2 = word; word2 = word;
return 0; return 0;
} }



extern char word_phonemes[N_WORD_PHONEMES]; // a word translated into phoneme codes extern char word_phonemes[N_WORD_PHONEMES]; // a word translated into phoneme codes


int Lookup(Translator *tr, const char *word, char *ph_out) int Lookup(Translator *tr, const char *word, char *ph_out)
return flags0; return flags0;
} }



int LookupFlags(Translator *tr, const char *word, unsigned int **flags_out) int LookupFlags(Translator *tr, const char *word, unsigned int **flags_out)
{ {
char buf[100]; char buf[100];
return flags[0]; return flags[0];
} }




int RemoveEnding(Translator *tr, char *word, int end_type, char *word_copy) int RemoveEnding(Translator *tr, char *word, int end_type, char *word_copy)
{ {
/* Removes a standard suffix from a word, once it has been indicated by the dictionary rules. /* Removes a standard suffix from a word, once it has been indicated by the dictionary rules.

+ 20
- 46
src/libespeak-ng/espeak_command.c View File

free(the_command->u.my_text.text); free(the_command->u.my_text.text);
} }
break; break;

case ET_MARK: case ET_MARK:
if (the_command->u.my_mark.text) if (the_command->u.my_mark.text)
free(the_command->u.my_mark.text); free(the_command->u.my_mark.text);
if (the_command->u.my_mark.index_mark) if (the_command->u.my_mark.index_mark)
free((void *)(the_command->u.my_mark.index_mark)); free((void *)(the_command->u.my_mark.index_mark));
break; break;

case ET_TERMINATED_MSG: case ET_TERMINATED_MSG:
{ {
// if the terminated msg is pending, // if the terminated msg is pending,
sync_espeak_terminated_msg(data->unique_identifier, data->user_data); sync_espeak_terminated_msg(data->unique_identifier, data->user_data);
} }
} }
break;

break;
case ET_KEY: case ET_KEY:
if (the_command->u.my_key.key_name) if (the_command->u.my_key.key_name)
free((void *)(the_command->u.my_key.key_name)); free((void *)(the_command->u.my_key.key_name));
break; break;

case ET_CHAR: case ET_CHAR:
case ET_PARAMETER: case ET_PARAMETER:
// No allocation // No allocation
break; break;

case ET_PUNCTUATION_LIST: case ET_PUNCTUATION_LIST:
if (the_command->u.my_punctuation_list) if (the_command->u.my_punctuation_list)
free((void *)(the_command->u.my_punctuation_list)); free((void *)(the_command->u.my_punctuation_list));
break; break;

case ET_VOICE_NAME: case ET_VOICE_NAME:
if (the_command->u.my_voice_name) if (the_command->u.my_voice_name)
free((void *)(the_command->u.my_voice_name)); free((void *)(the_command->u.my_voice_name));
break; break;

case ET_VOICE_SPEC: case ET_VOICE_SPEC:
{ {
espeak_VOICE *data = &(the_command->u.my_voice_spec); espeak_VOICE *data = &(the_command->u.my_voice_spec);
if (data->identifier) if (data->identifier)
free((void *)data->identifier); free((void *)data->identifier);
} }
break;

break;
default: default:
assert(0); assert(0);
} }
data->position, data->position_type, data->position, data->position_type,
data->end_position, data->flags, data->user_data); data->end_position, data->flags, data->user_data);
} }
break;

break;
case ET_MARK: case ET_MARK:
{ {
t_espeak_mark *data = &(the_command->u.my_mark); t_espeak_mark *data = &(the_command->u.my_mark);
data->index_mark, data->end_position, data->flags, data->index_mark, data->end_position, data->flags,
data->user_data); data->user_data);
} }
break;

break;
case ET_TERMINATED_MSG: case ET_TERMINATED_MSG:
{ {
t_espeak_terminated_msg *data = &(the_command->u.my_terminated_msg); t_espeak_terminated_msg *data = &(the_command->u.my_terminated_msg);
sync_espeak_terminated_msg(data->unique_identifier, data->user_data); sync_espeak_terminated_msg(data->unique_identifier, data->user_data);
} }
break;

break;
case ET_KEY: case ET_KEY:
{ {
const char *data = the_command->u.my_key.key_name; const char *data = the_command->u.my_key.key_name;
sync_espeak_Key(data); sync_espeak_Key(data);
} }
break;

break;
case ET_CHAR: case ET_CHAR:
{ {
const wchar_t data = the_command->u.my_char.character; const wchar_t data = the_command->u.my_char.character;
sync_espeak_Char(data); sync_espeak_Char(data);
} }
break;

break;
case ET_PARAMETER: case ET_PARAMETER:
{ {
t_espeak_parameter *data = &(the_command->u.my_param); t_espeak_parameter *data = &(the_command->u.my_param);
SetParameter(data->parameter, data->value, data->relative); SetParameter(data->parameter, data->value, data->relative);
} }
break;

break;
case ET_PUNCTUATION_LIST: case ET_PUNCTUATION_LIST:
{ {
const wchar_t *data = the_command->u.my_punctuation_list; const wchar_t *data = the_command->u.my_punctuation_list;
sync_espeak_SetPunctuationList(data); sync_espeak_SetPunctuationList(data);
} }
break;

break;
case ET_VOICE_NAME: case ET_VOICE_NAME:
{ {
const char *data = the_command->u.my_voice_name; const char *data = the_command->u.my_voice_name;
SetVoiceByName(data); SetVoiceByName(data);
} }
break;

break;
case ET_VOICE_SPEC: case ET_VOICE_SPEC:
{ {
espeak_VOICE *data = &(the_command->u.my_voice_spec); espeak_VOICE *data = &(the_command->u.my_voice_spec);
SetVoiceByProperties(data); SetVoiceByProperties(data);
} }
break;

break;
default: default:
assert(0); assert(0);
break; break;
t_espeak_text *data = &(the_command->u.my_text); t_espeak_text *data = &(the_command->u.my_text);
SHOW("display_espeak_command > (0x%x) uid=%d, TEXT=%s, user_data=0x%x\n", the_command, data->unique_identifier, (char *)data->text, (int)(data->user_data)); SHOW("display_espeak_command > (0x%x) uid=%d, TEXT=%s, user_data=0x%x\n", the_command, data->unique_identifier, (char *)data->text, (int)(data->user_data));
} }
break;

break;
case ET_MARK: case ET_MARK:
{ {
t_espeak_mark *data = &(the_command->u.my_mark); t_espeak_mark *data = &(the_command->u.my_mark);
SHOW("display_espeak_command > (0x%x) uid=%d, MARK=%s, user_data=0x%x\n", the_command, data->unique_identifier, (char *)data->text, (int)(data->user_data)); SHOW("display_espeak_command > (0x%x) uid=%d, MARK=%s, user_data=0x%x\n", the_command, data->unique_identifier, (char *)data->text, (int)(data->user_data));
} }
break;

break;
case ET_KEY: case ET_KEY:
{ {
const char *data = the_command->u.my_key.key_name; const char *data = the_command->u.my_key.key_name;
SHOW("display_espeak_command > (0x%x) KEY=%c\n", the_command, data); SHOW("display_espeak_command > (0x%x) KEY=%c\n", the_command, data);
} }
break;

break;
case ET_TERMINATED_MSG: case ET_TERMINATED_MSG:
{ {
t_espeak_terminated_msg *data = &(the_command->u.my_terminated_msg); t_espeak_terminated_msg *data = &(the_command->u.my_terminated_msg);
the_command, data->unique_identifier, data->user_data, the_command, data->unique_identifier, data->user_data,
the_command->state); the_command->state);
} }
break;

break;
case ET_CHAR: case ET_CHAR:
{ {
const wchar_t data = the_command->u.my_char.character; const wchar_t data = the_command->u.my_char.character;
SHOW("display_espeak_command > (0x%x) CHAR=%c\n", the_command, (char)data); SHOW("display_espeak_command > (0x%x) CHAR=%c\n", the_command, (char)data);
} }
break;

break;
case ET_PARAMETER: case ET_PARAMETER:
{ {
t_espeak_parameter *data = &(the_command->u.my_param); t_espeak_parameter *data = &(the_command->u.my_param);
SHOW("display_espeak_command > (0x%x) PARAMETER=%d, value=%d, relative=%d\n", SHOW("display_espeak_command > (0x%x) PARAMETER=%d, value=%d, relative=%d\n",
the_command, data->parameter, data->value, data->relative); the_command, data->parameter, data->value, data->relative);
} }
break;

break;
case ET_PUNCTUATION_LIST: case ET_PUNCTUATION_LIST:
{ {
const wchar_t *data = the_command->u.my_punctuation_list; const wchar_t *data = the_command->u.my_punctuation_list;
sync_espeak_SetPunctuationList(data); sync_espeak_SetPunctuationList(data);
SHOW("display_espeak_command > (0x%x) PUNCTLIST=%s\n", the_command, (char *)data); SHOW("display_espeak_command > (0x%x) PUNCTLIST=%s\n", the_command, (char *)data);
} }
break;

break;
case ET_VOICE_NAME: case ET_VOICE_NAME:
{ {
const char *data = the_command->u.my_voice_name; const char *data = the_command->u.my_voice_name;
SHOW("display_espeak_command > (0x%x) VOICE_NAME=%s\n", the_command, data); SHOW("display_espeak_command > (0x%x) VOICE_NAME=%s\n", the_command, data);
} }
break;

break;
case ET_VOICE_SPEC: case ET_VOICE_SPEC:
{ {
SHOW("display_espeak_command > (0x%x) VOICE_SPEC", the_command); SHOW("display_espeak_command > (0x%x) VOICE_SPEC", the_command);
} }
break;

break;
default: default:
assert(0); assert(0);
break; break;

+ 2
- 7
src/libespeak-ng/event.c View File

ACTIVITY_TIMEOUT = 50, // in ms, check that the stream is active ACTIVITY_TIMEOUT = 50, // in ms, check that the stream is active
MAX_ACTIVITY_CHECK = 6 }; MAX_ACTIVITY_CHECK = 6 };



typedef struct t_node { typedef struct t_node {
void *data; void *data;
struct t_node *next; struct t_node *next;
my_callback(NULL, 0, events); my_callback(NULL, 0, events);
a_old_uid = event->unique_identifier; a_old_uid = event->unique_identifier;
break; break;

case espeakEVENT_MSG_TERMINATED: case espeakEVENT_MSG_TERMINATED:
case espeakEVENT_MARK: case espeakEVENT_MARK:
case espeakEVENT_WORD: case espeakEVENT_WORD:
my_callback(NULL, 0, events); my_callback(NULL, 0, events);
a_old_uid = event->unique_identifier; a_old_uid = event->unique_identifier;
} }
break;

default:
break;
case espeakEVENT_LIST_TERMINATED: case espeakEVENT_LIST_TERMINATED:
case espeakEVENT_PLAY: case espeakEVENT_PLAY:
default:
break; break;
} }
} }
case espeakEVENT_MSG_TERMINATED: case espeakEVENT_MSG_TERMINATED:
event_notify(event); event_notify(event);
break; break;

case espeakEVENT_MARK: case espeakEVENT_MARK:
case espeakEVENT_PLAY: case espeakEVENT_PLAY:
if (event->id.name) if (event->id.name)
free((void *)(event->id.name)); free((void *)(event->id.name));
break; break;

default: default:
break; break;
} }

+ 0
- 1
src/libespeak-ng/fifo.c View File

#include "wave.h" #include "wave.h"
#include "debug.h" #include "debug.h"



// my_mutex: protects my_thread_is_talking, // my_mutex: protects my_thread_is_talking,
// my_stop_is_required, and the command fifo // my_stop_is_required, and the command fifo
static pthread_mutex_t my_mutex; static pthread_mutex_t my_mutex;

+ 0
- 53
src/libespeak-ng/intonation.c View File

#include "voice.h" #include "voice.h"
#include "translate.h" #include "translate.h"



/* Note this module is mostly old code that needs to be rewritten to /* Note this module is mostly old code that needs to be rewritten to
provide a more flexible intonation system. provide a more flexible intonation system.
*/ */


static SYLLABLE *syllable_tab; static SYLLABLE *syllable_tab;



static int tone_pitch_env; /* used to return pitch envelope */ static int tone_pitch_env; /* used to return pitch envelope */




/* Pitch data for tone types */ /* Pitch data for tone types */
/*****************************/ /*****************************/



#define PITCHfall 0 #define PITCHfall 0
#define PITCHrise 2 #define PITCHrise 2
#define PITCHfrise 4 // and 3 must be for the variant preceded by 'r' #define PITCHfrise 4 // and 3 must be for the variant preceded by 'r'
0x50, 0x5a, 0x64, 0x70, 0x7c, 0x83, 0x85, 0x88, 0x8a, 0x8c, 0x8e, 0x8f, 0x91, 0x92, 0x93, 0x93 0x50, 0x5a, 0x64, 0x70, 0x7c, 0x83, 0x85, 0x88, 0x8a, 0x8c, 0x8e, 0x8f, 0x91, 0x92, 0x93, 0x93
}; };





unsigned char *envelope_data[N_ENVELOPE_DATA] = { unsigned char *envelope_data[N_ENVELOPE_DATA] = {
env_fall, env_fall, env_fall, env_fall,
env_rise, env_rise, env_rise, env_rise,
env_risefallrise, env_risefallrise env_risefallrise, env_risefallrise
}; };




/* indexed by stress */ /* indexed by stress */
static int min_drop[] = { 6, 7, 9, 9, 20, 20, 20, 25 }; static int min_drop[] = { 6, 7, 9, 9, 20, 20, 20, 25 };


static signed char oflow_emf[] = { 10, 52, 32, 20, 10 }; static signed char oflow_emf[] = { 10, 52, 32, 20, 10 };
static signed char oflow_less[] = { 6, 38, 24, 14, 4 }; static signed char oflow_less[] = { 6, 38, 24, 14, 4 };



#define N_TONE_HEAD_TABLE 13 #define N_TONE_HEAD_TABLE 13
#define N_TONE_NUCLEUS_TABLE 13 #define N_TONE_NUCLEUS_TABLE 13



typedef struct { typedef struct {
unsigned char pre_start; unsigned char pre_start;
unsigned char pre_end; unsigned char pre_end;
signed char *overflow; signed char *overflow;
} TONE_HEAD; } TONE_HEAD;



typedef struct { typedef struct {
unsigned char pitch_env0; /* pitch envelope, tonic syllable at end */ unsigned char pitch_env0; /* pitch envelope, tonic syllable at end */
unsigned char tonic_max0; unsigned char tonic_max0;
{ PITCHfall, 70, 18, PITCHfall, 70, 24, NULL, 32, 20, 0 }, // 12 test { PITCHfall, 70, 18, PITCHfall, 70, 24, NULL, 32, 20, 0 }, // 12 test
}; };




/* index by 0=. 1=, 2=?, 3=! 4=none, 5=emphasized */ /* index by 0=. 1=, 2=?, 3=! 4=none, 5=emphasized */
unsigned char punctuation_to_tone[INTONATION_TYPES][PUNCT_INTONATIONS] = { unsigned char punctuation_to_tone[INTONATION_TYPES][PUNCT_INTONATIONS] = {
{ 0, 1, 2, 3, 0, 4 }, { 0, 1, 2, 3, 0, 4 },
{ 12, 12, 12, 12, 0, 0 } { 12, 12, 12, 12, 0, 0 }
}; };



int n_tunes = 0; int n_tunes = 0;
TUNE *tunes = NULL; TUNE *tunes = NULL;



#define SECONDARY 3 #define SECONDARY 3
#define PRIMARY 4 #define PRIMARY 4
#define PRIMARY_STRESSED 6 #define PRIMARY_STRESSED 6
#define PRIMARY_LAST 7 #define PRIMARY_LAST 7



static int number_pre; static int number_pre;
static int number_body; static int number_body;
static int number_tail; static int number_tail;
static int tone_posn2; static int tone_posn2;
static int no_tonic; static int no_tonic;



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 ix;


last_primary = ix; last_primary = ix;
} }

} }


if (number_pre < 0) if (number_pre < 0)
} }
} }





/* Count number of primary stresses up to tonic syllable or body_reset */ /* Count number of primary stresses up to tonic syllable or body_reset */
static int count_increments(int ix, int end_ix, int min_stress) static int count_increments(int ix, int end_ix, int min_stress)
{ {
return count; return count;
} }





// 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)
{ {
syl->flags |= flags; syl->flags |= flags;
} }



static int CountUnstressed(int start, int end, int limit) static int CountUnstressed(int start, int end, int limit)
{ {
int ix; int ix;
increment = pitch_range / (n_steps -1); increment = pitch_range / (n_steps -1);
else else
increment = 0; increment = 0;

} else if (syl_ix == head_final) { } else if (syl_ix == head_final) {
// a pitch has been specified for the last primary stress before the nucleus // a pitch has been specified for the last primary stress before the nucleus
pitch = tune->head_last << 8; pitch = tune->head_last << 8;
syl_ix++; syl_ix++;
} }
return syl_ix; return syl_ix;

} }




/* Calculate pitches until next RESET or tonic syllable, or end. /* Calculate pitches until next RESET or tonic syllable, or end.
Increment pitch if stress is >= min_stress. Increment pitch if stress is >= min_stress.
Used for tonic segment */ Used for tonic segment */
return ix; return ix;
} }




static void SetPitchGradient(int start_ix, int end_ix, int start_pitch, int end_pitch) static void SetPitchGradient(int start_ix, int end_ix, int start_pitch, int end_pitch)
{ {
// Set a linear pitch change over a number of syllables. // Set a linear pitch change over a number of syllables.
} }
} }




// 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)
{ {
return tone_pitch_env; return tone_pitch_env;
} }




// 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)
{ {
return tone_pitch_env; return tone_pitch_env;
} }







static void CalcPitches_Tone(Translator *tr, int clause_tone) static void CalcPitches_Tone(Translator *tr, int clause_tone)
{ {
// clause_tone: 0=. 1=, 2=?, 3=! 4=none // clause_tone: 0=. 1=, 2=?, 3=! 4=none
p->tone_ph = PhonemeCode('7'); // change default tone (tone 1) to falling tone at end of clause p->tone_ph = PhonemeCode('7'); // change default tone (tone 1) to falling tone at end of clause
} }



pause = 1; pause = 1;
tone_promoted = 0; tone_promoted = 0;




p->tone_ph = tone_ph; p->tone_ph = tone_ph;
tph = phoneme_tab[tone_ph]; tph = phoneme_tab[tone_ph];

} else } else
tone_promoted = 0; tone_promoted = 0;


p->pitch2 = pitch_adjust + phoneme_tab[tone_ph]->end_type; p->pitch2 = pitch_adjust + phoneme_tab[tone_ph]->end_type;
} }
} }


} }




void CalcPitches(Translator *tr, int clause_type) void CalcPitches(Translator *tr, int clause_type)
{ {
// clause_type: 0=. 1=, 2=?, 3=! 4=none // clause_type: 0=. 1=, 2=?, 3=! 4=none
if (n_st == 0) if (n_st == 0)
return; // nothing to do return; // nothing to do




if (tr->langopts.tone_language == 1) { if (tr->langopts.tone_language == 1) {
CalcPitches_Tone(tr, clause_type); CalcPitches_Tone(tr, clause_type);
return; return;
} }



option = tr->langopts.intonation_group; option = tr->langopts.intonation_group;
if (option >= INTONATION_TYPES) if (option >= INTONATION_TYPES)
option = 1; option = 1;
calc_pitches(option, st_start, st_ix, group_tone); calc_pitches(option, st_start, st_ix, group_tone);
} }



// unpack pitch data // unpack pitch data
st_ix = 0; st_ix = 0;
for (ix = ph_start; ix < ph_end; ix++) { for (ix = ph_start; ix < ph_end; ix++) {
st_ix++; st_ix++;
} }
} }

} }

+ 0
- 49
src/libespeak-ng/klatt.c View File

static int nsamples; static int nsamples;
static int sample_count; static int sample_count;



#ifdef _MSC_VER #ifdef _MSC_VER
#define getrandom(min, max) ((rand()%(int)(((max)+1)-(min)))+(min)) #define getrandom(min, max) ((rand()%(int)(((max)+1)-(min)))+(min))
#else #else
#define getrandom(min, max) ((rand()%(long)(((max)+1)-(min)))+(min)) #define getrandom(min, max) ((rand()%(long)(((max)+1)-(min)))+(min))
#endif #endif



/* function prototypes for functions private to this file */ /* function prototypes for functions private to this file */


static void flutter(klatt_frame_ptr); static void flutter(klatt_frame_ptr);
return (double)x; return (double)x;
} }




static double antiresonator2(resonator_ptr r, double input) static double antiresonator2(resonator_ptr r, double input)
{ {
register double x = (double)r->a * (double)input + (double)r->b * (double)r->p1 + (double)r->c * (double)r->p2; register double x = (double)r->a * (double)input + (double)r->b * (double)r->p1 + (double)r->c * (double)r->p2;
return (double)x; return (double)x;
} }




/* /*
function FLUTTER function FLUTTER


time_count++; time_count++;
} }




/* /*
function SAMPLED_SOURCE function SAMPLED_SOURCE


return result; return result;
} }





/* /*
function PARWAVE function PARWAVE


Converts synthesis parameters to a waveform. Converts synthesis parameters to a waveform.
*/ */



static int parwave(klatt_frame_ptr frame) static int parwave(klatt_frame_ptr frame)
{ {
double temp; double temp;
return 0; return 0;
} }






void KlattReset(int control) void KlattReset(int control)
{ {
int r_ix; int r_ix;
kt_globals.rsn[r_ix].p1 = 0; kt_globals.rsn[r_ix].p1 = 0;
kt_globals.rsn[r_ix].p2 = 0; kt_globals.rsn[r_ix].p2 = 0;
} }

} }


for (r_ix = 0; r_ix <= R6p; r_ix++) { for (r_ix = 0; r_ix <= R6p; r_ix++) {
} }
} }



/* /*
function FRAME_INIT function FRAME_INIT


kt_globals.rsn[F_NZ].b_inc = (kt_globals.rsn_next[F_NZ].b - kt_globals.rsn[F_NZ].b) / 64.0; kt_globals.rsn[F_NZ].b_inc = (kt_globals.rsn_next[F_NZ].b - kt_globals.rsn[F_NZ].b) / 64.0;
kt_globals.rsn[F_NZ].c_inc = (kt_globals.rsn_next[F_NZ].c - kt_globals.rsn[F_NZ].c) / 64.0; kt_globals.rsn[F_NZ].c_inc = (kt_globals.rsn_next[F_NZ].c - kt_globals.rsn[F_NZ].c) / 64.0;



/* Set coefficients of parallel resonators, and amplitude of outputs */ /* Set coefficients of parallel resonators, and amplitude of outputs */


for (ix = 0; ix <= 6; ix++) { for (ix = 0; ix <= 6; ix++) {
/* output low-pass filter */ /* output low-pass filter */


setabc((long)0.0, (long)(kt_globals.samrate/2), &(kt_globals.rsn[Rout])); setabc((long)0.0, (long)(kt_globals.samrate/2), &(kt_globals.rsn[Rout]));

} }




/* /*
function IMPULSIVE_SOURCE function IMPULSIVE_SOURCE


to Kopen. to Kopen.
*/ */



static double impulsive_source() static double impulsive_source()
{ {
static double doublet[] = { 0.0, 13000000.0, -13000000.0 }; static double doublet[] = { 0.0, 13000000.0, -13000000.0 };
return resonator(&(kt_globals.rsn[RGL]), vwave); return resonator(&(kt_globals.rsn[RGL]), vwave);
} }




/* /*
function NATURAL_SOURCE function NATURAL_SOURCE


return 0.0; return 0.0;
} }






/* /*
function PITCH_SYNC_PAR_RESET function PITCH_SYNC_PAR_RESET


kt_globals.nopen = 40; kt_globals.nopen = 40;
} }



/* Reset a & b, which determine shape of "natural" glottal waveform */ /* Reset a & b, which determine shape of "natural" glottal waveform */


kt_globals.pulse_shape_b = B0[kt_globals.nopen-40]; kt_globals.pulse_shape_b = B0[kt_globals.nopen-40];
} }
} }




/* /*
function SETABC function SETABC


equation constants. equation constants.
*/ */



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 r;
rp->a = 1.0 - rp->b - rp->c; rp->a = 1.0 - rp->b - rp->c;
} }



/* /*
function SETZEROABC function SETZEROABC


} }
} }



/* /*
function GEN_NOISE function GEN_NOISE


the origin in the z-plane, i.e. output = input + (0.75 * lastoutput) the origin in the z-plane, i.e. output = input + (0.75 * lastoutput)
*/ */



static double gen_noise(double noise) static double gen_noise(double noise)
{ {
long temp; long temp;
return noise; return noise;
} }



/* /*
function DBTOLIN function DBTOLIN


steps. steps.
*/ */



static double DBtoLIN(long dB) static double DBtoLIN(long dB)
{ {
static short amptable[88] = { static short amptable[88] = {
return (double)(amptable[dB]) * 0.001; return (double)(amptable[dB]) * 0.001;
} }






extern voice_t *wvoice; extern voice_t *wvoice;
static klatt_peaks_t peaks[N_PEAKS]; static klatt_peaks_t peaks[N_PEAKS];
static int end_wave; static int end_wave;
static double klattp1[N_KLATTP]; static double klattp1[N_KLATTP];
static double klattp_inc[N_KLATTP]; static double klattp_inc[N_KLATTP];





int Wavegen_Klatt(int resume) int Wavegen_Klatt(int resume)
{ {
int pk; int pk;
return 0; return 0;
} }



void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v, int control) void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v, int control)
{ {
int ix; int ix;
} }
} }



int Wavegen_Klatt2(int length, int modulation, int resume, frame_t *fr1, frame_t *fr2) int Wavegen_Klatt2(int length, int modulation, int resume, frame_t *fr1, frame_t *fr2)
{ {
if (resume == 0) if (resume == 0)
return Wavegen_Klatt(resume); return Wavegen_Klatt(resume);
} }




void KlattInit() void KlattInit()
{ {



+ 0
- 1
src/libespeak-ng/mbrowrap.c View File



#include "mbrowrap.h" #include "mbrowrap.h"



/* /*
* mbrola instance parameters * mbrola instance parameters
*/ */

+ 1
- 49
src/libespeak-ng/numbers.c View File

#include "voice.h" #include "voice.h"
#include "translate.h" #include "translate.h"



#define M_LIGATURE 0x8000 #define M_LIGATURE 0x8000
#define M_NAME 0 #define M_NAME 0
#define M_SMALLCAP 1 #define M_SMALLCAP 1
#define M_RETROFLEX 20 #define M_RETROFLEX 20
#define M_HOOK 21 #define M_HOOK 21



#define M_MIDDLE_DOT M_DOT_ABOVE // duplicate of M_DOT_ABOVE #define M_MIDDLE_DOT M_DOT_ABOVE // duplicate of M_DOT_ABOVE
#define M_IMPLOSIVE M_HOOK #define M_IMPLOSIVE M_HOOK


static int speak_missing_thousands; static int speak_missing_thousands;
static int number_control; static int number_control;



typedef struct { typedef struct {
const char *name; const char *name;
int accent_flags; // bit 0, say before the letter name int accent_flags; // bit 0, say before the letter name
{ "_hok", 0 }, // hook { "_hok", 0 }, // hook
}; };



#define CAPITAL 0 #define CAPITAL 0
#define LETTER(ch, mod1, mod2) (ch-59)+(mod1 << 6)+(mod2 << 11) #define LETTER(ch, mod1, mod2) (ch-59)+(mod1 << 6)+(mod2 << 11)
#define LIGATURE(ch1, ch2, mod1) (ch1-59)+((ch2-59) << 6)+(mod1 << 12)+M_LIGATURE #define LIGATURE(ch1, ch2, mod1) (ch1-59)+((ch2-59) << 6)+(mod1 << 12)+M_LIGATURE
#define L_RTAP 72 // U+27E #define L_RTAP 72 // U+27E
#define L_RLONG 73 // U+27C #define L_RLONG 73 // U+27C



static const short non_ascii_tab[] = { static const short non_ascii_tab[] = {
0, 0x3b1, 0x259, 0x25b, 0x3b3, 0x3b9, 0x153, 0x3c9, 0, 0x3b1, 0x259, 0x25b, 0x3b3, 0x3b9, 0x153, 0x3c9,
0x3c6, 0x283, 0x3c5, 0x292, 0x294, 0x27e, 0x27c 0x3c6, 0x283, 0x3c5, 0x292, 0x294, 0x27e, 0x27c
}; };



// characters U+00e0 to U+017f // characters U+00e0 to U+017f
static const unsigned short letter_accents_0e0[] = { static const unsigned short letter_accents_0e0[] = {
LETTER('a', M_GRAVE, 0), // U+00e0 LETTER('a', M_GRAVE, 0), // U+00e0
CAPITAL, CAPITAL,
LETTER('z', M_CARON, 0), LETTER('z', M_CARON, 0),
LETTER('s', M_NAME, 0), // long-s // U+17f LETTER('s', M_NAME, 0), // long-s // U+17f

}; };



// characters U+0250 to U+029F // characters U+0250 to U+029F
static const unsigned short letter_accents_250[] = { static const unsigned short letter_accents_250[] = {
LETTER('a', M_TURNED, 0), // U+250 LETTER('a', M_TURNED, 0), // U+250
return ph_buf[0]; return ph_buf[0];
} }



void LookupAccentedLetter(Translator *tr, unsigned int letter, char *ph_buf) void LookupAccentedLetter(Translator *tr, unsigned int letter, char *ph_buf)
{ {
// lookup the character in the accents table // lookup the character in the accents table
accent2 = (accent_data >> 11) & 0xf; accent2 = (accent_data >> 11) & 0xf;
} }



if ((accent1 == 0) && !(accent_data & M_LIGATURE)) { if ((accent1 == 0) && !(accent_data & M_LIGATURE)) {
// just a letter name, not an accented character or ligature // just a letter name, not an accented character or ligature
return; return;
} }


if ((flags1 = Lookup(tr, accents_tab[accent1].name, ph_accent1)) != 0) { if ((flags1 = Lookup(tr, accents_tab[accent1].name, ph_accent1)) != 0) {

if (LookupLetter2(tr, basic_letter, ph_letter1) != 0) { if (LookupLetter2(tr, basic_letter, ph_letter1) != 0) {
if (accent2 != 0) { if (accent2 != 0) {
flags2 = Lookup(tr, accents_tab[accent2].name, ph_accent2); flags2 = Lookup(tr, accents_tab[accent2].name, ph_accent2);
} }
} }




void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_buf1, int control) void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_buf1, int control)
{ {
// control, bit 0: not the first letter of a word // control, bit 0: not the first letter of a word
dict_flags[0] = 0; dict_flags[0] = 0;
dict_flags[1] = 0; dict_flags[1] = 0;
SetWordStress(tr, ph_buf1, dict_flags, -1, control & 1); SetWordStress(tr, ph_buf1, dict_flags, -1, control & 1);

} }



// unicode ranges for non-ascii digits 0-9 // unicode ranges for non-ascii digits 0-9
static const int number_ranges[] = { static const int number_ranges[] = {
0x660, 0x6f0, // arabic 0x660, 0x6f0, // arabic
0 0
}; // these must be in ascending order }; // these must be in ascending order



int NonAsciiNumber(int letter) int NonAsciiNumber(int letter)
{ {
// Change non-ascii digit into ascii digit '0' to '9', (or -1 if not) // Change non-ascii digit into ascii digit '0' to '9', (or -1 if not)
0, 0 0, 0
}; };



static const char *hex_letters[] = { "'e:j", "b'i:", "s'i:", "d'i:", "'i:", "'ef" }; // names, using phonemes available to all languages static const char *hex_letters[] = { "'e:j", "b'i:", "s'i:", "d'i:", "'i:", "'ef" }; // names, using phonemes available to all languages



int IsSuperscript(int letter) int IsSuperscript(int letter)
{ {
// is this a subscript or superscript letter ? // is this a subscript or superscript letter ?
return 0; return 0;
} }




int TranslateLetter(Translator *tr, char *word, char *phonemes, int control) int TranslateLetter(Translator *tr, char *word, char *phonemes, int control)
{ {
// get pronunciation for an isolated letter // get pronunciation for an isolated letter
} }
} }



// caution: SetWordStress() etc don't expect phonSWITCH + phoneme table number // caution: SetWordStress() etc don't expect phonSWITCH + phoneme table number


if (ph_buf[0] == 0) { if (ph_buf[0] == 0) {
return n_bytes; return n_bytes;
} }




void SetSpellingStress(Translator *tr, char *phonemes, int control, int n_chars) void SetSpellingStress(Translator *tr, char *phonemes, int control, int n_chars)
{ {
// Individual letter names, reduce the stress of some. // Individual letter names, reduce the stress of some.
*phonemes = 0; *phonemes = 0;
} }




// Numbers // Numbers


static char ph_ordinal2[12]; static char ph_ordinal2[12];
static char ph_ordinal2x[12]; static char ph_ordinal2x[12];



static int CheckDotOrdinal(Translator *tr, char *word, char *word_end, WORD_TAB *wtab, int roman) static int CheckDotOrdinal(Translator *tr, char *word, char *word_end, WORD_TAB *wtab, int roman)
{ {

int ordinal = 0; int ordinal = 0;
int c2; int c2;
int nextflags; int nextflags;
return ordinal; return ordinal;
} }



static int hu_number_e(const char *word, int thousandplex, int value) static int hu_number_e(const char *word, int thousandplex, int value)
{ {
// lang-hu: variant form of numbers when followed by hyphen and a suffix starting with 'a' or 'e' (but not a, e, az, ez, azt, ezt, att. ett // lang-hu: variant form of numbers when followed by hyphen and a suffix starting with 'a' or 'e' (but not a, e, az, ez, azt, ezt, att. ett
return 0; return 0;
} }




int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab) int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab)
{ {
int c; int c;
if (acc > tr->langopts.max_roman) if (acc > tr->langopts.max_roman)
return 0; return 0;



Lookup(tr, "_roman", ph_roman); // precede by "roman" if _rom is defined in *_list Lookup(tr, "_roman", ph_roman); // precede by "roman" if _rom is defined in *_list
p = &ph_out[0]; p = &ph_out[0];


return 1; return 1;
} }



static const char *M_Variant(int value) static const char *M_Variant(int value)
{ {
// returns M, or perhaps MA or MB for some cases // returns M, or perhaps MA or MB for some cases
if ((teens == 0) && ((value % 10) == 1)) if ((teens == 0) && ((value % 10) == 1))
return "1M"; return "1M";
break; break;

case 2: // lang=cs,sk case 2: // lang=cs,sk
if ((value >= 2) && (value <= 4)) if ((value >= 2) && (value <= 4))
return "0MA"; return "0MA";
break; break;

case 3: // lang=pl case 3: // lang=pl
if ((teens == 0) && (((value % 10) >= 2) && ((value % 10) <= 4))) if ((teens == 0) && (((value % 10) >= 2) && ((value % 10) <= 4)))
return "0MA"; return "0MA";
break; break;

case 4: // lang=lt case 4: // lang=lt
if ((teens == 1) || ((value % 10) == 0)) if ((teens == 1) || ((value % 10) == 0))
return "0MB"; return "0MB";
if ((value % 10) == 1) if ((value % 10) == 1)
return "0MA"; return "0MA";
break; break;

case 5: // lang=bs,hr,sr case 5: // lang=bs,hr,sr
if (teens == 0) { if (teens == 0) {
if ((value % 10) == 1) if ((value % 10) == 1)
return "0M"; return "0M";
} }



static int LookupThousands(Translator *tr, int value, int thousandplex, int thousands_exact, char *ph_out) static int LookupThousands(Translator *tr, int value, int thousandplex, int thousands_exact, char *ph_out)
{ {
// thousands_exact: bit 0 no hundreds,tens,or units, bit 1 ordinal numberr // thousands_exact: bit 0 no hundreds,tens,or units, bit 1 ordinal numberr
return found_value; return found_value;
} }



static int LookupNum2(Translator *tr, int value, int thousandplex, const int control, char *ph_out) static int LookupNum2(Translator *tr, int value, int thousandplex, const int control, char *ph_out)
{ {
// Lookup a 2 digit number // Lookup a 2 digit number
if (found) { if (found) {
ph_tens[0] = 0; ph_tens[0] = 0;
} else { } else {

if (is_ordinal) { if (is_ordinal) {
sprintf(string, "_%dX%c", tens, ord_type); sprintf(string, "_%dX%c", tens, ord_type);
if (Lookup(tr, string, ph_tens) != 0) { if (Lookup(tr, string, ph_tens) != 0) {
return used_and; return used_and;
} }



static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null, int thousandplex, int control) static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null, int thousandplex, int control)
{ {
// Translate a 3 digit number // Translate a 3 digit number
} }
} }



buf2[0] = 0; buf2[0] = 0;


if ((tensunits != 0) || (suppress_null == 0)) { if ((tensunits != 0) || (suppress_null == 0)) {
return 0; return 0;
} }



bool CheckThousandsGroup(char *word, int group_len) bool CheckThousandsGroup(char *word, int group_len)
{ {
// Is this a group of 3 digits which looks like a thousands group? // Is this a group of 3 digits which looks like a thousands group?
return true; return true;
} }



static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned int *flags, WORD_TAB *wtab, int control) static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned int *flags, WORD_TAB *wtab, int control)
{ {
// Number translation with various options // Number translation with various options
ph_append[0] = 0; ph_append[0] = 0;
ph_buf2[0] = 0; ph_buf2[0] = 0;



if ((word[0] == '0') && (prev_thousands == 0) && (word[1] != ' ') && (word[1] != tr->langopts.decimal_sep)) { if ((word[0] == '0') && (prev_thousands == 0) && (word[1] != ' ') && (word[1] != tr->langopts.decimal_sep)) {
if ((n_digits == 2) && (word[3] == ':') && IsDigit09(word[5]) && isspace(word[7])) { if ((n_digits == 2) && (word[3] == ':') && IsDigit09(word[5]) && isspace(word[7])) {
// looks like a time 02:30, omit the leading zero // looks like a time 02:30, omit the leading zero
{ {
case NUM_DFRACTION_4: case NUM_DFRACTION_4:
max_decimal_count = 5; max_decimal_count = 5;
// fallthrough
case NUM_DFRACTION_2: case NUM_DFRACTION_2:
// French/Polish decimal fraction // French/Polish decimal fraction
while (word[n_digits] == '0') { while (word[n_digits] == '0') {
n_digits += decimal_count; n_digits += decimal_count;
} }
break; break;

case NUM_DFRACTION_1: // italian, say "hundredths" if leading zero case NUM_DFRACTION_1: // italian, say "hundredths" if leading zero
case NUM_DFRACTION_5: // hungarian, always say "tenths" etc. case NUM_DFRACTION_5: // hungarian, always say "tenths" etc.
case NUM_DFRACTION_6: // kazakh, always say "tenths" etc, before the decimal fraction case NUM_DFRACTION_6: // kazakh, always say "tenths" etc, before the decimal fraction
strcat(ph_out, ph_buf); strcat(ph_out, ph_buf);
n_digits += decimal_count; n_digits += decimal_count;
break; break;

case NUM_DFRACTION_3: case NUM_DFRACTION_3:
// Romanian decimal fractions // Romanian decimal fractions
if ((decimal_count <= 4) && (word[n_digits] != '0')) { if ((decimal_count <= 4) && (word[n_digits] != '0')) {
n_digits += decimal_count; n_digits += decimal_count;
} }
break; break;

case NUM_DFRACTION_7: case NUM_DFRACTION_7:
// alternative form of decimal fraction digits, except the final digit // alternative form of decimal fraction digits, except the final digit
while (decimal_count-- > 1) { while (decimal_count-- > 1) {
return 1; return 1;
} }




int TranslateNumber(Translator *tr, char *word1, char *ph_out, unsigned int *flags, WORD_TAB *wtab, int control) int TranslateNumber(Translator *tr, char *word1, char *ph_out, unsigned int *flags, WORD_TAB *wtab, int control)
{ {
if ((option_sayas == SAYAS_DIGITS1) || (wtab[0].flags & FLAG_INDIVIDUAL_DIGITS)) if ((option_sayas == SAYAS_DIGITS1) || (wtab[0].flags & FLAG_INDIVIDUAL_DIGITS))

+ 0
- 7
src/libespeak-ng/phonemelist.c View File

#include "synthesize.h" #include "synthesize.h"
#include "translate.h" #include "translate.h"



const unsigned char pause_phonemes[8] = { 0, phonPAUSE_VSHORT, phonPAUSE_SHORT, phonPAUSE, phonPAUSE_LONG, phonGLOTTALSTOP, phonPAUSE_LONG, phonPAUSE_LONG }; const unsigned char pause_phonemes[8] = { 0, phonPAUSE_VSHORT, phonPAUSE_SHORT, phonPAUSE, phonPAUSE_LONG, phonGLOTTALSTOP, phonPAUSE_LONG, phonPAUSE_LONG };



extern int n_ph_list2; extern int n_ph_list2;
extern PHONEME_LIST2 ph_list2[N_PHONEME_LIST]; // first stage of text->phonemes extern PHONEME_LIST2 ph_list2[N_PHONEME_LIST]; // first stage of text->phonemes




static int SubstitutePhonemes(Translator *tr, PHONEME_LIST *plist_out) static int SubstitutePhonemes(Translator *tr, PHONEME_LIST *plist_out)
{ {
// 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
return n_plist_out; return n_plist_out;
} }




void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
{ {

int ix = 0; int ix = 0;
int j; int j;
int insert_ph = 0; int insert_ph = 0;

+ 0
- 78
src/libespeak-ng/readclause.c View File

#include <locale.h> #include <locale.h>
#define N_XML_BUF 500 #define N_XML_BUF 500



static const char *xmlbase = ""; // base URL from <speak> static const char *xmlbase = ""; // base URL from <speak>


static int namedata_ix = 0; static int namedata_ix = 0;
static int n_namedata = 0; static int n_namedata = 0;
char *namedata = NULL; char *namedata = NULL;



static FILE *f_input = NULL; static FILE *f_input = NULL;
static int ungot_char2 = 0; static int ungot_char2 = 0;
unsigned char *p_textinput; unsigned char *p_textinput;


0 }; 0 };



// indexed by (entry num. in punct_chars) + 1 // indexed by (entry num. in punct_chars) + 1
// bits 0-7 pause x 10mS, bits 12-14 intonation type, bit 15 don't need following space or bracket // bits 0-7 pause x 10mS, bits 12-14 intonation type, bit 15 don't need following space or bracket
static const unsigned int punct_attributes[] = { 0, static const unsigned int punct_attributes[] = { 0,
CLAUSE_SEMICOLON, // spare CLAUSE_SEMICOLON, // spare
0 }; 0 };



// stack for language and voice properties // stack for language and voice properties
// frame 0 is for the defaults, before any ssml tags. // frame 0 is for the defaults, before any ssml tags.
typedef struct { typedef struct {
static char base_voice_variant_name[40] = { 0 }; static char base_voice_variant_name[40] = { 0 };
static char current_voice_id[40] = { 0 }; static char current_voice_id[40] = { 0 };



#define N_PARAM_STACK 20 #define N_PARAM_STACK 20
static int n_param_stack; static int n_param_stack;
PARAM_STACK param_stack[N_PARAM_STACK]; PARAM_STACK param_stack[N_PARAM_STACK];
0, // voice type 0, // voice type
}; };



// additional Latin characters beyond the ascii character set // additional Latin characters beyond the ascii character set
#define MAX_WALPHA 0x24f #define MAX_WALPHA 0x24f
// indexed by character - 0x80 // indexed by character - 0x80
0, 0 0, 0
}; };



#ifdef NEED_WCHAR_FUNCTIONS #ifdef NEED_WCHAR_FUNCTIONS


// use ctype.h functions for Latin1 (character < 0x100) // use ctype.h functions for Latin1 (character < 0x100)
} }
#endif #endif



// use internal data for iswalpha up to U+024F // use internal data for iswalpha up to U+024F
// iswalpha() on Windows is unreliable (U+AA, U+BA). // iswalpha() on Windows is unreliable (U+AA, U+BA).
int iswalpha2(int c) int iswalpha2(int c)
return 0; return 0;
} }



static void GetC_unget(int c) static void GetC_unget(int c)
{ {
// This is only called with UTF8 input, not wchar input // This is only called with UTF8 input, not wchar input
return end_of_input; return end_of_input;
} }



static int GetC_get(void) static int GetC_get(void)
{ {
unsigned int c; unsigned int c;
return 0; return 0;
} }



static int GetC(void) static int GetC(void)
{ {
// Returns a unicode wide character // Returns a unicode wide character
return c1; return c1;
} }



static void UngetC(int c) static void UngetC(int c)
{ {
ungot_char = c; ungot_char = c;
} }



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
return buf; return buf;
} }



static const char *LookupSpecial(Translator *tr, const char *string, char *text_out) static const char *LookupSpecial(Translator *tr, const char *string, char *text_out)
{ {
unsigned int flags[2]; unsigned int flags[2];
return NULL; return NULL;
} }



static const char *LookupCharName(Translator *tr, int c, int only) static const char *LookupCharName(Translator *tr, int c, int only)
{ {
// 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
return acc; return acc;
} }



static int LoadSoundFile(const char *fname, int index) static int LoadSoundFile(const char *fname, int index)
{ {
FILE *f; FILE *f;
return 0; return 0;
} }



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
return -1; return -1;
} }



static int LoadSoundFile2(const char *fname) static int LoadSoundFile2(const char *fname)
{ {
// 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
return slot; return slot;
} }




static int AnnouncePunctuation(Translator *tr, int c1, int *c2_ptr, char *output, int *bufix, int end_clause) static int AnnouncePunctuation(Translator *tr, int c1, int *c2_ptr, char *output, int *bufix, int end_clause)
{ {
// announce punctuation names // announce punctuation names
// these tags have no effect if they are self-closing, eg. <voice /> // these tags have no effect if they are self-closing, eg. <voice />
static char ignore_if_self_closing[] = { 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0 }; static char ignore_if_self_closing[] = { 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0 };



static MNEM_TAB ssmltags[] = { static MNEM_TAB ssmltags[] = {
{ "speak", SSML_SPEAK }, { "speak", SSML_SPEAK },
{ "voice", SSML_VOICE }, { "voice", SSML_VOICE },
{ NULL, 0 } { NULL, 0 }
}; };





static const char *VoiceFromStack() static const char *VoiceFromStack()
{ {
// 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
return v_id; return v_id;
} }




static void ProcessParamStack(char *outbuf, int *outix) static void ProcessParamStack(char *outbuf, int *outix)
{ {
// Set the speech parameters from the parameter stack // Set the speech parameters from the parameter stack
int new_parameters[N_SPEECH_PARAM]; int new_parameters[N_SPEECH_PARAM];
static char cmd_letter[N_SPEECH_PARAM] = { 0, 'S', 'A', 'P', 'R', 0, 'C', 0, 0, 0, 0, 0, 'F' }; // embedded command letters static char cmd_letter[N_SPEECH_PARAM] = { 0, 'S', 'A', 'P', 'R', 0, 'C', 0, 0, 0, 0, 0, 'F' }; // embedded command letters



for (param = 0; param < N_SPEECH_PARAM; param++) for (param = 0; param < N_SPEECH_PARAM; param++)
new_parameters[param] = -1; new_parameters[param] = -1;


case espeakPUNCTUATION: case espeakPUNCTUATION:
option_punctuation = value-1; option_punctuation = value-1;
break; break;

case espeakCAPITALS: case espeakCAPITALS:
option_capitals = value; option_capitals = value;
break; break;

case espeakRATE: case espeakRATE:
case espeakVOLUME: case espeakVOLUME:
case espeakPITCH: case espeakPITCH:
} }
} }



static PARAM_STACK *PushParamStack(int tag_type) static PARAM_STACK *PushParamStack(int tag_type)
{ {
int ix; int ix;
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
ProcessParamStack(outbuf, outix); ProcessParamStack(outbuf, outix);
} }




static wchar_t *GetSsmlAttribute(wchar_t *pw, const char *name) static wchar_t *GetSsmlAttribute(wchar_t *pw, const char *name)
{ {
// Gets the value string for an attribute. // Gets the value string for an attribute.
return NULL; return NULL;
} }



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



static int attrlookup(const wchar_t *string1, const MNEM_TAB *mtab) static int attrlookup(const wchar_t *string1, const MNEM_TAB *mtab)
{ {
int ix; int ix;
return mtab[ix].value; return mtab[ix].value;
} }



static int attrnumber(const wchar_t *pw, int default_value, int type) static int attrnumber(const wchar_t *pw, int default_value, int type)
{ {
int value = 0; int value = 0;
return value; return value;
} }




static int attrcopy_utf8(char *buf, const wchar_t *pw, int len) static int attrcopy_utf8(char *buf, const wchar_t *pw, int len)
{ {
// Convert attribute string into utf8, write to buf, and return its utf8 length // Convert attribute string into utf8, write to buf, and return its utf8 length
return ix; return ix;
} }




static int attr_prosody_value(int param_type, const wchar_t *pw, int *value_out) static int attr_prosody_value(int param_type, const wchar_t *pw, int *value_out)
{ {
int sign = 0; int sign = 0;
return sign; // -1, 0, or 1 return sign; // -1, 0, or 1
} }



int AddNameData(const char *name, int wide) int AddNameData(const char *name, int wide)
{ {
// Add the name to the namedata and return its position // Add the name to the namedata and return its position
return ix; return ix;
} }



void SetVoiceStack(espeak_VOICE *v, const char *variant_name) void SetVoiceStack(espeak_VOICE *v, const char *variant_name)
{ {
SSML_STACK *sp; SSML_STACK *sp;
memcpy(&base_voice, &current_voice_selected, sizeof(base_voice)); memcpy(&base_voice, &current_voice_selected, sizeof(base_voice));
} }



static int GetVoiceAttributes(wchar_t *pw, int tag_type) static int GetVoiceAttributes(wchar_t *pw, int tag_type)
{ {
// Determines whether voice attribute are specified in this tag, and if so, whether this means // Determines whether voice attribute are specified in this tag, and if so, whether this means
return 0; return 0;
} }



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;
NULL, mnem_rate, mnem_volume, mnem_pitch, mnem_range NULL, mnem_rate, mnem_volume, mnem_pitch, mnem_range
}; };



if ((value = attrlookup(attr1, mnem_tabs[param_type])) >= 0) { if ((value = attrlookup(attr1, mnem_tabs[param_type])) >= 0) {
// 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;
} }
} }



static int ReplaceKeyName(char *outbuf, int index, int *outix) static int ReplaceKeyName(char *outbuf, int index, int *outix)
{ {
// Replace some key-names by single characters, so they can be pronounced in different languages // Replace some key-names by single characters, so they can be pronounced in different languages
return 0; return 0;
} }



static int ProcessSsmlTag(wchar_t *xml_buf, char *outbuf, int *outix, int n_outbuf, int self_closing) static int ProcessSsmlTag(wchar_t *xml_buf, char *outbuf, int *outix, int n_outbuf, int self_closing)
{ {
// xml_buf is the tag and attributes with a zero terminator in place of the original '>' // xml_buf is the tag and attributes with a zero terminator in place of the original '>'
return 0; return 0;
} }



voice_change_flag = 0; voice_change_flag = 0;
terminator = CLAUSE_NONE; terminator = CLAUSE_NONE;
ssml_sp = &ssml_stack[n_ssml_stack-1]; ssml_sp = &ssml_stack[n_ssml_stack-1];
} }
ProcessParamStack(outbuf, outix); ProcessParamStack(outbuf, outix);
break; break;

case SSML_PROSODY: case SSML_PROSODY:
sp = PushParamStack(tag_type); sp = PushParamStack(tag_type);




ProcessParamStack(outbuf, outix); ProcessParamStack(outbuf, outix);
break; break;

case SSML_EMPHASIS: case SSML_EMPHASIS:
sp = PushParamStack(tag_type); sp = PushParamStack(tag_type);
value = 3; // default is "moderate" value = 3; // default is "moderate"
} }
ProcessParamStack(outbuf, outix); ProcessParamStack(outbuf, outix);
break; break;

case SSML_STYLE + SSML_CLOSE: case SSML_STYLE + SSML_CLOSE:
case SSML_PROSODY + SSML_CLOSE: case SSML_PROSODY + SSML_CLOSE:
case SSML_EMPHASIS + SSML_CLOSE: case SSML_EMPHASIS + SSML_CLOSE:
PopParamStack(tag_type, outbuf, outix); PopParamStack(tag_type, outbuf, outix);
break; break;

case SSML_PHONEME: case SSML_PHONEME:
attr1 = GetSsmlAttribute(px, "alphabet"); attr1 = GetSsmlAttribute(px, "alphabet");
attr2 = GetSsmlAttribute(px, "ph"); attr2 = GetSsmlAttribute(px, "ph");
outbuf[(*outix)++] = ']'; outbuf[(*outix)++] = ']';
} }
break; break;

case SSML_SAYAS: case SSML_SAYAS:
attr1 = GetSsmlAttribute(px, "interpret-as"); attr1 = GetSsmlAttribute(px, "interpret-as");
attr2 = GetSsmlAttribute(px, "format"); attr2 = GetSsmlAttribute(px, "format");
sayas_start = *outix; sayas_start = *outix;
sayas_mode = value; // punctuation doesn't end clause during SAY-AS sayas_mode = value; // punctuation doesn't end clause during SAY-AS
break; break;

case SSML_SAYAS + SSML_CLOSE: case SSML_SAYAS + SSML_CLOSE:
if (sayas_mode == SAYAS_KEY) { if (sayas_mode == SAYAS_KEY) {
outbuf[*outix] = 0; outbuf[*outix] = 0;
outbuf[(*outix)++] = 'Y'; outbuf[(*outix)++] = 'Y';
sayas_mode = 0; sayas_mode = 0;
break; break;

case SSML_SUB: case SSML_SUB:
if ((attr1 = GetSsmlAttribute(px, "alias")) != NULL) { if ((attr1 = GetSsmlAttribute(px, "alias")) != NULL) {
// use the alias rather than the text // use the alias rather than the text
*outix += attrcopy_utf8(&outbuf[*outix], attr1, n_outbuf-*outix); *outix += attrcopy_utf8(&outbuf[*outix], attr1, n_outbuf-*outix);
} }
break; break;

case SSML_IGNORE_TEXT: case SSML_IGNORE_TEXT:
ignore_text = 1; ignore_text = 1;
break; break;

case SSML_SUB + SSML_CLOSE: case SSML_SUB + SSML_CLOSE:
case SSML_IGNORE_TEXT + SSML_CLOSE: case SSML_IGNORE_TEXT + SSML_CLOSE:
ignore_text = 0; ignore_text = 0;
break; break;

case SSML_MARK: case SSML_MARK:
if ((attr1 = GetSsmlAttribute(px, "name")) != NULL) { if ((attr1 = GetSsmlAttribute(px, "name")) != NULL) {
// add name to circular buffer of marker names // add name to circular buffer of marker names
} }
} }
break; break;

case SSML_AUDIO: case SSML_AUDIO:
sp = PushParamStack(tag_type); sp = PushParamStack(tag_type);


else else
audio_text = 1; audio_text = 1;
return CLAUSE_NONE; return CLAUSE_NONE;

case SSML_AUDIO + SSML_CLOSE: case SSML_AUDIO + SSML_CLOSE:
PopParamStack(tag_type, outbuf, outix); PopParamStack(tag_type, outbuf, outix);
audio_text = 0; audio_text = 0;
return CLAUSE_NONE; return CLAUSE_NONE;

case SSML_BREAK: case SSML_BREAK:
value = 21; value = 21;
terminator = CLAUSE_NONE; terminator = CLAUSE_NONE;
return terminator + value; return terminator + value;
} }
break; break;

case SSML_SPEAK: case SSML_SPEAK:
if ((attr1 = GetSsmlAttribute(px, "xml:base")) != NULL) { if ((attr1 = GetSsmlAttribute(px, "xml:base")) != NULL) {
attrcopy_utf8(buf, attr1, sizeof(buf)); attrcopy_utf8(buf, attr1, sizeof(buf));
if (GetVoiceAttributes(px, tag_type) == 0) if (GetVoiceAttributes(px, tag_type) == 0)
return 0; // no voice change return 0; // no voice change
return CLAUSE_VOICE; return CLAUSE_VOICE;

case SSML_VOICE: case SSML_VOICE:
if (GetVoiceAttributes(px, tag_type) == 0) if (GetVoiceAttributes(px, tag_type) == 0)
return 0; // no voice change return 0; // no voice change
return CLAUSE_VOICE; return CLAUSE_VOICE;

case SSML_SPEAK + SSML_CLOSE: case SSML_SPEAK + SSML_CLOSE:
// unwind stack until the previous <voice> or <speak> tag // unwind stack until the previous <voice> or <speak> tag
while ((n_ssml_stack > 1) && (ssml_stack[n_ssml_stack-1].tag_type != SSML_SPEAK)) while ((n_ssml_stack > 1) && (ssml_stack[n_ssml_stack-1].tag_type != SSML_SPEAK))
n_ssml_stack--; n_ssml_stack--;
return CLAUSE_PERIOD + GetVoiceAttributes(px, tag_type); return CLAUSE_PERIOD + GetVoiceAttributes(px, tag_type);

case SSML_VOICE + SSML_CLOSE: case SSML_VOICE + SSML_CLOSE:
// unwind stack until the previous <voice> or <speak> tag // unwind stack until the previous <voice> or <speak> tag
while ((n_ssml_stack > 1) && (ssml_stack[n_ssml_stack-1].tag_type != SSML_VOICE)) while ((n_ssml_stack > 1) && (ssml_stack[n_ssml_stack-1].tag_type != SSML_VOICE))


terminator = 0; // ?? Sentence intonation, but no pause ?? terminator = 0; // ?? Sentence intonation, but no pause ??
return terminator + GetVoiceAttributes(px, tag_type); return terminator + GetVoiceAttributes(px, tag_type);

case HTML_BREAK: case HTML_BREAK:
case HTML_BREAK + SSML_CLOSE: case HTML_BREAK + SSML_CLOSE:
return CLAUSE_COLON; return CLAUSE_COLON;

case SSML_SENTENCE: case SSML_SENTENCE:
if (ssml_sp->tag_type == SSML_SENTENCE) { if (ssml_sp->tag_type == SSML_SENTENCE) {
// new sentence implies end-of-sentence // new sentence implies end-of-sentence
} }
voice_change_flag |= GetVoiceAttributes(px, tag_type); voice_change_flag |= GetVoiceAttributes(px, tag_type);
return CLAUSE_PARAGRAPH + voice_change_flag; return CLAUSE_PARAGRAPH + voice_change_flag;


case SSML_PARAGRAPH: case SSML_PARAGRAPH:
if (ssml_sp->tag_type == SSML_SENTENCE) { if (ssml_sp->tag_type == SSML_SENTENCE) {
// new paragraph implies end-of-sentence or end-of-paragraph // new paragraph implies end-of-sentence or end-of-paragraph
} }
voice_change_flag |= GetVoiceAttributes(px, tag_type); voice_change_flag |= GetVoiceAttributes(px, tag_type);
return CLAUSE_PARAGRAPH + voice_change_flag; return CLAUSE_PARAGRAPH + voice_change_flag;


case SSML_SENTENCE + SSML_CLOSE: case SSML_SENTENCE + SSML_CLOSE:
if (ssml_sp->tag_type == SSML_SENTENCE) { if (ssml_sp->tag_type == SSML_SENTENCE) {
// end of a sentence which specified a language // end of a sentence which specified a language
voice_change_flag = GetVoiceAttributes(px, tag_type); voice_change_flag = GetVoiceAttributes(px, tag_type);
} }
return CLAUSE_PERIOD + voice_change_flag; return CLAUSE_PERIOD + voice_change_flag;


case SSML_PARAGRAPH + SSML_CLOSE: case SSML_PARAGRAPH + SSML_CLOSE:
if ((ssml_sp->tag_type == SSML_SENTENCE) || (ssml_sp->tag_type == SSML_PARAGRAPH)) { if ((ssml_sp->tag_type == SSML_SENTENCE) || (ssml_sp->tag_type == SSML_PARAGRAPH)) {
// End of a paragraph which specified a language. // End of a paragraph which specified a language.
return 0; return 0;
} }



static void RemoveChar(char *p) static void RemoveChar(char *p)
{ {
// Replace a UTF-8 character by spaces // Replace a UTF-8 character by spaces
memset(p, ' ', utf8_in(&c, p)); memset(p, ' ', utf8_in(&c, p));
} }



static MNEM_TAB xml_char_mnemonics[] = { static MNEM_TAB xml_char_mnemonics[] = {
{ "gt", '>' }, { "gt", '>' },
{ "lt", 0xe000 + '<' }, // private usage area, to avoid confusion with XML tag { "lt", 0xe000 + '<' }, // private usage area, to avoid confusion with XML tag
{ NULL, -1 } { NULL, -1 }
}; };



int ReadClause(Translator *tr, FILE *f_in, char *buf, short *charix, int *charix_top, int n_buf, int *tone_type, char *voice_change) int ReadClause(Translator *tr, FILE *f_in, char *buf, short *charix, int *charix_top, int n_buf, int *tone_type, char *voice_change)
{ {
/* Find the end of the current clause. /* Find the end of the current clause.
return CLAUSE_EOF; // end of file return CLAUSE_EOF; // end of file
} }



void InitNamedata(void) void InitNamedata(void)
{ {
namedata_ix = 0; namedata_ix = 0;
} }
} }



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

+ 0
- 21
src/libespeak-ng/setlengths.c View File

extern void DoSonicSpeed(int value); extern void DoSonicSpeed(int value);
extern int saved_parameters[]; extern int saved_parameters[];



// convert from words-per-minute to internal speed factor // convert from words-per-minute to internal speed factor
// Use this to calibrate speed for wpm 80-350 // Use this to calibrate speed for wpm 80-350
static unsigned char speed_lookup[] = { static unsigned char speed_lookup[] = {
9, 9, 8, 8, 8, // 355 9, 9, 8, 8, 8, // 355
}; };



// speed_factor1 adjustments for speeds 350 to 374: pauses // speed_factor1 adjustments for speeds 350 to 374: pauses
static unsigned char pause_factor_350[] = { static unsigned char pause_factor_350[] = {
22, 22, 22, 22, 22, 22, 22, 21, 21, 21, // 350 22, 22, 22, 22, 22, 22, 22, 21, 21, 21, // 350
static int speed2 = 121; static int speed2 = 121;
static int speed3 = 118; static int speed3 = 118;




#if HAVE_SONIC_H #if HAVE_SONIC_H


void SetSpeed(int control) void SetSpeed(int control)
embedded_value[EMBED_S2] = new_value; embedded_value[EMBED_S2] = new_value;
SetSpeed(3); SetSpeed(3);
break; break;

case espeakVOLUME: case espeakVOLUME:
embedded_value[EMBED_A] = new_value; embedded_value[EMBED_A] = new_value;
GetAmplitude(); GetAmplitude();
break; break;

case espeakPITCH: case espeakPITCH:
if (new_value > 99) new_value = 99; if (new_value > 99) new_value = 99;
if (new_value < 0) new_value = 0; if (new_value < 0) new_value = 0;
embedded_value[EMBED_P] = new_value; embedded_value[EMBED_P] = new_value;
break; break;

case espeakRANGE: case espeakRANGE:
if (new_value > 99) new_value = 99; if (new_value > 99) new_value = 99;
embedded_value[EMBED_R] = new_value; embedded_value[EMBED_R] = new_value;
break; break;

case espeakLINELENGTH: case espeakLINELENGTH:
option_linelength = new_value; option_linelength = new_value;
break; break;

case espeakWORDGAP: case espeakWORDGAP:
option_wordgap = new_value; option_wordgap = new_value;
break; break;

case espeakINTONATION: case espeakINTONATION:
if ((new_value & 0xff) != 0) if ((new_value & 0xff) != 0)
translator->langopts.intonation_group = new_value & 0xff; translator->langopts.intonation_group = new_value & 0xff;
option_tone_flags = new_value; option_tone_flags = new_value;
break; break;

default: default:
break; break;
} }
} }




static void DoEmbedded2(int *embix) static void DoEmbedded2(int *embix)
{ {
// There were embedded commands in the text at this point // There were embedded commands in the text at this point
} while ((word & 0x80) == 0); } while ((word & 0x80) == 0);
} }



void CalcLengths(Translator *tr) void CalcLengths(Translator *tr)
{ {
int ix; int ix;
case phPAUSE: case phPAUSE:
last_pitch = 0; last_pitch = 0;
break; break;

case phSTOP: case phSTOP:
last_pitch = 0; last_pitch = 0;
if (prev->type == phFRICATIVE) if (prev->type == phFRICATIVE)
if (p->synthflags & SFLAG_LENGTHEN) if (p->synthflags & SFLAG_LENGTHEN)
p->prepause += tr->langopts.long_stop; p->prepause += tr->langopts.long_stop;
break; break;

case phVFRICATIVE: case phVFRICATIVE:
case phFRICATIVE: case phFRICATIVE:
if (p->newword) { if (p->newword) {
p->length = (255 + prev->length)/2; p->length = (255 + prev->length)/2;
} }
break; break;

case phVSTOP: case phVSTOP:
if (prev->type == phVFRICATIVE || prev->type == phFRICATIVE || (prev->ph->phflags & phSIBILANT) || (prev->type == phLIQUID)) if (prev->type == phVFRICATIVE || prev->type == phFRICATIVE || (prev->ph->phflags & phSIBILANT) || (prev->type == phLIQUID))
p->prepause = 30; p->prepause = 30;
} }
if ((tr->langopts.word_gap & 0x10) && (p->newword) && (p->prepause < 20)) if ((tr->langopts.word_gap & 0x10) && (p->newword) && (p->prepause < 20))
p->prepause = 20; p->prepause = 20;

break; break;

case phLIQUID: case phLIQUID:
case phNASAL: case phNASAL:
p->amp = tr->stress_amps[0]; // unless changed later p->amp = tr->stress_amps[0]; // unless changed later
pre_voiced = 0; pre_voiced = 0;
} }
break; break;

case phVOWEL: case phVOWEL:
min_drop = 0; min_drop = 0;
next2 = &phoneme_list[ix+2]; next2 = &phoneme_list[ix+2];
} }
} }



if ((end_of_clause == 2) && !(tr->langopts.stress_flags & S_NO_EOC_LENGTHEN)) { if ((end_of_clause == 2) && !(tr->langopts.stress_flags & S_NO_EOC_LENGTHEN)) {
// this is the last syllable in the clause, lengthen it - more for short vowels // this is the last syllable in the clause, lengthen it - more for short vowels
len = (p->ph->std_length * 2); len = (p->ph->std_length * 2);

+ 1
- 67
src/libespeak-ng/speak_lib.c View File

char path_home[N_PATH_HOME]; // this is the espeak-data directory char path_home[N_PATH_HOME]; // this is the espeak-data directory
extern int saved_parameters[N_SPEECH_PARAM]; // Parameters saved on synthesis start extern int saved_parameters[N_SPEECH_PARAM]; // Parameters saved on synthesis start



void WVoiceChanged(voice_t *wvoice) void WVoiceChanged(voice_t *wvoice)
{ {
// Voice change in wavegen // Voice change in wavegen
voice_samplerate = wvoice->samplerate; voice_samplerate = wvoice->samplerate;
} }



#ifdef USE_ASYNC #ifdef USE_ASYNC


static int dispatch_audio(short *outbuf, int length, espeak_EVENT *event) static int dispatch_audio(short *outbuf, int length, espeak_EVENT *event)
a_wave_can_be_played = fifo_is_command_enabled(); a_wave_can_be_played = fifo_is_command_enabled();
} }
} }
break;

break;
case AUDIO_OUTPUT_RETRIEVAL: case AUDIO_OUTPUT_RETRIEVAL:
if (synth_callback) if (synth_callback)
synth_callback(outbuf, length, event); synth_callback(outbuf, length, event);
break; break;

case AUDIO_OUTPUT_SYNCHRONOUS: case AUDIO_OUTPUT_SYNCHRONOUS:
case AUDIO_OUTPUT_SYNCH_PLAYBACK: case AUDIO_OUTPUT_SYNCH_PLAYBACK:
break; break;
return a_wave_can_be_played == 0; // 1 = stop synthesis, -1 = error return a_wave_can_be_played == 0; // 1 = stop synthesis, -1 = error
} }




static int create_events(short *outbuf, int length, espeak_EVENT *event, uint32_t the_write_pos) static int create_events(short *outbuf, int length, espeak_EVENT *event, uint32_t the_write_pos)
{ {
int finished; int finished;
return finished; return finished;
} }



int sync_espeak_terminated_msg(uint32_t unique_identifier, void *user_data) int sync_espeak_terminated_msg(uint32_t unique_identifier, void *user_data)
{ {
ENTER("sync_espeak_terminated_msg"); ENTER("sync_espeak_terminated_msg");


#endif #endif



static void select_output(espeak_AUDIO_OUTPUT output_type) static void select_output(espeak_AUDIO_OUTPUT output_type)
{ {
my_mode = output_type; my_mode = output_type;
// wave_init() is now called just before the first wave_write() // wave_init() is now called just before the first wave_write()
synchronous_mode = 0; synchronous_mode = 0;
break; break;

case AUDIO_OUTPUT_RETRIEVAL: case AUDIO_OUTPUT_RETRIEVAL:
synchronous_mode = 0; synchronous_mode = 0;
break; break;

case AUDIO_OUTPUT_SYNCHRONOUS: case AUDIO_OUTPUT_SYNCHRONOUS:
break; break;

case AUDIO_OUTPUT_SYNCH_PLAYBACK: case AUDIO_OUTPUT_SYNCH_PLAYBACK:
option_waveout = 0; option_waveout = 0;
WavegenInitSound(); WavegenInitSound();
} }
} }





#pragma GCC visibility push(default) #pragma GCC visibility push(default)
int GetFileLength(const char *filename) int GetFileLength(const char *filename)
{ {
} }
#pragma GCC visibility pop #pragma GCC visibility pop



char *Alloc(int size) char *Alloc(int size)
{ {
char *p; char *p;
free(ptr); free(ptr);
} }




static void init_path(const char *path) static void init_path(const char *path)
{ {
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
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);

#else #else
char *env; char *env;


return 0; return 0;
} }



static espeak_ERROR Synthesize(unsigned int unique_identifier, const void *text, int flags) static espeak_ERROR Synthesize(unsigned int unique_identifier, const void *text, int flags)
{ {
// Fill the buffer with output sound // Fill the buffer with output sound
}; };
#endif #endif



void MarkerEvent(int type, unsigned int char_position, int value, int value2, unsigned char *out_ptr) void MarkerEvent(int type, unsigned int char_position, int value, int value2, unsigned char *out_ptr)
{ {
// 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
ep->id.number = value; ep->id.number = value;
} }





espeak_ERROR sync_espeak_Synth(unsigned int unique_identifier, const void *text, size_t size, espeak_ERROR sync_espeak_Synth(unsigned int unique_identifier, const void *text, size_t size,
unsigned int position, espeak_POSITION_TYPE position_type, unsigned int position, espeak_POSITION_TYPE position_type,
unsigned int end_position, unsigned int flags, void *user_data) unsigned int end_position, unsigned int flags, void *user_data)
{ {

#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
ENTER("sync_espeak_Synth"); ENTER("sync_espeak_Synth");
SHOW("sync_espeak_Synth > position=%d, position_type=%d, end_position=%d, flags=%d, user_data=0x%x, text=%s\n", position, position_type, end_position, flags, user_data, text); SHOW("sync_espeak_Synth > position=%d, position_type=%d, end_position=%d, flags=%d, user_data=0x%x, text=%s\n", position, position_type, end_position, flags, user_data, text);
case POS_CHARACTER: case POS_CHARACTER:
skip_characters = position; skip_characters = position;
break; break;

case POS_WORD: case POS_WORD:
skip_words = position; skip_words = position;
break; break;

case POS_SENTENCE: case POS_SENTENCE:
skip_sentences = position; skip_sentences = position;
break; break;
return aStatus; return aStatus;
} }





espeak_ERROR sync_espeak_Synth_Mark(unsigned int unique_identifier, const void *text, size_t size, espeak_ERROR sync_espeak_Synth_Mark(unsigned int unique_identifier, const void *text, size_t size,
const char *index_mark, unsigned int end_position, const char *index_mark, unsigned int end_position,
unsigned int flags, void *user_data) unsigned int flags, void *user_data)


end_character_position = end_position; end_character_position = end_position;



aStatus = Synthesize(unique_identifier, text, flags | espeakSSML); aStatus = Synthesize(unique_identifier, text, flags | espeakSSML);
SHOW_TIME("LEAVE sync_espeak_Synth_Mark"); SHOW_TIME("LEAVE sync_espeak_Synth_Mark");


return aStatus; return aStatus;
} }




void sync_espeak_Key(const char *key) void sync_espeak_Key(const char *key)
{ {
// 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?
Synthesize(0, key, 0); // speak key as a text string Synthesize(0, key, 0); // speak key as a text string
} }



void sync_espeak_Char(wchar_t character) void sync_espeak_Char(wchar_t character)
{ {
// is there a system resource of character names per language? // is there a system resource of character names per language?
Synthesize(0, buf, espeakSSML); Synthesize(0, buf, espeakSSML);
} }




void sync_espeak_SetPunctuationList(const wchar_t *punctlist) void sync_espeak_SetPunctuationList(const wchar_t *punctlist)
{ {
// Set the list of punctuation which are spoken for "some". // Set the list of punctuation which are spoken for "some".
} }
} }





#pragma GCC visibility push(default) #pragma GCC visibility push(default)



ESPEAK_API void espeak_SetSynthCallback(t_espeak_callback *SynthCallback) ESPEAK_API void espeak_SetSynthCallback(t_espeak_callback *SynthCallback)
{ {
ENTER("espeak_SetSynthCallback"); ENTER("espeak_SetSynthCallback");
uri_callback = UriCallback; uri_callback = UriCallback;
} }



ESPEAK_API void espeak_SetPhonemeCallback(int (*PhonemeCallback)(const char *)) ESPEAK_API void espeak_SetPhonemeCallback(int (*PhonemeCallback)(const char *))
{ {
phoneme_callback = PhonemeCallback; phoneme_callback = PhonemeCallback;
return samplerate; return samplerate;
} }




ESPEAK_API espeak_ERROR espeak_Synth(const void *text, size_t size, ESPEAK_API espeak_ERROR espeak_Synth(const void *text, size_t size,
unsigned int position, unsigned int position,
espeak_POSITION_TYPE position_type, espeak_POSITION_TYPE position_type,
delete_espeak_command(c1); delete_espeak_command(c1);
delete_espeak_command(c2); delete_espeak_command(c2);
} }

#endif #endif
return a_error; return a_error;
} }




ESPEAK_API espeak_ERROR espeak_Synth_Mark(const void *text, size_t size, ESPEAK_API espeak_ERROR espeak_Synth_Mark(const void *text, size_t size,
const char *index_mark, const char *index_mark,
unsigned int end_position, unsigned int end_position,
if (f_logespeak) if (f_logespeak)
fprintf(f_logespeak, "\nSYNTH MARK %s posn %d flags 0x%x\n%s\n", index_mark, end_position, flags, (const char *)text); fprintf(f_logespeak, "\nSYNTH MARK %s posn %d flags 0x%x\n%s\n", index_mark, end_position, flags, (const char *)text);



if (unique_identifier == NULL) if (unique_identifier == NULL)
unique_identifier = &temp_identifier; unique_identifier = &temp_identifier;
*unique_identifier = 0; *unique_identifier = 0;
delete_espeak_command(c1); delete_espeak_command(c1);
delete_espeak_command(c2); delete_espeak_command(c2);
} }

#endif #endif
return a_error; return a_error;
} }




ESPEAK_API espeak_ERROR espeak_Key(const char *key) ESPEAK_API espeak_ERROR espeak_Key(const char *key)
{ {
ENTER("espeak_Key"); ENTER("espeak_Key");
a_error = fifo_add_command(c); a_error = fifo_add_command(c);
if (a_error != EE_OK) if (a_error != EE_OK)
delete_espeak_command(c); delete_espeak_command(c);

#endif #endif
return a_error; return a_error;
} }



ESPEAK_API espeak_ERROR espeak_Char(wchar_t character) ESPEAK_API espeak_ERROR espeak_Char(wchar_t character)
{ {
ENTER("espeak_Char"); ENTER("espeak_Char");
#endif #endif
} }



ESPEAK_API espeak_ERROR espeak_SetVoiceByName(const char *name) ESPEAK_API espeak_ERROR espeak_SetVoiceByName(const char *name)
{ {
ENTER("espeak_SetVoiceByName"); ENTER("espeak_SetVoiceByName");
return SetVoiceByName(name); return SetVoiceByName(name);
} }




ESPEAK_API espeak_ERROR espeak_SetVoiceByProperties(espeak_VOICE *voice_selector) ESPEAK_API espeak_ERROR espeak_SetVoiceByProperties(espeak_VOICE *voice_selector)
{ {
ENTER("espeak_SetVoiceByProperties"); ENTER("espeak_SetVoiceByProperties");
return SetVoiceByProperties(voice_selector); return SetVoiceByProperties(voice_selector);
} }



ESPEAK_API int espeak_GetParameter(espeak_PARAMETER parameter, int current) ESPEAK_API int espeak_GetParameter(espeak_PARAMETER parameter, int current)
{ {
ENTER("espeak_GetParameter"); ENTER("espeak_GetParameter");
return param_defaults[parameter]; return param_defaults[parameter];
} }



ESPEAK_API espeak_ERROR espeak_SetParameter(espeak_PARAMETER parameter, int value, int relative) ESPEAK_API espeak_ERROR espeak_SetParameter(espeak_PARAMETER parameter, int value, int relative)
{ {
ENTER("espeak_SetParameter"); ENTER("espeak_SetParameter");
#endif #endif
} }



ESPEAK_API espeak_ERROR espeak_SetPunctuationList(const wchar_t *punctlist) ESPEAK_API espeak_ERROR espeak_SetPunctuationList(const wchar_t *punctlist)
{ {
ENTER("espeak_SetPunctuationList"); ENTER("espeak_SetPunctuationList");
#endif #endif
} }



ESPEAK_API void espeak_SetPhonemeTrace(int phonememode, FILE *stream) ESPEAK_API void espeak_SetPhonemeTrace(int phonememode, FILE *stream)
{ {
ENTER("espeak_SetPhonemes"); ENTER("espeak_SetPhonemes");
f_trans = stream; f_trans = stream;
if (stream == NULL) if (stream == NULL)
f_trans = stderr; f_trans = stderr;

} }



ESPEAK_API const char *espeak_TextToPhonemes(const void **textptr, int textmode, int phonememode) ESPEAK_API const char *espeak_TextToPhonemes(const void **textptr, int textmode, int phonememode)
{ {
/* phoneme_mode /* phoneme_mode
return GetTranslatedPhonemeString(phonememode); return GetTranslatedPhonemeString(phonememode);
} }



ESPEAK_API void espeak_CompileDictionary(const char *path, FILE *log, int flags) ESPEAK_API void espeak_CompileDictionary(const char *path, FILE *log, int flags)
{ {
ENTER("espeak_CompileDictionary"); ENTER("espeak_CompileDictionary");
CompileDictionary(path, dictionary_name, log, NULL, flags); CompileDictionary(path, dictionary_name, log, NULL, flags);
} }



ESPEAK_API espeak_ERROR espeak_Cancel(void) ESPEAK_API espeak_ERROR espeak_Cancel(void)
{ {
#ifdef USE_ASYNC #ifdef USE_ASYNC
return EE_OK; return EE_OK;
} }



ESPEAK_API int espeak_IsPlaying(void) ESPEAK_API int espeak_IsPlaying(void)
{ {
#ifdef USE_ASYNC #ifdef USE_ASYNC
#endif #endif
} }



ESPEAK_API espeak_ERROR espeak_Synchronize(void) ESPEAK_API espeak_ERROR espeak_Synchronize(void)
{ {
espeak_ERROR berr = err; espeak_ERROR berr = err;
return berr; return berr;
} }



extern void FreePhData(void); extern void FreePhData(void);
extern void FreeVoiceList(void); extern void FreeVoiceList(void);


wave_terminate(); wave_terminate();
out_samplerate = 0; out_samplerate = 0;
} }

#endif #endif
Free(event_list); Free(event_list);
event_list = NULL; event_list = NULL;

+ 0
- 10
src/libespeak-ng/spect.c View File

return y; return y;
} }



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




int LoadFrame(SpectFrame *frame, FILE *stream, int file_format_type) int LoadFrame(SpectFrame *frame, FILE *stream, int file_format_type)
{ {
short ix; short ix;
return 0; return 0;
} }




double GetFrameRms(SpectFrame *frame, int seq_amplitude) double GetFrameRms(SpectFrame *frame, int seq_amplitude)
{ {
int h; int h;
return frame->rms; return frame->rms;
} }



SpectSeq *SpectSeqCreate() SpectSeq *SpectSeqCreate()
{ {
SpectSeq *spect = malloc(sizeof(SpectSeq)); SpectSeq *spect = malloc(sizeof(SpectSeq));
free(spect); free(spect);
} }



static float GetFrameLength(SpectSeq *spect, int frame) static float GetFrameLength(SpectSeq *spect, int frame)
{ {
int ix; int ix;
return (spect->frames[ix]->time - spect->frames[frame]->time) * 1000.0 + adjust; return (spect->frames[ix]->time - spect->frames[frame]->time) * 1000.0 + adjust;
} }




int LoadSpectSeq(SpectSeq *spect, const char *filename) int LoadSpectSeq(SpectSeq *spect, const char *filename)
{ {
short n, temp; short n, temp;
frame_width = (int)((FRAME_WIDTH*spect->max_x)/MAX_DISPLAY_FREQ); frame_width = (int)((FRAME_WIDTH*spect->max_x)/MAX_DISPLAY_FREQ);
if (frame_width > FRAME_WIDTH) frame_width = FRAME_WIDTH; if (frame_width > FRAME_WIDTH) frame_width = FRAME_WIDTH;



// start times from zero // start times from zero
time_offset = spect->frames[0]->time; time_offset = spect->frames[0]->time;
for (ix = 0; ix < spect->numframes; ix++) for (ix = 0; ix < spect->numframes; ix++)

+ 0
- 21
src/libespeak-ng/synth_mbrola.c View File

#include "translate.h" #include "translate.h"
#include "voice.h" #include "voice.h"



#ifdef INCLUDE_MBROLA #ifdef INCLUDE_MBROLA


extern int Read4Bytes(FILE *f); extern int Read4Bytes(FILE *f);
PROCIV getFreq_MBR; PROCIV getFreq_MBR;
PROCVF setVolumeRatio_MBR; PROCVF setVolumeRatio_MBR;




HINSTANCE hinstDllMBR = NULL; HINSTANCE hinstDllMBR = NULL;



BOOL load_MBR() BOOL load_MBR()
{ {
if (hinstDllMBR != NULL) if (hinstDllMBR != NULL)
return TRUE; return TRUE;
} }



void unload_MBR() void unload_MBR()
{ {
if (hinstDllMBR) { if (hinstDllMBR) {


#endif // windows #endif // windows



static MBROLA_TAB *mbrola_tab = NULL; static MBROLA_TAB *mbrola_tab = NULL;
static int mbrola_control = 0; static int mbrola_control = 0;
static int mbr_name_prefix = 0; static int mbr_name_prefix = 0;
return EE_OK; return EE_OK;
} }



static int GetMbrName(PHONEME_LIST *plist, PHONEME_TAB *ph, PHONEME_TAB *ph_prev, PHONEME_TAB *ph_next, int *name2, int *split, int *control) static int GetMbrName(PHONEME_LIST *plist, PHONEME_TAB *ph, PHONEME_TAB *ph_prev, PHONEME_TAB *ph_next, int *name2, int *split, int *control)
{ {
// Look up a phoneme in the mbrola phoneme name translation table // Look up a phoneme in the mbrola phoneme name translation table
return mnem; return mnem;
} }



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.
output[0] = 0; output[0] = 0;
pitch_env = envelope_data[env]; pitch_env = envelope_data[env];



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



env_split = (split * 128)/100; env_split = (split * 128)/100;
if (env_split < 0) if (env_split < 0)
env_split = 0-env_split; env_split = 0-env_split;
p1 = ((pitch_env[0]*pitch_range)>>8) + pitch_base; // Hz << 12 p1 = ((pitch_env[0]*pitch_range)>>8) + pitch_base; // Hz << 12
p_end = ((pitch_env[127]*pitch_range)>>8) + pitch_base; 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);
strcat(output, buf); strcat(output, buf);
return output; return output;
} }



int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbrola) int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbrola)
{ {
// Generate a mbrola pho file // Generate a mbrola pho file
} }
done = 1; done = 1;
break; break;

case phSTOP: case phSTOP:
released = 0; released = 0;
if (next->type == phVOWEL) released = 1; if (next->type == phVOWEL) released = 1;
len = (len * 1000)/samplerate; // convert to mS len = (len * 1000)/samplerate; // convert to mS
len += PauseLength(p->prepause, 1); len += PauseLength(p->prepause, 1);
break; break;

case phVSTOP: case phVSTOP:
len = (80 * speed.wav_factor)/256; len = (80 * speed.wav_factor)/256;
break; break;

case phFRICATIVE: case phFRICATIVE:
len = 0; len = 0;
InterpretPhoneme(NULL, 0, p, &phdata, NULL); InterpretPhoneme(NULL, 0, p, &phdata, NULL);


len = (len * 1000)/samplerate; // convert to mS len = (len * 1000)/samplerate; // convert to mS
break; break;

case phNASAL: case phNASAL:
if (next->type != phVOWEL) { if (next->type != phVOWEL) {
memset(&fmtp, 0, sizeof(fmtp)); memset(&fmtp, 0, sizeof(fmtp));
final_pitch = WritePitch(p->env, p->pitch1, p->pitch2, 0, 1); final_pitch = WritePitch(p->env, p->pitch1, p->pitch2, 0, 1);
} }
break; break;

case phLIQUID: case phLIQUID:
if (next->type == phPAUSE) { if (next->type == phPAUSE) {
len += 50; len += 50;
return 0; return 0;
} }



int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
{ {
FILE *f_mbrola = NULL; FILE *f_mbrola = NULL;
return again; return again;
} }



int MbrolaFill(int length, int resume, int amplitude) int MbrolaFill(int length, int resume, int amplitude)
{ {
// Read audio data from Mbrola (length is in millisecs) // Read audio data from Mbrola (length is in millisecs)
return n_samples ? 1 : 0; return n_samples ? 1 : 0;
} }



void MbrolaReset(void) void MbrolaReset(void)
{ {
// Reset the Mbrola engine and flush the pending audio // Reset the Mbrola engine and flush the pending audio
{ {
} }



#endif // INCLUDE_MBROLA #endif // INCLUDE_MBROLA

+ 0
- 67
src/libespeak-ng/synthdata.c View File

#include <stdint.h> #include <stdint.h>
#endif #endif



#include "speak_lib.h" #include "speak_lib.h"
#include "speech.h" #include "speech.h"
#include "phoneme.h" #include "phoneme.h"


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);




static char *ReadPhFile(void *ptr, const char *fname, int *size) static char *ReadPhFile(void *ptr, const char *fname, int *size)
{ {
FILE *f_in; FILE *f_in;
return p; return p;
} }



int LoadPhData(int *srate) int LoadPhData(int *srate)
{ {
int ix; int ix;
return result; return result;
} }



void FreePhData(void) void FreePhData(void)
{ {
Free(phoneme_tab_data); Free(phoneme_tab_data);
tunes = NULL; tunes = NULL;
} }



int PhonemeCode(unsigned int mnem) int PhonemeCode(unsigned int mnem)
{ {
int ix; int ix;
return 0; return 0;
} }



int LookupPhonemeString(const char *string) int LookupPhonemeString(const char *string)
{ {
int ix; int ix;
return PhonemeCode(mnem); return PhonemeCode(mnem);
} }





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;
seqk = (SPECT_SEQK *)seq; seqk = (SPECT_SEQK *)seq;
nf = seq->n_frames; nf = seq->n_frames;



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


return frames; return frames;
} }




unsigned char *GetEnvelope(int index) unsigned char *GetEnvelope(int index)
{ {
if (index == 0) { if (index == 0) {
return (unsigned char *)&phondata_ptr[index]; return (unsigned char *)&phondata_ptr[index];
} }



static void SetUpPhonemeTable(int number, int recursing) static void SetUpPhonemeTable(int number, int recursing)
{ {
int ix; int ix;
} }
} }



void SelectPhonemeTable(int number) void SelectPhonemeTable(int number)
{ {
n_phoneme_tab = 0; n_phoneme_tab = 0;
current_phoneme_table = number; current_phoneme_table = number;
} }



int LookupPhonemeTable(const char *name) int LookupPhonemeTable(const char *name)
{ {
int ix; int ix;
return ix; return ix;
} }



int SelectPhonemeTableName(const char *name) int SelectPhonemeTableName(const char *name)
{ {
// Look up a phoneme set by name, and select it if it exists // Look up a phoneme set by name, and select it if it exists
return ix; return ix;
} }





void LoadConfig(void) void LoadConfig(void)
{ {
// Load configuration file, if one exists // Load configuration file, if one exists
fclose(f); fclose(f);
} }





PHONEME_DATA this_ph_data; PHONEME_DATA this_ph_data;



static void InvalidInstn(PHONEME_TAB *ph, int instn) static void InvalidInstn(PHONEME_TAB *ph, int instn)
{ {
fprintf(stderr, "Invalid instruction %.4x for phoneme '%s'\n", instn, WordToString(ph->mnemonic)); fprintf(stderr, "Invalid instruction %.4x for phoneme '%s'\n", instn, WordToString(ph->mnemonic));
} }



static bool StressCondition(Translator *tr, PHONEME_LIST *plist, int condition, int control) static bool StressCondition(Translator *tr, PHONEME_LIST *plist, int condition, int control)
{ {
// condition: // condition:


} }



static int CountVowelPosition(PHONEME_LIST *plist) static int CountVowelPosition(PHONEME_LIST *plist)
{ {
int count = 0; int count = 0;
return count; return count;
} }



static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, USHORT *p_prog, WORD_PH_DATA *worddata) static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, USHORT *p_prog, WORD_PH_DATA *worddata)
{ {
int which; int which;
return false; return false;
} }



switch (which) switch (which)
{ {
case 0: // prevPh case 0: // prevPh
plist--; plist--;
check_endtype = 1; check_endtype = 1;
break; break;

case 1: // thisPh case 1: // thisPh
break; break;

case 2: // nextPh case 2: // nextPh
case 4: // nextPhW case 4: // nextPhW
plist++; plist++;
break; break;

case 3: // next2Ph case 3: // next2Ph
case 6: // next2PhW case 6: // next2PhW
plist += 2; plist += 2;
break; break;

case 7: case 7:
// nextVowel, not word boundary // nextVowel, not word boundary
for (which = 1;; which++) { for (which = 1;; which++) {
} }
} }
break; break;

case 8: // prevVowel in this word case 8: // prevVowel in this word
if ((worddata == NULL) || (worddata->prev_vowel.ph == NULL)) if ((worddata == NULL) || (worddata->prev_vowel.ph == NULL))
return false; // no previous vowel return false; // no previous vowel
plist = &(worddata->prev_vowel); plist = &(worddata->prev_vowel);
check_endtype = 1; check_endtype = 1;
break; break;

case 9: // next3PhW case 9: // next3PhW
for (ix = 1; ix <= 3; ix++) { for (ix = 1; ix <= 3; ix++) {
if (plist[ix].sourceix) if (plist[ix].sourceix)
} }
plist = &plist[3]; plist = &plist[3];
break; break;

case 10: // prev2PhW case 10: // prev2PhW
if ((plist[0].sourceix) || (plist[-1].sourceix)) if ((plist[0].sourceix) || (plist[-1].sourceix))
return false; return false;
// phoneme type, vowel, nasal, fricative, etc // phoneme type, vowel, nasal, fricative, etc
return ph->type == data; return ph->type == data;
break; break;

case 0x20: case 0x20:
// place of articulation // place of articulation
return ((ph->phflags >> 16) & 0xf) == data; return ((ph->phflags >> 16) & 0xf) == data;
break; break;

case 0x40: case 0x40:
// is a bit set in phoneme flags // is a bit set in phoneme flags
return (ph->phflags & (1 << data)) != 0; return (ph->phflags & (1 << data)) != 0;
break; break;

case 0x80: case 0x80:
switch (data) switch (data)
{ {
case 3: case 3:
case 4: case 4:
return StressCondition(tr, plist, data, 0); return StressCondition(tr, plist, data, 0);

case 5: // isBreak, Either pause phoneme, or (stop/vstop/vfric not followed by vowel or (liquid in same word)) case 5: // isBreak, Either pause phoneme, or (stop/vstop/vfric not followed by vowel or (liquid in same word))
return (ph->type == phPAUSE) || (plist_this->synthflags & SFLAG_NEXT_PAUSE); return (ph->type == phPAUSE) || (plist_this->synthflags & SFLAG_NEXT_PAUSE);

case 6: // isWordStart case 6: // isWordStart
return plist->sourceix != 0; return plist->sourceix != 0;

case 7: // notWordStart case 7: // notWordStart
return plist->sourceix == 0; return plist->sourceix == 0;

case 8: // isWordEnd case 8: // isWordEnd
return plist[1].sourceix || (plist[1].ph->type == phPAUSE); return plist[1].sourceix || (plist[1].ph->type == phPAUSE);
break; break;

case 9: // isAfterStress case 9: // isAfterStress
if (plist->sourceix != 0) if (plist->sourceix != 0)
return false; return false;


} while (plist->sourceix == 0); } while (plist->sourceix == 0);
break; break;

case 10: // isNotVowel case 10: // isNotVowel
return ph->type != phVOWEL; return ph->type != phVOWEL;

case 11: // isFinalVowel case 11: // isFinalVowel
for (;;) { for (;;) {
plist++; plist++;
return false; return false;
} }
break; break;

case 12: // isVoiced case 12: // isVoiced
return (ph->type == phVOWEL) || (ph->type == phLIQUID) || (ph->phflags & phVOICED); return (ph->type == phVOWEL) || (ph->type == phLIQUID) || (ph->phflags & phVOICED);

case 13: // isFirstVowel case 13: // isFirstVowel
return CountVowelPosition(plist) == 1; return CountVowelPosition(plist) == 1;

case 14: // isSecondVowel case 14: // isSecondVowel
return CountVowelPosition(plist) == 2; return CountVowelPosition(plist) == 2;

case 15: // isSeqFlag1 case 15: // isSeqFlag1
// is this preceded by a sequence if 1 or more vowels which have 'flag1' ? (lang=hi) // is this preceded by a sequence if 1 or more vowels which have 'flag1' ? (lang=hi)
if (plist->sourceix != 0) if (plist->sourceix != 0)
break; break;
} }
return count > 0; return count > 0;

case 0x10: // isTranslationGiven case 0x10: // isTranslationGiven
return (plist->synthflags & SFLAG_DICTIONARY) != 0; return (plist->synthflags & SFLAG_DICTIONARY) != 0;
} }
return false; return false;
} }



static void SwitchOnVowelType(PHONEME_LIST *plist, PHONEME_DATA *phdata, USHORT **p_prog, int instn_type) static void SwitchOnVowelType(PHONEME_LIST *plist, PHONEME_DATA *phdata, USHORT **p_prog, int instn_type)
{ {
USHORT *prog; USHORT *prog;
*p_prog += 12; *p_prog += 12;
} }



int NumInstnWords(USHORT *prog) int NumInstnWords(USHORT *prog)
{ {
int instn; int instn;
return n+1; return n+1;
} }
return 1; return 1;

case 6: case 6:
type2 = (instn & 0xf00) >> 9; type2 = (instn & 0xf00) >> 9;
if ((type2 == 5) || (type2 == 6)) if ((type2 == 5) || (type2 == 6))
return 12; // switch on vowel type return 12; // switch on vowel type
return 1; return 1;

case 2: case 2:
case 3: case 3:
// a condition, check for a 2-word instruction // a condition, check for a 2-word instruction
if (((n = instn & 0x0f00) == 0x600) || (n == 0x0d00)) if (((n = instn & 0x0f00) == 0x600) || (n == 0x0d00))
return 2; return 2;
return 1; return 1;

default: default:
// instn_type 11 to 15, 2 words // instn_type 11 to 15, 2 words
instn2 = prog[2]; instn2 = prog[2];
} }
} }




void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_DATA *phdata, WORD_PH_DATA *worddata) void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_DATA *phdata, WORD_PH_DATA *worddata)
{ {
// control: // control:
} else } else
InvalidInstn(ph, instn); InvalidInstn(ph, instn);
break; break;

case 1: case 1:
if (tr == NULL) if (tr == NULL)
break; // ignore if in synthesis stage break; // ignore if in synthesis stage
} }
} }
break; break;

case 2: case 2:
case 3: case 3:
// conditions // conditions
} }
prog--; prog--;
break; break;

case 6: case 6:
// JUMP // JUMP
switch (instn2 >> 1) switch (instn2 >> 1)
break; break;
} }
break; break;

case 9: case 9:
data = ((instn & 0xf) << 16) + prog[1]; data = ((instn & 0xf) << 16) + prog[1];
prog++; prog++;
prog = &phoneme_index[data] - 1; prog = &phoneme_index[data] - 1;
} }
break; break;

case 2: case 2:
// pitch envelope // pitch envelope
phdata->pitch_env = data; phdata->pitch_env = data;
break; break;

case 3: case 3:
// amplitude envelope // amplitude envelope
phdata->amp_env = data; phdata->amp_env = data;
break; break;
} }
break; break;

case 10: // Vowelin, Vowelout case 10: // Vowelin, Vowelout
if (instn2 == 1) if (instn2 == 1)
ix = 0; ix = 0;
phdata->vowel_transition[ix+1] = (prog[2] << 16) + prog[3]; phdata->vowel_transition[ix+1] = (prog[2] << 16) + prog[3];
prog += 3; prog += 3;
break; break;

case 11: // FMT case 11: // FMT
case 12: // WAV case 12: // WAV
case 13: // VowelStart case 13: // VowelStart
} }
} }
break; break;

default: default:
InvalidInstn(ph, instn); InvalidInstn(ph, instn);
break; break;
} }
} }



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

+ 0
- 69
src/libespeak-ng/synthesize.c View File

#include "voice.h" #include "voice.h"
#include "translate.h" #include "translate.h"



extern FILE *f_log; extern FILE *f_log;
static void SmoothSpect(void); static void SmoothSpect(void);



// list of phonemes in a clause // list of phonemes in a clause
int n_phoneme_list = 0; int n_phoneme_list = 0;
PHONEME_LIST phoneme_list[N_PHONEME_LIST+1]; PHONEME_LIST phoneme_list[N_PHONEME_LIST+1];


#define VOWEL_FRONT_LENGTH 50 #define VOWEL_FRONT_LENGTH 50




// a dummy phoneme_list entry which looks like a pause // a dummy phoneme_list entry which looks like a pause
static PHONEME_LIST next_pause; static PHONEME_LIST next_pause;



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
return buf; return buf;
} }




void SynthesizeInit() void SynthesizeInit()
{ {
last_pitch_cmd = 0; last_pitch_cmd = 0;
next_pause.newword = 0; next_pause.newword = 0;
} }




static void EndAmplitude(void) static void EndAmplitude(void)
{ {
if (amp_length > 0) { if (amp_length > 0) {
} }
} }




static void EndPitch(int voice_break) static void EndPitch(int voice_break)
{ {
// posssible end of pitch envelope, fill in the length // posssible end of pitch envelope, fill in the length
} }
} }




static void DoAmplitude(int amp, unsigned char *amp_env) static void DoAmplitude(int amp, unsigned char *amp_env)
{ {
intptr_t *q; intptr_t *q;
WcmdqInc(); WcmdqInc();
} }




static void DoPitch(unsigned char *env, int pitch1, int pitch2) static void DoPitch(unsigned char *env, int pitch1, int pitch2)
{ {
intptr_t *q; intptr_t *q;
WcmdqInc(); WcmdqInc();
} }




int PauseLength(int pause, int control) int PauseLength(int pause, int control)
{ {
unsigned int len; unsigned int len;
return len; return len;
} }



static void DoPause(int length, int control) static void DoPause(int length, int control)
{ {
// length in nominal mS // length in nominal mS
} }
} }



extern int seq_len_adjust; // temporary fix to advance the start point for playing the wav sample extern int seq_len_adjust; // temporary fix to advance the start point for playing the wav sample



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 length;
q[3] = wav_scale + (amp << 8); q[3] = wav_scale + (amp << 8);
WcmdqInc(); WcmdqInc();



while (length > len4*3) { while (length > len4*3) {
x = len4; x = len4;
if (wav_scale == 0) if (wav_scale == 0)
return length; return length;
} }




int DoSample3(PHONEME_DATA *phdata, int length_mod, int amp) int DoSample3(PHONEME_DATA *phdata, int length_mod, int amp)
{ {
int amp2; int amp2;
return len; return len;
} }





static frame_t *AllocFrame() static frame_t *AllocFrame()
{ {
// Allocate a temporary spectrum frame for the wavegen queue. Use a pool which is big // Allocate a temporary spectrum frame for the wavegen queue. Use a pool which is big
return &frame_pool[ix]; return &frame_pool[ix];
} }



static void set_frame_rms(frame_t *fr, int new_rms) static void set_frame_rms(frame_t *fr, int new_rms)
{ {
// Each frame includes its RMS amplitude value, so to set a new // Each frame includes its RMS amplitude value, so to set a new
} }
} }




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
} }
} }



static frame_t *CopyFrame(frame_t *frame1, int copy) static frame_t *CopyFrame(frame_t *frame1, int copy)
{ {
// create a copy of the specified frame in temporary buffer // create a copy of the specified frame in temporary buffer
return frame2; return frame2;
} }



static frame_t *DuplicateLastFrame(frameref_t *seq, int n_frames, int length) static frame_t *DuplicateLastFrame(frameref_t *seq, int n_frames, int length)
{ {
frame_t *fr; frame_t *fr;
return fr; return fr;
} }



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; int x;
formants_reduce_hf(fr, hf_reduce); formants_reduce_hf(fr, hf_reduce);
} }



static int VowelCloseness(frame_t *fr) static int VowelCloseness(frame_t *fr)
{ {
// return a value 0-3 depending on the vowel's f1 // return a value 0-3 depending on the vowel's f1
return 0; return 0;
} }



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 ix;
return 0; return 0;
} }




static void SmoothSpect(void) static void SmoothSpect(void)
{ {
// Limit the rate of frequence change of formants, to reduce chirping // Limit the rate of frequence change of formants, to reduce chirping
break; break;


if (q[0] <= WCMD_SPECT2) { if (q[0] <= WCMD_SPECT2) {

len = q[1] & 0xffff; len = q[1] & 0xffff;


frame1 = (frame_t *)q[2]; frame1 = (frame_t *)q[2];
syllable_start = syllable_end; syllable_start = syllable_end;
} }



static void StartSyllable(void) static void StartSyllable(void)
{ {
// start of syllable, if not already started // start of syllable, if not already started
syllable_end = wcmdq_tail; syllable_end = wcmdq_tail;
} }




int DoSpect2(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, PHONEME_LIST *plist, int modulation) int DoSpect2(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, PHONEME_LIST *plist, int modulation)
{ {
// which: 0 not a vowel, 1 start of vowel, 2 body and end of vowel // which: 0 not a vowel, 1 start of vowel, 2 body and end of vowel
WcmdqInc(); WcmdqInc();
} }



return total_len; return total_len;
} }





void DoMarker(int type, int char_posn, int length, int value) void DoMarker(int type, int char_posn, int length, int value)
{ {
// This could be used to return an index to the word currently being spoken // This could be used to return an index to the word currently being spoken
} }
} }



void DoPhonemeMarker(int type, int char_posn, int length, char *name) void DoPhonemeMarker(int type, int char_posn, int length, char *name)
{ {
// This could be used to return an index to the word currently being spoken // This could be used to return an index to the word currently being spoken
} }
} }



#if HAVE_SONIC_H #if HAVE_SONIC_H
void DoSonicSpeed(int value) void DoSonicSpeed(int value)
{ {
} }
#endif #endif



void DoVoiceChange(voice_t *v) void DoVoiceChange(voice_t *v)
{ {
// allocate memory for a copy of the voice data, and free it in wavegenfill() // allocate memory for a copy of the voice data, and free it in wavegenfill()
WcmdqInc(); WcmdqInc();
} }



void DoEmbedded(int *embix, int sourceix) void DoEmbedded(int *embix, int sourceix)
{ {
// There were embedded commands in the text at this point // There were embedded commands in the text at this point
SetEmbedded((command & 0x60) + EMBED_S2, value); // adjusts embedded_value[EMBED_S2] SetEmbedded((command & 0x60) + EMBED_S2, value); // adjusts embedded_value[EMBED_S2]
SetSpeed(2); SetSpeed(2);
break; break;

case EMBED_I: // play dynamically loaded wav data (sound icon) case EMBED_I: // play dynamically loaded wav data (sound icon)
if ((int)value < n_soundicon_tab) { if ((int)value < n_soundicon_tab) {
if (soundicon_tab[value].length != 0) { if (soundicon_tab[value].length != 0) {
} }
} }
break; break;

case EMBED_M: // named marker case EMBED_M: // named marker
DoMarker(espeakEVENT_MARK, (sourceix & 0x7ff) + clause_start_char, 0, value); DoMarker(espeakEVENT_MARK, (sourceix & 0x7ff) + clause_start_char, 0, value);
break; break;

case EMBED_U: // play sound case EMBED_U: // play sound
DoMarker(espeakEVENT_PLAY, count_characters+1, 0, value); // always occurs at end of clause DoMarker(espeakEVENT_PLAY, count_characters+1, 0, value); // always occurs at end of clause
break; break;

default: default:
DoPause(10, 0); // ensure a break in the speech DoPause(10, 0); // ensure a break in the speech
wcmdq[wcmdq_tail][0] = WCMD_EMBEDDED; wcmdq[wcmdq_tail][0] = WCMD_EMBEDDED;
} while ((word & 0x80) == 0); } while ((word & 0x80) == 0);
} }




int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
{ {
static int ix; static int ix;
DoPause(p->length, 0); DoPause(p->length, 0);
p->std_length = p->ph->std_length; p->std_length = p->ph->std_length;
break; break;

case phSTOP: case phSTOP:
released = 0; released = 0;
ph = p->ph; ph = p->ph;
phdata.pd_control |= pd_DONTLENGTHEN; phdata.pd_control |= pd_DONTLENGTHEN;
DoSample3(&phdata, 0, 0); DoSample3(&phdata, 0, 0);
break; break;

case phFRICATIVE: case phFRICATIVE:
InterpretPhoneme(NULL, 0, p, &phdata, &worddata); InterpretPhoneme(NULL, 0, p, &phdata, &worddata);


DoSample3(&phdata, p->length, 0); // play it twice for [s:] etc. DoSample3(&phdata, p->length, 0); // play it twice for [s:] etc.
DoSample3(&phdata, p->length, 0); DoSample3(&phdata, p->length, 0);
break; break;

case phVSTOP: case phVSTOP:
ph = p->ph; ph = p->ph;
memset(&fmtp, 0, sizeof(fmtp)); memset(&fmtp, 0, sizeof(fmtp));
DoPause(12, 0); DoPause(12, 0);
} }
break; break;

case phVFRICATIVE: case phVFRICATIVE:
if (next->type == phVOWEL) { if (next->type == phVOWEL) {
DoAmplitude(p->amp, NULL); DoAmplitude(p->amp, NULL);
DoSpect2(p->ph, 0, &fmtp, p, 0); DoSpect2(p->ph, 0, &fmtp, p, 0);
DoSpect2(p->ph, 0, &fmtp, p, 0); DoSpect2(p->ph, 0, &fmtp, p, 0);
break; break;

case phNASAL: case phNASAL:
memset(&fmtp, 0, sizeof(fmtp)); memset(&fmtp, 0, sizeof(fmtp));
if (!(p->synthflags & SFLAG_SEQCONTINUE)) { if (!(p->synthflags & SFLAG_SEQCONTINUE)) {
} }


break; break;

case phLIQUID: case phLIQUID:
memset(&fmtp, 0, sizeof(fmtp)); memset(&fmtp, 0, sizeof(fmtp));
modulation = 0; modulation = 0;
fmtp.wav_addr = phdata.sound_addr[pd_ADDWAV]; fmtp.wav_addr = phdata.sound_addr[pd_ADDWAV];
fmtp.wav_amp = phdata.sound_param[pd_ADDWAV]; fmtp.wav_amp = phdata.sound_param[pd_ADDWAV];
DoSpect2(p->ph, 0, &fmtp, p, modulation); DoSpect2(p->ph, 0, &fmtp, p, modulation);

break; break;

case phVOWEL: case phVOWEL:
ph = p->ph; ph = p->ph;
stress = p->stresslevel & 0xf; stress = p->stresslevel & 0xf;
} }


DoSpect2(ph, 2, &fmtp, p, modulation); DoSpect2(ph, 2, &fmtp, p, modulation);

break; break;
} }
ix++; ix++;
return 0; // finished the phoneme list return 0; // finished the phoneme list
} }





static int timer_on = 0; static int timer_on = 0;
static int paused = 0; static int paused = 0;


return 0; return 0;
} }



int SynthStatus() int SynthStatus()
{ {
return timer_on | paused; return timer_on | paused;
} }




int SpeakNextClause(FILE *f_in, const void *text_in, int control) int SpeakNextClause(FILE *f_in, const void *text_in, int control)
{ {
// Speak text from file (f_in) or memory (text_in) // Speak text from file (f_in) or memory (text_in)

+ 56
- 146
src/libespeak-ng/tr_languages.c View File

#include "synthesize.h" #include "synthesize.h"
#include "translate.h" #include "translate.h"




#define L_qa 0x716100 #define L_qa 0x716100
#define L_grc 0x677263 // grc Ancient Greek #define L_grc 0x677263 // grc Ancient Greek
#define L_jbo 0x6a626f // jbo Lojban #define L_jbo 0x6a626f // jbo Lojban
#define OFFSET_KOREAN 0x1100 #define OFFSET_KOREAN 0x1100
#define OFFSET_ETHIOPIC 0x1200 #define OFFSET_ETHIOPIC 0x1200



// character ranges must be listed in ascending unicode order // character ranges must be listed in ascending unicode order
ALPHABET alphabets[] = { ALPHABET alphabets[] = {
{ "_el", OFFSET_GREEK, 0x380, 0x3ff, L('e', 'l'), AL_DONT_NAME | AL_NOT_LETTERS | AL_WORDS }, { "_el", OFFSET_GREEK, 0x380, 0x3ff, L('e', 'l'), AL_DONT_NAME | AL_NOT_LETTERS | AL_WORDS },
{ NULL, 0, 0, 0, 0, 0 } { NULL, 0, 0, 0, 0, 0 }
}; };



ALPHABET *AlphabetFromName(const char *name) ALPHABET *AlphabetFromName(const char *name)
{ {
ALPHABET *alphabet; ALPHABET *alphabet;
return NULL; return NULL;
} }



ALPHABET *AlphabetFromChar(int c) ALPHABET *AlphabetFromChar(int c)
{ {
// Find the alphabet from a character. // Find the alphabet from a character.
return NULL; return NULL;
} }




static void Translator_Russian(Translator *tr); static void Translator_Russian(Translator *tr);




static void SetLetterVowel(Translator *tr, int c) static void SetLetterVowel(Translator *tr, int c)
{ {
tr->letter_bits[c] = (tr->letter_bits[c] & 0x40) | 0x81; // keep value for group 6 (front vowels e,i,y) tr->letter_bits[c] = (tr->letter_bits[c] & 0x40) | 0x81; // keep value for group 6 (front vowels e,i,y)


const char string_ordinal[] = { 0xc2, 0xba, 0 }; // masculine ordinal character, UTF-8 const char string_ordinal[] = { 0xc2, 0xba, 0 }; // masculine ordinal character, UTF-8



static Translator *NewTranslator(void) static Translator *NewTranslator(void)
{ {
Translator *tr; Translator *tr;
SetLetterBits(tr, 6, "eiy"); // Letter group Y, front vowels SetLetterBits(tr, 6, "eiy"); // Letter group Y, front vowels
SetLetterBits(tr, 7, "aeiouy"); // vowels, including y SetLetterBits(tr, 7, "aeiouy"); // vowels, including y



tr->char_plus_apostrophe = empty_wstring; tr->char_plus_apostrophe = empty_wstring;
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;
0x7fff 0x7fff
}; };




static const unsigned int replace_cyrillic_latin[] = static const unsigned int replace_cyrillic_latin[] =
{ 0x430, 'a', { 0x430, 'a',
0x431, 'b', 0x431, 'b',
0x45c, 0x107, 0x45c, 0x107,
0 }; // ѓ ѕ ќ 0 }; // ѓ ѕ ќ



static const unsigned char ru_vowels[] = { 0x10, 0x15, 0x31, 0x18, 0x1e, 0x23, 0x2b, 0x2d, 0x2e, 0x2f, 0xb9, 0xc9, 0x91, 0x8f, 0x36, 0 }; // also kazakh static const unsigned char ru_vowels[] = { 0x10, 0x15, 0x31, 0x18, 0x1e, 0x23, 0x2b, 0x2d, 0x2e, 0x2f, 0xb9, 0xc9, 0x91, 0x8f, 0x36, 0 }; // also kazakh
static const unsigned char ru_consonants[] = { 0x11, 0x12, 0x13, 0x14, 0x16, 0x17, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2c, 0x73, 0x7b, 0x83, 0x9b, 0 }; static const unsigned char ru_consonants[] = { 0x11, 0x12, 0x13, 0x14, 0x16, 0x17, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2c, 0x73, 0x7b, 0x83, 0x9b, 0 };


SetLetterBits(tr, LETTERGP_VOWEL2, (char *)ru_vowels); SetLetterBits(tr, LETTERGP_VOWEL2, (char *)ru_vowels);
} }



void SetIndicLetters(Translator *tr) void SetIndicLetters(Translator *tr)
{ {
// Set letter types for Indic scripts, Devanagari, Tamill, etc // Set letter types for Indic scripts, Devanagari, Tamill, etc
tr->langopts.suffix_add_e = tr->letter_bits_offset + 0x4d; // virama tr->langopts.suffix_add_e = tr->letter_bits_offset + 0x4d; // virama
} }



void SetupTranslator(Translator *tr, const short *lengths, const unsigned char *amps) void SetupTranslator(Translator *tr, const short *lengths, const unsigned char *amps)
{ {
if (lengths != NULL) if (lengths != NULL)
memcpy(tr->stress_amps, amps, sizeof(tr->stress_amps)); memcpy(tr->stress_amps, amps, sizeof(tr->stress_amps));
} }



Translator *SelectTranslator(const char *name) Translator *SelectTranslator(const char *name)
{ {
int name2 = 0; int name2 = 0;
tr->langopts.numbers = NUM_SWAP_TENS | NUM_HUNDRED_AND | NUM_SINGLE_AND | NUM_ROMAN | NUM_1900; tr->langopts.numbers = NUM_SWAP_TENS | NUM_HUNDRED_AND | NUM_SINGLE_AND | NUM_ROMAN | NUM_1900;
tr->langopts.accents = 1; tr->langopts.accents = 1;
} }
break;

break;
case L('a', 'm'): // Amharic, Ethiopia case L('a', 'm'): // Amharic, Ethiopia
{ {
SetupTranslator(tr, stress_lengths_fr, stress_amps_fr); SetupTranslator(tr, stress_lengths_fr, stress_amps_fr);
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words
tr->langopts.numbers = NUM_OMIT_1_HUNDRED; tr->langopts.numbers = NUM_OMIT_1_HUNDRED;
} }
break;




break;
case L('a', 'r'): // Arabic case L('a', 'r'): // Arabic
tr->transpose_min = 0x620; // for ar_list, use 6-bit character codes tr->transpose_min = 0x620; // for ar_list, use 6-bit character codes
tr->transpose_max = 0x65f; tr->transpose_max = 0x65f;
tr->langopts.numbers = NUM_SWAP_TENS | NUM_AND_UNITS | NUM_HUNDRED_AND | NUM_OMIT_1_HUNDRED | NUM_AND_HUNDRED | NUM_THOUSAND_AND | NUM_OMIT_1_THOUSAND; tr->langopts.numbers = NUM_SWAP_TENS | NUM_AND_UNITS | NUM_HUNDRED_AND | NUM_OMIT_1_HUNDRED | NUM_AND_HUNDRED | NUM_THOUSAND_AND | NUM_OMIT_1_THOUSAND;
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words
break; break;

case L('b', 'g'): // Bulgarian case L('b', 'g'): // Bulgarian
{ {
SetCyrillicLetters(tr); SetCyrillicLetters(tr);
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_OMIT_1_HUNDRED | NUM_HUNDRED_AND | NUM_AND_UNITS | NUM_SINGLE_AND | NUM_ROMAN | NUM_ROMAN_ORDINAL | NUM_ROMAN_CAPITALS; tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_OMIT_1_HUNDRED | NUM_HUNDRED_AND | NUM_AND_UNITS | NUM_SINGLE_AND | NUM_ROMAN | NUM_ROMAN_ORDINAL | NUM_ROMAN_CAPITALS;
tr->langopts.thousands_sep = ' '; // don't allow dot as thousands separator tr->langopts.thousands_sep = ' '; // don't allow dot as thousands separator
} }
break;

break;
case L('b', 'n'): // Bengali case L('b', 'n'): // Bengali
case L('a', 's'): // Assamese case L('a', 's'): // Assamese
case L_mni: // Manipuri (temporary placement - it's not indo-european) case L_mni: // Manipuri (temporary placement - it's not indo-european)
} }


} }
break;

break;
case L('b', 'o'): // Tibet case L('b', 'o'): // Tibet
{ {
tr->langopts.stress_rule = STRESSPOSN_1L; tr->langopts.stress_rule = STRESSPOSN_1L;
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words
tr->langopts.numbers = 1; tr->langopts.numbers = 1;
} }
break;

break;
case L('c', 'y'): // Welsh case L('c', 'y'): // Welsh
{ {
static const short stress_lengths_cy[8] = { 170, 220, 180, 180, 0, 0, 250, 270 }; static const short stress_lengths_cy[8] = { 170, 220, 180, 180, 0, 0, 250, 270 };
SetLetterVowel(tr, 'w'); // add letter to vowels and remove from consonants SetLetterVowel(tr, 'w'); // add letter to vowels and remove from consonants
SetLetterVowel(tr, 'y'); SetLetterVowel(tr, 'y');
} }
break;

break;
case L('d', 'a'): // Danish case L('d', 'a'): // Danish
{ {
static const short stress_lengths_da[8] = { 160, 140, 200, 200, 0, 0, 220, 230 }; static const short stress_lengths_da[8] = { 160, 140, 200, 200, 0, 0, 220, 230 };
SetLetterVowel(tr, 'y'); SetLetterVowel(tr, 'y');
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_SWAP_TENS | NUM_HUNDRED_AND | NUM_OMIT_1_HUNDRED | NUM_ORDINAL_DOT | NUM_1900 | NUM_ROMAN | NUM_ROMAN_CAPITALS | NUM_ROMAN_ORDINAL; tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_SWAP_TENS | NUM_HUNDRED_AND | NUM_OMIT_1_HUNDRED | NUM_ORDINAL_DOT | NUM_1900 | NUM_ROMAN | NUM_ROMAN_CAPITALS | NUM_ROMAN_ORDINAL;
} }
break;


break;
case L('d', 'e'): case L('d', 'e'):
{ {
static const short stress_lengths_de[8] = { 150, 130, 200, 200, 0, 0, 270, 270 }; static const short stress_lengths_de[8] = { 150, 130, 200, 200, 0, 0, 270, 270 };
SetLetterVowel(tr, 'y'); SetLetterVowel(tr, 'y');
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 2; // use de_rules for unpronouncable rules tr->langopts.param[LOPT_UNPRONOUNCABLE] = 2; // use de_rules for unpronouncable rules
} }
break;

break;
case L('d', 'v'): // Divehi (Maldives) case L('d', 'v'): // Divehi (Maldives)
{ {
SetupTranslator(tr, stress_lengths_ta, stress_amps_ta); SetupTranslator(tr, stress_lengths_ta, stress_amps_ta);
tr->langopts.break_numbers = 0x14a8; // 1000, 100,000 10,000,000 tr->langopts.break_numbers = 0x14a8; // 1000, 100,000 10,000,000
tr->langopts.numbers = 1; tr->langopts.numbers = 1;
} }
break;

break;
case L('e', 'n'): case L('e', 'n'):
{ {
static const short stress_lengths_en[8] = { 182, 140, 220, 220, 0, 0, 248, 275 }; static const short stress_lengths_en[8] = { 182, 140, 220, 220, 0, 0, 248, 275 };
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 2; // use en_rules for unpronouncable rules tr->langopts.param[LOPT_UNPRONOUNCABLE] = 2; // use en_rules for unpronouncable rules
SetLetterBits(tr, 6, "aeiouy"); // Group Y: vowels, including y SetLetterBits(tr, 6, "aeiouy"); // Group Y: vowels, including y
} }
break;

break;
case L('e', 'l'): // Greek case L('e', 'l'): // Greek
case L_grc: // Ancient Greek case L_grc: // Ancient Greek
{ {
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1;
} }
} }
break;

break;
case L('e', 'o'): case L('e', 'o'):
{ {
static const short stress_lengths_eo[8] = { 150, 140, 180, 180, 0, 0, 200, 200 }; static const short stress_lengths_eo[8] = { 150, 140, 180, 180, 0, 0, 200, 200 };


tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_OMIT_1_HUNDRED | NUM_ALLOW_SPACE | NUM_ROMAN; tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_OMIT_1_HUNDRED | NUM_ALLOW_SPACE | NUM_ROMAN;
} }
break;

break;
case L('e', 's'): // Spanish case L('e', 's'): // Spanish
case L('a', 'n'): // Aragonese case L('a', 'n'): // Aragonese
case L('c', 'a'): // Catalan case L('c', 'a'): // Catalan
} else } else
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 2; // use es_rules for unpronouncable rules tr->langopts.param[LOPT_UNPRONOUNCABLE] = 2; // use es_rules for unpronouncable rules
} }
break;

break;
case L('e', 'u'): // basque case L('e', 'u'): // basque
{ {
static const short stress_lengths_eu[8] = { 200, 200, 200, 200, 0, 0, 210, 230 }; // very weak stress static const short stress_lengths_eu[8] = { 200, 200, 200, 200, 0, 0, 210, 230 }; // very weak stress
tr->langopts.param[LOPT_SUFFIX] = 1; tr->langopts.param[LOPT_SUFFIX] = 1;
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA | NUM_HUNDRED_AND | NUM_OMIT_1_HUNDRED | NUM_OMIT_1_THOUSAND | NUM_VIGESIMAL; tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA | NUM_HUNDRED_AND | NUM_OMIT_1_HUNDRED | NUM_OMIT_1_THOUSAND | NUM_VIGESIMAL;
} }
break;


break;
case L('f', 'a'): // Farsi case L('f', 'a'): // Farsi
{ {
// Convert characters in the range 0x620 to 0x6cc to the range 1 to 63. // Convert characters in the range 0x620 to 0x6cc to the range 1 to 63.


tr->chars_ignore = chars_ignore_zwnj_hyphen; // replace ZWNJ by hyphen tr->chars_ignore = chars_ignore_zwnj_hyphen; // replace ZWNJ by hyphen
} }
break;


break;
case L('e', 't'): // Estonian case L('e', 't'): // Estonian
tr->charset_a0 = charsets[4]; // ISO-8859-4 tr->charset_a0 = charsets[4]; // ISO-8859-4
// drop through to Finnish
// drop through to Finnish
case L('f', 'i'): // Finnish case L('f', 'i'): // Finnish
{ {
static const unsigned char stress_amps_fi[8] = { 18, 16, 22, 22, 20, 22, 22, 22 }; static const unsigned char stress_amps_fi[8] = { 18, 16, 22, 22, 20, 22, 22, 22 };
tr->langopts.spelling_stress = 1; tr->langopts.spelling_stress = 1;
tr->langopts.intonation_group = 3; // less intonation, don't raise pitch at comma tr->langopts.intonation_group = 3; // less intonation, don't raise pitch at comma
} }
break;

break;
case L('f', 'r'): // french case L('f', 'r'): // french
{ {
SetupTranslator(tr, stress_lengths_fr, stress_amps_fr); SetupTranslator(tr, stress_lengths_fr, stress_amps_fr);
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_OMIT_1_HUNDRED | NUM_NOPAUSE | NUM_ROMAN | NUM_ROMAN_CAPITALS | NUM_ROMAN_AFTER | NUM_VIGESIMAL | NUM_DFRACTION_4; tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_OMIT_1_HUNDRED | NUM_NOPAUSE | NUM_ROMAN | NUM_ROMAN_CAPITALS | NUM_ROMAN_AFTER | NUM_VIGESIMAL | NUM_DFRACTION_4;
SetLetterVowel(tr, 'y'); SetLetterVowel(tr, 'y');
} }
break;

break;
case L('g', 'a'): // irish case L('g', 'a'): // irish
case L('g', 'd'): // scots gaelic case L('g', 'd'): // scots gaelic
{ {
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 3; // don't count apostrophe tr->langopts.param[LOPT_UNPRONOUNCABLE] = 3; // don't count apostrophe
tr->langopts.param[LOPT_IT_LENGTHEN] = 1; // remove [:] phoneme from non-stressed syllables (Lang=gd) tr->langopts.param[LOPT_IT_LENGTHEN] = 1; // remove [:] phoneme from non-stressed syllables (Lang=gd)
} }
break;

break;
case L('h', 'i'): // Hindi case L('h', 'i'): // Hindi
case L('n', 'e'): // Nepali case L('n', 'e'): // Nepali
case L('o', 'r'): // Oriya case L('o', 'r'): // Oriya
tr->letter_bits_offset = OFFSET_ORIYA; tr->letter_bits_offset = OFFSET_ORIYA;
SetIndicLetters(tr); SetIndicLetters(tr);
} }
break;


break;
case L('h', 'r'): // Croatian case L('h', 'r'): // Croatian
case L('b', 's'): // Bosnian case L('b', 's'): // Bosnian
case L('s', 'r'): // Serbian case L('s', 'r'): // Serbian
SetLetterVowel(tr, 'y'); SetLetterVowel(tr, 'y');
SetLetterVowel(tr, 'r'); SetLetterVowel(tr, 'r');
} }
break;


break;
case L('h', 't'): // Haitian Creole case L('h', 't'): // Haitian Creole
tr->langopts.stress_rule = STRESSPOSN_1R; // stress on final syllable tr->langopts.stress_rule = STRESSPOSN_1R; // stress on final syllable
tr->langopts.stress_flags = S_NO_AUTO_2 | S_FINAL_DIM; // don't use secondary stress tr->langopts.stress_flags = S_NO_AUTO_2 | S_FINAL_DIM; // don't use secondary stress
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_OMIT_1_HUNDRED | NUM_NOPAUSE | NUM_ROMAN | NUM_VIGESIMAL | NUM_DFRACTION_4; tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_OMIT_1_HUNDRED | NUM_NOPAUSE | NUM_ROMAN | NUM_VIGESIMAL | NUM_DFRACTION_4;
break; break;


case L('h', 'u'): // Hungarian case L('h', 'u'): // Hungarian
{ {
static const unsigned char stress_amps_hu[8] = { 17, 17, 19, 19, 20, 22, 22, 21 }; static const unsigned char stress_amps_hu[8] = { 17, 17, 19, 19, 20, 22, 22, 21 };
tr->langopts.spelling_stress = 1; tr->langopts.spelling_stress = 1;
SetLengthMods(tr, 3); // all equal SetLengthMods(tr, 3); // all equal
} }
break;

break;
case L('h', 'y'): // Armenian case L('h', 'y'): // Armenian
{ {
static const short stress_lengths_hy[8] = { 250, 200, 250, 250, 0, 0, 250, 250 }; static const short stress_lengths_hy[8] = { 250, 200, 250, 250, 0, 0, 250, 250 };
tr->langopts.max_initial_consonants = 6; tr->langopts.max_initial_consonants = 6;
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_OMIT_1_HUNDRED; tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_OMIT_1_HUNDRED;
} }
break;

break;
case L('i', 'd'): // Indonesian case L('i', 'd'): // Indonesian
case L('m', 's'): // Malay case L('m', 's'): // Malay
{ {
tr->langopts.stress_flags = S_FINAL_DIM_ONLY | S_FINAL_NO_2; tr->langopts.stress_flags = S_FINAL_DIM_ONLY | S_FINAL_NO_2;
tr->langopts.accents = 2; // "capital" after letter name tr->langopts.accents = 2; // "capital" after letter name
} }
break;

break;
case L('i', 's'): // Icelandic case L('i', 's'): // Icelandic
{ {
static const short stress_lengths_is[8] = { 180, 160, 200, 200, 0, 0, 240, 250 }; static const short stress_lengths_is[8] = { 180, 160, 200, 200, 0, 0, 240, 250 };
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_SINGLE_AND | NUM_HUNDRED_AND | NUM_AND_UNITS | NUM_1900; tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_SINGLE_AND | NUM_HUNDRED_AND | NUM_AND_UNITS | NUM_1900;
tr->langopts.numbers2 = 0x2; tr->langopts.numbers2 = 0x2;
} }
break;

break;
case L('i', 't'): // Italian case L('i', 't'): // Italian
{ {
static const short stress_lengths_it[8] = static const short stress_lengths_it[8] =
tr->langopts.accents = 2; // Say "Capital" after the letter. tr->langopts.accents = 2; // Say "Capital" after the letter.
SetLetterVowel(tr, 'y'); SetLetterVowel(tr, 'y');
} }
break;

break;
case L_jbo: // Lojban case L_jbo: // Lojban
{ {
static const short stress_lengths_jbo[8] = { 145, 145, 170, 160, 0, 0, 330, 350 }; static const short stress_lengths_jbo[8] = { 145, 145, 170, 160, 0, 0, 330, 350 };
SetLetterVowel(tr, 'y'); SetLetterVowel(tr, 'y');
tr->langopts.max_lengthmod = 368; tr->langopts.max_lengthmod = 368;
} }
break;

break;
case L('k', 'a'): // Georgian case L('k', 'a'): // Georgian
{ {
// character codes offset by 0x1080 // character codes offset by 0x1080
tr->langopts.alt_alphabet = OFFSET_CYRILLIC; tr->langopts.alt_alphabet = OFFSET_CYRILLIC;
tr->langopts.alt_alphabet_lang = L('r', 'u'); tr->langopts.alt_alphabet_lang = L('r', 'u');
} }
break;

break;
case L('k', 'k'): // Kazakh case L('k', 'k'): // Kazakh
{ {
static const unsigned char stress_amps_tr[8] = { 18, 16, 20, 21, 20, 21, 21, 20 }; static const unsigned char stress_amps_tr[8] = { 18, 16, 20, 21, 20, 21, 21, 20 };
tr->langopts.max_initial_consonants = 2; tr->langopts.max_initial_consonants = 2;
SetLengthMods(tr, 3); // all equal SetLengthMods(tr, 3); // all equal
} }
break;

break;
case L('k', 'l'): // Greenlandic case L('k', 'l'): // Greenlandic
{ {
SetupTranslator(tr, stress_lengths_equal, stress_amps_equal); SetupTranslator(tr, stress_lengths_equal, stress_amps_equal);
tr->langopts.stress_flags = S_NO_AUTO_2; tr->langopts.stress_flags = S_NO_AUTO_2;
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_SWAP_TENS | NUM_HUNDRED_AND | NUM_OMIT_1_HUNDRED | NUM_ORDINAL_DOT | NUM_1900 | NUM_ROMAN | NUM_ROMAN_CAPITALS | NUM_ROMAN_ORDINAL; tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_SWAP_TENS | NUM_HUNDRED_AND | NUM_OMIT_1_HUNDRED | NUM_ORDINAL_DOT | NUM_1900 | NUM_ROMAN | NUM_ROMAN_CAPITALS | NUM_ROMAN_ORDINAL;
} }
break;

break;
case L('k', 'o'): // Korean, TEST case L('k', 'o'): // Korean, TEST
{ {
static const char ko_ivowels[] = { 0x63, 0x64, 0x67, 0x68, 0x6d, 0x72, 0x74, 0x75, 0 }; // y and i vowels static const char ko_ivowels[] = { 0x63, 0x64, 0x67, 0x68, 0x6d, 0x72, 0x74, 0x75, 0 }; // y and i vowels
tr->langopts.break_numbers = 0x1111110; tr->langopts.break_numbers = 0x1111110;
tr->langopts.max_digits = 20; tr->langopts.max_digits = 20;
} }
break;

break;
case L('k', 'u'): // Kurdish case L('k', 'u'): // Kurdish
{ {
static const unsigned char stress_amps_ku[8] = { 18, 18, 20, 20, 20, 22, 22, 21 }; static const unsigned char stress_amps_ku[8] = { 18, 18, 20, 20, 20, 22, 22, 21 };
tr->langopts.numbers = NUM_HUNDRED_AND | NUM_AND_UNITS | NUM_OMIT_1_HUNDRED | NUM_AND_HUNDRED; tr->langopts.numbers = NUM_HUNDRED_AND | NUM_AND_UNITS | NUM_OMIT_1_HUNDRED | NUM_AND_HUNDRED;
tr->langopts.max_initial_consonants = 2; tr->langopts.max_initial_consonants = 2;
} }
break;

break;
case L('l', 'a'): // Latin case L('l', 'a'): // Latin
{ {
tr->charset_a0 = charsets[4]; // ISO-8859-4, includes a,e,i,o,u-macron tr->charset_a0 = charsets[4]; // ISO-8859-4, includes a,e,i,o,u-macron
tr->langopts.numbers = NUM_ROMAN; tr->langopts.numbers = NUM_ROMAN;
tr->langopts.max_roman = 5000; tr->langopts.max_roman = 5000;
} }
break;

break;
case L('l', 't'): // Lithuanian case L('l', 't'): // Lithuanian
{ {
tr->charset_a0 = charsets[4]; // ISO-8859-4 tr->charset_a0 = charsets[4]; // ISO-8859-4
tr->langopts.numbers2 = NUM2_THOUSANDS_VAR4; tr->langopts.numbers2 = NUM2_THOUSANDS_VAR4;
tr->langopts.max_roman = 5000; tr->langopts.max_roman = 5000;
} }
break;

break;
case L('l', 'v'): // latvian case L('l', 'v'): // latvian
{ {
static const unsigned char stress_amps_lv[8] = { 17, 13, 20, 20, 20, 22, 22, 21 }; static const unsigned char stress_amps_lv[8] = { 17, 13, 20, 20, 20, 22, 22, 21 };
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_OMIT_1_HUNDRED | NUM_DFRACTION_4 | NUM_ORDINAL_DOT; tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_OMIT_1_HUNDRED | NUM_DFRACTION_4 | NUM_ORDINAL_DOT;
tr->langopts.stress_flags = S_FINAL_DIM_ONLY | S_FINAL_NO_2 | S_EO_CLAUSE1; tr->langopts.stress_flags = S_FINAL_DIM_ONLY | S_FINAL_NO_2 | S_EO_CLAUSE1;
} }
break;

break;
case L('m', 'k'): // Macedonian case L('m', 'k'): // Macedonian
{ {
static wchar_t vowels_cyrillic[] = { 0x440, // also include 'р' [R] static wchar_t vowels_cyrillic[] = { 0x440, // also include 'р' [R]
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_AND_UNITS | NUM_OMIT_1_HUNDRED | NUM_OMIT_1_THOUSAND | NUM_DFRACTION_2; tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_AND_UNITS | NUM_OMIT_1_HUNDRED | NUM_OMIT_1_THOUSAND | NUM_DFRACTION_2;
tr->langopts.numbers2 = 0x8a; // variant numbers before thousands,milliards tr->langopts.numbers2 = 0x8a; // variant numbers before thousands,milliards
} }
break;

break;
case L('m', 't'): // Maltese case L('m', 't'): // Maltese
{ {
tr->charset_a0 = charsets[3]; // ISO-8859-3 tr->charset_a0 = charsets[3]; // ISO-8859-3
tr->langopts.stress_rule = STRESSPOSN_2R; // penultimate tr->langopts.stress_rule = STRESSPOSN_2R; // penultimate
tr->langopts.numbers = 1; tr->langopts.numbers = 1;
} }
break;

break;
case L('n', 'l'): // Dutch case L('n', 'l'): // Dutch
{ {
static const short stress_lengths_nl[8] = { 160, 135, 210, 210, 0, 0, 260, 280 }; static const short stress_lengths_nl[8] = { 160, 135, 210, 210, 0, 0, 260, 280 };
tr->langopts.stress_flags = S_FIRST_PRIMARY; tr->langopts.stress_flags = S_FIRST_PRIMARY;
memcpy(tr->stress_lengths, stress_lengths_nl, sizeof(tr->stress_lengths)); memcpy(tr->stress_lengths, stress_lengths_nl, sizeof(tr->stress_lengths));
} }
break;

break;
case L('n', 'o'): // Norwegian case L('n', 'o'): // Norwegian
{ {
static const short stress_lengths_no[8] = { 160, 140, 200, 200, 0, 0, 220, 230 }; static const short stress_lengths_no[8] = { 160, 140, 200, 200, 0, 0, 220, 230 };
SetLetterVowel(tr, 'y'); SetLetterVowel(tr, 'y');
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_HUNDRED_AND | NUM_ALLOW_SPACE | NUM_1900 | NUM_ORDINAL_DOT; tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_HUNDRED_AND | NUM_ALLOW_SPACE | NUM_1900 | NUM_ORDINAL_DOT;
} }
break;

break;
case L('o', 'm'): // Oromo case L('o', 'm'): // Oromo
{ {
static const unsigned char stress_amps_om[] = { 18, 15, 20, 20, 20, 22, 22, 22 }; static const unsigned char stress_amps_om[] = { 18, 15, 20, 20, 20, 22, 22, 22 };
tr->langopts.numbers = NUM_OMIT_1_HUNDRED | NUM_HUNDRED_AND; tr->langopts.numbers = NUM_OMIT_1_HUNDRED | NUM_HUNDRED_AND;
tr->langopts.numbers2 = 0x200; // say "thousands" before its number tr->langopts.numbers2 = 0x200; // say "thousands" before its number
} }
break;

break;
case L('p', 'l'): // Polish case L('p', 'l'): // Polish
{ {
static const short stress_lengths_pl[8] = { 160, 190, 175, 175, 0, 0, 200, 210 }; static const short stress_lengths_pl[8] = { 160, 190, 175, 175, 0, 0, 200, 210 };
tr->langopts.param[LOPT_COMBINE_WORDS] = 4 + 0x100; // combine 'nie' (marked with $alt2) with some 1-syllable (and 2-syllable) words (marked with $alt) tr->langopts.param[LOPT_COMBINE_WORDS] = 4 + 0x100; // combine 'nie' (marked with $alt2) with some 1-syllable (and 2-syllable) words (marked with $alt)
SetLetterVowel(tr, 'y'); SetLetterVowel(tr, 'y');
} }
break;

break;
case L('p', 't'): // Portuguese case L('p', 't'): // Portuguese
{ {
static const short stress_lengths_pt[8] = { 170, 115, 210, 240, 0, 0, 260, 280 }; static const short stress_lengths_pt[8] = { 170, 115, 210, 240, 0, 0, 260, 280 };
tr->langopts.param[LOPT_ALT] = 2; // call ApplySpecialAttributes2() if a word has $alt or $alt2 tr->langopts.param[LOPT_ALT] = 2; // call ApplySpecialAttributes2() if a word has $alt or $alt2
tr->langopts.accents = 2; // 'capital' after letter name tr->langopts.accents = 2; // 'capital' after letter name
} }
break;

break;
case L('r', 'o'): // Romanian case L('r', 'o'): // Romanian
{ {
static const short stress_lengths_ro[8] = { 170, 170, 180, 180, 0, 0, 240, 260 }; static const short stress_lengths_ro[8] = { 170, 170, 180, 180, 0, 0, 240, 260 };
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_DFRACTION_3 | NUM_AND_UNITS | NUM_ROMAN; tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_DFRACTION_3 | NUM_AND_UNITS | NUM_ROMAN;
tr->langopts.numbers2 = 0x1e; // variant numbers before all thousandplex tr->langopts.numbers2 = 0x1e; // variant numbers before all thousandplex
} }
break;

break;
case L('r', 'u'): // Russian case L('r', 'u'): // Russian
Translator_Russian(tr); Translator_Russian(tr);
break; break;

case L('r', 'w'): // Kiryarwanda case L('r', 'w'): // Kiryarwanda
{ {
tr->langopts.stress_rule = STRESSPOSN_2R; tr->langopts.stress_rule = STRESSPOSN_2R;
tr->langopts.numbers = NUM_HUNDRED_AND | NUM_AND_UNITS | NUM_DFRACTION_2 | NUM_AND_HUNDRED; tr->langopts.numbers = NUM_HUNDRED_AND | NUM_AND_UNITS | NUM_DFRACTION_2 | NUM_AND_HUNDRED;
tr->langopts.numbers2 = 0x200; // say "thousands" before its number tr->langopts.numbers2 = 0x200; // say "thousands" before its number
} }
break;

break;
case L('s', 'k'): // Slovak case L('s', 'k'): // Slovak
case L('c', 's'): // Czech case L('c', 's'): // Czech
{ {
ResetLetterBits(tr, 0x20); ResetLetterBits(tr, 0x20);
SetLetterBits(tr, 5, sk_voiced); SetLetterBits(tr, 5, sk_voiced);
} }
break;

break;
case L('s', 'i'): // Sinhala case L('s', 'i'): // Sinhala
{ {
SetupTranslator(tr, stress_lengths_ta, stress_amps_ta); SetupTranslator(tr, stress_lengths_ta, stress_amps_ta);
tr->langopts.numbers2 = NUM2_PERCENT_BEFORE; tr->langopts.numbers2 = NUM2_PERCENT_BEFORE;
tr->langopts.break_numbers = 0x14aa8; // for languages which have numbers for 100,000 and 100,00,000, eg Hindi tr->langopts.break_numbers = 0x14aa8; // for languages which have numbers for 100,000 and 100,00,000, eg Hindi
} }
break;

break;
case L('s', 'l'): // Slovenian case L('s', 'l'): // Slovenian
tr->charset_a0 = charsets[2]; // ISO-8859-2 tr->charset_a0 = charsets[2]; // ISO-8859-2
tr->langopts.stress_rule = STRESSPOSN_2R; // Temporary tr->langopts.stress_rule = STRESSPOSN_2R; // Temporary
tr->langopts.thousands_sep = ' '; // don't allow dot as thousands separator tr->langopts.thousands_sep = ' '; // don't allow dot as thousands separator
tr->langopts.replace_chars = replace_cyrillic_latin; tr->langopts.replace_chars = replace_cyrillic_latin;
break; break;

case L('s', 'q'): // Albanian case L('s', 'q'): // Albanian
{ {
static const short stress_lengths_sq[8] = { 150, 150, 180, 180, 0, 0, 300, 300 }; static const short stress_lengths_sq[8] = { 150, 150, 180, 180, 0, 0, 300, 300 };
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_HUNDRED_AND | NUM_AND_UNITS | NUM_DFRACTION_4; tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_HUNDRED_AND | NUM_AND_UNITS | NUM_DFRACTION_4;
tr->langopts.accents = 2; // "capital" after letter name tr->langopts.accents = 2; // "capital" after letter name
} }
break;


break;
case L('s', 'v'): // Swedish case L('s', 'v'): // Swedish
{ {
static const unsigned char stress_amps_sv[] = { 16, 16, 20, 20, 20, 22, 22, 21 }; static const unsigned char stress_amps_sv[] = { 16, 16, 20, 20, 20, 22, 22, 21 };
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_1900; tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_1900;
tr->langopts.accents = 1; tr->langopts.accents = 1;
} }
break;

break;
case L('s', 'w'): // Swahili case L('s', 'w'): // Swahili
case L('t', 'n'): // Setswana case L('t', 'n'): // Setswana
{ {
tr->langopts.numbers = NUM_AND_UNITS | NUM_HUNDRED_AND | NUM_SINGLE_AND | NUM_OMIT_1_HUNDRED; tr->langopts.numbers = NUM_AND_UNITS | NUM_HUNDRED_AND | NUM_SINGLE_AND | NUM_OMIT_1_HUNDRED;
tr->langopts.break_numbers = 0x49249268; // for languages which have numbers for 100,000 and 1,000,000 tr->langopts.break_numbers = 0x49249268; // for languages which have numbers for 100,000 and 1,000,000
} }
break;

break;
case L('t', 'a'): // Tamil case L('t', 'a'): // Tamil
case L('k', 'n'): // Kannada case L('k', 'n'): // Kannada
case L('m', 'l'): // Malayalam case L('m', 'l'): // Malayalam
SetIndicLetters(tr); // call this after setting OFFSET_ SetIndicLetters(tr); // call this after setting OFFSET_
SetLetterBitsRange(tr, LETTERGP_B, 0x4e, 0x4e); // chillu-virama (unofficial) SetLetterBitsRange(tr, LETTERGP_B, 0x4e, 0x4e); // chillu-virama (unofficial)
} }
break;

break;
case L('t', 'r'): // Turkish case L('t', 'r'): // Turkish
case L('a', 'z'): // Azerbaijan case L('a', 'z'): // Azerbaijan
{ {
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA | NUM_OMIT_1_HUNDRED | NUM_OMIT_1_THOUSAND | NUM_DFRACTION_2; tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA | NUM_OMIT_1_HUNDRED | NUM_OMIT_1_THOUSAND | NUM_DFRACTION_2;
tr->langopts.max_initial_consonants = 2; tr->langopts.max_initial_consonants = 2;
} }
break;

break;
case L('t', 't'): // Tatar case L('t', 't'): // Tatar
{ {
SetCyrillicLetters(tr); SetCyrillicLetters(tr);
tr->langopts.stress_flags = S_NO_AUTO_2; // no automatic secondary stress tr->langopts.stress_flags = S_NO_AUTO_2; // no automatic secondary stress
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA | NUM_OMIT_1_HUNDRED | NUM_OMIT_1_THOUSAND | NUM_DFRACTION_4; tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA | NUM_OMIT_1_HUNDRED | NUM_OMIT_1_THOUSAND | NUM_DFRACTION_4;
} }
break;

break;
case L('u', 'k'): // Ukrainian case L('u', 'k'): // Ukrainian
{ {
SetCyrillicLetters(tr); SetCyrillicLetters(tr);
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 0x432; // [v] don't count this character at start of word tr->langopts.param[LOPT_UNPRONOUNCABLE] = 0x432; // [v] don't count this character at start of word
} }
break;

break;
case L('u', 'r'): // Urdu case L('u', 'r'): // Urdu
case L('s', 'd'): // Sindhi case L('s', 'd'): // Sindhi
{ {
tr->langopts.numbers = NUM_SWAP_TENS; tr->langopts.numbers = NUM_SWAP_TENS;
tr->langopts.break_numbers = 0x52a8; // for languages which have numbers for 100,000 and 100,00,000, eg Hindi tr->langopts.break_numbers = 0x52a8; // for languages which have numbers for 100,000 and 100,00,000, eg Hindi
} }
break;

break;
case L('v', 'i'): // Vietnamese case L('v', 'i'): // Vietnamese
{ {
static const short stress_lengths_vi[8] = { 150, 150, 180, 180, 210, 230, 230, 240 }; static const short stress_lengths_vi[8] = { 150, 150, 180, 180, 210, 230, 230, 240 };
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_HUNDRED_AND_DIGIT | NUM_DFRACTION_4 | NUM_ZERO_HUNDRED; tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_HUNDRED_AND_DIGIT | NUM_DFRACTION_4 | NUM_ZERO_HUNDRED;


} }
break;

break;
case L('w', 'o'): case L('w', 'o'):
tr->langopts.stress_rule = STRESSPOSN_1L; tr->langopts.stress_rule = STRESSPOSN_1L;
tr->langopts.numbers = NUM_AND_UNITS | NUM_HUNDRED_AND | NUM_OMIT_1_HUNDRED | NUM_OMIT_1_THOUSAND | NUM_SINGLE_STRESS; tr->langopts.numbers = NUM_AND_UNITS | NUM_HUNDRED_AND | NUM_OMIT_1_HUNDRED | NUM_OMIT_1_THOUSAND | NUM_SINGLE_STRESS;
break; break;

case L('z', 'h'): case L('z', 'h'):
case L_zhy: case L_zhy:
{ {
tr->langopts.break_numbers = 0x00018; tr->langopts.break_numbers = 0x00018;
} }
} }
break;

break;
default: default:
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words
break; break;
return tr; return tr;
} }



void ProcessLanguageOptions(LANGUAGE_OPTIONS *langopts) void ProcessLanguageOptions(LANGUAGE_OPTIONS *langopts)
{ {
if (langopts->numbers & NUM_DECIMAL_COMMA) { if (langopts->numbers & NUM_DECIMAL_COMMA) {
langopts->thousands_sep = 0; // don't allow thousands separator, except space langopts->thousands_sep = 0; // don't allow thousands separator, except space
} }



static void Translator_Russian(Translator *tr) static void Translator_Russian(Translator *tr)
{ {
static const unsigned char stress_amps_ru[] = { 16, 16, 18, 18, 20, 24, 24, 22 }; static const unsigned char stress_amps_ru[] = { 16, 16, 18, 18, 20, 24, 24, 22 };
tr->langopts.numbers2 = 0x2 + NUM2_THOUSANDS_VAR1; // variant numbers before thousands tr->langopts.numbers2 = 0x2 + NUM2_THOUSANDS_VAR1; // variant numbers before thousands
tr->langopts.phoneme_change = 1; tr->langopts.phoneme_change = 1;
tr->langopts.testing = 2; tr->langopts.testing = 2;

} }

+ 0
- 58
src/libespeak-ng/translate.c View File



#define WORD_STRESS_CHAR '*' #define WORD_STRESS_CHAR '*'



Translator *translator = NULL; // the main translator Translator *translator = NULL; // the main translator
Translator *translator2 = NULL; // secondary translator for certain words Translator *translator2 = NULL; // secondary translator for certain words
static char translator2_language[20] = { 0 }; static char translator2_language[20] = { 0 };
int pre_pause; int pre_pause;
ALPHABET *current_alphabet; ALPHABET *current_alphabet;



// these were previously in translator class // these were previously in translator class
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
char word_phonemes[N_WORD_PHONEMES*2]; // longer, because snprint() is not available char word_phonemes[N_WORD_PHONEMES*2]; // longer, because snprint() is not available
int n_ph_list2; int n_ph_list2;
PHONEME_LIST2 ph_list2[N_PHONEME_LIST]; // first stage of text->phonemes PHONEME_LIST2 ph_list2[N_PHONEME_LIST]; // first stage of text->phonemes




wchar_t option_punctlist[N_PUNCTLIST] = { 0 }; wchar_t option_punctlist[N_PUNCTLIST] = { 0 };
char ctrl_embedded = '\001'; // to allow an alternative CTRL for embedded commands char ctrl_embedded = '\001'; // to allow an alternative CTRL for embedded commands
int option_multibyte = espeakCHARS_AUTO; // 0=auto, 1=utf8, 2=8bit, 3=wchar, 4=16bit int option_multibyte = espeakCHARS_AUTO; // 0=auto, 1=utf8, 2=8bit, 3=wchar, 4=16bit
int n_replace_phonemes; int n_replace_phonemes;
REPLACE_PHONEMES replace_phonemes[N_REPLACE_PHONEMES]; REPLACE_PHONEMES replace_phonemes[N_REPLACE_PHONEMES];



// brackets, also 0x2014 to 0x021f which don't need to be in this list // brackets, also 0x2014 to 0x021f which don't need to be in this list
static const unsigned short brackets[] = { static const unsigned short brackets[] = {
'(', ')', '[', ']', '{', '}', '<', '>', '"', '\'', '`', '(', ')', '[', ']', '{', '}', '<', '>', '"', '\'', '`',
110, 120, 100, 110, 110, 110, 110, 110, 110, 110 110, 120, 100, 110, 110, 110, 110, 110, 110, 110
}; };



static unsigned char *length_mod_tabs[6] = { static unsigned char *length_mod_tabs[6] = {
length_mods_en, length_mods_en,
length_mods_en, // 1 length_mods_en, // 1
length_mods_equal // 5 length_mods_equal // 5
}; };



void SetLengthMods(Translator *tr, int value) void SetLengthMods(Translator *tr, int value)
{ {
int value2; int value2;
tr->langopts.length_mods0 = length_mod_tabs[value2]; tr->langopts.length_mods0 = length_mod_tabs[value2];
} }




int IsAlpha(unsigned int c) int IsAlpha(unsigned int c)
{ {
// Replacement for iswalph() which also checks for some in-word symbols // Replacement for iswalph() which also checks for some in-word symbols
return iswspace(c); return iswspace(c);
} }



void DeleteTranslator(Translator *tr) void DeleteTranslator(Translator *tr)
{ {
if (tr->data_dictlist != NULL) if (tr->data_dictlist != NULL)
Free(tr); Free(tr);
} }



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 ?
return 0; return 0;
} }



int lookupwchar2(const unsigned short *list, int c) int lookupwchar2(const unsigned short *list, int c)
{ {
// Replace character c by another character. // Replace character c by another character.
return 0; return 0;
} }



int IsBracket(int c) int IsBracket(int c)
{ {
if ((c >= 0x2014) && (c <= 0x201f)) if ((c >= 0x2014) && (c <= 0x201f))
return lookupwchar(brackets, c); return lookupwchar(brackets, c);
} }



int utf8_out(unsigned int c, char *buf) int utf8_out(unsigned int c, char *buf)
{ {
// write a unicode character into a buffer as utf8 // write a unicode character into a buffer as utf8
return n_bytes+1; return n_bytes+1;
} }



int utf8_nbytes(const char *buf) int utf8_nbytes(const char *buf)
{ {
// Returns the number of bytes for the first UTF-8 character in buf // Returns the number of bytes for the first UTF-8 character in buf
return 4; return 4;
} }



int utf8_in2(int *c, const char *buf, int backwards) int utf8_in2(int *c, const char *buf, int backwards)
{ {
// Read a unicode characater from a UTF8 string // Read a unicode characater from a UTF8 string
return n_bytes+1; return n_bytes+1;
} }



#pragma GCC visibility push(default) #pragma GCC visibility push(default)
int utf8_in(int *c, const char *buf) int utf8_in(int *c, const char *buf)
{ {
} }
#pragma GCC visibility pop #pragma GCC visibility pop



char *strchr_w(const char *s, int c) char *strchr_w(const char *s, int c)
{ {
// return NULL for any non-ascii character // return NULL for any non-ascii character
return strchr((char *)s, c); // (char *) is needed for Borland compiler return strchr((char *)s, c); // (char *) is needed for Borland compiler
} }



int IsAllUpper(const char *word) int IsAllUpper(const char *word)
{ {
int c; int c;
return 1; return 1;
} }



static char *SpeakIndividualLetters(Translator *tr, char *word, char *phonemes, int spell_word) static char *SpeakIndividualLetters(Translator *tr, char *word, char *phonemes, int spell_word)
{ {
int posn = 0; int posn = 0;
return word; return word;
} }




static int CheckDottedAbbrev(char *word1, WORD_TAB *wtab) static int CheckDottedAbbrev(char *word1, WORD_TAB *wtab)
{ {
int wc; int wc;
return count; return count;
} }



extern char *phondata_ptr; extern char *phondata_ptr;


int ChangeEquivalentPhonemes(Translator *tr, int lang2, char *phonemes) int ChangeEquivalentPhonemes(Translator *tr, int lang2, char *phonemes)
return 1; return 1;
} }





int TranslateWord(Translator *tr, char *word_start, int next_pause, WORD_TAB *wtab, char *word_out) int TranslateWord(Translator *tr, char *word_start, int next_pause, WORD_TAB *wtab, char *word_out)
{ {
// word1 is terminated by space (0x20) character // word1 is terminated by space (0x20) character
if (!found) if (!found)
found = LookupDictList(tr, &word1, phonemes, dictionary_flags, FLAG_ALLOW_TEXTMODE, wtab); // the original word found = LookupDictList(tr, &word1, phonemes, dictionary_flags, FLAG_ALLOW_TEXTMODE, wtab); // the original word



if ((dictionary_flags[0] & (FLAG_ALLOW_DOT | FLAG_NEEDS_DOT)) && (wordx[1] == '.')) if ((dictionary_flags[0] & (FLAG_ALLOW_DOT | FLAG_NEEDS_DOT)) && (wordx[1] == '.'))
wordx[1] = ' '; // remove a Dot after this word wordx[1] = ' '; // remove a Dot after this word


} }
} }



// if textmode, LookupDictList() replaces word1 by the new text and returns found=0 // if textmode, LookupDictList() replaces word1 by the new text and returns found=0


if (phonemes[0] == phonSWITCH) { if (phonemes[0] == phonSWITCH) {
} }
} }





if ((end_type != 0) && !(end_type & SUFX_P)) { if ((end_type != 0) && !(end_type & SUFX_P)) {
end_type1 = end_type; end_type1 = end_type;
strcpy(phonemes2, phonemes); strcpy(phonemes2, phonemes);
memcpy(wordx, word_copy, strlen(word_copy)); memcpy(wordx, word_copy, strlen(word_copy));
} }





wordx[-1] = c_temp; wordx[-1] = c_temp;
} }
} }


wflags |= emphasize_allcaps; wflags |= emphasize_allcaps;



/* determine stress pattern for this word */ /* determine stress pattern for this word */
/******************************************/ /******************************************/
add_suffix_phonemes = 0; add_suffix_phonemes = 0;
ChangeWordStress(tr, word_phonemes, 3); ChangeWordStress(tr, word_phonemes, 3);
} }



// dictionary flags for this word give a clue about which alternative pronunciations of // dictionary flags for this word give a clue about which alternative pronunciations of
// following words to use. // following words to use.
if (end_type1 & SUFX_F) { if (end_type1 & SUFX_F) {
return dictionary_flags[0]; return dictionary_flags[0];
} }




static void SetPlist2(PHONEME_LIST2 *p, unsigned char phcode) static void SetPlist2(PHONEME_LIST2 *p, unsigned char phcode)
{ {
p->phcode = phcode; p->phcode = phcode;
return count; return count;
} }



void Word_EmbeddedCmd() void Word_EmbeddedCmd()
{ {
// Process embedded commands for emphasis, sayas, and break // Process embedded commands for emphasis, sayas, and break
} while (((embedded_cmd & 0x80) == 0) && (embedded_read < embedded_ix)); } while (((embedded_cmd & 0x80) == 0) && (embedded_read < embedded_ix));
} }



int SetTranslator2(const char *new_language) int SetTranslator2(const char *new_language)
{ {
// Set translator2 to a second language // Set translator2 to a second language
return new_phoneme_tab; return new_phoneme_tab;
} }




static int TranslateWord2(Translator *tr, char *word, WORD_TAB *wtab, int pre_pause, int next_pause) static int TranslateWord2(Translator *tr, char *word, WORD_TAB *wtab, int pre_pause, int next_pause)
{ {
int flags = 0; int flags = 0;
return flags; return flags;
} }




static int EmbeddedCommand(unsigned int *source_index_out) static int EmbeddedCommand(unsigned int *source_index_out)
{ {
// An embedded command to change the pitch, volume, etc. // An embedded command to change the pitch, volume, etc.
return 1; return 1;
} }




static int SubstituteChar(Translator *tr, unsigned int c, unsigned int next_in, int *insert, int *wordflags) static int SubstituteChar(Translator *tr, unsigned int c, unsigned int next_in, int *insert, int *wordflags)
{ {
int ix; int ix;


*wordflags |= FLAG_CHAR_REPLACED; *wordflags |= FLAG_CHAR_REPLACED;
return new_c; return new_c;

} }



static int TranslateChar(Translator *tr, char *ptr, int prev_in, unsigned int c, unsigned int next_in, int *insert, int *wordflags) static int TranslateChar(Translator *tr, char *ptr, int prev_in, unsigned int c, unsigned int next_in, int *insert, int *wordflags)
{ {
// To allow language specific examination and replacement of characters // To allow language specific examination and replacement of characters
case L('n', 'l'): case L('n', 'l'):
// look for 'n and replace by a special character (unicode: schwa) // look for 'n and replace by a special character (unicode: schwa)



if (!iswalpha2(prev_in)) { if (!iswalpha2(prev_in)) {
utf8_in(&next2, &ptr[1]); utf8_in(&next2, &ptr[1]);


return SubstituteChar(tr, c, next_in, insert, wordflags); return SubstituteChar(tr, c, next_in, insert, wordflags);
} }



static const char *UCase_ga[] = { "bp", "bhf", "dt", "gc", "hA", "mb", "nd", "ng", "ts", "tA", "nA", NULL }; static const char *UCase_ga[] = { "bp", "bhf", "dt", "gc", "hA", "mb", "nd", "ng", "ts", "tA", "nA", NULL };


int UpperCaseInWord(Translator *tr, char *word, int c) int UpperCaseInWord(Translator *tr, char *word, int c)
return 0; return 0;
} }



void *TranslateClause(Translator *tr, FILE *f_text, const void *vp_input, int *tone_out, char **voice_change) void *TranslateClause(Translator *tr, FILE *f_text, const void *vp_input, int *tone_out, char **voice_change)
{ {
int ix; int ix;
} }
words[0].flags |= FLAG_FIRST_WORD; words[0].flags |= FLAG_FIRST_WORD;



for (ix = 0; ix < word_count; ix++) { for (ix = 0; ix < word_count; ix++) {
int nx; int nx;
int c_temp; int c_temp;
embedded_list[embedded_ix] = 0x80; embedded_list[embedded_ix] = 0x80;
} }



prev_clause_pause = clause_pause; prev_clause_pause = clause_pause;


if (tone_out != NULL) if (tone_out != NULL)
if (terminator & CLAUSE_BIT_SENTENCE) if (terminator & CLAUSE_BIT_SENTENCE)
new_sentence = 1; // next clause is a new sentence new_sentence = 1; // next clause is a new sentence



if (voice_change != NULL) { if (voice_change != NULL) {
// return new voice name if an embedded voice change command terminated the clause // return new voice name if an embedded voice change command terminated the clause
if (terminator & CLAUSE_BIT_VOICE) if (terminator & CLAUSE_BIT_VOICE)
return (void *)p_textinput; return (void *)p_textinput;
} }






void InitText(int control) void InitText(int control)
{ {
count_sentences = 0; count_sentences = 0;

+ 6
- 103
src/libespeak-ng/voices.c View File

#include "voice.h" #include "voice.h"
#include "translate.h" #include "translate.h"



MNEM_TAB genders[] = { MNEM_TAB genders[] = {
{ "unknown", 0 }, { "unknown", 0 },
{ "male", 1 }, { "male", 1 },
static int formant_rate_22050[9] = { 240, 170, 170, 170, 170, 170, 170, 170, 170 }; // values for 22kHz sample rate static int formant_rate_22050[9] = { 240, 170, 170, 170, 170, 170, 170, 170, 170 }; // values for 22kHz sample rate
int formant_rate[9]; // values adjusted for actual sample rate int formant_rate[9]; // values adjusted for actual sample rate




#define DEFAULT_LANGUAGE_PRIORITY 5 #define DEFAULT_LANGUAGE_PRIORITY 5
#define N_VOICES_LIST 250 #define N_VOICES_LIST 250
static int n_voices_list = 0; static int n_voices_list = 0;


espeak_VOICE current_voice_selected; espeak_VOICE current_voice_selected;



enum { enum {
V_NAME = 1, V_NAME = 1,
V_LANGUAGE, V_LANGUAGE,
V_CONSONANTS V_CONSONANTS
}; };




static MNEM_TAB options_tab[] = { static MNEM_TAB options_tab[] = {
{ "reduce_t", LOPT_REDUCE_T }, { "reduce_t", LOPT_REDUCE_T },
{ "bracket", LOPT_BRACKET_PAUSE }, { "bracket", LOPT_BRACKET_PAUSE },
{ NULL, 0 } { NULL, 0 }
}; };



#define N_VOICE_VARIANTS 12 #define N_VOICE_VARIANTS 12
const char variants_either[N_VOICE_VARIANTS] = { 1, 2, 12, 3, 13, 4, 14, 5, 11, 0 }; const char variants_either[N_VOICE_VARIANTS] = { 1, 2, 12, 3, 13, 4, 14, 5, 11, 0 };
const char variants_male[N_VOICE_VARIANTS] = { 1, 2, 3, 4, 5, 6, 0 }; const char variants_male[N_VOICE_VARIANTS] = { 1, 2, 3, 4, 5, 6, 0 };
static voice_t voicedata; static voice_t voicedata;
voice_t *voice = &voicedata; voice_t *voice = &voicedata;



static char *fgets_strip(char *buf, int size, FILE *f_in) static char *fgets_strip(char *buf, int size, FILE *f_in)
{ {
// strip trailing spaces, and truncate lines at // comment // strip trailing spaces, and truncate lines at // comment
return buf; return buf;
} }



static int LookupTune(const char *name) static int LookupTune(const char *name)
{ {
int ix; int ix;
return -1; return -1;
} }




static void SetToneAdjust(voice_t *voice, int *tone_pts) static void SetToneAdjust(voice_t *voice, int *tone_pts)
{ {
int ix; int ix;
} }
} }



void ReadTonePoints(char *string, int *tone_pts) void ReadTonePoints(char *string, int *tone_pts)
{ {
// tone_pts[] is int[12] // tone_pts[] is int[12]
&tone_pts[8], &tone_pts[9]); &tone_pts[8], &tone_pts[9]);
} }





static espeak_VOICE *ReadVoiceFile(FILE *f_in, const char *fname, const char *leafname) static espeak_VOICE *ReadVoiceFile(FILE *f_in, const char *fname, const char *leafname)
{ {
// Read a Voice file, allocate a VOICE_DATA and set data from the // Read a Voice file, allocate a VOICE_DATA and set data from the
char vlanguage[80]; char vlanguage[80];
char languages[300]; // allow space for several alternate language names and priorities char languages[300]; // allow space for several alternate language names and priorities



unsigned int len; unsigned int len;
int langix = 0; int langix = 0;
int n_languages = 0; int n_languages = 0;
return voice_data; return voice_data;
} }





void VoiceReset(int tone_only) void VoiceReset(int tone_only)
{ {
// Set voice to the default values // Set voice to the default values
} }
} }



static void VoiceFormant(char *p) static void VoiceFormant(char *p)
{ {
// Set parameters for a formant // Set parameters for a formant
voice->freqadd[formant] = freqadd; voice->freqadd[formant] = freqadd;
} }






static void PhonemeReplacement(int type, char *p) static void PhonemeReplacement(int type, char *p)
{ {
int n; int n;
replace_phonemes[n_replace_phonemes++].type = flags; replace_phonemes[n_replace_phonemes++].type = flags;
} }




static int Read8Numbers(char *data_in, int *data) static int Read8Numbers(char *data_in, int *data)
{ {
// Read 8 integer numbers // Read 8 integer numbers
&data[0], &data[1], &data[2], &data[3], &data[4], &data[5], &data[6], &data[7]); &data[0], &data[1], &data[2], &data[3], &data[4], &data[5], &data[6], &data[7]);
} }



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')
return value; return value;
} }



voice_t *LoadVoice(const char *vname, int control) voice_t *LoadVoice(const char *vname, int control)
{ {
// control, bit 0 1= no_default // control, bit 0 1= no_default
static const char *voices_europe = static const char *voices_europe =
"an bg bs ca cs cy da de el en en-us es et eu fi fr fr-be ga hr hu is it lt lv mk nl no pl pt-pt ro ru sk sq sr sv "; "an bg bs ca cs cy da de el en en-us es et eu fi fr fr-be ga hr hu is it lt lv mk nl no pl pt-pt ro ru sk sq sr sv ";



strncpy0(voicename, vname, sizeof(voicename)); strncpy0(voicename, vname, sizeof(voicename));
if (control & 0x10) { if (control & 0x10) {
strcpy(buf, vname); strcpy(buf, vname);
strcpy(new_dictionary, language_type); strcpy(new_dictionary, language_type);
strcpy(phonemes_name, language_type); strcpy(phonemes_name, language_type);



if (!tone_only) { if (!tone_only) {
voice = &voicedata; voice = &voicedata;
strncpy0(voice_identifier, vname, sizeof(voice_identifier)); strncpy0(voice_identifier, vname, sizeof(voice_identifier));
if (!tone_only) if (!tone_only)
SelectPhonemeTableName(phonemes_name); // set up phoneme_tab SelectPhonemeTableName(phonemes_name); // set up phoneme_tab



while ((f_voice != NULL) && (fgets_strip(buf, sizeof(buf), f_voice) != NULL)) { while ((f_voice != NULL) && (fgets_strip(buf, sizeof(buf), f_voice) != NULL)) {
// isolate the attribute name // isolate the attribute name
for (p = buf; (*p != 0) && !isspace(*p); p++) ; for (p = buf; (*p != 0) && !isspace(*p); p++) ;
strncpy0(voice->language_name, language_name, sizeof(voice->language_name)); strncpy0(voice->language_name, language_name, sizeof(voice->language_name));
} }
} }
break;

break;
case V_NAME: case V_NAME:
if (tone_only == 0) { if (tone_only == 0) {
while (isspace(*p)) p++; while (isspace(*p)) p++;
strncpy0(voice_name, p, sizeof(voice_name)); strncpy0(voice_name, p, sizeof(voice_name));
} }
break; break;

case V_GENDER: case V_GENDER:
{ {
int age = 0; int age = 0;
current_voice_selected.gender = LookupMnem(genders, vgender); current_voice_selected.gender = LookupMnem(genders, vgender);
current_voice_selected.age = age; current_voice_selected.age = age;
} }
break;

break;
case V_TRANSLATOR: case V_TRANSLATOR:
if (tone_only) break; if (tone_only) break;


new_translator = SelectTranslator(translator_name); new_translator = SelectTranslator(translator_name);
langopts = &new_translator->langopts; langopts = &new_translator->langopts;
break; break;

case V_DICTIONARY: // dictionary case V_DICTIONARY: // dictionary
sscanf(p, "%s", new_dictionary); sscanf(p, "%s", new_dictionary);
break; break;

case V_PHONEMES: // phoneme table case V_PHONEMES: // phoneme table
sscanf(p, "%s", phonemes_name); sscanf(p, "%s", phonemes_name);
break; break;

case V_FORMANT: case V_FORMANT:
VoiceFormant(p); VoiceFormant(p);
break; break;

case V_PITCH: case V_PITCH:
{ {
double factor; double factor;
factor = (double)(pitch1 - 82)/82; factor = (double)(pitch1 - 82)/82;
voice->formant_factor = (int)((1+factor/4) * 256); // nominal formant shift for a different voice pitch voice->formant_factor = (int)((1+factor/4) * 256); // nominal formant shift for a different voice pitch
} }
break;

break;
case V_STRESSLENGTH: // stressLength case V_STRESSLENGTH: // stressLength
stress_lengths_set = Read8Numbers(p, stress_lengths); stress_lengths_set = Read8Numbers(p, stress_lengths);
break; break;

case V_STRESSAMP: // stressAmp case V_STRESSAMP: // stressAmp
stress_amps_set = Read8Numbers(p, stress_amps); stress_amps_set = Read8Numbers(p, stress_amps);
break; break;

case V_STRESSADD: // stressAdd case V_STRESSADD: // stressAdd
stress_add_set = Read8Numbers(p, stress_add); stress_add_set = Read8Numbers(p, stress_add);
break; break;

case V_INTONATION: // intonation case V_INTONATION: // intonation
sscanf(p, "%d %d", &option_tone_flags, &option_tone2); sscanf(p, "%d %d", &option_tone_flags, &option_tone2);
if ((option_tone_flags & 0xff) != 0) if ((option_tone_flags & 0xff) != 0)
langopts->intonation_group = option_tone_flags & 0xff; langopts->intonation_group = option_tone_flags & 0xff;
break; break;

case V_TUNES: case V_TUNES:
n = sscanf(p, "%s %s %s %s %s %s", names[0], names[1], names[2], names[3], names[4], names[5]); n = sscanf(p, "%s %s %s %s %s %s", names[0], names[1], names[2], names[3], names[4], names[5]);
langopts->intonation_group = 0; langopts->intonation_group = 0;
langopts->tunes[ix] = value; langopts->tunes[ix] = value;
} }
break; break;

case V_DICTRULES: // conditional dictionary rules and list entries case V_DICTRULES: // conditional dictionary rules and list entries
case V_NUMBERS: case V_NUMBERS:
case V_STRESSOPT: case V_STRESSOPT:
} }
ProcessLanguageOptions(langopts); ProcessLanguageOptions(langopts);
break; break;

case V_REPLACE: case V_REPLACE:
if (phonemes_set == 0) { if (phonemes_set == 0) {
// must set up a phoneme table before we can lookup phoneme mnemonics // must set up a phoneme table before we can lookup phoneme mnemonics
} }
PhonemeReplacement(key, p); PhonemeReplacement(key, p);
break; break;

case V_WORDGAP: // words case V_WORDGAP: // words
sscanf(p, "%d %d", &langopts->word_gap, &langopts->vowel_pause); sscanf(p, "%d %d", &langopts->word_gap, &langopts->vowel_pause);
break; break;

case V_STRESSRULE: case V_STRESSRULE:
sscanf(p, "%d %d %d %d", &langopts->stress_rule, sscanf(p, "%d %d %d %d", &langopts->stress_rule,
&langopts->stress_flags, &langopts->stress_flags,
&langopts->unstressed_wd1, &langopts->unstressed_wd1,
&langopts->unstressed_wd2); &langopts->unstressed_wd2);
break; break;

case V_CHARSET: case V_CHARSET:
if ((sscanf(p, "%d", &value) == 1) && (value < N_CHARSETS)) if ((sscanf(p, "%d", &value) == 1) && (value < N_CHARSETS))
new_translator->charset_a0 = charsets[value]; new_translator->charset_a0 = charsets[value];
break; break;

case V_OPTION: case V_OPTION:
value2 = 0; value2 = 0;
if (((sscanf(p, "%s %d %d", option_name, &value, &value2) >= 2) && ((ix = LookupMnem(options_tab, option_name)) >= 0)) || if (((sscanf(p, "%s %d %d", option_name, &value, &value2) >= 2) && ((ix = LookupMnem(options_tab, option_name)) >= 0)) ||
} else } else
fprintf(stderr, "Bad voice option: %s %s\n", buf, p); fprintf(stderr, "Bad voice option: %s %s\n", buf, p);
break; break;

case V_ECHO: case V_ECHO:
// echo. suggest: 135mS 11% // echo. suggest: 135mS 11%
value = 0; value = 0;
voice->echo_amp = 0; voice->echo_amp = 0;
sscanf(p, "%d %d", &voice->echo_delay, &voice->echo_amp); sscanf(p, "%d %d", &voice->echo_delay, &voice->echo_amp);
break; break;

case V_FLUTTER: // flutter case V_FLUTTER: // flutter
if (sscanf(p, "%d", &value) == 1) if (sscanf(p, "%d", &value) == 1)
voice->flutter = value * 32; voice->flutter = value * 32;
break; break;

case V_ROUGHNESS: // roughness case V_ROUGHNESS: // roughness
if (sscanf(p, "%d", &value) == 1) if (sscanf(p, "%d", &value) == 1)
voice->roughness = value; voice->roughness = value;
break; break;

case V_CLARITY: // formantshape case V_CLARITY: // formantshape
if (sscanf(p, "%d", &value) == 1) { if (sscanf(p, "%d", &value) == 1) {
if (value > 4) { if (value > 4) {
voice->n_harmonic_peaks = 1+value; voice->n_harmonic_peaks = 1+value;
} }
break; break;

case V_TONE: case V_TONE:
{ {
int tone_data[12]; int tone_data[12];
ReadTonePoints(p, tone_data); ReadTonePoints(p, tone_data);
SetToneAdjust(voice, tone_data); SetToneAdjust(voice, tone_data);
} }
break;

break;
case V_VOICING: case V_VOICING:
if (sscanf(p, "%d", &value) == 1) if (sscanf(p, "%d", &value) == 1)
voice->voicing = (value * 64)/100; voice->voicing = (value * 64)/100;
break; break;

case V_BREATH: case V_BREATH:
voice->breath[0] = Read8Numbers(p, &voice->breath[1]); voice->breath[0] = Read8Numbers(p, &voice->breath[1]);
for (ix = 1; ix < 8; ix++) { for (ix = 1; ix < 8; ix++) {
voice->breath[ix] = -voice->breath[ix]; voice->breath[ix] = -voice->breath[ix];
} }
break; break;

case V_BREATHW: case V_BREATHW:
voice->breathw[0] = Read8Numbers(p, &voice->breathw[1]); voice->breathw[0] = Read8Numbers(p, &voice->breathw[1]);
break; break;

case V_CONSONANTS: case V_CONSONANTS:
value = sscanf(p, "%d %d", &voice->consonant_amp, &voice->consonant_ampv); value = sscanf(p, "%d %d", &voice->consonant_amp, &voice->consonant_ampv);
break; break;

case V_SPEED: case V_SPEED:
sscanf(p, "%d", &voice->speed_percent); sscanf(p, "%d", &voice->speed_percent);
break; break;

case V_MBROLA: case V_MBROLA:
{ {
int srate = 16000; int srate = 16000;
} }
voice->samplerate = srate; voice->samplerate = srate;
} }
break;

break;
case V_KLATT: case V_KLATT:
voice->klattv[0] = 1; // default source: IMPULSIVE voice->klattv[0] = 1; // default source: IMPULSIVE
Read8Numbers(p, voice->klattv); Read8Numbers(p, voice->klattv);
voice->klattv[KLATT_Kopen] -= 40; voice->klattv[KLATT_Kopen] -= 40;
break; break;

case V_FAST: case V_FAST:
Read8Numbers(p, speed.fast_settings); Read8Numbers(p, speed.fast_settings);
SetSpeed(3); SetSpeed(3);
break; break;

case V_DICTMIN: case V_DICTMIN:
sscanf(p, "%d", &dict_min); sscanf(p, "%d", &dict_min);
break; break;

case V_ALPHABET2: case V_ALPHABET2:
{ {
ALPHABET *alphabet; ALPHABET *alphabet;
} else } else
fprintf(stderr, "alphabet name '%s' not found\n", name1); fprintf(stderr, "alphabet name '%s' not found\n", name1);
} }
break;

break;
case V_DICTDIALECT: case V_DICTDIALECT:
// specify a dialect to use for foreign words, eg, en-us for _^_EN // specify a dialect to use for foreign words, eg, en-us for _^_EN
if (sscanf(p, "%s", name1) == 1) { if (sscanf(p, "%s", name1) == 1) {
fprintf(stderr, "dictdialect name '%s' not recognized\n", name1); fprintf(stderr, "dictdialect name '%s' not recognized\n", name1);
} }
break; break;

default: default:
if ((key & 0xff00) == 0x100) if ((key & 0xff00) == 0x100)
sscanf(p, "%d", &langopts->param[key &0xff]); sscanf(p, "%d", &langopts->param[key &0xff]);
return voice; return voice;
} }



static char *ExtractVoiceVariantName(char *vname, int variant_num, int add_dir) static char *ExtractVoiceVariantName(char *vname, int variant_num, int add_dir)
{ {
// Remove any voice variant suffix (name or number) from a voice name // Remove any voice variant suffix (name or number) from a voice name
return variant_name; return variant_name;
} }




voice_t *LoadVoiceVariant(const char *vname, int variant_num) voice_t *LoadVoiceVariant(const char *vname, int variant_num)
{ {
// Load a voice file. // Load a voice file.
return v; return v;
} }




static int __cdecl VoiceNameSorter(const void *p1, const void *p2) static int __cdecl VoiceNameSorter(const void *p1, const void *p2)
{ {
int ix; int ix;
espeak_VOICE *v1 = *(espeak_VOICE **)p1; espeak_VOICE *v1 = *(espeak_VOICE **)p1;
espeak_VOICE *v2 = *(espeak_VOICE **)p2; espeak_VOICE *v2 = *(espeak_VOICE **)p2;



if ((ix = strcmp(&v1->languages[1], &v2->languages[1])) != 0) // primary language name if ((ix = strcmp(&v1->languages[1], &v2->languages[1])) != 0) // primary language name
return ix; return ix;
if ((ix = v1->languages[0] - v2->languages[0]) != 0) // priority number if ((ix = v1->languages[0] - v2->languages[0]) != 0) // priority number
return strcmp(v1->name, v2->name); return strcmp(v1->name, v2->name);
} }



static int __cdecl VoiceScoreSorter(const void *p1, const void *p2) static int __cdecl VoiceScoreSorter(const void *p1, const void *p2)
{ {
int ix; int ix;
return strcmp(v1->name, v2->name); return strcmp(v1->name, v2->name);
} }



static int ScoreVoice(espeak_VOICE *voice_spec, const char *spec_language, int spec_n_parts, int spec_lang_len, espeak_VOICE *voice) static int ScoreVoice(espeak_VOICE *voice_spec, const char *spec_language, int spec_n_parts, int spec_lang_len, espeak_VOICE *voice)
{ {
int ix; int ix;
return score; return score;
} }



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
language[lang_len] = 0; language[lang_len] = 0;
n_parts = -1; n_parts = -1;
} }

} }


// select those voices which match the specified language // select those voices which match the specified language
return nv; return nv;
} }





espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name2) espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name2)
{ {
int ix; int ix;
return voices[match_name]; return voices[match_name];
} }





char const *SelectVoice(espeak_VOICE *voice_select, int *found) char const *SelectVoice(espeak_VOICE *voice_select, int *found)
{ {
// Returns a path within espeak-voices, with a possible +variant suffix // Returns a path within espeak-voices, with a possible +variant suffix
return vp->identifier; return vp->identifier;
} }




static void GetVoices(const char *path) static void GetVoices(const char *path)
{ {
FILE *f_voice; FILE *f_voice;
} }
} while (FindNextFileA(hFind, &FindFileData) != 0); } while (FindNextFileA(hFind, &FindFileData) != 0);
FindClose(hFind); FindClose(hFind);

#else #else
DIR *dir; DIR *dir;
struct dirent *ent; struct dirent *ent;
#endif #endif
} }




espeak_ERROR SetVoiceByName(const char *name) espeak_ERROR SetVoiceByName(const char *name)
{ {
espeak_VOICE *v; espeak_VOICE *v;
return EE_INTERNAL_ERROR; // voice name not found return EE_INTERNAL_ERROR; // voice name not found
} }




espeak_ERROR SetVoiceByProperties(espeak_VOICE *voice_selector) espeak_ERROR SetVoiceByProperties(espeak_VOICE *voice_selector)
{ {
const char *voice_id; const char *voice_id;
return EE_OK; return EE_OK;
} }



void FreeVoiceList() void FreeVoiceList()
{ {
int ix; int ix;
n_voices_list = 0; n_voices_list = 0;
} }



#pragma GCC visibility push(default) #pragma GCC visibility push(default)



ESPEAK_API const espeak_VOICE **espeak_ListVoices(espeak_VOICE *voice_spec) ESPEAK_API const espeak_VOICE **espeak_ListVoices(espeak_VOICE *voice_spec)
{ {
char path_voices[sizeof(path_home)+12]; char path_voices[sizeof(path_home)+12];



#ifdef PLATFORM_RISCOS #ifdef PLATFORM_RISCOS
if (n_voices_list == 0) { if (n_voices_list == 0) {
sprintf(path_voices, "%s%cvoices", path_home, PATHSEP); sprintf(path_voices, "%s%cvoices", path_home, PATHSEP);
voices_list[n_voices_list] = NULL; // voices list terminator voices_list[n_voices_list] = NULL; // voices list terminator
} }
return (const espeak_VOICE **)voices_list; return (const espeak_VOICE **)voices_list;

#else #else
int ix; int ix;
int j; int j;
qsort(voices_list, n_voices_list, sizeof(espeak_VOICE *), qsort(voices_list, n_voices_list, sizeof(espeak_VOICE *),
(int(__cdecl *)(const void *, const void *))VoiceNameSorter); (int(__cdecl *)(const void *, const void *))VoiceNameSorter);



if (voice_spec) { if (voice_spec) {
// select the voices which match the voice_spec, and sort them by preference // select the voices which match the voice_spec, and sort them by preference
SetVoiceScores(voice_spec, voices, 1); SetVoiceScores(voice_spec, voices, 1);
#endif #endif
} }




ESPEAK_API espeak_VOICE *espeak_GetCurrentVoice(void) ESPEAK_API espeak_VOICE *espeak_GetCurrentVoice(void)
{ {
return &current_voice_selected; return &current_voice_selected;

+ 0
- 12
src/libespeak-ng/wave.c View File

}; };
#endif /* HAVE_STRUCT_TIMESPEC */ #endif /* HAVE_STRUCT_TIMESPEC */



enum { ONE_BILLION = 1000000000 }; enum { ONE_BILLION = 1000000000 };


#ifdef USE_PORTAUDIO #ifdef USE_PORTAUDIO
#define USE_PORTAUDIO 18 #define USE_PORTAUDIO 18
#endif #endif





#ifdef USE_PULSEAUDIO #ifdef USE_PULSEAUDIO
// create some wrappers for runtime detection // create some wrappers for runtime detection




#endif // USE_PULSEAUDIO #endif // USE_PULSEAUDIO



static t_wave_callback *my_callback_is_output_enabled = NULL; static t_wave_callback *my_callback_is_output_enabled = NULL;


#define N_WAV_BUF 10 #define N_WAV_BUF 10
return aResult; return aResult;
} }



void wave_flush(void *theHandler) void wave_flush(void *theHandler)
{ {
ENTER("wave_flush"); ENTER("wave_flush");
out_channels = 1; out_channels = 1;


#if USE_PORTAUDIO == 18 #if USE_PORTAUDIO == 18

PaDeviceID playbackDevice = Pa_GetDefaultOutputDeviceID(); PaDeviceID playbackDevice = Pa_GetDefaultOutputDeviceID();


PaError err = Pa_OpenStream(&pa_stream, PaError err = Pa_OpenStream(&pa_stream,


SHOW("wave_is_busy: %d\n", active); SHOW("wave_is_busy: %d\n", active);



return active == 1; return active == 1;
} }


ENTER("wave_terminate"); ENTER("wave_terminate");


Pa_Terminate(); Pa_Terminate();

} }


uint32_t wave_get_read_position(void *theHandler) uint32_t wave_get_read_position(void *theHandler)
return myWrite; return myWrite;
} }



#else #else



int wave_init(int srate) { int wave_init(int srate) {
return 1; return 1;
} }
ts->tv_nsec = (long int)t_ns; ts->tv_nsec = (long int)t_ns;
} }



#endif // USE_ASYNC #endif // USE_ASYNC

+ 0
- 18
src/libespeak-ng/wave_pulse.c View File

case PA_CONTEXT_FAILED: case PA_CONTEXT_FAILED:
pa_threaded_mainloop_signal(mainloop, 0); pa_threaded_mainloop_signal(mainloop, 0);
break; break;

case PA_CONTEXT_UNCONNECTED: case PA_CONTEXT_UNCONNECTED:
case PA_CONTEXT_CONNECTING: case PA_CONTEXT_CONNECTING:
case PA_CONTEXT_AUTHORIZING: case PA_CONTEXT_AUTHORIZING:


switch (pa_stream_get_state(s)) switch (pa_stream_get_state(s))
{ {

case PA_STREAM_READY: case PA_STREAM_READY:
case PA_STREAM_FAILED: case PA_STREAM_FAILED:
case PA_STREAM_TERMINATED: case PA_STREAM_TERMINATED:
pa_threaded_mainloop_signal(mainloop, 0); pa_threaded_mainloop_signal(mainloop, 0);
break; break;

case PA_STREAM_UNCONNECTED: case PA_STREAM_UNCONNECTED:
case PA_STREAM_CREATING: case PA_STREAM_CREATING:
break; break;
static void pulse_write(void *ptr, int length) { static void pulse_write(void *ptr, int length) {
ENTER(__FUNCTION__); ENTER(__FUNCTION__);



SHOW("pulse_write > length=%d\n", length); SHOW("pulse_write > length=%d\n", length);


CHECK_CONNECTED_NO_RETVAL(); CHECK_CONNECTED_NO_RETVAL();


do_trigger = 0; do_trigger = 0;
written += length; written += length;

fail: fail:

pa_threaded_mainloop_unlock(mainloop); pa_threaded_mainloop_unlock(mainloop);
} }


SHOW("pa_stream_drain() failed: %s\n", pa_strerror(pa_context_errno(context))); SHOW("pa_stream_drain() failed: %s\n", pa_strerror(pa_context_errno(context)));
else else
ret = PULSE_OK; ret = PULSE_OK;

fail: fail:
SHOW_TIME("pa_operation_unref (call)"); SHOW_TIME("pa_operation_unref (call)");
if (o) if (o)
return ret; return ret;
} }



static void pulse_close(void) { static void pulse_close(void) {


ENTER(__FUNCTION__); ENTER(__FUNCTION__);


} }



static int pulse_open() static int pulse_open()
{ {
ENTER(__FUNCTION__); ENTER(__FUNCTION__);
SHOW_TIME("pulse_open (ret true)"); SHOW_TIME("pulse_open (ret true)");


return PULSE_OK; return PULSE_OK;

unlock_and_fail: unlock_and_fail:

if (o) if (o)
pa_operation_unref(o); pa_operation_unref(o);


pa_threaded_mainloop_unlock(mainloop); pa_threaded_mainloop_unlock(mainloop);

fail: fail:

if (ret == PULSE_NO_CONNECTION) { if (ret == PULSE_NO_CONNECTION) {
if (context) { if (context) {
SHOW_TIME("pa_context_disconnect (call)"); SHOW_TIME("pa_context_disconnect (call)");
SHOW_TIME("pulse_open (ret false)"); SHOW_TIME("pulse_open (ret false)");


return ret; return ret;

} }


void wave_flush(void *theHandler) void wave_flush(void *theHandler)
} }


pulse_write(aBuffer, bytes_to_write); pulse_write(aBuffer, bytes_to_write);

terminate: terminate:
pthread_mutex_unlock(&pulse_mutex); pthread_mutex_unlock(&pulse_mutex);
SHOW("wave_write: theSize=%d", theSize); SHOW("wave_write: theSize=%d", theSize);
return NULL; return NULL;
} }



#else #else



int wave_init(return 1; ) { int wave_init(return 1; ) {
} }
void *wave_open(const char *the_api) { void *wave_open(const char *the_api) {
} }
#endif // ifndef USE_PORTAUDIO #endif // ifndef USE_PORTAUDIO



#endif // USE_ASYNC #endif // USE_ASYNC

+ 0
- 72
src/libespeak-ng/wavegen.c View File

#include <stdint.h> #include <stdint.h>
#endif #endif




#include "speak_lib.h" #include "speak_lib.h"
#include "speech.h" #include "speech.h"
#include "phoneme.h" #include "phoneme.h"
#define N_SINTAB 2048 #define N_SINTAB 2048
#include "sintab.h" #include "sintab.h"



#define PI 3.1415927 #define PI 3.1415927
#define PI2 6.283185307 #define PI2 6.283185307
#define N_WAV_BUF 10 #define N_WAV_BUF 10


static int harm_sqrt_n = 0; static int harm_sqrt_n = 0;



#define N_LOWHARM 30 #define N_LOWHARM 30
static int harm_inc[N_LOWHARM]; // only for these harmonics do we interpolate amplitude between steps static int harm_inc[N_LOWHARM]; // only for these harmonics do we interpolate amplitude between steps
static int *harmspect; static int *harmspect;
static int glottal_flag = 0; static int glottal_flag = 0;
static int glottal_reduce = 0; static int glottal_reduce = 0;



WGEN_DATA wdata; WGEN_DATA wdata;


static int amp_ix; static int amp_ix;
static double minus_pi_t; static double minus_pi_t;
static double two_pi_t; static double two_pi_t;



unsigned char *out_ptr; unsigned char *out_ptr;
unsigned char *out_start; unsigned char *out_start;
unsigned char *out_end; unsigned char *out_end;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}; };



// set from y = pow(2,x) * 128, x=-1 to 1 // set from y = pow(2,x) * 128, x=-1 to 1
unsigned char pitch_adjust_tab[MAX_PITCH_VALUE+1] = { unsigned char pitch_adjust_tab[MAX_PITCH_VALUE+1] = {
64, 65, 66, 67, 68, 69, 70, 71, 64, 65, 66, 67, 68, 69, 70, 71,
242, 246, 249, 252, 254, 255 242, 246, 249, 252, 254, 255
}; };



void WcmdqStop() void WcmdqStop()
{ {
wcmdq_head = 0; wcmdq_head = 0;
MbrolaReset(); MbrolaReset();
} }



int WcmdqFree() int WcmdqFree()
{ {
int i; int i;
return N_WCMDQ - WcmdqFree(); return N_WCMDQ - WcmdqFree();
} }



void WcmdqInc() void WcmdqInc()
{ {
wcmdq_tail++; wcmdq_tail++;
if (wcmdq_head >= N_WCMDQ) wcmdq_head = 0; if (wcmdq_head >= N_WCMDQ) wcmdq_head = 0;
} }




#define PEAKSHAPEW 256 #define PEAKSHAPEW 256


unsigned char pk_shape1[PEAKSHAPEW+1] = { unsigned char pk_shape1[PEAKSHAPEW+1] = {


static unsigned char *pk_shape; static unsigned char *pk_shape;



#ifdef USE_PORTAUDIO #ifdef USE_PORTAUDIO
// PortAudio interface // PortAudio interface


unsigned char *outbuffer = NULL; unsigned char *outbuffer = NULL;
int outbuffer_size = 0; int outbuffer_size = 0;



#if USE_PORTAUDIO == 18 #if USE_PORTAUDIO == 18
static int WaveCallback(void *inputBuffer, void *outputBuffer, static int WaveCallback(void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer, PaTimestamp outTime, void *userData) unsigned long framesPerBuffer, PaTimestamp outTime, void *userData)
#else #else
return result; return result;
#endif #endif

} }



#if USE_PORTAUDIO == 19 #if USE_PORTAUDIO == 19
/* This is a fixed version of Pa_OpenDefaultStream() for use if the version in portaudio V19 /* This is a fixed version of Pa_OpenDefaultStream() for use if the version in portaudio V19
is broken */ is broken */
} }
#endif #endif



int WavegenOpenSound() int WavegenOpenSound()
{ {
PaError err, err2; PaError err, err2;
return 0; return 0;
} }




int WavegenCloseSound() int WavegenCloseSound()
{ {
PaError active; PaError active;
return 0; return 0;
} }



int WavegenInitSound() int WavegenInitSound()
{ {
PaError err; PaError err;
} }
#endif #endif



void WavegenInit(int rate, int wavemult_fact) void WavegenInit(int rate, int wavemult_fact)
{ {
int ix; int ix;
for (ix = 0; ix < N_EMBEDDED_VALUES; ix++) for (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
// single peak for HF peaks // single peak for HF peaks
wavemult_max = (samplerate * wavemult_fact)/(256 * 50); wavemult_max = (samplerate * wavemult_fact)/(256 * 50);
#endif #endif
} }



int GetAmplitude(void) int GetAmplitude(void)
{ {
int amp; int amp;
return general_amplitude; return general_amplitude;
} }



static void WavegenSetEcho(void) static void WavegenSetEcho(void)
{ {
int delay; int delay;
general_amplitude = ((general_amplitude * (500-amp))/500); general_amplitude = ((general_amplitude * (500-amp))/500);
} }




int PeaksToHarmspect(wavegen_peaks_t *peaks, int pitch, int *htab, int control) int PeaksToHarmspect(wavegen_peaks_t *peaks, int pitch, int *htab, int control)
{ {
// Calculate the amplitude of each harmonics from the formants // Calculate the amplitude of each harmonics from the formants
return hmax; // highest harmonic number return hmax; // highest harmonic number
} }




static void AdvanceParameters() static void AdvanceParameters()
{ {
// Called every 64 samples to increment the formant freq, height, and widths // Called every 64 samples to increment the formant freq, height, and widths
#endif #endif
} }



#ifndef PLATFORM_RISCOS #ifndef PLATFORM_RISCOS
static double resonator(RESONATOR *r, double input) static double resonator(RESONATOR *r, double input)
{ {
return x; return x;
} }




static void setresonator(RESONATOR *rp, int freq, int bwidth, int init) static void setresonator(RESONATOR *rp, int freq, int bwidth, int init)
{ {
// freq Frequency of resonator in Hz // freq Frequency of resonator in Hz
} }
#endif #endif



void InitBreath(void) void InitBreath(void)
{ {
#ifndef PLATFORM_RISCOS #ifndef PLATFORM_RISCOS
#endif #endif
} }




static void SetBreath() static void SetBreath()
{ {
#ifndef PLATFORM_RISCOS #ifndef PLATFORM_RISCOS
#endif #endif
} }



static int ApplyBreath(void) static int ApplyBreath(void)
{ {
int value = 0; int value = 0;
return value; return value;
} }




int Wavegen() int Wavegen()
{ {
unsigned short waveph; unsigned short waveph;
return 0; return 0;
} }



static int PlaySilence(int length, int resume) static int PlaySilence(int length, int resume)
{ {
static int n_samples; static int n_samples;
return 0; return 0;
} }




static int PlayWave(int length, int resume, unsigned char *data, int scale, int amp) static int PlayWave(int length, int resume, unsigned char *data, int scale, int amp)
{ {
static int n_samples; static int n_samples;
return 0; return 0;
} }



static int SetWithRange0(int value, int max) static int SetWithRange0(int value, int max)
{ {
if (value < 0) if (value < 0)
return value; return value;
} }



static void SetPitchFormants() static void SetPitchFormants()
{ {
int ix; int ix;
wvoice->height[1] = (wvoice->height2[1] * (256 - factor))/256; wvoice->height[1] = (wvoice->height2[1] * (256 - factor))/256;
} }



void SetEmbedded(int control, int value) void SetEmbedded(int control, int value)
{ {
// there was an embedded command in the text at this point // there was an embedded command in the text at this point
case EMBED_P: case EMBED_P:
SetPitchFormants(); SetPitchFormants();
break; break;

case EMBED_A: // amplitude case EMBED_A: // amplitude
general_amplitude = GetAmplitude(); general_amplitude = GetAmplitude();
break; break;

case EMBED_F: // emphasis case EMBED_F: // emphasis
general_amplitude = GetAmplitude(); general_amplitude = GetAmplitude();
break; break;

case EMBED_H: case EMBED_H:
WavegenSetEcho(); WavegenSetEcho();
break; break;
} }
} }



void WavegenSetVoice(voice_t *v) void WavegenSetVoice(voice_t *v)
{ {
static voice_t v2; static voice_t v2;
MarkerEvent(espeakEVENT_SAMPLERATE, 0, wvoice->samplerate, 0, out_ptr); MarkerEvent(espeakEVENT_SAMPLERATE, 0, wvoice->samplerate, 0, out_ptr);
} }



static void SetAmplitude(int length, unsigned char *amp_env, int value) static void SetAmplitude(int length, unsigned char *amp_env, int value)
{ {
amp_ix = 0; amp_ix = 0;
amplitude_env = amp_env; amplitude_env = amp_env;
} }



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 x;
*pitch_range = base + (pitch2 * range)/2 - *pitch_base; *pitch_range = base + (pitch2 * range)/2 - *pitch_base;
} }



void SetPitch(int length, unsigned char *env, int pitch1, int pitch2) void SetPitch(int length, unsigned char *env, int pitch1, int pitch2)
{ {
// length in samples // length in samples
wdata.pitch = ((wdata.pitch_env[0] * wdata.pitch_range) >>8) + wdata.pitch_base; // Hz << 12 wdata.pitch = ((wdata.pitch_env[0] * wdata.pitch_range) >>8) + wdata.pitch_base; // Hz << 12


flutter_amp = wvoice->flutter; flutter_amp = wvoice->flutter;

} }






void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v) void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v)
{ {
int ix; int ix;
} }
} }



static int Wavegen2(int length, int modulation, int resume, frame_t *fr1, frame_t *fr2) static int Wavegen2(int length, int modulation, int resume, frame_t *fr1, frame_t *fr2)
{ {
if (resume == 0) if (resume == 0)
} }
} }




int WavegenFill2(int fill_zeros) int WavegenFill2(int fill_zeros)
{ {
// Pick up next wavegen commands from the queue // Pick up next wavegen commands from the queue
case WCMD_PITCH: case WCMD_PITCH:
SetPitch(length, (unsigned char *)q[2], q[3] >> 16, q[3] & 0xffff); SetPitch(length, (unsigned char *)q[2], q[3] >> 16, q[3] & 0xffff);
break; break;

case WCMD_PAUSE: case WCMD_PAUSE:
if (resume == 0) if (resume == 0)
echo_complete -= length; echo_complete -= length;
#endif #endif
result = PlaySilence(length, resume); result = PlaySilence(length, resume);
break; break;

case WCMD_WAVE: case WCMD_WAVE:
echo_complete = echo_length; echo_complete = echo_length;
wdata.n_mix_wavefile = 0; wdata.n_mix_wavefile = 0;
#endif #endif
result = PlayWave(length, resume, (unsigned char *)q[2], q[3] & 0xff, q[3] >> 8); result = PlayWave(length, resume, (unsigned char *)q[2], q[3] & 0xff, q[3] >> 8);
break; break;

case WCMD_WAVE2: case WCMD_WAVE2:
// wave file to be played at the same time as synthesis // wave file to be played at the same time as synthesis
wdata.mix_wave_amp = q[3] >> 8; wdata.mix_wave_amp = q[3] >> 8;
wdata.mix_wavefile_offset = 0; wdata.mix_wavefile_offset = 0;
wdata.mix_wavefile = (unsigned char *)q[2]; wdata.mix_wavefile = (unsigned char *)q[2];
break; break;

case WCMD_SPECT2: // as WCMD_SPECT but stop any concurrent wave file case WCMD_SPECT2: // as WCMD_SPECT but stop any concurrent wave file
wdata.n_mix_wavefile = 0; // ... and drop through to WCMD_SPECT case wdata.n_mix_wavefile = 0; // ... and drop through to WCMD_SPECT case
case WCMD_SPECT: case WCMD_SPECT:
echo_complete = echo_length; echo_complete = echo_length;
result = Wavegen2(length & 0xffff, q[1] >> 16, resume, (frame_t *)q[2], (frame_t *)q[3]); result = Wavegen2(length & 0xffff, q[1] >> 16, resume, (frame_t *)q[2], (frame_t *)q[3]);
break; break;

#ifdef INCLUDE_KLATT #ifdef INCLUDE_KLATT
case WCMD_KLATT2: // as WCMD_SPECT but stop any concurrent wave file case WCMD_KLATT2: // as WCMD_SPECT but stop any concurrent wave file
wdata.n_mix_wavefile = 0; // ... and drop through to WCMD_SPECT case wdata.n_mix_wavefile = 0; // ... and drop through to WCMD_SPECT case
result = Wavegen_Klatt2(length & 0xffff, q[1] >> 16, resume, (frame_t *)q[2], (frame_t *)q[3]); result = Wavegen_Klatt2(length & 0xffff, q[1] >> 16, resume, (frame_t *)q[2], (frame_t *)q[3]);
break; break;
#endif #endif

case WCMD_MARKER: case WCMD_MARKER:
marker_type = q[0] >> 8; marker_type = q[0] >> 8;
MarkerEvent(marker_type, q[1], q[2], q[3], out_ptr); MarkerEvent(marker_type, q[1], q[2], q[3], out_ptr);
if (marker_type == 1) // word marker if (marker_type == 1) // word marker
current_source_index = q[1] & 0xffffff; current_source_index = q[1] & 0xffffff;
break; break;

case WCMD_AMPLITUDE: case WCMD_AMPLITUDE:
SetAmplitude(length, (unsigned char *)q[2], q[3]); SetAmplitude(length, (unsigned char *)q[2], q[3]);
break; break;

case WCMD_VOICE: case WCMD_VOICE:
WavegenSetVoice((voice_t *)q[2]); WavegenSetVoice((voice_t *)q[2]);
free((voice_t *)q[2]); free((voice_t *)q[2]);
break; break;

case WCMD_EMBEDDED: case WCMD_EMBEDDED:
SetEmbedded(q[1], q[2]); SetEmbedded(q[1], q[2]);
break; break;

case WCMD_MBROLA_DATA: case WCMD_MBROLA_DATA:
result = MbrolaFill(length, resume, (general_amplitude * wvoice->voicing)/64); result = MbrolaFill(length, resume, (general_amplitude * wvoice->voicing)/64);
break; break;

case WCMD_FMT_AMPLITUDE: case WCMD_FMT_AMPLITUDE:
if ((wdata.amplitude_fmt = q[1]) == 0) if ((wdata.amplitude_fmt = q[1]) == 0)
wdata.amplitude_fmt = 100; // percentage, but value=0 means 100% wdata.amplitude_fmt = 100; // percentage, but value=0 means 100%
break; break;

#if HAVE_SONIC_H #if HAVE_SONIC_H
case WCMD_SONIC_SPEED: case WCMD_SONIC_SPEED:
sonicSpeed = (double)q[1] / 1024; sonicSpeed = (double)q[1] / 1024;
return 0; return 0;
} }



#if HAVE_SONIC_H #if HAVE_SONIC_H
/* Speed up the audio samples with libsonic. */ /* Speed up the audio samples with libsonic. */
static int SpeedUp(short *outbuf, int length_in, int length_out, int end_of_text) static int SpeedUp(short *outbuf, int length_in, int length_out, int end_of_text)
} }
#endif #endif



/* 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)
{ {

+ 0
- 51
src/speak-ng.c View File

#include "voice.h" #include "voice.h"
#include "translate.h" #include "translate.h"




extern void Write4Bytes(FILE *f, int value); extern void Write4Bytes(FILE *f, int value);
char path_home[N_PATH_HOME]; // this is the espeak-data directory char path_home[N_PATH_HOME]; // this is the espeak-data directory


"\t List the available voices for the specified language.\n" "\t List the available voices for the specified language.\n"
"\t If <language> is omitted, then list all voices.\n"; "\t If <language> is omitted, then list all voices.\n";



void DisplayVoices(FILE *f_out, char *language); void DisplayVoices(FILE *f_out, char *language);


USHORT voice_pcnt[N_PEAKS+1][3]; USHORT voice_pcnt[N_PEAKS+1][3];




void DisplayVoices(FILE *f_out, char *language) void DisplayVoices(FILE *f_out, char *language)
{ {
int ix; int ix;
} }
} }



static int OpenWaveFile(const char *path, int rate) static int OpenWaveFile(const char *path, int rate)
{ {
// Set the length of 0x7ffff000 for --stdout // Set the length of 0x7ffff000 for --stdout
return 1; return 1;
} }





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


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

} }





static int WavegenFile(void) static int WavegenFile(void)
{ {
int finished; int finished;
return finished; return finished;
} }




static void init_path(char *argv0, char *path_specified) static void init_path(char *argv0, char *path_specified)
{ {

if (path_specified) { if (path_specified) {
sprintf(path_home, "%s/espeak-data", path_specified); sprintf(path_home, "%s/espeak-data", path_specified);
return; return;
#endif #endif
} }



static int initialise(void) static int initialise(void)
{ {
int param; int param;
} }
#endif #endif



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");
return 0; return 0;
} }




#ifdef NEED_GETOPT #ifdef NEED_GETOPT
struct option { struct option {
char *name; char *name;
if ((sscanf(optarg2, "%d", &value) == 1) && (value <= 4)) if ((sscanf(optarg2, "%d", &value) == 1) && (value <= 4))
option_multibyte = value; option_multibyte = value;
break; break;

case 'h': case 'h':
init_path(argv[0], data_path); init_path(argv[0], data_path);
printf("\nspeak text-to-speech: %s Data at: %s\n%s", version_string, path_home, help_text); printf("\nspeak text-to-speech: %s Data at: %s\n%s", version_string, path_home, help_text);
exit(0); exit(0);

case 'k': case 'k':
option_capitals = atoi(optarg2); option_capitals = atoi(optarg2);
break; break;

case 'x': case 'x':
phoneme_options |= espeakPHONEMES_SHOW; phoneme_options |= espeakPHONEMES_SHOW;
break; break;

case 'X': case 'X':
phoneme_options |= espeakPHONEMES_TRACE; phoneme_options |= espeakPHONEMES_TRACE;
break; break;

case 'm': case 'm':
option_ssml = 1; option_ssml = 1;
break; break;

case 'p': case 'p':
pitch_adjustment = atoi(optarg2); pitch_adjustment = atoi(optarg2);
if (pitch_adjustment > 99) pitch_adjustment = 99; if (pitch_adjustment > 99) pitch_adjustment = 99;
break; break;

case 'q': case 'q':
quiet = 1; quiet = 1;
break; break;

case 'f': case 'f':
strncpy0(filename, optarg2, sizeof(filename)); strncpy0(filename, optarg2, sizeof(filename));
break; break;

case 'l': case 'l':
value = 0; value = 0;
value = atoi(optarg2); value = atoi(optarg2);
option_linelength = value; option_linelength = value;
break; break;

case 'a': case 'a':
amp = atoi(optarg2); amp = atoi(optarg2);
break; break;

case 's': case 's':
speed = atoi(optarg2); speed = atoi(optarg2);
break; break;

case 'g': case 'g':
wordgap = atoi(optarg2); wordgap = atoi(optarg2);
break; break;

case 'v': case 'v':
strncpy0(voicename, optarg2, sizeof(voicename)); strncpy0(voicename, optarg2, sizeof(voicename));
break; break;

case 'w': case 'w':
option_waveout = 1; option_waveout = 1;
strncpy0(wavefile, optarg2, sizeof(wavefile)); strncpy0(wavefile, optarg2, sizeof(wavefile));
break; break;

case 'z': case 'z':
option_endpause = 0; option_endpause = 0;
break; break;

case 0x100: // --stdin case 0x100: // --stdin
flag_stdin = 1; flag_stdin = 1;
break; break;

case 0x105: // --stdout case 0x105: // --stdout
option_waveout = 1; option_waveout = 1;
strcpy(wavefile, "stdout"); strcpy(wavefile, "stdout");
break; break;

case 0x101: // --compile-debug case 0x101: // --compile-debug
case 0x102: // --compile case 0x102: // --compile
if (optarg2 != NULL) if (optarg2 != NULL)
strncpy0(voicename, optarg2, sizeof(voicename)); strncpy0(voicename, optarg2, sizeof(voicename));
flag_compile = c; flag_compile = c;
break; break;

case 0x103: // --punct case 0x103: // --punct
option_punctuation = 1; option_punctuation = 1;
if (optarg2 != NULL) { if (optarg2 != NULL) {
option_punctuation = 2; option_punctuation = 2;
} }
break; break;

case 0x104: // --voices case 0x104: // --voices
init_path(argv[0], data_path); init_path(argv[0], data_path);
DisplayVoices(stdout, optarg2); DisplayVoices(stdout, optarg2);
exit(0); exit(0);

case 0x106: // -- split case 0x106: // -- split
if (optarg2 == NULL) if (optarg2 == NULL)
samples_split = 30; // default 30 minutes samples_split = 30; // default 30 minutes
else else
samples_split = atoi(optarg2); samples_split = atoi(optarg2);
break; break;

case 0x107: // --path case 0x107: // --path
data_path = optarg2; data_path = optarg2;
break; break;

case 0x108: // --phonout case 0x108: // --phonout
if ((f_trans = fopen(optarg2, "w")) == NULL) { if ((f_trans = fopen(optarg2, "w")) == NULL) {
fprintf(stderr, "Can't write to: %s\n", optarg2); fprintf(stderr, "Can't write to: %s\n", optarg2);
f_trans = stderr; f_trans = stderr;
} }
break; break;

case 0x109: // --pho case 0x109: // --pho
phoneme_options |= espeakPHONEMES_MBROLA; phoneme_options |= espeakPHONEMES_MBROLA;
break; break;

case 0x10a: // --ipa case 0x10a: // --ipa
phoneme_options |= espeakPHONEMES_IPA; phoneme_options |= espeakPHONEMES_IPA;
if (optarg2 != NULL) { if (optarg2 != NULL) {
phoneme_options |= espeakPHONEMES_TIE; phoneme_options |= espeakPHONEMES_TIE;
break; break;
} }

} }
break; break;

case 0x10b: // --version case 0x10b: // --version
init_path(argv[0], data_path); init_path(argv[0], data_path);
printf("speak text-to-speech: %s Data at: %s\n", version_string, path_home); printf("speak text-to-speech: %s Data at: %s\n", version_string, path_home);
exit(0); exit(0);

case 0x10c: // --sep case 0x10c: // --sep
phoneme_options |= espeakPHONEMES_SHOW; phoneme_options |= espeakPHONEMES_SHOW;
if (optarg2 == 0) if (optarg2 == 0)
if (phonemes_separator == 'z') if (phonemes_separator == 'z')
phonemes_separator = 0x200c; // ZWNJ phonemes_separator = 0x200c; // ZWNJ
break; break;

case 0x10d: // --tie case 0x10d: // --tie
phoneme_options |= (espeakPHONEMES_SHOW | espeakPHONEMES_TIE); phoneme_options |= (espeakPHONEMES_SHOW | espeakPHONEMES_TIE);
if (optarg2 == 0) if (optarg2 == 0)
if (phonemes_separator == 'z') if (phonemes_separator == 'z')
phonemes_separator = 0x200d; // ZWJ phonemes_separator = 0x200d; // ZWJ
break; break;

default: default:
exit(0); exit(0);
} }
exit(0); exit(0);
} }



SetParameter(espeakRATE, speed, 0); SetParameter(espeakRATE, speed, 0);
SetParameter(espeakVOLUME, amp, 0); SetParameter(espeakVOLUME, amp, 0);
SetParameter(espeakCAPITALS, option_capitals, 0); SetParameter(espeakCAPITALS, option_capitals, 0);

Loading…
Cancel
Save