~ubuntu-branches/ubuntu/trusty/espeak/trusty-proposed

« back to all changes in this revision

Viewing changes to src/voices.cpp

  • Committer: Package Import Robot
  • Author(s): Samuel Thibault, Jason White, Samuel Thibault
  • Date: 2013-06-19 20:57:44 UTC
  • mfrom: (1.2.25)
  • Revision ID: package-import@ubuntu.com-20130619205744-hok0oml2q4zd35lb
Tags: 1.47.11-1
* New upstream release
* debian/rules: Use phondata-manifest in the espeak-data directory
* Updated espeak manpage
* Updated copyright

[ Jason White ]
* Pass compiler flags on make command line so they won't be ignored.
  (Closes: #707925)
* Rebuild object files with AUDIO=runtime after building static library
  without it. (Closes: #707912)

[ Samuel Thibault ]
* Add utf-8-init patch to fix initialization of utf-8 locale for proper
  character properties detection.
* Add pulse-trigger-on-final-chunk patch to flush the pulse output.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/***************************************************************************
2
 
 *   Copyright (C) 2005 to 2010 by Jonathan Duddington                     *
 
2
 *   Copyright (C) 2005 to 2013 by Jonathan Duddington                     *
3
3
 *   email: jonsd@users.sourceforge.net                                    *
4
4
 *                                                                         *
5
5
 *   This program is free software; you can redistribute it and/or modify  *
47
47
        {"unknown", 0},
48
48
        {"male", 1},
49
49
        {"female", 2},
50
 
        {NULL, 0 }};
 
50
        {NULL, 0 }
 
51
};
51
52
 
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};
61
62
 
62
63
 
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;
98
99
        V_STRESSADD,
99
100
        V_DICTRULES,
100
101
        V_STRESSRULE,
 
102
        V_STRESSOPT,
101
103
        V_CHARSET,
102
104
        V_NUMBERS,
103
105
        V_OPTION,
106
108
        V_KLATT,
107
109
        V_FAST,
108
110
        V_SPEED,
 
111
        V_DICTMIN,
 
112
        V_ALPHABET2,
109
113
 
110
114
// these need a phoneme table to have been specified
111
115
        V_REPLACE,
117
121
static MNEM_TAB options_tab[] = {
118
122
        {"reduce_t",  LOPT_REDUCE_T},
119
123
        {"bracket", LOPT_BRACKET_PAUSE},
120
 
        {NULL,   -1} };
 
124
        {NULL,   -1}
 
125
};
121
126
 
122
127
static MNEM_TAB keyword_tab[] = {
123
128
        {"name",       V_NAME},
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},
136
141
        {"tunes",      V_TUNES},
137
142
        {"dictrules",   V_DICTRULES},
138
143
        {"stressrule", V_STRESSRULE},
 
144
        {"stressopt",  V_STRESSOPT},
139
145
        {"charset",    V_CHARSET},
140
146
        {"replace",    V_REPLACE},
141
147
        {"words",      V_WORDGAP},
154
160
        {"klatt",      V_KLATT},
155
161
        {"fast_test2",  V_FAST},
156
162
        {"speed",      V_SPEED},
 
163
        {"dict_min",   V_DICTMIN},
 
164
        {"alphabet2",  V_ALPHABET2},
157
165
 
158
166
        // these just set a value in langopts.param[]
159
167
        {"l_dieresis", 0x100+LOPT_DIERESES},
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},
166
 
        {NULL,   0} };
 
174
        {"apostrophe", 0x100+LOPT_APOSTROPHE},
 
175
        {NULL,   0}
 
176
};
167
177
 
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};
184
194
        if(fgets(buf,size,f_in) == NULL)
185
195
                return(NULL);
186
196
 
 
197
        if(buf[0] == '#')
 
198
        {
 
199
                buf[0] = 0;
 
200
                return(buf);
 
201
        }
 
202
 
187
203
        len = strlen(buf);
188
204
        while((--len > 0) && isspace(buf[len]))
189
205
                buf[len] = 0;
257
273
                tone_pts[ix] = -1;
258
274
 
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]);
263
279
}
264
280
 
265
281
 
313
329
                        while(isspace(*p)) p++;
314
330
                        strncpy0(vname,p,sizeof(vname));
315
331
                }
316
 
                else
317
 
                if(memcmp(linebuf,"language",8)==0)
 
332
                else if(memcmp(linebuf,"language",8)==0)
318
333
                {
319
334
                        priority = DEFAULT_LANGUAGE_PRIORITY;
320
335
                        vlanguage[0] = 0;
331
346
                                n_languages++;
332
347
                        }
333
348
                }
334
 
                else
335
 
                if(memcmp(linebuf,"gender",6)==0)
 
349
                else if(memcmp(linebuf,"gender",6)==0)
336
350
                {
337
351
                        sscanf(&linebuf[6],"%s %d",vgender,&age);
338
352
                }
339
 
                else
340
 
                if(memcmp(linebuf,"variants",8)==0)
 
353
                else if(memcmp(linebuf,"variants",8)==0)
341
354
                {
342
355
                        sscanf(&linebuf[8],"%d",&n_variants);
343
356
                }
384
397
// Set voice to the default values
385
398
 
386
399
        int  pk;
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};
389
404
 
390
405
        static int breath_widths[N_PEAKS] = {0,200,200,400,400,400,600,600,600};
391
406
 
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));
413
428
 
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;
436
451
        }
437
 
        voice->height[2] = 240;  // reduce F2 slightly
438
452
 
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);
444
458
 
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]));
 
532
}
 
533
 
 
534
 
 
535
static unsigned int StringToWord2(const char *string)
 
536
{//======================================================
 
537
// Convert a language name string to a word such as L('e','n')
 
538
        int ix;
 
539
        int c;
 
540
        unsigned int value = 0;
 
541
 
 
542
        for(ix=0; (ix<4) && ((c = string[ix]) != 0); ix++)
 
543
        {
 
544
                value = (value << 8) | (c & 0xff);
 
545
        }
 
546
        return(value);
518
547
}
519
548
 
520
549
 
551
580
        char phonemes_name[40];
552
581
        char option_name[40];
553
582
        const char *language_type;
554
 
        char buf[200];
 
583
        char buf[sizeof(path_home)+30];
555
584
        char path_voices[sizeof(path_home)+12];
556
 
        char langname[4];
557
585
 
 
586
        int dict_min = 0;
558
587
        int stress_amps[8];
559
588
        int stress_lengths[8];
560
589
        int stress_add[8];
561
590
        char names[8][40];
 
591
        char name1[40];
 
592
        char name2[80];
 
593
        const char *voice_dir;
562
594
 
563
595
        int pitch1;
564
596
        int pitch2;
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
569
601
 
570
 
        strcpy(voicename,vname);
571
 
        if(voicename[0]==0)
572
 
                strcpy(voicename,"default");
573
 
 
 
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 ";
 
607
 
 
608
 
 
609
        strncpy0(voicename, vname, sizeof(voicename));
574
610
        if(control & 0x10)
575
611
        {
576
612
                strcpy(buf,vname);
579
615
        }
580
616
        else
581
617
        {
 
618
                if(voicename[0]==0)
 
619
                        strcpy(voicename,"default");
 
620
 
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
584
623
 
585
624
                if(GetFileLength(buf) <= 0)
586
625
                {
587
 
                        // look for the voice in a sub-directory of the language name
588
 
                        langname[0] = voicename[0];
589
 
                        langname[1] = voicename[1];
590
 
                        langname[2] = 0;
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'))
 
628
                        {
 
629
                                voice_dir = "mb";   // mbrola voices
 
630
                        }
 
631
                        else
 
632
                        {
 
633
                                sprintf(name2, "%s ", voicename);
 
634
                                if(strstr(voices_europe, voicename) != NULL)
 
635
                                        voice_dir = "europe";
 
636
                                else if(strstr(voices_asia, voicename) != NULL)
 
637
                                        voice_dir = "asia";
 
638
                                else
 
639
                                        voice_dir = "other";
592
640
 
593
 
                        if(GetFileLength(buf) <= 0)
594
 
                        {
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);
597
642
 
598
643
                                if(GetFileLength(buf) <= 0)
599
644
                                {
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);
602
647
                                }
603
648
                        }
666
711
                switch(key)
667
712
                {
668
713
                case V_LANGUAGE:
669
 
                        {
670
 
                                unsigned int len;
671
 
                                int priority;
672
 
 
673
 
                                if(tone_only)
674
 
                                        break;
675
 
        
676
 
                                priority = DEFAULT_LANGUAGE_PRIORITY;
677
 
                                language_name[0] = 0;
678
 
        
679
 
                                sscanf(p,"%s %d",language_name,&priority);
680
 
                                if(strcmp(language_name,"variant") == 0)
681
 
                                        break;
682
 
        
683
 
                                len = strlen(language_name) + 2;
684
 
                                // check for space in languages[]
685
 
                                if(len < (sizeof(voice_languages)-langix-1))
686
 
                                {
687
 
                                        voice_languages[langix] = priority;
688
 
        
689
 
                                        strcpy(&voice_languages[langix+1],language_name);
690
 
                                        langix += len;
691
 
                                }
692
 
        
693
 
                                // only act on the first language line
694
 
                                if(language_set == 0)
695
 
                                {
696
 
                                        language_type = strtok(language_name,"-");
697
 
                                        language_set = 1;
698
 
                                        strcpy(translator_name,language_type);
699
 
                                        strcpy(new_dictionary,language_type);
700
 
                                        strcpy(phonemes_name,language_type);
701
 
                                        SelectPhonemeTableName(phonemes_name);
702
 
                
703
 
                                        if(new_translator != NULL)
704
 
                                                        DeleteTranslator(new_translator);
705
 
                
706
 
                                        new_translator = SelectTranslator(translator_name);
707
 
                                        langopts = &new_translator->langopts;
708
 
                                }
709
 
                        }
710
 
                        break;
 
714
                {
 
715
                        unsigned int len;
 
716
                        int priority;
 
717
 
 
718
                        if(tone_only)
 
719
                                break;
 
720
 
 
721
                        priority = DEFAULT_LANGUAGE_PRIORITY;
 
722
                        language_name[0] = 0;
 
723
 
 
724
                        sscanf(p,"%s %d",language_name,&priority);
 
725
                        if(strcmp(language_name,"variant") == 0)
 
726
                                break;
 
727
 
 
728
                        len = strlen(language_name) + 2;
 
729
                        // check for space in languages[]
 
730
                        if(len < (sizeof(voice_languages)-langix-1))
 
731
                        {
 
732
                                voice_languages[langix] = priority;
 
733
 
 
734
                                strcpy(&voice_languages[langix+1],language_name);
 
735
                                langix += len;
 
736
                        }
 
737
 
 
738
                        // only act on the first language line
 
739
                        if(language_set == 0)
 
740
                        {
 
741
                                language_type = strtok(language_name,"-");
 
742
                                language_set = 1;
 
743
                                strcpy(translator_name,language_type);
 
744
                                strcpy(new_dictionary,language_type);
 
745
                                strcpy(phonemes_name,language_type);
 
746
                                SelectPhonemeTableName(phonemes_name);
 
747
 
 
748
                                if(new_translator != NULL)
 
749
                                        DeleteTranslator(new_translator);
 
750
 
 
751
                                new_translator = SelectTranslator(translator_name);
 
752
                                langopts = &new_translator->langopts;
 
753
                                strncpy0(voice->language_name, language_name, sizeof(voice->language_name));
 
754
                        }
 
755
                }
 
756
                break;
711
757
 
712
758
                case V_NAME:
713
759
                        if(tone_only == 0)
718
764
                        break;
719
765
 
720
766
                case V_GENDER:
721
 
                        {
722
 
                                int age = 0;
723
 
                                char vgender[80];
724
 
                                sscanf(p,"%s %d",vgender,&age);
725
 
                                current_voice_selected.gender = LookupMnem(genders,vgender);
726
 
                                current_voice_selected.age = age;
727
 
                        }
728
 
                        break;
 
767
                {
 
768
                        int age = 0;
 
769
                        char vgender[80];
 
770
                        sscanf(p,"%s %d",vgender,&age);
 
771
                        current_voice_selected.gender = LookupMnem(genders,vgender);
 
772
                        current_voice_selected.age = age;
 
773
                }
 
774
                break;
729
775
 
730
776
                case V_TRANSLATOR:
731
777
                        if(tone_only) break;
733
779
                        sscanf(p,"%s",translator_name);
734
780
 
735
781
                        if(new_translator != NULL)
736
 
                                        DeleteTranslator(new_translator);
 
782
                                DeleteTranslator(new_translator);
737
783
 
738
784
                        new_translator = SelectTranslator(translator_name);
739
785
                        langopts = &new_translator->langopts;
752
798
                        break;
753
799
 
754
800
                case V_PITCH:
755
 
                        {
756
 
                                double factor;
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
763
 
                        }
764
 
                        break;
 
801
                {
 
802
                        double factor;
 
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
 
809
                }
 
810
                break;
765
811
 
766
812
                case V_STRESSLENGTH:   // stressLength
767
813
                        stress_lengths_set = Read8Numbers(p,stress_lengths);
797
843
                        break;
798
844
 
799
845
                case V_DICTRULES:   // conditional dictionary rules and list entries
 
846
                case V_NUMBERS:
 
847
                case V_STRESSOPT:
 
848
                        // expect a list of numbers
800
849
                        while(*p != 0)
801
850
                        {
802
851
                                while(isspace(*p)) p++;
803
852
                                n = -1;
804
 
                                if(((n = atoi(p)) > 0) && (n < 32))
 
853
                                if((n = atoi(p)) > 0)
805
854
                                {
806
855
                                        p++;
807
 
                                        conditional_rules |= (1 << n);
 
856
                                        if(n < 32)
 
857
                                        {
 
858
                                                if(key==V_DICTRULES)
 
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);
 
864
                                        }
 
865
                                        else
 
866
                                        {
 
867
                                                if((key==V_NUMBERS) && (n < 64))
 
868
                                                        langopts->numbers |= (1 << (n-32));
 
869
                                                else
 
870
                                                        fprintf(stderr,"Bad option number %d\n", n);
 
871
                                        }
808
872
                                }
809
873
                                while(isalnum(*p)) p++;
810
874
                        }
826
890
 
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);
832
896
                        break;
833
897
 
834
898
                case V_CHARSET:
836
900
                                new_translator->charset_a0 = charsets[value];
837
901
                        break;
838
902
 
839
 
                case V_NUMBERS:
840
 
                        sscanf(p,"%d %d",&langopts->numbers,&langopts->numbers2);
841
 
                        break;
842
 
 
843
903
                case V_OPTION:
844
904
                        value2 = 0;
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)))
846
907
                        {
847
908
                                langopts->param[ix] = value;
848
909
                                langopts->param2[ix] = value2;
883
944
                        break;
884
945
 
885
946
                case V_TONE:
886
 
                        {
887
 
                                int tone_data[12];
888
 
                                ReadTonePoints(p,tone_data);
889
 
                                SetToneAdjust(voice,tone_data);
890
 
                        }
891
 
                        break;
 
947
                {
 
948
                        int tone_data[12];
 
949
                        ReadTonePoints(p,tone_data);
 
950
                        SetToneAdjust(voice,tone_data);
 
951
                }
 
952
                break;
892
953
 
893
954
                case V_VOICING:
894
955
                        if(sscanf(p,"%d",&value)==1)
896
957
                        break;
897
958
 
898
959
                case V_BREATH:
899
 
                                voice->breath[0] = Read8Numbers(p,&voice->breath[1]);
900
 
                                for(ix=1; ix<8; ix++)
901
 
                                {
902
 
                                        if(ix % 2)
903
 
                                                voice->breath[ix] = -voice->breath[ix];
904
 
                                }
 
960
                        voice->breath[0] = Read8Numbers(p,&voice->breath[1]);
 
961
                        for(ix=1; ix<8; ix++)
 
962
                        {
 
963
                                if(ix % 2)
 
964
                                        voice->breath[ix] = -voice->breath[ix];
 
965
                        }
905
966
                        break;
906
967
 
907
968
                case V_BREATHW:
908
 
                                voice->breathw[0] = Read8Numbers(p,&voice->breathw[1]);
 
969
                        voice->breathw[0] = Read8Numbers(p,&voice->breathw[1]);
909
970
                        break;
910
971
 
911
972
                case V_CONSONANTS:
917
978
                        break;
918
979
 
919
980
                case V_MBROLA:
 
981
                {
 
982
                        int srate = 16000;
 
983
 
 
984
                        name2[0] = 0;
 
985
                        sscanf(p,"%s %s %d",name1,name2,&srate);
 
986
                        if(LoadMbrolaTable(name1,name2,srate) != EE_OK)
920
987
                        {
921
 
                                int srate = 16000;
922
 
                                char name[40];
923
 
                                char phtrans[40];
924
 
 
925
 
                                phtrans[0] = 0;
926
 
                                sscanf(p,"%s %s %d",name,phtrans,&srate);
927
 
                                if(LoadMbrolaTable(name,phtrans,srate) != EE_OK)
928
 
                                {
929
 
                                        fprintf(stderr,"mbrola voice not found\n");
930
 
                                }
931
 
                                voice->samplerate = srate;
 
988
                                fprintf(stderr,"mbrola voice not found\n");
932
989
                        }
933
 
                        break;
 
990
                        voice->samplerate = srate;
 
991
                }
 
992
                break;
934
993
 
935
994
                case V_KLATT:
936
995
                        voice->klattv[0] = 1;  // default source: IMPULSIVE
943
1002
                        SetSpeed(3);
944
1003
                        break;
945
1004
 
 
1005
                case V_DICTMIN:
 
1006
                        sscanf(p,"%d",&dict_min);
 
1007
                        break;
 
1008
 
 
1009
                case V_ALPHABET2:
 
1010
                        {
 
1011
                                ALPHABET *alphabet;
 
1012
                                name1[0] = name2[0] = 0;
 
1013
                                sscanf(p, "%s %s", name1, name2);
 
1014
 
 
1015
                                if(strcmp(name1, "latin") == 0)
 
1016
                                {
 
1017
                                        strncpy0(langopts->ascii_language,name2,sizeof(langopts->ascii_language));
 
1018
                                }
 
1019
                                else if((alphabet = AlphabetFromName(name1)) != 0)
 
1020
                                {
 
1021
                                        langopts->alt_alphabet = alphabet->offset;
 
1022
                                        langopts->alt_alphabet_lang = StringToWord2(name2);
 
1023
                                }
 
1024
                                else
 
1025
                                {
 
1026
                                        fprintf(stderr,"alphabet name '%s' not found\n", name1);
 
1027
                                }
 
1028
                        }
 
1029
                        break;
 
1030
 
946
1031
                default:
947
1032
                        if((key & 0xff00) == 0x100)
948
1033
                        {
985
1070
                }
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
1009
1095
                translator = new_translator;
1010
1096
        }
1011
1097
 
 
1098
 
1012
1099
        // relative lengths of different stress syllables
1013
1100
        for(ix=0; ix<stress_lengths_set; ix++)
1014
1101
        {
1049
1136
                        // The voice name has a +variant suffix
1050
1137
                        variant_num = 0;
1051
1138
                        *p++ = 0;   // delete the suffix from the voice name
1052
 
                        if(isdigit(*p))
 
1139
                        if(IsDigit09(*p))
1053
1140
                        {
1054
1141
                                variant_num = atoi(p);  // variant number
1055
1142
                        }
1057
1144
                        {
1058
1145
                                // voice variant name, not number
1059
1146
                                sprintf(variant_name, "%s%s", variant_prefix, p);
1060
 
                        }       
 
1147
                        }
1061
1148
                }
1062
1149
        }
1063
 
        
 
1150
 
1064
1151
        if(variant_num > 0)
1065
1152
        {
1066
1153
                if(variant_num < 10)
1142
1229
 
1143
1230
        p = voice->languages;  // list of languages+dialects for which this voice is suitable
1144
1231
 
1145
 
        if(strcmp(spec_language,"mbrola")==0)
 
1232
        if(spec_n_parts < 0)
1146
1233
        {
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)
1149
1236
                        return(100);
1150
1237
                return(0);
1151
1238
        }
1223
1310
                        // match on voice name
1224
1311
                        score += 500;
1225
1312
                }
1226
 
                else
1227
 
                if(strcmp(voice_spec->name,voice->identifier)==0)
 
1313
                else if(strcmp(voice_spec->name,voice->identifier)==0)
1228
1314
                {
1229
1315
                        score += 400;
1230
1316
                }
1231
1317
        }
1232
1318
 
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)))
1235
1321
        {
1236
1322
                if(voice_spec->gender == voice->gender)
1237
1323
                        score += 50;
1279
1365
        int lang_len=0;
1280
1366
        espeak_VOICE *vp;
1281
1367
        char language[80];
 
1368
        char buf[sizeof(path_home)+80];
1282
1369
 
1283
1370
        // count number of parts in the specified language
1284
1371
        if((voice_select->languages != NULL) && (voice_select->languages[0] != 0))
1291
1378
                                n_parts++;
1292
1379
                }
1293
1380
        }
 
1381
 
 
1382
        if((n_parts == 1) && (control & 1))
 
1383
        {
 
1384
                if(strcmp(language, "mbrola") == 0)
 
1385
                {
 
1386
                        language[2] = 0;  // truncate to "mb"
 
1387
                        lang_len = 2;
 
1388
                }
 
1389
 
 
1390
                sprintf(buf, "%s/voices/%s", path_home, language);
 
1391
                if(GetFileLength(buf) == -2)
 
1392
                {
 
1393
                        // A subdirectory name has been specified.  List all the voices in that subdirectory
 
1394
                        language[lang_len++] = PATHSEP;
 
1395
                        language[lang_len] = 0;
 
1396
                        n_parts = -1;
 
1397
                }
 
1398
 
 
1399
        }
 
1400
 
1294
1401
        // select those voices which match the specified language
1295
1402
        nv = 0;
1296
1403
        for(ix=0; ix<n_voices_list; ix++)
1363
1470
                        {
1364
1471
                                match_fname = ix;  // matching identifier, use this if no matching name
1365
1472
                        }
1366
 
                        else
1367
 
                        if(strcmp(last_part,&id[strlen(id)-last_part_len])==0)
 
1473
                        else if(strcmp(last_part,&id[strlen(id)-last_part_len])==0)
1368
1474
                        {
1369
1475
                                match_fname2 = ix;
1370
1476
                        }
1419
1525
        {
1420
1526
                // no language is specified. Get language from the named voice
1421
1527
                static char buf[60];
1422
 
        
 
1528
 
1423
1529
                if(voice_select2.name == NULL)
1424
1530
                {
1425
1531
                        if((voice_select2.name = voice_select2.identifier) == NULL)
1426
1532
                                voice_select2.name = "default";
1427
1533
                }
1428
 
        
 
1534
 
1429
1535
                strncpy0(buf,voice_select2.name,sizeof(buf));
1430
1536
                variant_name = ExtractVoiceVariantName(buf,0,0);
1431
1537
 
1461
1567
        gender = 0;
1462
1568
        if((voice_select2.gender == 2) || ((voice_select2.age > 0) && (voice_select2.age < 13)))
1463
1569
                gender = 2;
1464
 
        else
1465
 
        if(voice_select2.gender == 1)
 
1570
        else if(voice_select2.gender == 1)
1466
1571
                gender = 1;
1467
1572
 
1468
1573
#define AGE_OLD  60
1490
1595
                }
1491
1596
                if(skip==0)
1492
1597
                {
1493
 
                        voices2[ix2++] = vp; 
 
1598
                        voices2[ix2++] = vp;
1494
1599
                }
1495
1600
 
1496
1601
                for(j=0; (j < vp->xx1) && (n_variants < N_VOICE_VARIANTS);)
1577
1682
                }
1578
1683
                else
1579
1684
                {
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)
1582
1687
                                continue;
1583
 
                
 
1688
 
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);
1593
1698
        }
1594
1699
#else
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;
1598
1703
 
1599
1704
#undef UNICODE         // we need FindFirstFileA() which takes an 8-bit c-string
1600
1705
        sprintf(fname,"%s\\*",path);
1603
1708
                return;
1604
1709
 
1605
1710
        do {
1606
 
                sprintf(fname,"%s%c%s",path,PATHSEP,FindFileData.cFileName);
1607
 
 
1608
 
                ftype = GetFileLength(fname);
1609
 
 
1610
 
                if((ftype == -2) && (FindFileData.cFileName[0] != '.'))
1611
 
                {
1612
 
                        // a sub-sirectory
1613
 
                        GetVoices(fname);
1614
 
                }
1615
 
                else
1616
 
                if(ftype > 0)
1617
 
                {
1618
 
                        // a regular line, add it to the voices list    
1619
 
                        if((f_voice = fopen(fname,"r")) == NULL)
1620
 
                                continue;
1621
 
                
1622
 
                        // pass voice file name within the voices directory
1623
 
                        voice_data = ReadVoiceFile(f_voice, fname+len_path_voices, FindFileData.cFileName);
1624
 
                        fclose(f_voice);
1625
 
 
1626
 
                        if(voice_data != NULL)
1627
 
                        {
1628
 
                                voices_list[n_voices_list++] = voice_data;
 
1711
                if(n_voices_list >= (N_VOICES_LIST-2))
 
1712
                        break;   // voices list is full
 
1713
 
 
1714
                if(FindFileData.cFileName[0] != '.')
 
1715
                {
 
1716
                        sprintf(fname,"%s%c%s",path,PATHSEP,FindFileData.cFileName);
 
1717
                        ftype = GetFileLength(fname);
 
1718
 
 
1719
                        if(ftype == -2)
 
1720
                        {
 
1721
                                // a sub-sirectory
 
1722
                                GetVoices(fname);
 
1723
                        }
 
1724
                        else if(ftype > 0)
 
1725
                        {
 
1726
                                // a regular line, add it to the voices list
 
1727
                                if((f_voice = fopen(fname,"r")) == NULL)
 
1728
                                        continue;
 
1729
 
 
1730
                                // pass voice file name within the voices directory
 
1731
                                voice_data = ReadVoiceFile(f_voice, fname+len_path_voices, FindFileData.cFileName);
 
1732
                                fclose(f_voice);
 
1733
 
 
1734
                                if(voice_data != NULL)
 
1735
                                {
 
1736
                                        voices_list[n_voices_list++] = voice_data;
 
1737
                                }
1629
1738
                        }
1630
1739
                }
1631
1740
        } while(FindNextFileA(hFind, &FindFileData) != 0);
1643
1752
                if(n_voices_list >= (N_VOICES_LIST-2))
1644
1753
                        break;   // voices list is full
1645
1754
 
 
1755
                if(ent->d_name[0] == '.')
 
1756
                        continue;
 
1757
 
1646
1758
                sprintf(fname,"%s%c%s",path,PATHSEP,ent->d_name);
1647
1759
 
1648
1760
                ftype = GetFileLength(fname);
1649
1761
 
1650
 
                if((ftype == -2) && (ent->d_name[0] != '.'))
 
1762
                if(ftype == -2)
1651
1763
                {
1652
1764
                        // a sub-sirectory
1653
1765
                        GetVoices(fname);
1654
1766
                }
1655
 
                else
1656
 
                if(ftype > 0)
 
1767
                else if(ftype > 0)
1657
1768
                {
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)
1660
1771
                                continue;
1661
 
                
 
1772
 
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;
 
1793
        int ix;
1682
1794
        espeak_VOICE voice_selector;
1683
1795
        char *variant_name;
1684
1796
        static char buf[60];
1685
1797
 
1686
1798
        strncpy0(buf,name,sizeof(buf));
 
1799
 
1687
1800
        variant_name = ExtractVoiceVariantName(buf, 0, 1);
1688
1801
 
 
1802
        for(ix=0; ; ix++)
 
1803
        {
 
1804
                // convert voice name to lower case  (ascii)
 
1805
                if((buf[ix] = tolower(buf[ix])) == 0)
 
1806
                        break;
 
1807
        }
 
1808
 
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 ??
1692
1811
 
1693
1812
        // first check for a voice with this filename
1701
1820
                }
1702
1821
 
1703
1822
                DoVoiceChange(voice);
 
1823
                voice_selector.languages = voice->language_name;
1704
1824
                SetVoiceStack(&voice_selector, variant_name);
1705
1825
                return(EE_OK);
1706
1826
        }
1717
1837
                                LoadVoice(variant_name,2);
1718
1838
                        }
1719
1839
                        DoVoiceChange(voice);
 
1840
                        voice_selector.languages = voice->language_name;
1720
1841
                        SetVoiceStack(&voice_selector, variant_name);
1721
1842
                        return(EE_OK);
1722
1843
                }
1766
1887
 
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];
 
1891
 
 
1892
 
 
1893
#ifdef PLATFORM_RISCOS
 
1894
        if(n_voices_list == 0)
 
1895
        {
 
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
 
1900
        }
 
1901
        return((const espeak_VOICE **)voices_list);
 
1902
 
 
1903
#else
1770
1904
        int ix;
1771
1905
        int j;
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;
1775
1908
 
1776
1909
        // free previous voice list data
1777
1910
        FreeVoiceList();
1781
1914
 
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));
1784
1918
 
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);
1788
1922
 
1789
1923
 
1790
1924
        if(voice_spec)
1794
1928
        }
1795
1929
        else
1796
1930
        {
1797
 
                // list all: omit variant voices and mbrola voices
 
1931
                // list all: omit variant voices and mbrola voices and test voices
1798
1932
                j = 0;
1799
1933
                for(ix=0; (v = voices_list[ix]) != NULL; ix++)
1800
1934
                {
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))
1802
1937
                        {
1803
1938
                                voices[j++] = v;
1804
1939
                        }
1807
1942
        }
1808
1943
        return((const espeak_VOICE **)voices);
1809
1944
#endif
1810
 
        return((const espeak_VOICE **)voices_list);
1811
1945
}  //  end of espeak_ListVoices
1812
1946
 
1813
1947