52
53
int tone_points[12] = {600,170, 1200,135, 2000,110, 3000,110, -1,0};
53
54
//int tone_points[12] = {250,200, 400,170, 600,170, 1200,135, 2000,110, -1,0};
63
64
#define DEFAULT_LANGUAGE_PRIORITY 5
64
#define N_VOICES_LIST 150
65
#define N_VOICES_LIST 250
65
66
static int n_voices_list = 0;
66
67
static espeak_VOICE *voices_list[N_VOICES_LIST];
67
68
static int len_path_voices;
127
132
{"formant", V_FORMANT},
128
133
{"pitch", V_PITCH},
129
134
{"phonemes", V_PHONEMES},
130
{"translator", V_TRANSLATOR},
135
{"translator", V_TRANSLATOR},
131
136
{"dictionary", V_DICTIONARY},
132
137
{"stressLength", V_STRESSLENGTH},
133
138
{"stressAmp", V_STRESSAMP},
163
171
{"l_unpronouncable", 0x100+LOPT_UNPRONOUNCABLE},
164
172
{"l_sonorant_min", 0x100+LOPT_SONORANT_MIN},
165
173
{"l_length_mods", 0x100+LOPT_LENGTH_MODS},
174
{"apostrophe", 0x100+LOPT_APOSTROPHE},
168
178
#define N_VOICE_VARIANTS 12
169
179
const char variants_either[N_VOICE_VARIANTS] = {1,2,12,3,13,4,14,5,11,0};
257
273
tone_pts[ix] = -1;
259
275
sscanf(string,"%d %d %d %d %d %d %d %d %d %d",
260
&tone_pts[0],&tone_pts[1],&tone_pts[2],&tone_pts[3],
261
&tone_pts[4],&tone_pts[5],&tone_pts[6],&tone_pts[7],
262
&tone_pts[8],&tone_pts[9]);
276
&tone_pts[0],&tone_pts[1],&tone_pts[2],&tone_pts[3],
277
&tone_pts[4],&tone_pts[5],&tone_pts[6],&tone_pts[7],
278
&tone_pts[8],&tone_pts[9]);
313
329
while(isspace(*p)) p++;
314
330
strncpy0(vname,p,sizeof(vname));
317
if(memcmp(linebuf,"language",8)==0)
332
else if(memcmp(linebuf,"language",8)==0)
319
334
priority = DEFAULT_LANGUAGE_PRIORITY;
320
335
vlanguage[0] = 0;
335
if(memcmp(linebuf,"gender",6)==0)
349
else if(memcmp(linebuf,"gender",6)==0)
337
351
sscanf(&linebuf[6],"%s %d",vgender,&age);
340
if(memcmp(linebuf,"variants",8)==0)
353
else if(memcmp(linebuf,"variants",8)==0)
342
355
sscanf(&linebuf[8],"%d",&n_variants);
384
397
// Set voice to the default values
387
static unsigned char default_heights[N_PEAKS] = {128,128,120,120,110,110,128,128,128};
388
static unsigned char default_widths[N_PEAKS] = {128,128,128,160,171,171,128,128,128};
400
static unsigned char default_heights[N_PEAKS] = {130,128,120,116,100,100,128,128,128}; // changed for v.1.47
401
static unsigned char default_widths[N_PEAKS] = {140,128,128,160,171,171,128,128,128};
402
// static unsigned char default_heights[N_PEAKS] = {128,128,120,120,110,110,128,128,128}; // previous version
403
// static unsigned char default_widths[N_PEAKS] = {128,128,128,160,171,171,128,128,128};
390
405
static int breath_widths[N_PEAKS] = {0,200,200,400,400,400,600,600,600};
406
421
voice->n_harmonic_peaks = 5;
407
422
voice->peak_shape = 0;
408
423
voice->voicing = 64;
409
voice->consonant_amp = 100;
424
voice->consonant_amp = 90; // change from 100 to 90 for v.1.47
410
425
voice->consonant_ampv = 100;
411
voice->samplerate = 22050;
426
voice->samplerate = samplerate_native;
412
427
memset(voice->klattv,0,sizeof(voice->klattv));
414
429
speed.fast_settings[0] = 450;
434
449
// adjust formant smoothing depending on sample rate
435
450
formant_rate[pk] = (formant_rate_22050[pk] * 22050)/samplerate;
437
voice->height[2] = 240; // reduce F2 slightly
439
453
// This table provides the opportunity for tone control.
440
454
// Adjustment of harmonic amplitudes, steps of 8Hz
441
455
// value of 128 means no change
442
456
// memset(voice->tone_adjust,128,sizeof(voice->tone_adjust));
443
SetToneAdjust(voice,tone_points);
457
SetToneAdjust(voice,tone_points);
445
459
// default values of speed factors
446
460
voice->speedf1 = 256;
514
528
// Read 8 integer numbers
515
529
memset(data, 0, 8+sizeof(int));
516
530
return(sscanf(data_in,"%d %d %d %d %d %d %d %d",
517
&data[0],&data[1],&data[2],&data[3],&data[4],&data[5],&data[6],&data[7]));
531
&data[0],&data[1],&data[2],&data[3],&data[4],&data[5],&data[6],&data[7]));
535
static unsigned int StringToWord2(const char *string)
536
{//======================================================
537
// Convert a language name string to a word such as L('e','n')
540
unsigned int value = 0;
542
for(ix=0; (ix<4) && ((c = string[ix]) != 0); ix++)
544
value = (value << 8) | (c & 0xff);
567
599
static char voice_name[40]; // voice name for current_voice_selected
568
600
static char voice_languages[100]; // list of languages and priorities for current_voice_selected
570
strcpy(voicename,vname);
572
strcpy(voicename,"default");
602
// which directory to look for a named voice. List of voice names, must end in a space.
603
static const char *voices_asia =
604
"az bn fa fa-pin hi hy hy-west id ka kn ku ml ms ne pa ta te tr vi vi-hue vi-sgn zh zh-yue ";
605
static const char *voices_europe =
606
"an bg bs ca cs cy da de el en en-us es et fi fr fr-be ga hr hu is it lt lv mk nl no pl pt-pt ro ru sk sq sr sv ";
609
strncpy0(voicename, vname, sizeof(voicename));
574
610
if(control & 0x10)
576
612
strcpy(buf,vname);
619
strcpy(voicename,"default");
582
621
sprintf(path_voices,"%s%cvoices%c",path_home,PATHSEP,PATHSEP);
583
sprintf(buf,"%s%s",path_voices,voicename);
622
sprintf(buf,"%s%s",path_voices,voicename); // first, look in the main voices directory
585
624
if(GetFileLength(buf) <= 0)
587
// look for the voice in a sub-directory of the language name
588
langname[0] = voicename[0];
589
langname[1] = voicename[1];
591
sprintf(buf,"%s%s%c%s",path_voices,langname,PATHSEP,voicename);
626
// then look in the appropriate subdirectory
627
if((voicename[0]=='m') && (voicename[1]=='b'))
629
voice_dir = "mb"; // mbrola voices
633
sprintf(name2, "%s ", voicename);
634
if(strstr(voices_europe, voicename) != NULL)
635
voice_dir = "europe";
636
else if(strstr(voices_asia, voicename) != NULL)
593
if(GetFileLength(buf) <= 0)
595
// look in "extra" sub-directory
596
sprintf(buf,"%sextra%c%s",path_voices,PATHSEP,voicename);
641
sprintf(buf,"%s%s%c%s", path_voices,voice_dir,PATHSEP,voicename);
598
643
if(GetFileLength(buf) <= 0)
600
// look in "test" sub-directory
645
// if not found, look in "test" sub-directory
601
646
sprintf(buf,"%stest%c%s",path_voices,PATHSEP,voicename);
676
priority = DEFAULT_LANGUAGE_PRIORITY;
677
language_name[0] = 0;
679
sscanf(p,"%s %d",language_name,&priority);
680
if(strcmp(language_name,"variant") == 0)
683
len = strlen(language_name) + 2;
684
// check for space in languages[]
685
if(len < (sizeof(voice_languages)-langix-1))
687
voice_languages[langix] = priority;
689
strcpy(&voice_languages[langix+1],language_name);
693
// only act on the first language line
694
if(language_set == 0)
696
language_type = strtok(language_name,"-");
698
strcpy(translator_name,language_type);
699
strcpy(new_dictionary,language_type);
700
strcpy(phonemes_name,language_type);
701
SelectPhonemeTableName(phonemes_name);
703
if(new_translator != NULL)
704
DeleteTranslator(new_translator);
706
new_translator = SelectTranslator(translator_name);
707
langopts = &new_translator->langopts;
721
priority = DEFAULT_LANGUAGE_PRIORITY;
722
language_name[0] = 0;
724
sscanf(p,"%s %d",language_name,&priority);
725
if(strcmp(language_name,"variant") == 0)
728
len = strlen(language_name) + 2;
729
// check for space in languages[]
730
if(len < (sizeof(voice_languages)-langix-1))
732
voice_languages[langix] = priority;
734
strcpy(&voice_languages[langix+1],language_name);
738
// only act on the first language line
739
if(language_set == 0)
741
language_type = strtok(language_name,"-");
743
strcpy(translator_name,language_type);
744
strcpy(new_dictionary,language_type);
745
strcpy(phonemes_name,language_type);
746
SelectPhonemeTableName(phonemes_name);
748
if(new_translator != NULL)
749
DeleteTranslator(new_translator);
751
new_translator = SelectTranslator(translator_name);
752
langopts = &new_translator->langopts;
753
strncpy0(voice->language_name, language_name, sizeof(voice->language_name));
713
759
if(tone_only == 0)
724
sscanf(p,"%s %d",vgender,&age);
725
current_voice_selected.gender = LookupMnem(genders,vgender);
726
current_voice_selected.age = age;
770
sscanf(p,"%s %d",vgender,&age);
771
current_voice_selected.gender = LookupMnem(genders,vgender);
772
current_voice_selected.age = age;
730
776
case V_TRANSLATOR:
731
777
if(tone_only) break;
733
779
sscanf(p,"%s",translator_name);
735
781
if(new_translator != NULL)
736
DeleteTranslator(new_translator);
782
DeleteTranslator(new_translator);
738
784
new_translator = SelectTranslator(translator_name);
739
785
langopts = &new_translator->langopts;
757
// default is pitch 82 118
758
n = sscanf(p,"%d %d",&pitch1,&pitch2);
759
voice->pitch_base = (pitch1 - 9) << 12;
760
voice->pitch_range = (pitch2 - pitch1) * 108;
761
factor = double(pitch1 - 82)/82;
762
voice->formant_factor = (int)((1+factor/4) * 256); // nominal formant shift for a different voice pitch
803
// default is pitch 82 118
804
n = sscanf(p,"%d %d",&pitch1,&pitch2);
805
voice->pitch_base = (pitch1 - 9) << 12;
806
voice->pitch_range = (pitch2 - pitch1) * 108;
807
factor = double(pitch1 - 82)/82;
808
voice->formant_factor = (int)((1+factor/4) * 256); // nominal formant shift for a different voice pitch
766
812
case V_STRESSLENGTH: // stressLength
767
813
stress_lengths_set = Read8Numbers(p,stress_lengths);
799
845
case V_DICTRULES: // conditional dictionary rules and list entries
848
// expect a list of numbers
802
851
while(isspace(*p)) p++;
804
if(((n = atoi(p)) > 0) && (n < 32))
853
if((n = atoi(p)) > 0)
807
conditional_rules |= (1 << n);
859
conditional_rules |= (1 << n);
860
else if(key==V_NUMBERS)
861
langopts->numbers |= (1 << n);
862
else if(key==V_STRESSOPT)
863
langopts->stress_flags |= (1 << n);
867
if((key==V_NUMBERS) && (n < 64))
868
langopts->numbers |= (1 << (n-32));
870
fprintf(stderr,"Bad option number %d\n", n);
809
873
while(isalnum(*p)) p++;
827
891
case V_STRESSRULE:
828
892
sscanf(p,"%d %d %d %d",&langopts->stress_rule,
829
&langopts->stress_flags,
830
&langopts->unstressed_wd1,
831
&langopts->unstressed_wd2);
893
&langopts->stress_flags,
894
&langopts->unstressed_wd1,
895
&langopts->unstressed_wd2);
836
900
new_translator->charset_a0 = charsets[value];
840
sscanf(p,"%d %d",&langopts->numbers,&langopts->numbers2);
845
if((sscanf(p,"%s %d %d",option_name,&value,&value2) >= 2) && ((ix = LookupMnem(options_tab, option_name)) >= 0))
905
if(((sscanf(p,"%s %d %d",option_name,&value,&value2) >= 2) && ((ix = LookupMnem(options_tab, option_name)) >= 0)) ||
906
((sscanf(p,"%d %d %d",&ix,&value,&value2) >= 2) && (ix < N_LOPTS)))
847
908
langopts->param[ix] = value;
848
909
langopts->param2[ix] = value2;
888
ReadTonePoints(p,tone_data);
889
SetToneAdjust(voice,tone_data);
949
ReadTonePoints(p,tone_data);
950
SetToneAdjust(voice,tone_data);
894
955
if(sscanf(p,"%d",&value)==1)
899
voice->breath[0] = Read8Numbers(p,&voice->breath[1]);
900
for(ix=1; ix<8; ix++)
903
voice->breath[ix] = -voice->breath[ix];
960
voice->breath[0] = Read8Numbers(p,&voice->breath[1]);
961
for(ix=1; ix<8; ix++)
964
voice->breath[ix] = -voice->breath[ix];
908
voice->breathw[0] = Read8Numbers(p,&voice->breathw[1]);
969
voice->breathw[0] = Read8Numbers(p,&voice->breathw[1]);
911
972
case V_CONSONANTS:
985
sscanf(p,"%s %s %d",name1,name2,&srate);
986
if(LoadMbrolaTable(name1,name2,srate) != EE_OK)
926
sscanf(p,"%s %s %d",name,phtrans,&srate);
927
if(LoadMbrolaTable(name,phtrans,srate) != EE_OK)
929
fprintf(stderr,"mbrola voice not found\n");
931
voice->samplerate = srate;
988
fprintf(stderr,"mbrola voice not found\n");
990
voice->samplerate = srate;
936
995
voice->klattv[0] = 1; // default source: IMPULSIVE
1006
sscanf(p,"%d",&dict_min);
1012
name1[0] = name2[0] = 0;
1013
sscanf(p, "%s %s", name1, name2);
1015
if(strcmp(name1, "latin") == 0)
1017
strncpy0(langopts->ascii_language,name2,sizeof(langopts->ascii_language));
1019
else if((alphabet = AlphabetFromName(name1)) != 0)
1021
langopts->alt_alphabet = alphabet->offset;
1022
langopts->alt_alphabet_lang = StringToWord2(name2);
1026
fprintf(stderr,"alphabet name '%s' not found\n", name1);
947
1032
if((key & 0xff00) == 0x100)
986
1071
voice->phoneme_tab_ix = ix;
987
1072
new_translator->phoneme_tab_ix = ix;
1073
new_translator->dict_min_size = dict_min;
988
1074
LoadDictionary(new_translator, new_dictionary, control & 4);
989
1075
if(dictionary_name[0]==0)
990
1076
return(NULL); // no dictionary loaded
1143
1230
p = voice->languages; // list of languages+dialects for which this voice is suitable
1145
if(strcmp(spec_language,"mbrola")==0)
1232
if(spec_n_parts < 0)
1147
// only list mbrola voices
1148
if(memcmp(voice->identifier,"mb/",3) == 0)
1234
// match on the subdirectory
1235
if(memcmp(voice->identifier, spec_language, spec_lang_len) == 0)
1223
1310
// match on voice name
1227
if(strcmp(voice_spec->name,voice->identifier)==0)
1313
else if(strcmp(voice_spec->name,voice->identifier)==0)
1233
1319
if(((voice_spec->gender == 1) || (voice_spec->gender == 2)) &&
1234
((voice->gender == 1) || (voice->gender == 2)))
1320
((voice->gender == 1) || (voice->gender == 2)))
1236
1322
if(voice_spec->gender == voice->gender)
1382
if((n_parts == 1) && (control & 1))
1384
if(strcmp(language, "mbrola") == 0)
1386
language[2] = 0; // truncate to "mb"
1390
sprintf(buf, "%s/voices/%s", path_home, language);
1391
if(GetFileLength(buf) == -2)
1393
// A subdirectory name has been specified. List all the voices in that subdirectory
1394
language[lang_len++] = PATHSEP;
1395
language[lang_len] = 0;
1294
1401
// select those voices which match the specified language
1296
1403
for(ix=0; ix<n_voices_list; ix++)
1420
1526
// no language is specified. Get language from the named voice
1421
1527
static char buf[60];
1423
1529
if(voice_select2.name == NULL)
1425
1531
if((voice_select2.name = voice_select2.identifier) == NULL)
1426
1532
voice_select2.name = "default";
1429
1535
strncpy0(buf,voice_select2.name,sizeof(buf));
1430
1536
variant_name = ExtractVoiceVariantName(buf,0,0);
1580
// a regular line, add it to the voices list
1685
// a regular line, add it to the voices list
1581
1686
if((f_voice = fopen(fname,"r")) == NULL)
1584
1689
// pass voice file name within the voices directory
1585
1690
voice_data = ReadVoiceFile(f_voice, fname+len_path_voices, &buf[20]);
1586
1691
fclose(f_voice);
1595
1700
#ifdef PLATFORM_WINDOWS
1596
WIN32_FIND_DATAA FindFileData;
1597
HANDLE hFind = INVALID_HANDLE_VALUE;
1701
WIN32_FIND_DATAA FindFileData;
1702
HANDLE hFind = INVALID_HANDLE_VALUE;
1599
1704
#undef UNICODE // we need FindFirstFileA() which takes an 8-bit c-string
1600
1705
sprintf(fname,"%s\\*",path);
1606
sprintf(fname,"%s%c%s",path,PATHSEP,FindFileData.cFileName);
1608
ftype = GetFileLength(fname);
1610
if((ftype == -2) && (FindFileData.cFileName[0] != '.'))
1618
// a regular line, add it to the voices list
1619
if((f_voice = fopen(fname,"r")) == NULL)
1622
// pass voice file name within the voices directory
1623
voice_data = ReadVoiceFile(f_voice, fname+len_path_voices, FindFileData.cFileName);
1626
if(voice_data != NULL)
1628
voices_list[n_voices_list++] = voice_data;
1711
if(n_voices_list >= (N_VOICES_LIST-2))
1712
break; // voices list is full
1714
if(FindFileData.cFileName[0] != '.')
1716
sprintf(fname,"%s%c%s",path,PATHSEP,FindFileData.cFileName);
1717
ftype = GetFileLength(fname);
1726
// a regular line, add it to the voices list
1727
if((f_voice = fopen(fname,"r")) == NULL)
1730
// pass voice file name within the voices directory
1731
voice_data = ReadVoiceFile(f_voice, fname+len_path_voices, FindFileData.cFileName);
1734
if(voice_data != NULL)
1736
voices_list[n_voices_list++] = voice_data;
1631
1740
} while(FindNextFileA(hFind, &FindFileData) != 0);
1643
1752
if(n_voices_list >= (N_VOICES_LIST-2))
1644
1753
break; // voices list is full
1755
if(ent->d_name[0] == '.')
1646
1758
sprintf(fname,"%s%c%s",path,PATHSEP,ent->d_name);
1648
1760
ftype = GetFileLength(fname);
1650
if((ftype == -2) && (ent->d_name[0] != '.'))
1652
1764
// a sub-sirectory
1653
1765
GetVoices(fname);
1658
// a regular line, add it to the voices list
1769
// a regular line, add it to the voices list
1659
1770
if((f_voice = fopen(fname,"r")) == NULL)
1662
1773
// pass voice file name within the voices directory
1663
1774
voice_data = ReadVoiceFile(f_voice, fname+len_path_voices, ent->d_name);
1664
1775
fclose(f_voice);
1679
1790
espeak_ERROR SetVoiceByName(const char *name)
1680
1791
{//=========================================
1681
1792
espeak_VOICE *v;
1682
1794
espeak_VOICE voice_selector;
1683
1795
char *variant_name;
1684
1796
static char buf[60];
1686
1798
strncpy0(buf,name,sizeof(buf));
1687
1800
variant_name = ExtractVoiceVariantName(buf, 0, 1);
1804
// convert voice name to lower case (ascii)
1805
if((buf[ix] = tolower(buf[ix])) == 0)
1689
1809
memset(&voice_selector,0,sizeof(voice_selector));
1690
// voice_selector.name = buf;
1691
1810
voice_selector.name = (char *)name; // include variant name in voice stack ??
1693
1812
// first check for a voice with this filename
1767
1888
ESPEAK_API const espeak_VOICE **espeak_ListVoices(espeak_VOICE *voice_spec)
1768
1889
{//========================================================================
1769
#ifndef PLATFORM_RISCOS
1890
char path_voices[sizeof(path_home)+12];
1893
#ifdef PLATFORM_RISCOS
1894
if(n_voices_list == 0)
1896
sprintf(path_voices,"%s%cvoices",path_home,PATHSEP);
1897
len_path_voices = strlen(path_voices)+1;
1898
GetVoices(path_voices);
1899
voices_list[n_voices_list] = NULL; // voices list terminator
1901
return((const espeak_VOICE **)voices_list);
1772
1906
espeak_VOICE *v;
1773
static espeak_VOICE *voices[N_VOICES_LIST];
1774
char path_voices[sizeof(path_home)+12];
1907
static espeak_VOICE **voices = NULL;
1776
1909
// free previous voice list data
1777
1910
FreeVoiceList();
1782
1915
GetVoices(path_voices);
1783
1916
voices_list[n_voices_list] = NULL; // voices list terminator
1917
voices = (espeak_VOICE **)realloc(voices, sizeof(espeak_VOICE *)*(n_voices_list+1));
1785
1919
// sort the voices list
1786
1920
qsort(voices_list,n_voices_list,sizeof(espeak_VOICE *),
1787
(int (__cdecl *)(const void *,const void *))VoiceNameSorter);
1921
(int (__cdecl *)(const void *,const void *))VoiceNameSorter);
1797
// list all: omit variant voices and mbrola voices
1931
// list all: omit variant voices and mbrola voices and test voices
1799
1933
for(ix=0; (v = voices_list[ix]) != NULL; ix++)
1801
if((v->languages[0] != 0) && (strcmp(&v->languages[1],"variant") != 0) && (memcmp(v->identifier,"mb/",3) != 0))
1935
if((v->languages[0] != 0) && (strcmp(&v->languages[1],"variant") != 0)
1936
&& (memcmp(v->identifier,"mb/",3) != 0) && (memcmp(v->identifier,"test/",5) != 0))
1803
1938
voices[j++] = v;