mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-11-11 08:30:31 +00:00
[1.42.21]
New format for phoneme source files. Update phoneme data for Klatt synthesizer. git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@235 d46cf337-b52f-0410-862d-fd96e6ae7743
This commit is contained in:
+2305
-1513
File diff suppressed because it is too large
Load Diff
+71
-70
@@ -36,7 +36,6 @@
|
||||
#include "translate.h"
|
||||
|
||||
|
||||
|
||||
int dictionary_skipwords;
|
||||
char dictionary_name[40];
|
||||
|
||||
@@ -482,7 +481,7 @@ void DecodePhonemes(const char *inptr, char *outptr)
|
||||
if((ph = phoneme_tab[phcode]) == NULL)
|
||||
continue;
|
||||
|
||||
if((ph->type == phSTRESS) && (ph->std_length <= 4) && (ph->spect == 0))
|
||||
if((ph->type == phSTRESS) && (ph->std_length <= 4) && (ph->program == 0))
|
||||
{
|
||||
if(ph->std_length > 1)
|
||||
*outptr++ = stress_chars[ph->std_length];
|
||||
@@ -847,26 +846,26 @@ return(0);
|
||||
|
||||
|
||||
|
||||
static int GetVowelStress(Translator *tr, unsigned char *phonemes, unsigned 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
|
||||
unsigned char phcode;
|
||||
PHONEME_TAB *ph;
|
||||
unsigned char *ph_out = phonemes;
|
||||
int count = 1;
|
||||
int max_stress = 0;
|
||||
int max_stress = -1;
|
||||
int ix;
|
||||
int j;
|
||||
int stress = 0;
|
||||
int stress = -1;
|
||||
int primary_posn = 0;
|
||||
|
||||
vowel_stress[0] = 0;
|
||||
vowel_stress[0] = 1;
|
||||
while(((phcode = *phonemes++) != 0) && (count < (N_WORD_PHONEMES/2)-1))
|
||||
{
|
||||
if((ph = phoneme_tab[phcode]) == NULL)
|
||||
continue;
|
||||
|
||||
if((ph->type == phSTRESS) && (ph->spect == 0))
|
||||
if((ph->type == phSTRESS) && (ph->program == 0))
|
||||
{
|
||||
/* stress marker, use this for the following vowel */
|
||||
|
||||
@@ -876,7 +875,7 @@ static int GetVowelStress(Translator *tr, unsigned char *phonemes, unsigned char
|
||||
j = count - 1;
|
||||
while((j > 0) && (stressed_syllable == 0) && (vowel_stress[j] < 4))
|
||||
{
|
||||
if(vowel_stress[j] != 1)
|
||||
if((vowel_stress[j] != 0) && (vowel_stress[j] != 1))
|
||||
{
|
||||
// don't promote a phoneme which must be unstressed
|
||||
vowel_stress[j] = 4;
|
||||
@@ -920,11 +919,11 @@ static int GetVowelStress(Translator *tr, unsigned char *phonemes, unsigned char
|
||||
max_stress = stress;
|
||||
}
|
||||
|
||||
if((stress == 0) && (control & 1) && (ph->phflags & phUNSTRESSED))
|
||||
if((stress < 0) && (control & 1) && (ph->phflags & phUNSTRESSED))
|
||||
vowel_stress[count] = 1; /* weak vowel, must be unstressed */
|
||||
|
||||
count++;
|
||||
stress = 0;
|
||||
stress = -1;
|
||||
}
|
||||
else
|
||||
if(phcode == phonSYLLABIC)
|
||||
@@ -937,7 +936,7 @@ static int GetVowelStress(Translator *tr, unsigned char *phonemes, unsigned char
|
||||
|
||||
*ph_out++ = phcode;
|
||||
}
|
||||
vowel_stress[count] = 0;
|
||||
vowel_stress[count] = 1;
|
||||
*ph_out = 0;
|
||||
|
||||
/* has the position of the primary stress been specified by $1, $2, etc? */
|
||||
@@ -959,7 +958,7 @@ static int GetVowelStress(Translator *tr, unsigned char *phonemes, unsigned char
|
||||
if(vowel_stress[ix] == 4)
|
||||
{
|
||||
if(tr->langopts.stress_flags & 0x20000)
|
||||
vowel_stress[ix] = 0;
|
||||
vowel_stress[ix] = 1;
|
||||
else
|
||||
vowel_stress[ix] = 3;
|
||||
}
|
||||
@@ -980,7 +979,7 @@ static int GetVowelStress(Translator *tr, unsigned char *phonemes, unsigned char
|
||||
|
||||
|
||||
|
||||
static char stress_phonemes[] = {phonSTRESS_U, phonSTRESS_D, phonSTRESS_2, phonSTRESS_3,
|
||||
static char stress_phonemes[] = {phonSTRESS_D, phonSTRESS_U, phonSTRESS_2, phonSTRESS_3,
|
||||
phonSTRESS_P, phonSTRESS_P2, phonSTRESS_TONIC};
|
||||
|
||||
|
||||
@@ -992,7 +991,7 @@ void ChangeWordStress(Translator *tr, char *word, int new_stress)
|
||||
int vowel_count; // num of vowels + 1
|
||||
int stressed_syllable=0; // position of stressed syllable
|
||||
unsigned char phonetic[N_WORD_PHONEMES];
|
||||
unsigned char vowel_stress[N_WORD_PHONEMES/2];
|
||||
signed char vowel_stress[N_WORD_PHONEMES/2];
|
||||
|
||||
strcpy((char *)phonetic,word);
|
||||
max_stress = GetVowelStress(tr, phonetic, vowel_stress, vowel_count, stressed_syllable, 0);
|
||||
@@ -1026,8 +1025,8 @@ void ChangeWordStress(Translator *tr, char *word, int new_stress)
|
||||
{
|
||||
if((phoneme_tab[*p]->type == phVOWEL) && !(phoneme_tab[*p]->phflags & phNONSYLLABIC))
|
||||
{
|
||||
if(vowel_stress[ix] != 0)
|
||||
*word++ = stress_phonemes[vowel_stress[ix]];
|
||||
if((vowel_stress[ix] == 0) || (vowel_stress[ix] > 1))
|
||||
*word++ = stress_phonemes[(unsigned char)vowel_stress[ix]];
|
||||
|
||||
ix++;
|
||||
}
|
||||
@@ -1073,7 +1072,7 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags,
|
||||
int done;
|
||||
int stressflags;
|
||||
|
||||
unsigned char vowel_stress[N_WORD_PHONEMES/2];
|
||||
signed char vowel_stress[N_WORD_PHONEMES/2];
|
||||
char syllable_weight[N_WORD_PHONEMES/2];
|
||||
char vowel_length[N_WORD_PHONEMES/2];
|
||||
unsigned char phonetic[N_WORD_PHONEMES];
|
||||
@@ -1116,12 +1115,15 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags,
|
||||
}
|
||||
|
||||
max_stress = GetVowelStress(tr, phonetic, vowel_stress, vowel_count, stressed_syllable, 1);
|
||||
|
||||
if((max_stress == 0) && (tr->langopts.stress_flags & 1) && (vowel_count == 2))
|
||||
if(max_stress < 0)
|
||||
{
|
||||
// option: don't stress monosyllables except at end-of-clause
|
||||
vowel_stress[1] = 1;
|
||||
dictionary_flags[0] |= FLAG_STRESS_END2;
|
||||
if((tr->langopts.stress_flags & 1) && (vowel_count == 2))
|
||||
{
|
||||
// lang=fr: don't stress monosyllables except at end-of-clause
|
||||
vowel_stress[1] = 0;
|
||||
dictionary_flags[0] |= FLAG_STRESS_END2;
|
||||
}
|
||||
max_stress = 0;
|
||||
}
|
||||
|
||||
// heavy or light syllables
|
||||
@@ -1233,7 +1235,7 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags,
|
||||
}
|
||||
}
|
||||
|
||||
if(vowel_stress[stressed_syllable] == 1)
|
||||
if((vowel_stress[stressed_syllable] == 0) || (vowel_stress[stressed_syllable] == 1))
|
||||
{
|
||||
// but this vowel is explicitly marked as unstressed
|
||||
if(stressed_syllable > 1)
|
||||
@@ -1248,7 +1250,7 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags,
|
||||
}
|
||||
|
||||
// only set the stress if it's not already marked explicitly
|
||||
if(vowel_stress[stressed_syllable] == 0)
|
||||
if(vowel_stress[stressed_syllable] < 0)
|
||||
{
|
||||
// don't stress if next and prev syllables are stressed
|
||||
if((vowel_stress[stressed_syllable-1] < 4) || (vowel_stress[stressed_syllable+1] < 4))
|
||||
@@ -1267,7 +1269,7 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags,
|
||||
while(stressed_syllable > 0)
|
||||
{
|
||||
// find the last vowel which is not unstressed
|
||||
if(vowel_stress[stressed_syllable] == 0)
|
||||
if(vowel_stress[stressed_syllable] < 0)
|
||||
{
|
||||
vowel_stress[stressed_syllable] = 4;
|
||||
break;
|
||||
@@ -1329,7 +1331,7 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags,
|
||||
// find the heaviest syllable, excluding the final syllable
|
||||
for(ix = 1; ix < (vowel_count-1); ix++)
|
||||
{
|
||||
if(vowel_stress[ix] == 0)
|
||||
if(vowel_stress[ix] < 0)
|
||||
{
|
||||
if((wt = syllable_weight[ix]) >= max_weight)
|
||||
{
|
||||
@@ -1377,7 +1379,7 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags,
|
||||
case 9: // mark all as stressed
|
||||
for(ix=1; ix<vowel_count; ix++)
|
||||
{
|
||||
if(vowel_stress[ix] == 0)
|
||||
if(vowel_stress[ix] < 0)
|
||||
vowel_stress[ix] = 4;
|
||||
}
|
||||
break;
|
||||
@@ -1399,7 +1401,7 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags,
|
||||
vowel_stress[1] = 3;
|
||||
}
|
||||
|
||||
if((stressflags & 0x2000) && (vowel_stress[1] == 0))
|
||||
if((stressflags & 0x2000) && (vowel_stress[1] < 0))
|
||||
{
|
||||
// If there is only one syllable before the primary stress, give it a secondary stress
|
||||
if((vowel_count > 2) && (vowel_stress[2] >= 4))
|
||||
@@ -1411,7 +1413,7 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags,
|
||||
done = 0;
|
||||
for(v=1; v<vowel_count; v++)
|
||||
{
|
||||
if(vowel_stress[v] == 0)
|
||||
if(vowel_stress[v] < 0)
|
||||
{
|
||||
if((stressflags & 0x10) && (stress < 4) && (v == vowel_count-1))
|
||||
{
|
||||
@@ -1541,33 +1543,33 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags,
|
||||
if((v > 1) && (max_stress >= 4) && (stressflags & 4) && (v == (vowel_count-1)))
|
||||
{
|
||||
// option: mark unstressed final syllable as diminished
|
||||
v_stress = 1;
|
||||
v_stress = 0;
|
||||
}
|
||||
else
|
||||
if((stressflags & 2) || (v == 1) || (v == (vowel_count-1)))
|
||||
{
|
||||
// first or last syllable, or option 'don't set diminished stress'
|
||||
v_stress = 0;
|
||||
v_stress = 1;
|
||||
}
|
||||
else
|
||||
if((v == (vowel_count-2)) && (vowel_stress[vowel_count-1] <= 1))
|
||||
{
|
||||
// penultimate syllable, followed by an unstressed final syllable
|
||||
v_stress = 0;
|
||||
v_stress = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// unstressed syllable within a word
|
||||
if((vowel_stress[v-1] != 1) || ((stressflags & 0x10000) == 0))
|
||||
if((vowel_stress[v-1] < 0) || ((stressflags & 0x10000) == 0))
|
||||
{
|
||||
v_stress = 1; /* change from 0 (unstressed) to 1 (diminished stress) */
|
||||
v_stress = 0; /* change to 0 (diminished stress) */
|
||||
vowel_stress[v] = v_stress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(v_stress > 0)
|
||||
*output++ = stress_phonemes[v_stress]; // mark stress of all vowels except 0 (unstressed)
|
||||
if((v_stress == 0) || (v_stress > 1))
|
||||
*output++ = stress_phonemes[v_stress]; // mark stress of all vowels except 1 (unstressed)
|
||||
|
||||
|
||||
if(vowel_stress[v] > max_stress)
|
||||
@@ -2830,39 +2832,39 @@ void ApplySpecialAttribute(Translator *tr, char *phonemes, int dict_flags)
|
||||
|
||||
// common letter pairs, encode these as a single byte
|
||||
static const short pairs_ru[] = {
|
||||
0x010c, // ла 21052 0x23
|
||||
0x010e, // на 18400
|
||||
0x0113, // та 14254
|
||||
0x0301, // ав 31083
|
||||
0x030f, // ов 13420
|
||||
0x060e, // не 21798
|
||||
0x0611, // ре 19458
|
||||
0x0903, // ви 16226
|
||||
0x0b01, // ак 14456
|
||||
0x0b0f, // ок 17836
|
||||
0x0c01, // ал 13324
|
||||
0x0c09, // ил 16877
|
||||
0x0e01, // ан 15359
|
||||
0x0e06, // ен 13543 0x30
|
||||
0x0e09, // ин 17168
|
||||
0x0e0e, // нн 15973
|
||||
0x0e0f, // он 22373
|
||||
0x0e1c, // ын 15052
|
||||
0x0f03, // во 24947
|
||||
0x0f11, // ро 13552
|
||||
0x0f12, // со 16368
|
||||
0x100f, // оп 19054
|
||||
0x1011, // рп 17067
|
||||
0x1101, // ар 23967
|
||||
0x1106, // ер 18795
|
||||
0x1109, // ир 13797
|
||||
0x110f, // ор 21737
|
||||
0x1213, // тс 25076
|
||||
0x1220, // яс 14310
|
||||
0x010c, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂûÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂð 21052 0x23
|
||||
0x010e, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂýÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂð 18400
|
||||
0x0113, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂð 14254
|
||||
0x0301, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂðÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂò 31083
|
||||
0x030f, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂþÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂò 13420
|
||||
0x060e, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂýÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂõ 21798
|
||||
0x0611, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂõ 19458
|
||||
0x0903, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂòÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂø 16226
|
||||
0x0b01, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂðÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂú 14456
|
||||
0x0b0f, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂþÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂú 17836
|
||||
0x0c01, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂðÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂû 13324
|
||||
0x0c09, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂøÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂû 16877
|
||||
0x0e01, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂðÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂý 15359
|
||||
0x0e06, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂõÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂý 13543 0x30
|
||||
0x0e09, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂøÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂý 17168
|
||||
0x0e0e, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂýÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂý 15973
|
||||
0x0e0f, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂþÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂý 22373
|
||||
0x0e1c, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂý 15052
|
||||
0x0f03, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂòÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂþ 24947
|
||||
0x0f11, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂþ 13552
|
||||
0x0f12, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂþ 16368
|
||||
0x100f, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂþÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÿ 19054
|
||||
0x1011, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÿ 17067
|
||||
0x1101, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂðÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂà23967
|
||||
0x1106, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂõÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂà18795
|
||||
0x1109, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂøÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂà13797
|
||||
0x110f, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂþÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂà21737
|
||||
0x1213, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂ 25076
|
||||
0x1220, // ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂ 14310
|
||||
0x7fff};
|
||||
//0x040f ог 12976
|
||||
//0x1306 ет 12826
|
||||
//0x0f0d мо 12688
|
||||
//0x040f ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂþÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂó 12976
|
||||
//0x1306 ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂõÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂà12826
|
||||
//0x0f0d ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂüÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂþ 12688
|
||||
|
||||
|
||||
int TransposeAlphabet(char *text, int offset, int min, int max)
|
||||
@@ -2985,7 +2987,6 @@ static const char *LookupDict2(Translator *tr, const char *word, const char *wor
|
||||
wlen = strlen(word);
|
||||
}
|
||||
|
||||
|
||||
hash = HashDictionary(word);
|
||||
p = tr->dict_hashtab[hash];
|
||||
|
||||
|
||||
+5
-5
@@ -37,8 +37,8 @@ static const char *help_text =
|
||||
"\nspeak [options] [\"<words>\"]\n\n"
|
||||
"-f <text file> Text file to speak\n"
|
||||
"--stdin Read text input from stdin instead of a file\n\n"
|
||||
"If neither -f nor --stdin, <words> are spoken, or if none then text is\n"
|
||||
"spoken from stdin, each line separately.\n\n"
|
||||
"If neither -f nor --stdin, then <words> are spoken, or if none then text\n"
|
||||
"is spoken from stdin, each line separately.\n\n"
|
||||
"-a <integer>\n"
|
||||
"\t Amplitude, 0 to 200, default is 100\n"
|
||||
"-g <integer>\n"
|
||||
@@ -63,11 +63,11 @@ static const char *help_text =
|
||||
"--stdout Write speech output to stdout\n"
|
||||
"--compile=<voice name>\n"
|
||||
"\t Compile the pronunciation rules and dictionary in the current\n"
|
||||
"\t directory. =<voice name> is optional and specifies which language\n"
|
||||
"\t directory. <voice name> specifies the language\n"
|
||||
"--path=\"<path>\"\n"
|
||||
"\t Specifies the directory containing the espeak-data directory\n"
|
||||
"--phonout=\"<filename>\"\n"
|
||||
"\t Write output from -x -X commands and mbrola phoneme data to this file\n"
|
||||
"\t Write output from -x -X commands, and mbrola phoneme data, to this file\n"
|
||||
"--punct=\"<characters>\"\n"
|
||||
"\t Speak the names of punctuation characters during speaking. If\n"
|
||||
"\t =<characters> is omitted, all punctuation is spoken.\n"
|
||||
@@ -78,7 +78,7 @@ static const char *help_text =
|
||||
"\t If <language> is omitted, then list all voices.\n"
|
||||
"-k <integer>\n"
|
||||
"\t Indicate capital letters with: 1=sound, 2=the word \"capitals\",\n"
|
||||
"\t higher values = a pitch increase (try -k20).\n";
|
||||
"\t higher values indicate a pitch increase (try -k20).\n";
|
||||
|
||||
|
||||
|
||||
|
||||
+3
-3
@@ -62,7 +62,7 @@ extern void ConvertToUtf8();
|
||||
extern void FormatDictionary(const char *dictname);
|
||||
|
||||
extern void init_z();
|
||||
extern void CompileInit(void);
|
||||
extern void CompilePhonemeData(void);
|
||||
extern void CompileMbrola();
|
||||
extern void InitSpectrumDisplay();
|
||||
extern void InitProsodyDisplay();
|
||||
@@ -146,7 +146,7 @@ extern void VoiceReset(int control);
|
||||
|
||||
if(strcmp(param,"--compile")==0)
|
||||
{
|
||||
CompileInit();
|
||||
CompilePhonemeData();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
@@ -558,7 +558,7 @@ void MyFrame::OnTools(wxCommandEvent& event)
|
||||
break;
|
||||
|
||||
case MENU_COMPILE_PH:
|
||||
CompileInit();
|
||||
CompilePhonemeData();
|
||||
break;
|
||||
|
||||
case MENU_COMPILE_MBROLA:
|
||||
|
||||
+7
-8
@@ -232,7 +232,7 @@ static void DecodePhonemes2(const char *inptr, char *outptr)
|
||||
if((ph = phoneme_tab[phcode]) == NULL)
|
||||
continue;
|
||||
|
||||
if((ph->type == phSTRESS) && (ph->std_length <= 4) && (ph->spect == 0))
|
||||
if((ph->type == phSTRESS) && (ph->std_length <= 4) && (ph->program == 0))
|
||||
{
|
||||
if(ph->std_length > 2)
|
||||
*outptr++ = stress_chars[ph->std_length];
|
||||
@@ -305,7 +305,7 @@ void Lexicon_It(int pass)
|
||||
FILE *f_in;
|
||||
FILE *f_out;
|
||||
FILE *f_listx;
|
||||
FILE *f_list_in;
|
||||
FILE *f_list_in = NULL;
|
||||
long int displ;
|
||||
const char *alt_string;
|
||||
char buf[200];
|
||||
@@ -1322,8 +1322,8 @@ void FormatDictionary(const char *dictname)
|
||||
char *p_start;
|
||||
unsigned short *pw;
|
||||
unsigned short *pw_match;
|
||||
unsigned short *pw_post;
|
||||
unsigned short *pw_phonemes;
|
||||
unsigned short *pw_post = NULL;
|
||||
unsigned short *pw_phonemes = NULL;
|
||||
int c;
|
||||
int ix;
|
||||
int n_pre;
|
||||
@@ -1733,6 +1733,7 @@ void Test2()
|
||||
|
||||
|
||||
const char* text1 = "Hello world. Testing.";
|
||||
extern void TestCompile2(void);
|
||||
|
||||
void TestTest(int control)
|
||||
{//=======================
|
||||
@@ -1747,8 +1748,6 @@ void TestTest(int control)
|
||||
//CharsetToUnicode("ISO-8859-4");
|
||||
//CharsetToUnicode("ISCII");
|
||||
|
||||
return;
|
||||
|
||||
if(control==2)
|
||||
{
|
||||
return;
|
||||
@@ -1778,8 +1777,8 @@ if(control==2)
|
||||
espeak_SetSynthCallback(TestSynthCallback);
|
||||
espeak_SetUriCallback(TestUriCallback);
|
||||
|
||||
espeak_Synth(text1, strlen(text1)+1, 0, POS_CHARACTER, 0, espeakSSML|espeakCHARS_UTF8, &unique_identifier, (void *)user_data);
|
||||
espeak_Synth(text1, strlen(text1)+1, 0, POS_CHARACTER, 0, espeakSSML|espeakCHARS_UTF8, &unique_identifier, (void *)(user_data+1));
|
||||
espeak_Synth(textbuf, strlen(textbuf)+1, 0, POS_CHARACTER, 0, espeakSSML|espeakCHARS_UTF8, &unique_identifier, (void *)user_data);
|
||||
// espeak_Synth(text1, strlen(text1)+1, 0, POS_CHARACTER, 0, espeakSSML|espeakCHARS_UTF8, &unique_identifier, (void *)(user_data+1));
|
||||
|
||||
espeak_SetParameter(espeakPUNCTUATION, 1, 0);
|
||||
espeak_Synchronize();
|
||||
|
||||
+2
-2
@@ -840,7 +840,7 @@ static void CalcPitches_Tone(Translator *tr, int clause_tone)
|
||||
p->tone_ph = PhonemeCode2('4','4');
|
||||
|
||||
// tone 5 is unstressed (shorter)
|
||||
p->stresslevel = 1; // diminished stress
|
||||
p->stresslevel = 0; // diminished stress
|
||||
}
|
||||
}
|
||||
|
||||
@@ -859,7 +859,7 @@ static void CalcPitches_Tone(Translator *tr, int clause_tone)
|
||||
{
|
||||
tone_ph = p->tone_ph;
|
||||
|
||||
if(p->stresslevel != 1) // TEST, consider all syllables as stressed
|
||||
if(p->stresslevel != 0) // TEST, consider all syllables as stressed
|
||||
{
|
||||
if(ix == final_stressed)
|
||||
{
|
||||
|
||||
+67
-70
@@ -241,8 +241,6 @@ static int parwave(klatt_frame_ptr frame)
|
||||
static double sourc;
|
||||
int ix;
|
||||
|
||||
frame_init(frame); /* get parameters for next frame of speech */
|
||||
|
||||
flutter(frame); /* add f0 flutter */
|
||||
|
||||
#ifdef LOG_FRAMES
|
||||
@@ -468,7 +466,7 @@ if(option_log_frames)
|
||||
{
|
||||
temp = 32767.0;
|
||||
}
|
||||
|
||||
|
||||
*out_ptr++ = int(temp);
|
||||
*out_ptr++ = int(temp) >> 8;
|
||||
sample_count++;
|
||||
@@ -483,28 +481,36 @@ if(option_log_frames)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
function PARWAVE_INIT
|
||||
|
||||
Initialises all parameters used in parwave, sets resonator internal memory
|
||||
to zero.
|
||||
*/
|
||||
|
||||
static void reset_resonators()
|
||||
void KlattReset(int control)
|
||||
{
|
||||
int r_ix;
|
||||
#ifdef LOG_FRAMES
|
||||
if(option_log_frames)
|
||||
{
|
||||
FILE *f_log;
|
||||
f_log=fopen("log-klatt","a");
|
||||
if(f_log != NULL)
|
||||
|
||||
if(control == 2)
|
||||
{
|
||||
fprintf(f_log,"Reset\n");
|
||||
fclose(f_log);
|
||||
//Full reset
|
||||
kt_globals.FLPhz = (950 * kt_globals.samrate) / 10000;
|
||||
kt_globals.BLPhz = (630 * kt_globals.samrate) / 10000;
|
||||
kt_globals.minus_pi_t = -PI / kt_globals.samrate;
|
||||
kt_globals.two_pi_t = -2.0 * kt_globals.minus_pi_t;
|
||||
setabc(kt_globals.FLPhz,kt_globals.BLPhz,&(kt_globals.rsn[RLP]));
|
||||
|
||||
}
|
||||
|
||||
if(control > 0)
|
||||
{
|
||||
kt_globals.nper = 0;
|
||||
kt_globals.T0 = 0;
|
||||
kt_globals.nopen = 0;
|
||||
kt_globals.nmod = 0;
|
||||
|
||||
for(r_ix=RGL; r_ix < N_RSN; r_ix++)
|
||||
{
|
||||
kt_globals.rsn[r_ix].p1 = 0;
|
||||
kt_globals.rsn[r_ix].p2 = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for(r_ix=0; r_ix <= R6p; r_ix++)
|
||||
{
|
||||
@@ -514,22 +520,6 @@ if(option_log_frames)
|
||||
}
|
||||
|
||||
|
||||
void KlattReset()
|
||||
{
|
||||
kt_globals.FLPhz = (950 * kt_globals.samrate) / 10000;
|
||||
kt_globals.BLPhz = (630 * kt_globals.samrate) / 10000;
|
||||
kt_globals.minus_pi_t = -PI / kt_globals.samrate;
|
||||
kt_globals.two_pi_t = -2.0 * kt_globals.minus_pi_t;
|
||||
setabc(kt_globals.FLPhz,kt_globals.BLPhz,&(kt_globals.rsn[RLP]));
|
||||
kt_globals.nper = 0;
|
||||
kt_globals.T0 = 0;
|
||||
kt_globals.nopen = 0;
|
||||
kt_globals.nmod = 0;
|
||||
|
||||
reset_resonators();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
function FRAME_INIT
|
||||
|
||||
@@ -996,6 +986,7 @@ int Wavegen_Klatt(int resume)
|
||||
int pk;
|
||||
int x;
|
||||
int ix;
|
||||
int fade;
|
||||
|
||||
if(resume==0)
|
||||
{
|
||||
@@ -1071,22 +1062,37 @@ int Wavegen_Klatt(int resume)
|
||||
if(kt_globals.nspfr > STEPSIZE)
|
||||
kt_globals.nspfr = STEPSIZE;
|
||||
|
||||
frame_init(&kt_frame); /* get parameters for next frame of speech */
|
||||
|
||||
if(parwave(&kt_frame) == 1)
|
||||
{
|
||||
return(1);
|
||||
return(1); // output buffer is full
|
||||
}
|
||||
}
|
||||
|
||||
if(end_wave == 1)
|
||||
if(end_wave > 0)
|
||||
{
|
||||
#ifdef deleted
|
||||
if(end_wave == 2)
|
||||
{
|
||||
fade = (kt_globals.T0 - kt_globals.nper)/4; // samples until end of current cycle
|
||||
if(fade < 64)
|
||||
fade = 64;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
fade = 64; // not followd by formant synthesis
|
||||
}
|
||||
|
||||
// fade out to avoid a click
|
||||
kt_globals.fadeout = 64;
|
||||
kt_globals.fadeout = fade;
|
||||
end_wave = 0;
|
||||
sample_count -= 64;
|
||||
kt_globals.nspfr = 64;
|
||||
sample_count -= fade;
|
||||
kt_globals.nspfr = fade;
|
||||
if(parwave(&kt_frame) == 1)
|
||||
{
|
||||
return(1);
|
||||
return(1); // output buffer is full
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1100,6 +1106,7 @@ void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v
|
||||
DOUBLEX next;
|
||||
int qix;
|
||||
int cmd;
|
||||
frame_t *fr3;
|
||||
static frame_t prev_fr;
|
||||
|
||||
if(wvoice != NULL)
|
||||
@@ -1129,6 +1136,17 @@ void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v
|
||||
if(cmd==WCMD_KLATT)
|
||||
{
|
||||
end_wave = 0; // next wave generation is from another spectrum
|
||||
|
||||
fr3 = (frame_t *)wcmdq[qix][2];
|
||||
for(ix=1; ix<6; ix++)
|
||||
{
|
||||
if(fr3->ffreq[ix] != fr2->ffreq[ix])
|
||||
{
|
||||
// there is a discontinuity in formants
|
||||
end_wave = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if((cmd==WCMD_WAVE) || (cmd==WCMD_PAUSE))
|
||||
@@ -1162,39 +1180,18 @@ if(option_log_frames)
|
||||
|
||||
if(control & 1)
|
||||
{
|
||||
if(wdata.prev_was_synth == 0)
|
||||
for(ix=1; ix<6; ix++)
|
||||
{
|
||||
// A break, not following on from another synthesized sound.
|
||||
// Reset the synthesizer
|
||||
KlattReset();
|
||||
}
|
||||
else
|
||||
{
|
||||
for(ix=1; ix<6; ix++)
|
||||
if(prev_fr.ffreq[ix] != fr1->ffreq[ix])
|
||||
{
|
||||
if(prev_fr.ffreq[ix] != fr1->ffreq[ix])
|
||||
{
|
||||
// Discontinuity in formants.
|
||||
// fade out to avoid a click, but only up to the end of output buffer
|
||||
ix = (out_end - out_ptr)/2;
|
||||
if(ix > 64)
|
||||
ix = 64;
|
||||
kt_globals.fadeout = ix;
|
||||
kt_globals.nspfr = ix;
|
||||
parwave(&kt_frame);
|
||||
reset_resonators();
|
||||
break;
|
||||
}
|
||||
// Discontinuity in formants.
|
||||
// end_wave was set in SetSynth_Klatt() to fade out the previous frame
|
||||
KlattReset(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
wdata.prev_was_synth = 1;
|
||||
memcpy(&prev_fr,fr2,sizeof(prev_fr));
|
||||
}
|
||||
if(fr2->frflags & FRFLAG_BREAK)
|
||||
{
|
||||
// fr2 = fr1;
|
||||
// reset_resonators(&kt_globals);
|
||||
}
|
||||
|
||||
for(ix=0; ix<N_KLATTP; ix++)
|
||||
{
|
||||
@@ -1313,7 +1310,7 @@ void KlattInit()
|
||||
kt_globals.outsl = 0;
|
||||
kt_globals.f0_flutter = 20;
|
||||
|
||||
KlattReset();
|
||||
KlattReset(2);
|
||||
|
||||
// set default values for frame parameters
|
||||
for(ix=0; ix<=9; ix++)
|
||||
|
||||
+12
-17
@@ -48,6 +48,7 @@
|
||||
#define phAPPENDPH 0x2000 // always insert another phoneme (link_out) after this one
|
||||
#define phBRKAFTER 0x4000 // [*] add a post-pause
|
||||
#define phBEFOREPAUSE 0x8000 // replace with the link_out phoneme if the next phoneme is a pause
|
||||
#define phSINGLE_INSTN 0x1000 // this phoneme has a single instruction program, with an implicit Return
|
||||
|
||||
#define phALTERNATIVE 0x1c00 // bits 10,11,12 specifying use of alternative_ph
|
||||
#define phBEFOREVOWEL 0x0000
|
||||
@@ -61,6 +62,7 @@
|
||||
#define phLONG 0x200000
|
||||
#define phLENGTHENSTOP 0x400000 // make the pre-pause slightly longer
|
||||
#define phRHOTIC 0x800000
|
||||
#define phLOCAL 0x80000000 // used during compilation
|
||||
|
||||
// fixed phoneme code numbers, these can be used from the program code
|
||||
#define phonCONTROL 1
|
||||
@@ -78,7 +80,6 @@
|
||||
#define phonSCHWA 13
|
||||
#define phonSCHWA_SHORT 14
|
||||
#define phonEND_WORD 15
|
||||
#define phonSONORANT 16
|
||||
#define phonDEFAULTTONE 17
|
||||
#define phonCAPITAL 18
|
||||
#define phonGLOTTALSTOP 19
|
||||
@@ -90,6 +91,7 @@
|
||||
#define phonT_REDUCED 25
|
||||
#define phonSTRESS_TONIC 26
|
||||
#define phonPAUSE_CLAUSE 27
|
||||
#define phonVOWELTYPES 28 // 28 to 33
|
||||
|
||||
extern const unsigned char pause_phonemes[8]; // 0, vshort, short, pause, long, glottalstop
|
||||
|
||||
@@ -103,29 +105,22 @@ extern const unsigned char pause_phonemes[8]; // 0, vshort, short, pause, long,
|
||||
#define N_PHONEME_TAB_NAME 32 // must be multiple of 4
|
||||
|
||||
// main table of phonemes, index by phoneme number (1-254)
|
||||
|
||||
typedef struct {
|
||||
unsigned int mnemonic; // 1st char is in the l.s.byte
|
||||
unsigned int phflags; // bits 28-30 reduce_to level, bits 16-19 place of articulation
|
||||
// bits 10-11 alternative ph control
|
||||
|
||||
unsigned short std_length; // for vowels, in mS; for phSTRESS, the stress/tone type
|
||||
unsigned short spect;
|
||||
unsigned short before;
|
||||
unsigned short after;
|
||||
|
||||
unsigned char code; // the phoneme number
|
||||
unsigned char type; // phVOWEL, phPAUSE, phSTOP etc
|
||||
unsigned int mnemonic; // 1st char is in the l.s.byte
|
||||
unsigned int phflags; // bits 16-19 place of articulation
|
||||
unsigned short program;
|
||||
unsigned char code; // the phoneme number
|
||||
unsigned char type; // phVOWEL, phPAUSE, phSTOP etc
|
||||
unsigned char start_type;
|
||||
unsigned char end_type;
|
||||
|
||||
unsigned char length_mod; // a length_mod group number, used to access length_mod_tab
|
||||
unsigned char reduce_to; // change to this phoneme if unstressed
|
||||
unsigned char alternative_ph; // change to this phoneme if a vowel follows/doesn't follow
|
||||
unsigned char link_out; // insert linking phoneme if a vowel follows
|
||||
unsigned char std_length; // for vowels, in mS/2; for phSTRESS, the stress/tone type
|
||||
unsigned char length_mod; // a length_mod group number, used to access length_mod_tab
|
||||
|
||||
} PHONEME_TAB;
|
||||
|
||||
|
||||
|
||||
// Several phoneme tables may be loaded into memory. phoneme_tab points to
|
||||
// one for the current voice
|
||||
extern int n_phoneme_tab;
|
||||
|
||||
+103
-211
@@ -38,20 +38,8 @@ extern PHONEME_LIST2 ph_list2[N_PHONEME_LIST]; // first stage of text->phonemes
|
||||
|
||||
|
||||
|
||||
static int ChangePhonemes(Translator *tr, PHONEME_LIST2 *phlist, int n_ph, int index, PHONEME_TAB *ph, CHANGEPH *ch)
|
||||
{//=================================================================================================================
|
||||
// Called for each phoneme in the phoneme list, to allow a language to make changes
|
||||
// ph The current phoneme
|
||||
|
||||
if(tr->translator_name == L('r','u'))
|
||||
return(ChangePhonemes_ru(tr, phlist, n_ph, index, ph, ch));
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
static int SubstitutePhonemes(Translator *tr, PHONEME_LIST2 *plist_out)
|
||||
{//====================================================================
|
||||
static int SubstitutePhonemes(Translator *tr, PHONEME_LIST *plist_out)
|
||||
{//===================================================================
|
||||
// Copy the phonemes list and perform any substitutions that are required for the
|
||||
// current voice
|
||||
int ix;
|
||||
@@ -59,14 +47,8 @@ static int SubstitutePhonemes(Translator *tr, PHONEME_LIST2 *plist_out)
|
||||
int replace_flags;
|
||||
int n_plist_out = 0;
|
||||
int word_end;
|
||||
int max_stress = -1;
|
||||
int switched_language = 0;
|
||||
int max_stress_posn=0;
|
||||
int n_syllables = 0;
|
||||
int syllable = 0;
|
||||
int syllable_stressed = 0;
|
||||
PHONEME_LIST2 *plist2;
|
||||
PHONEME_LIST2 *pl;
|
||||
PHONEME_TAB *next=NULL;
|
||||
|
||||
for(ix=0; (ix < n_ph_list2) && (n_plist_out < N_PHONEME_LIST); ix++)
|
||||
@@ -86,66 +68,6 @@ static int SubstitutePhonemes(Translator *tr, PHONEME_LIST2 *plist_out)
|
||||
if((plist2+1)->sourceix || ((next != 0) && (next->type == phPAUSE)))
|
||||
word_end = 1; // this phoneme is the end of a word
|
||||
|
||||
if(tr->langopts.phoneme_change != 0)
|
||||
{
|
||||
// this language does changes to phonemes after translation
|
||||
|
||||
if(plist2->sourceix)
|
||||
{
|
||||
// start of a word, find the stressed vowel
|
||||
syllable = 0;
|
||||
syllable_stressed = 0;
|
||||
n_syllables = 0;
|
||||
|
||||
max_stress = -1;
|
||||
max_stress_posn = ix;
|
||||
for(k=ix; k < n_ph_list2; k++)
|
||||
{
|
||||
if(((pl = &ph_list2[k])->sourceix != 0) && (k > ix))
|
||||
break;
|
||||
|
||||
pl->stresslevel &= 0xf;
|
||||
|
||||
if(phoneme_tab[pl->phcode]->type == phVOWEL)
|
||||
{
|
||||
n_syllables++;
|
||||
|
||||
if(pl->stresslevel > max_stress)
|
||||
{
|
||||
syllable_stressed = n_syllables;
|
||||
max_stress = pl->stresslevel;
|
||||
max_stress_posn = k;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(phoneme_tab[plist2->phcode]->type == phVOWEL)
|
||||
{
|
||||
syllable++;
|
||||
}
|
||||
|
||||
// make any language specific changes
|
||||
int flags;
|
||||
CHANGEPH ch;
|
||||
flags = 0;
|
||||
if(ix == max_stress_posn)
|
||||
flags |= 2;
|
||||
if(ix > max_stress_posn)
|
||||
flags |= 4;
|
||||
if(ph_list2[ix].synthflags & SFLAG_DICTIONARY)
|
||||
flags |= 8;
|
||||
ch.flags = flags | word_end;
|
||||
|
||||
ch.stress = plist2->stresslevel;
|
||||
ch.stress_highest = max_stress;
|
||||
ch.n_vowels = n_syllables;
|
||||
ch.vowel_this = syllable;
|
||||
ch.vowel_stressed = syllable_stressed;
|
||||
|
||||
ChangePhonemes(tr, ph_list2, n_ph_list2, ix, phoneme_tab[ph_list2[ix].phcode], &ch);
|
||||
}
|
||||
|
||||
// check whether a Voice has specified that we should replace this phoneme
|
||||
for(k=0; k<n_replace_phonemes; k++)
|
||||
{
|
||||
@@ -174,7 +96,8 @@ static int SubstitutePhonemes(Translator *tr, PHONEME_LIST2 *plist_out)
|
||||
}
|
||||
|
||||
// copy phoneme into the output list
|
||||
memcpy(&plist_out[n_plist_out++],plist2,sizeof(PHONEME_LIST2));
|
||||
memcpy(&plist_out[n_plist_out],plist2,sizeof(PHONEME_LIST2));
|
||||
n_plist_out++;
|
||||
}
|
||||
return(n_plist_out);
|
||||
} // end of SubstitutePhonemes
|
||||
@@ -199,11 +122,15 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
int end_sourceix;
|
||||
int alternative;
|
||||
int first_vowel=0; // first vowel in a word
|
||||
PHONEME_LIST2 ph_list3[N_PHONEME_LIST];
|
||||
PHONEME_DATA phdata;
|
||||
|
||||
int n_ph_list3;
|
||||
PHONEME_LIST *plist3;
|
||||
PHONEME_LIST *plist3_inserted = NULL;
|
||||
PHONEME_LIST ph_list3[N_PHONEME_LIST];
|
||||
|
||||
static PHONEME_LIST2 ph_list2_null = {0,0,0,0,0};
|
||||
PHONEME_LIST2 *plist2 = &ph_list2_null;
|
||||
PHONEME_LIST2 *plist2_inserted = NULL;
|
||||
|
||||
plist2 = ph_list2;
|
||||
phlist = phoneme_list;
|
||||
@@ -271,9 +198,9 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
voicing = 1;
|
||||
}
|
||||
else
|
||||
if((voicing==2) && ((ph->phflags & phALTERNATIVE)==phSWITCHVOICING))
|
||||
if((voicing==2) && (ph->end_type != 0)) // use end_type field for voicing_switch for consonants
|
||||
{
|
||||
plist2[j].phcode = ph->alternative_ph; // change to voiced equivalent
|
||||
plist2[j].phcode = ph->end_type; // change to voiced equivalent
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -284,9 +211,9 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
voicing = 2;
|
||||
}
|
||||
else
|
||||
if((voicing==1) && ((ph->phflags & phALTERNATIVE)==phSWITCHVOICING))
|
||||
if((voicing==1) && (ph->end_type != 0))
|
||||
{
|
||||
plist2[j].phcode = ph->alternative_ph; // change to unvoiced equivalent
|
||||
plist2[j].phcode = ph->end_type; // change to unvoiced equivalent
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -310,47 +237,56 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
}
|
||||
}
|
||||
|
||||
n_ph_list2 = SubstitutePhonemes(tr,ph_list3) - 2;
|
||||
n_ph_list3 = SubstitutePhonemes(tr,ph_list3) - 2;
|
||||
|
||||
// transfer all the phonemes of the clause into phoneme_list
|
||||
ph = phoneme_tab[phonPAUSE];
|
||||
ph_list3[0].ph = ph;
|
||||
|
||||
switched_language = 0;
|
||||
|
||||
for(j=0; insert_ph || ((j < n_ph_list2) && (ix < N_PHONEME_LIST-3)); j++)
|
||||
for(j=0; insert_ph || ((j < n_ph_list3) && (ix < N_PHONEME_LIST-3)); j++)
|
||||
{
|
||||
prev = ph;
|
||||
|
||||
plist2 = &ph_list3[j];
|
||||
plist3 = &ph_list3[j];
|
||||
|
||||
if(insert_ph != 0)
|
||||
{
|
||||
// we have a (linking) phoneme which we need to insert here
|
||||
next = phoneme_tab[plist2->phcode]; // this phoneme, i.e. after the insert
|
||||
next = phoneme_tab[plist3->phcode]; // this phoneme, i.e. after the insert
|
||||
|
||||
// re-use the previous entry for the inserted phoneme.
|
||||
// That's OK because we don't look backwards from plist2
|
||||
// That's OK because we don't look backwards from plist3
|
||||
j--;
|
||||
plist2 = plist2_inserted = &ph_list3[j];
|
||||
memset(plist2, 0, sizeof(*plist2));
|
||||
plist2->phcode = insert_ph;
|
||||
plist3 = plist3_inserted = &ph_list3[j];
|
||||
if(j > 0)
|
||||
{
|
||||
memcpy(&plist3[-1], &plist3[0], sizeof(*plist3));
|
||||
}
|
||||
memset(&plist3[0], 0, sizeof(*plist3));
|
||||
plist3->phcode = insert_ph;
|
||||
ph = phoneme_tab[insert_ph];
|
||||
plist3->ph = ph;
|
||||
insert_ph = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise get the next phoneme from the list
|
||||
ph = phoneme_tab[plist2->phcode];
|
||||
ph = phoneme_tab[plist3->phcode];
|
||||
plist3[0].ph = ph;
|
||||
|
||||
if(plist2->phcode == phonSWITCH)
|
||||
if(plist3->phcode == phonSWITCH)
|
||||
{
|
||||
// change phoneme table
|
||||
SelectPhonemeTable(plist2->tone_ph);
|
||||
SelectPhonemeTable(plist3->tone_ph);
|
||||
switched_language ^= SFLAG_SWITCHED_LANG;
|
||||
}
|
||||
next = phoneme_tab[(plist2+1)->phcode]; // the phoneme after this one
|
||||
next = phoneme_tab[plist3[1].phcode]; // the phoneme after this one
|
||||
plist3[1].ph = next;
|
||||
}
|
||||
|
||||
if(plist2->sourceix)
|
||||
if(plist3->sourceix)
|
||||
{
|
||||
// start of a word
|
||||
int k;
|
||||
@@ -358,7 +294,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
first_vowel = 1;
|
||||
|
||||
// find the highest stress level in this word
|
||||
for(k=j+1; k < n_ph_list2; k++)
|
||||
for(k=j+1; k < n_ph_list3; k++)
|
||||
{
|
||||
if(ph_list3[k].sourceix)
|
||||
break; // start of the next word
|
||||
@@ -366,14 +302,46 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
if(ph_list3[k].stresslevel > word_stress)
|
||||
word_stress = ph_list3[k].stresslevel;
|
||||
}
|
||||
while(--k >= j)
|
||||
{
|
||||
ph_list3[k].wordstress = word_stress;
|
||||
}
|
||||
}
|
||||
|
||||
if(ph == NULL) continue;
|
||||
|
||||
InterpretPhoneme(tr, 0x100, plist3, &phdata);
|
||||
|
||||
if((alternative = phdata.pd_param[pd_CHANGEPHONEME]) == 1)
|
||||
continue; // NULL phoneme, discard
|
||||
|
||||
if(alternative > 1)
|
||||
{
|
||||
PHONEME_TAB *ph2;
|
||||
ph2 = ph;
|
||||
ph = phoneme_tab[alternative];
|
||||
plist3->phcode = alternative;
|
||||
plist3->ph = ph;
|
||||
|
||||
if(ph->type == phVOWEL)
|
||||
{
|
||||
plist3->synthflags |= SFLAG_SYLLABLE;
|
||||
if(ph2->type != phVOWEL)
|
||||
plist3->stresslevel = 0; // change from non-vowel to vowel, make sure it's unstressed
|
||||
}
|
||||
else
|
||||
plist3->synthflags &= ~SFLAG_SYLLABLE;
|
||||
|
||||
// re-interpret the changed phoneme
|
||||
// But it doesn't obey a second ChangePhoneme()
|
||||
InterpretPhoneme(tr, 0x100, plist3, &phdata);
|
||||
}
|
||||
|
||||
if(ph->type == phVOWEL)
|
||||
{
|
||||
// check for consecutive unstressed syllables
|
||||
if(plist2->stresslevel == 0)
|
||||
// Check for consecutive unstressed syllables, even across word boundaries.
|
||||
// Do this after changing phonemes according to stress level.
|
||||
if(plist3->stresslevel == 1)
|
||||
{
|
||||
// an unstressed vowel
|
||||
unstress_count++;
|
||||
@@ -381,14 +349,14 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
{
|
||||
// in a sequence of unstressed syllables, reduce alternate syllables to 'diminished'
|
||||
// stress. But not for the last phoneme of a stressed word
|
||||
if((tr->langopts.stress_flags & 0x2) || ((word_stress > 3) && ((plist2+1)->sourceix!=0)))
|
||||
if((tr->langopts.stress_flags & 0x2) || ((word_stress > 3) && ((plist3+1)->sourceix!=0)))
|
||||
{
|
||||
// An unstressed final vowel of a stressed word
|
||||
unstress_count=1; // try again for next syllable
|
||||
}
|
||||
else
|
||||
{
|
||||
plist2->stresslevel = 1; // change stress to 'diminished'
|
||||
plist3->stresslevel = 0; // change stress to 'diminished'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -398,82 +366,21 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
}
|
||||
}
|
||||
|
||||
alternative = 0;
|
||||
|
||||
if(ph->alternative_ph > 0)
|
||||
{
|
||||
switch(ph->phflags & phALTERNATIVE)
|
||||
{
|
||||
// This phoneme changes if vowel follows, or doesn't follow, depending on its phNOTFOLLOWS flag
|
||||
case phBEFORENOTVOWEL:
|
||||
if(next->type != phVOWEL)
|
||||
alternative = ph->alternative_ph;
|
||||
break;
|
||||
|
||||
case phBEFORENOTVOWEL2: // LANG=tr
|
||||
if(((plist2+1)->sourceix != 0) ||
|
||||
((next->type != phVOWEL) && ((phoneme_tab[(plist2+2)->phcode]->type != phVOWEL) || ((plist2+2)->sourceix != 0))))
|
||||
{
|
||||
alternative = ph->alternative_ph;
|
||||
}
|
||||
break;
|
||||
|
||||
case phBEFOREVOWELPAUSE:
|
||||
if((next->type == phVOWEL) || (next->type == phPAUSE))
|
||||
alternative = ph->alternative_ph;
|
||||
break;
|
||||
|
||||
case phBEFOREVOWEL:
|
||||
if(next->type == phVOWEL)
|
||||
alternative = ph->alternative_ph;
|
||||
break;
|
||||
|
||||
case phBEFORE_R:
|
||||
if(next->phflags & phRHOTIC)
|
||||
{
|
||||
alternative = ph->alternative_ph;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(ph->phflags & phBEFOREPAUSE)
|
||||
{
|
||||
if(next->type == phPAUSE)
|
||||
alternative = ph->link_out; // replace with the link_out phoneme
|
||||
}
|
||||
|
||||
if(alternative == 1)
|
||||
continue; // NULL phoneme, discard
|
||||
|
||||
if(alternative > 1)
|
||||
{
|
||||
PHONEME_TAB *ph2;
|
||||
ph2 = ph;
|
||||
ph = phoneme_tab[alternative];
|
||||
|
||||
if(ph->type == phVOWEL)
|
||||
{
|
||||
plist2->synthflags |= SFLAG_SYLLABLE;
|
||||
if(ph2->type != phVOWEL)
|
||||
plist2->stresslevel = 0; // change from non-vowel to vowel, make sure it's unstressed
|
||||
}
|
||||
else
|
||||
plist2->synthflags &= ~SFLAG_SYLLABLE;
|
||||
}
|
||||
|
||||
#ifdef deleted
|
||||
if(tr->langopts.param[LOPT_REDUCE_T])
|
||||
{
|
||||
if((ph->mnemonic == 't') && (plist2->sourceix == 0) && ((prev->type == phVOWEL) || (prev->mnemonic == 'n')))
|
||||
if((ph->mnemonic == 't') && (plist3->sourceix == 0) && ((prev->type == phVOWEL) || (prev->mnemonic == 'n')))
|
||||
{
|
||||
if(((plist2+1)->sourceix == 0) && ((plist2+1)->stresslevel < 3) && (next->type == phVOWEL))
|
||||
if(((plist3+1)->sourceix == 0) && ((plist3+1)->stress < 3) && (next->type == phVOWEL))
|
||||
{
|
||||
ph = phoneme_tab[phonT_REDUCED];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
while((ph->reduce_to != 0) && (!(plist2->synthflags & SFLAG_DICTIONARY) || (tr->langopts.param[LOPT_REDUCE] & 1)))
|
||||
#ifdef deleted
|
||||
while((ph->reduce_to != 0) && (!(plist3->synthflags & SFLAG_DICTIONARY) || (tr->langopts.param[LOPT_REDUCE] & 1)))
|
||||
{
|
||||
int reduce_level;
|
||||
int stress_level;
|
||||
@@ -483,13 +390,13 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
|
||||
if(ph->type == phVOWEL)
|
||||
{
|
||||
stress_level = plist2->stresslevel;
|
||||
stress_level = plist3->stress;
|
||||
}
|
||||
else
|
||||
{
|
||||
// consonant, get stress from the following vowel
|
||||
if(next->type == phVOWEL)
|
||||
stress_level = (plist2+1)->stresslevel;
|
||||
stress_level = (plist3+1)->stress;
|
||||
else
|
||||
break;
|
||||
}
|
||||
@@ -514,22 +421,23 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
else
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(ph->type == phVOWEL)
|
||||
first_vowel = 0;
|
||||
|
||||
if((plist2+1)->synthflags & SFLAG_LENGTHEN)
|
||||
if((plist3+1)->synthflags & SFLAG_LENGTHEN)
|
||||
{
|
||||
static char types_double[] = {phFRICATIVE,phVFRICATIVE,phNASAL,phLIQUID,0};
|
||||
if(strchr(types_double,next->type))
|
||||
{
|
||||
// lengthen this consonant by doubling it
|
||||
insert_ph = next->code;
|
||||
(plist2+1)->synthflags ^= SFLAG_LENGTHEN;
|
||||
(plist3+1)->synthflags ^= SFLAG_LENGTHEN;
|
||||
}
|
||||
}
|
||||
|
||||
if((plist2+1)->sourceix != 0)
|
||||
if((plist3+1)->sourceix != 0)
|
||||
{
|
||||
int x;
|
||||
|
||||
@@ -562,7 +470,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
insert_ph = phonPAUSE_VSHORT;
|
||||
}
|
||||
|
||||
if(((plist2+1)->stresslevel >= 4) && (tr->langopts.vowel_pause & 0x100))
|
||||
if(((plist3+1)->stresslevel >= 4) && (tr->langopts.vowel_pause & 0x100))
|
||||
{
|
||||
// pause before a words which starts with a stressed vowel
|
||||
insert_ph = phonPAUSE_SHORT;
|
||||
@@ -570,7 +478,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
}
|
||||
}
|
||||
|
||||
if(plist2 != plist2_inserted)
|
||||
if(plist3 != plist3_inserted)
|
||||
{
|
||||
if((x = (tr->langopts.word_gap & 0x7)) != 0)
|
||||
{
|
||||
@@ -587,33 +495,12 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
}
|
||||
}
|
||||
|
||||
next2 = phoneme_tab[(plist2+2)->phcode];
|
||||
next2 = phoneme_tab[plist3[2].phcode];
|
||||
plist3[2].ph = next2;
|
||||
|
||||
if((insert_ph == 0) && (ph->link_out != 0) && !(ph->phflags & phBEFOREPAUSE) && (((plist2+1)->synthflags & SFLAG_EMBEDDED)==0))
|
||||
if((insert_ph == 0) && (phdata.pd_param[pd_APPENDPHONEME] != 0))
|
||||
{
|
||||
if(ph->phflags & phAPPENDPH)
|
||||
{
|
||||
// always append the specified phoneme, unless it already is the next phoneme
|
||||
if((ph->link_out != (plist2+1)->phcode) && (next->type == phVOWEL))
|
||||
// if(ph->link_out != (plist2+1)->phcode)
|
||||
{
|
||||
insert_ph = ph->link_out;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(((tr->langopts.word_gap & 8)==0) || ((plist2+1)->sourceix == 0))
|
||||
{
|
||||
// This phoneme can be linked to a following vowel by inserting a linking phoneme
|
||||
if(next->type == phVOWEL)
|
||||
insert_ph = ph->link_out;
|
||||
else
|
||||
if(next->code == phonPAUSE_SHORT)
|
||||
{
|
||||
// Pause followed by Vowel, replace the Short Pause with the linking phoneme,
|
||||
if(next2->type == phVOWEL)
|
||||
(plist2+1)->phcode = ph->link_out; // replace pause by linking phoneme
|
||||
}
|
||||
}
|
||||
insert_ph = phdata.pd_param[pd_APPENDPHONEME];
|
||||
}
|
||||
|
||||
if(ph->phflags & phVOICED)
|
||||
@@ -627,14 +514,16 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
phlist[ix].ph = ph;
|
||||
phlist[ix].type = ph->type;
|
||||
phlist[ix].env = PITCHfall; // default, can be changed in the "intonation" module
|
||||
phlist[ix].synthflags = plist2->synthflags | switched_language;
|
||||
phlist[ix].stresslevel = plist2->stresslevel & 0xf;
|
||||
phlist[ix].tone_ph = plist2->tone_ph;
|
||||
phlist[ix].synthflags = plist3->synthflags | switched_language;
|
||||
phlist[ix].stresslevel = plist3->stresslevel & 0xf;
|
||||
phlist[ix].wordstress = plist3->wordstress;
|
||||
phlist[ix].tone_ph = plist3->tone_ph;
|
||||
phlist[ix].sourceix = 0;
|
||||
phlist[ix].phcode = ph->code;
|
||||
|
||||
if(plist2->sourceix != 0)
|
||||
if(plist3->sourceix != 0)
|
||||
{
|
||||
phlist[ix].sourceix = plist2->sourceix;
|
||||
phlist[ix].sourceix = plist3->sourceix;
|
||||
phlist[ix].newword = 1; // this phoneme is the start of a word
|
||||
|
||||
if(start_sentence)
|
||||
@@ -648,7 +537,8 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
phlist[ix].newword = 0;
|
||||
}
|
||||
|
||||
phlist[ix].length = ph->std_length;
|
||||
// phlist[ix].length = ph->std_length;
|
||||
phlist[ix].length = phdata.pd_param[i_SET_LENGTH]*2;
|
||||
if((ph->code == phonPAUSE_LONG) && (option_wordgap > 0))
|
||||
{
|
||||
phlist[ix].ph = phoneme_tab[phonPAUSE_SHORT];
|
||||
@@ -669,12 +559,14 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
}
|
||||
phlist[ix].newword = 2; // end of clause
|
||||
|
||||
phlist[ix].phcode = phonPAUSE;
|
||||
phlist[ix].type = phPAUSE; // terminate with 2 Pause phonemes
|
||||
phlist[ix].length = post_pause; // length of the pause, depends on the punctuation
|
||||
phlist[ix].sourceix = end_sourceix;
|
||||
phlist[ix].synthflags = 0;
|
||||
|
||||
phlist[ix++].ph = phoneme_tab[phonPAUSE];
|
||||
|
||||
phlist[ix].phcode = phonPAUSE;
|
||||
phlist[ix].type = phPAUSE;
|
||||
phlist[ix].length = 0;
|
||||
phlist[ix].sourceix=0;
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "phoneme.h"
|
||||
#include "synthesize.h"
|
||||
#include "prosodydisplay.h"
|
||||
#include "translate.h"
|
||||
|
||||
extern MyFrame *myframe;
|
||||
extern ChildFrProsody *prosodyframe;
|
||||
@@ -113,7 +114,7 @@ int ProsodyDisplay::GetWidth(PHONEME_LIST *p)
|
||||
if(p->ph == NULL)
|
||||
return(0);
|
||||
|
||||
w = p->ph->std_length;
|
||||
w = (p->ph->std_length * 2);
|
||||
if(w == 0) w = 60;
|
||||
|
||||
if(p->length != 0)
|
||||
@@ -334,6 +335,7 @@ void ProsodyDisplay::DrawEnv(wxDC& dc, int x1, int y1, int width, PHONEME_LIST *
|
||||
int x,y;
|
||||
int y2=0;
|
||||
unsigned char *env;
|
||||
PHONEME_DATA phdata_tone;
|
||||
|
||||
if(width <= 0) return;
|
||||
|
||||
@@ -354,7 +356,8 @@ void ProsodyDisplay::DrawEnv(wxDC& dc, int x1, int y1, int width, PHONEME_LIST *
|
||||
if((ph->type == phVOWEL) && (ph->tone_ph != 0))
|
||||
{
|
||||
// the envelope is given by a Tone phoneme acting on this vowel
|
||||
env = LookupEnvelope(phoneme_tab[ph->tone_ph]->spect);
|
||||
InterpretPhoneme2(ph->tone_ph, &phdata_tone);
|
||||
env = LookupEnvelope(phdata_tone.pitch_env);
|
||||
}
|
||||
|
||||
for(ix=0; ix<=width; ix+=4)
|
||||
|
||||
+10
-4
@@ -298,6 +298,7 @@ void CalcLengths(Translator *tr)
|
||||
int emphasized;
|
||||
int tone_mod;
|
||||
unsigned char *pitch_env=NULL;
|
||||
PHONEME_DATA phdata_tone;
|
||||
|
||||
for(ix=1; ix<n_phoneme_list; ix++)
|
||||
{
|
||||
@@ -408,7 +409,7 @@ void CalcLengths(Translator *tr)
|
||||
|
||||
case phLIQUID:
|
||||
case phNASAL:
|
||||
p->amp = tr->stress_amps[1]; // unless changed later
|
||||
p->amp = tr->stress_amps[0]; // unless changed later
|
||||
p->length = 256; // TEMPORARY
|
||||
min_drop = 0;
|
||||
|
||||
@@ -474,6 +475,10 @@ void CalcLengths(Translator *tr)
|
||||
|
||||
if(stress > 7) stress = 7;
|
||||
|
||||
if(stress <= 1)
|
||||
{
|
||||
stress = stress ^ 1; // swap diminished and unstressed (until we swap stress_amps,stress_lengths in tr_languages)
|
||||
}
|
||||
if(pre_sonorant)
|
||||
p->amp = tr->stress_amps[stress]-1;
|
||||
else
|
||||
@@ -562,7 +567,7 @@ void CalcLengths(Translator *tr)
|
||||
{
|
||||
length_mod += 20;
|
||||
}
|
||||
|
||||
|
||||
if((len = tr->stress_lengths[stress]) == 0)
|
||||
len = tr->stress_lengths[6];
|
||||
|
||||
@@ -580,7 +585,7 @@ void CalcLengths(Translator *tr)
|
||||
if(end_of_clause == 2)
|
||||
{
|
||||
// this is the last syllable in the clause, lengthen it - more for short vowels
|
||||
len = p->ph->std_length;
|
||||
len = (p->ph->std_length * 2);
|
||||
if(tr->langopts.stress_flags & 0x40000)
|
||||
len=200; // don't lengthen short vowels more than long vowels at end-of-clause
|
||||
length_mod = length_mod * (256 + (280 - len)/3)/256;
|
||||
@@ -608,7 +613,8 @@ if(p->type != phVOWEL)
|
||||
|
||||
if(p->tone_ph != 0)
|
||||
{
|
||||
pitch_env = LookupEnvelope(phoneme_tab[p->tone_ph]->spect);
|
||||
InterpretPhoneme2(p->tone_ph, &phdata_tone);
|
||||
pitch_env = LookupEnvelope(phdata_tone.pitch_env);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+5
-5
@@ -69,8 +69,8 @@ static const char *help_text =
|
||||
"\nspeak [options] [\"<words>\"]\n\n"
|
||||
"-f <text file> Text file to speak\n"
|
||||
"--stdin Read text input from stdin instead of a file\n\n"
|
||||
"If neither -f nor --stdin, <words> are spoken, or if none then text is\n"
|
||||
"spoken from stdin, each line separately.\n\n"
|
||||
"If neither -f nor --stdin, then <words> are spoken, or if none then text\n"
|
||||
"is spoken from stdin, each line separately.\n\n"
|
||||
"-a <integer>\n"
|
||||
"\t Amplitude, 0 to 200, default is 100\n"
|
||||
"-g <integer>\n"
|
||||
@@ -95,11 +95,11 @@ static const char *help_text =
|
||||
"--stdout Write speech output to stdout\n"
|
||||
"--compile=<voice name>\n"
|
||||
"\t Compile the pronunciation rules and dictionary in the current\n"
|
||||
"\t directory. =<voice name> is optional and specifies which language\n"
|
||||
"\t directory. <voice name> specifies the language\n"
|
||||
"--path=\"<path>\"\n"
|
||||
"\t Specifies the directory containing the espeak-data directory\n"
|
||||
"--phonout=\"<filename>\"\n"
|
||||
"\t Write output from -x -X commands and mbrola phoneme data to this file\n"
|
||||
"\t Write output from -x -X commands, and mbrola phoneme data, to this file\n"
|
||||
"--punct=\"<characters>\"\n"
|
||||
"\t Speak the names of punctuation characters during speaking. If\n"
|
||||
"\t =<characters> is omitted, all punctuation is spoken.\n"
|
||||
@@ -110,7 +110,7 @@ static const char *help_text =
|
||||
"\t If <language> is omitted, then list all voices.\n"
|
||||
"-k <integer>\n"
|
||||
"\t Indicate capital letters with: 1=sound, 2=the word \"capitals\",\n"
|
||||
"\t higher values = a pitch increase (try -k20).\n";
|
||||
"\t higher values indicate a pitch increase (try -k20).\n";
|
||||
|
||||
|
||||
void DisplayVoices(FILE *f_out, char *language);
|
||||
|
||||
@@ -171,6 +171,7 @@ void SpectDisplay::OnActivate(int active)
|
||||
}
|
||||
else
|
||||
{
|
||||
formantdlg->GetValues(spectseq, sframe);
|
||||
ReadDialogValues();
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -41,7 +41,7 @@ extern int Wavegen_Klatt(int resume);
|
||||
extern void SetSynth(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v);
|
||||
extern int Wavegen();
|
||||
extern void CloseWaveFile2();
|
||||
extern void KlattReset();
|
||||
extern void KlattReset(int control);
|
||||
extern FILE *f_wave;
|
||||
|
||||
static int frame_width;
|
||||
@@ -1006,7 +1006,7 @@ void SpectSeq::MakeWave(int start, int end, PitchEnvelope &pitch)
|
||||
if(voice->klattv[0])
|
||||
{
|
||||
synthesizer_type = 1;
|
||||
KlattReset();
|
||||
KlattReset(2);
|
||||
}
|
||||
|
||||
SpeakNextClause(NULL,NULL,2); // stop speaking file
|
||||
@@ -1125,7 +1125,7 @@ void SpectFrame::MakeWaveF(int control, PitchEnvelope &pitche, int amplitude, in
|
||||
if(voice->klattv[0])
|
||||
{
|
||||
synthesizer_type = 1;
|
||||
KlattReset();
|
||||
KlattReset(2);
|
||||
}
|
||||
|
||||
SpeakNextClause(NULL,NULL,2); // stop speaking file
|
||||
|
||||
+16
-7
@@ -540,6 +540,8 @@ void MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, FILE *f_mbrola)
|
||||
PHONEME_LIST *p;
|
||||
PHONEME_LIST *next;
|
||||
PHONEME_LIST *prev;
|
||||
PHONEME_DATA phdata;
|
||||
FMT_PARAMS fmtp;
|
||||
int pause = 0;
|
||||
int released;
|
||||
int name2;
|
||||
@@ -655,10 +657,11 @@ void MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, FILE *f_mbrola)
|
||||
if(next->type==phVOWEL) released = 1;
|
||||
if(next->type==phLIQUID && !next->newword) released = 1;
|
||||
|
||||
if(released)
|
||||
len = DoSample(p->ph,next->ph,2,0,-1);
|
||||
else
|
||||
len = DoSample(p->ph,phoneme_tab[phonPAUSE],2,0,-1);
|
||||
if(released == 0)
|
||||
p->synthflags |= SFLAG_NEXT_PAUSE;
|
||||
InterpretPhoneme(NULL, 0, p, &phdata);
|
||||
len = DoSample3(&phdata, 0, -1);
|
||||
|
||||
len = (len * 1000)/samplerate; // convert to mS
|
||||
len += PauseLength(p->prepause,1);
|
||||
break;
|
||||
@@ -669,9 +672,10 @@ void MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, FILE *f_mbrola)
|
||||
|
||||
case phFRICATIVE:
|
||||
len = 0;
|
||||
InterpretPhoneme(NULL, 0, p, &phdata);
|
||||
if(p->synthflags & SFLAG_LENGTHEN)
|
||||
len = DoSample(ph,ph_next,2,p->length,-1); // play it twice for [s:] etc.
|
||||
len += DoSample(ph,ph_next,2,p->length,-1);
|
||||
len = DoSample3(&phdata, p->length, -1); // play it twice for [s:] etc.
|
||||
len += DoSample3(&phdata, p->length, -1);
|
||||
|
||||
len = (len * 1000)/samplerate; // convert to mS
|
||||
break;
|
||||
@@ -679,7 +683,12 @@ void MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, FILE *f_mbrola)
|
||||
case phNASAL:
|
||||
if(next->type != phVOWEL)
|
||||
{
|
||||
len = DoSpect(p->ph,prev->ph,phoneme_tab[phonPAUSE],2,p,-1);
|
||||
memset(&fmtp, 0, sizeof(fmtp));
|
||||
InterpretPhoneme(NULL, 0, p, &phdata);
|
||||
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
|
||||
fmtp.fmt_length = phdata.sound_param[pd_FMT];
|
||||
len = DoSpect2(p->ph, 0, &fmtp, p, -1);
|
||||
// len = DoSpect(p->ph,prev->ph,phoneme_tab[phonPAUSE],2,p,-1);
|
||||
len = (len * 1000)/samplerate;
|
||||
if(next->type == phPAUSE)
|
||||
len += 50;
|
||||
|
||||
+588
-227
@@ -35,8 +35,8 @@
|
||||
#include "translate.h"
|
||||
#include "wave.h"
|
||||
|
||||
const char *version_string = "1.42.09 13.Dec.09";
|
||||
const int version_phdata = 0x014200;
|
||||
const char *version_string = "1.42.21 19.Dec.09";
|
||||
const int version_phdata = 0x014220;
|
||||
|
||||
int option_device_number = -1;
|
||||
FILE *f_logespeak = NULL;
|
||||
@@ -48,7 +48,7 @@ int current_phoneme_table;
|
||||
PHONEME_TAB *phoneme_tab[N_PHONEME_TAB];
|
||||
unsigned char phoneme_tab_flags[N_PHONEME_TAB]; // bit 0: not inherited
|
||||
|
||||
static unsigned int *phoneme_index=NULL;
|
||||
static USHORT *phoneme_index=NULL;
|
||||
char *spects_data=NULL;
|
||||
unsigned char *wavefile_data=NULL;
|
||||
static unsigned char *phoneme_tab_data = NULL;
|
||||
@@ -116,7 +116,7 @@ int LoadPhData()
|
||||
|
||||
if((phoneme_tab_data = (unsigned char *)ReadPhFile((void *)(phoneme_tab_data),"phontab")) == NULL)
|
||||
return(-1);
|
||||
if((phoneme_index = (unsigned int *)ReadPhFile((void *)(phoneme_index),"phonindex")) == NULL)
|
||||
if((phoneme_index = (USHORT *)ReadPhFile((void *)(phoneme_index),"phonindex")) == NULL)
|
||||
return(-1);
|
||||
if((spects_data = ReadPhFile((void *)(spects_data),"phondata")) == NULL)
|
||||
return(-1);
|
||||
@@ -204,172 +204,9 @@ int LookupPhonemeString(const char *string)
|
||||
|
||||
|
||||
|
||||
static unsigned int LookupSound2(int index, unsigned int other_phcode, int control)
|
||||
{//================================================================================
|
||||
// control=1 get formant transition data only
|
||||
|
||||
unsigned int code;
|
||||
unsigned int value, value2;
|
||||
|
||||
while((value = phoneme_index[index++]) != 0)
|
||||
{
|
||||
if((code = (value & 0xff)) == other_phcode)
|
||||
{
|
||||
while(((value2 = phoneme_index[index]) != 0) && ((value2 & 0xff) < 8))
|
||||
{
|
||||
switch(value2 & 0xff)
|
||||
{
|
||||
case 0:
|
||||
// next entry is a wavefile to be played along with the synthesis
|
||||
if(control==0)
|
||||
{
|
||||
wavefile_ix = value2 >> 8;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if(control==0)
|
||||
{
|
||||
seq_len_adjust = value2 >> 8;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if(control==0)
|
||||
{
|
||||
seq_len_adjust = value2 >> 8;
|
||||
seq_len_adjust = -seq_len_adjust;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if(control==0)
|
||||
{
|
||||
wavefile_amp = value2 >> 8;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
// formant transition data, 2 words
|
||||
vowel_transition[0] = value2 >> 8;
|
||||
vowel_transition[1] = phoneme_index[index++ + 1];
|
||||
break;
|
||||
case 5:
|
||||
// formant transition data, 2 words
|
||||
vowel_transition[2] = value2 >> 8;
|
||||
vowel_transition[3] = phoneme_index[index++ + 1];
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
return(value >> 8);
|
||||
}
|
||||
else
|
||||
if((code == 4) || (code == 5))
|
||||
{
|
||||
// formant transition data, ignore next word of data
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return(3); // not found
|
||||
} // end of LookupSound2
|
||||
|
||||
|
||||
unsigned int LookupSound(PHONEME_TAB *this_ph, PHONEME_TAB *other_ph, int which, int *match_level, int control)
|
||||
{//============================================================================================================
|
||||
// follows, 1 other_ph preceeds this_ph, 2 other_ph follows this_ph
|
||||
// control: 1= get formant transition data only
|
||||
int spect_list;
|
||||
int spect_list2;
|
||||
int s_list;
|
||||
unsigned char virtual_ph;
|
||||
int result;
|
||||
int level=0;
|
||||
unsigned int other_code;
|
||||
unsigned int other_virtual;
|
||||
|
||||
if(control==0)
|
||||
{
|
||||
wavefile_ix = 0;
|
||||
wavefile_amp = 32;
|
||||
seq_len_adjust = 0;
|
||||
}
|
||||
memset(vowel_transition,0,sizeof(vowel_transition));
|
||||
|
||||
other_code = other_ph->code;
|
||||
if(phoneme_tab[other_code]->type == phPAUSE)
|
||||
other_code = phonPAUSE_SHORT; // use this version of Pause for matching
|
||||
|
||||
if(which==1)
|
||||
{
|
||||
spect_list = this_ph->after;
|
||||
virtual_ph = this_ph->start_type;
|
||||
spect_list2 = phoneme_tab[virtual_ph]->after;
|
||||
other_virtual = other_ph->end_type;
|
||||
}
|
||||
else
|
||||
{
|
||||
spect_list = this_ph->before;
|
||||
virtual_ph = this_ph->end_type;
|
||||
spect_list2 = phoneme_tab[virtual_ph]->before;
|
||||
other_virtual = other_ph->start_type;
|
||||
}
|
||||
|
||||
result = 3;
|
||||
// look for ph1-ph2 combination
|
||||
if((s_list = spect_list) != 0)
|
||||
{
|
||||
if((result = LookupSound2(s_list,other_code,control)) != 3)
|
||||
{
|
||||
level = 2;
|
||||
}
|
||||
else
|
||||
if(other_virtual != 0)
|
||||
{
|
||||
if((result = LookupSound2(spect_list,other_virtual,control)) != 3)
|
||||
{
|
||||
level = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// not found, look in a virtual phoneme if one is given for this phoneme
|
||||
if((result==3) && (virtual_ph != 0) && ((s_list = spect_list2) != 0))
|
||||
{
|
||||
if((result = LookupSound2(s_list,other_code,control)) != 3)
|
||||
{
|
||||
level = 1;
|
||||
}
|
||||
else
|
||||
if(other_virtual != 0)
|
||||
{
|
||||
if((result = LookupSound2(spect_list2,other_virtual,control)) != 3)
|
||||
{
|
||||
level = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(match_level != NULL)
|
||||
*match_level = level;
|
||||
|
||||
if(result==0)
|
||||
return(0); // NULL was given in the phoneme source
|
||||
|
||||
// note: values = 1 indicates use the default for this phoneme, even though we found a match
|
||||
// which set a secondary reference
|
||||
if(result >= 4)
|
||||
{
|
||||
// values 1-3 can be used for special codes
|
||||
// 1 = DFT from the phoneme source file
|
||||
return(result);
|
||||
}
|
||||
|
||||
// no match found for other_ph, return the default
|
||||
return(LookupSound2(this_ph->spect,phonPAUSE,control));
|
||||
|
||||
} // end of LookupSound
|
||||
|
||||
|
||||
|
||||
frameref_t *LookupSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB *next_ph,
|
||||
int which, int *match_level, 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 nf;
|
||||
int nf1;
|
||||
@@ -380,19 +217,10 @@ frameref_t *LookupSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB
|
||||
int length_factor;
|
||||
SPECT_SEQ *seq, *seq2;
|
||||
SPECT_SEQK *seqk, *seqk2;
|
||||
PHONEME_TAB *next2_ph;
|
||||
frame_t *frame;
|
||||
static frameref_t frames_buf[N_SEQ_FRAMES];
|
||||
|
||||
PHONEME_TAB *other_ph;
|
||||
if(which == 1)
|
||||
other_ph = prev_ph;
|
||||
else
|
||||
other_ph = next_ph;
|
||||
|
||||
if((ix = LookupSound(this_ph,other_ph,which,match_level,0)) < 4)
|
||||
return(NULL);
|
||||
seq = (SPECT_SEQ *)(&spects_data[ix]);
|
||||
seq = (SPECT_SEQ *)(&spects_data[fmt_params->fmt_addr]);
|
||||
seqk = (SPECT_SEQK *)seq;
|
||||
nf = seq->n_frames;
|
||||
|
||||
@@ -400,8 +228,8 @@ frameref_t *LookupSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB
|
||||
if(nf >= N_SEQ_FRAMES)
|
||||
nf = N_SEQ_FRAMES - 1;
|
||||
|
||||
seq_len_adjust = fmt_params->fmt2_lenadj + fmt_params->fmt_length;
|
||||
seq_break = 0;
|
||||
length1 = 0;
|
||||
|
||||
for(ix=0; ix<nf; ix++)
|
||||
{
|
||||
@@ -431,46 +259,21 @@ frameref_t *LookupSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB
|
||||
}
|
||||
|
||||
// do we need to modify a frame for blending with a consonant?
|
||||
if(this_ph->type == phVOWEL)
|
||||
if((this_ph->type == phVOWEL) && (fmt_params->fmt2_addr == 0) && (fmt_params->use_vowelin))
|
||||
{
|
||||
if((which==2) && ((frames[nf-1].frflags & FRFLAG_BREAK) == 0))
|
||||
{
|
||||
// lookup formant transition for the following phoneme
|
||||
|
||||
if((*match_level == 0) || (next_ph->type == phNASAL))
|
||||
{
|
||||
LookupSound(next_ph,this_ph,1,NULL,1);
|
||||
seq_len_adjust += FormantTransition2(frames,nf,vowel_transition[2],vowel_transition[3],next_ph,which);
|
||||
}
|
||||
else
|
||||
if(next_ph->phflags == phVOWEL2)
|
||||
{
|
||||
// not really a consonant, rather a coloured vowel
|
||||
if(LookupSound(next_ph,this_ph,1,NULL,1) == 0)
|
||||
{
|
||||
next2_ph = plist[2].ph;
|
||||
LookupSound(next2_ph,next_ph,1,NULL,1);
|
||||
seq_len_adjust += FormantTransition2(frames,nf,vowel_transition[2],vowel_transition[3],next2_ph,which);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(*match_level == 0)
|
||||
seq_len_adjust = FormantTransition2(frames,nf,vowel_transition0,vowel_transition1,prev_ph,which);
|
||||
}
|
||||
seq_len_adjust += FormantTransition2(frames,nf,fmt_params->transition0,fmt_params->transition1,NULL,which);
|
||||
}
|
||||
|
||||
length1 = 0;
|
||||
nf1 = nf - 1;
|
||||
for(ix=0; ix<nf1; ix++)
|
||||
length1 += frames[ix].length;
|
||||
|
||||
|
||||
if((wavefile_ix != 0) && ((wavefile_ix & 0x800000)==0))
|
||||
if(fmt_params->fmt2_addr != 0)
|
||||
{
|
||||
// a secondary reference has been returned, which is not a wavefile
|
||||
// add these spectra to the main sequence
|
||||
seq2 = (SPECT_SEQ *)(&spects_data[wavefile_ix]);
|
||||
seq2 = (SPECT_SEQ *)(&spects_data[fmt_params->fmt2_addr]);
|
||||
seqk2 = (SPECT_SEQK *)seq2;
|
||||
|
||||
// first frame of the addition just sets the length of the last frame of the main seq
|
||||
@@ -493,18 +296,18 @@ frameref_t *LookupSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB
|
||||
wavefile_ix = 0;
|
||||
}
|
||||
|
||||
if((this_ph->type == phVOWEL) && (length1 > 0))
|
||||
if(length1 > 0)
|
||||
{
|
||||
if(which==2)
|
||||
{
|
||||
// adjust the length of the main part to match the standard length specified for the vowel
|
||||
// less the front part of the vowel and any added suffix
|
||||
|
||||
length_std = this_ph->std_length + seq_len_adjust - 45;
|
||||
|
||||
length_std = fmt_params->std_length + seq_len_adjust - 45;
|
||||
if(length_std < 10)
|
||||
length_std = 10;
|
||||
if(plist->synthflags & SFLAG_LENGTHEN)
|
||||
length_std += phoneme_tab[phonLENGTHEN]->std_length; // phoneme was followed by an extra : symbol
|
||||
length_std += (phoneme_tab[phonLENGTHEN]->std_length * 2); // phoneme was followed by an extra : symbol
|
||||
|
||||
// can adjust vowel length for stressed syllables here
|
||||
|
||||
@@ -518,22 +321,29 @@ frameref_t *LookupSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB
|
||||
}
|
||||
else
|
||||
{
|
||||
// front of a vowel
|
||||
if(*match_level == 0)
|
||||
if(which == 1)
|
||||
{
|
||||
// allow very short vowels to have shorter front parts
|
||||
if(this_ph->std_length < 130)
|
||||
frames[0].length = (frames[0].length * this_ph->std_length)/130;
|
||||
// front of a vowel
|
||||
if(fmt_params->fmt_control == 1)
|
||||
{
|
||||
// This is the default start of a vowel.
|
||||
// Allow very short vowels to have shorter front parts
|
||||
if(fmt_params->std_length < 130)
|
||||
frames[0].length = (frames[0].length * fmt_params->std_length)/130;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//not a vowel
|
||||
if(fmt_params->std_length > 0)
|
||||
{
|
||||
seq_len_adjust += (fmt_params->std_length - length1);
|
||||
}
|
||||
}
|
||||
|
||||
if(seq_len_adjust != 0)
|
||||
{
|
||||
length_std = 0;
|
||||
for(ix=0; ix<nf1; ix++)
|
||||
{
|
||||
length_std += frames[ix].length;
|
||||
}
|
||||
length_factor = ((length_std + seq_len_adjust) * 256)/length_std;
|
||||
length_factor = ((length1 + seq_len_adjust) * 256)/length1;
|
||||
for(ix=0; ix<nf1; ix++)
|
||||
{
|
||||
frames[ix].length = (frames[ix].length * length_factor)/256;
|
||||
@@ -547,11 +357,12 @@ frameref_t *LookupSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB
|
||||
} // end of LookupSpect
|
||||
|
||||
|
||||
|
||||
unsigned char *LookupEnvelope(int ix)
|
||||
{//================================
|
||||
if(ix==0)
|
||||
return(NULL);
|
||||
return((unsigned char *)&spects_data[phoneme_index[ix]]);
|
||||
return((unsigned char *)&spects_data[ix]);
|
||||
}
|
||||
|
||||
|
||||
@@ -689,6 +500,556 @@ void LoadConfig(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
} // end of LoadConfig
|
||||
|
||||
|
||||
|
||||
|
||||
PHONEME_DATA this_ph_data;
|
||||
|
||||
|
||||
static void InvalidInstn(PHONEME_TAB *ph, int instn)
|
||||
{//====================================================
|
||||
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)
|
||||
{//========================================================================================
|
||||
// condition:
|
||||
// 0 if diminished, 1 if unstressed, 2 if not stressed, 3 if stressed, 4 if max stress
|
||||
|
||||
int stress_level;
|
||||
PHONEME_LIST *pl;
|
||||
static int condition_level[4] = {1,2,4,15};
|
||||
|
||||
if(phoneme_tab[plist[0].phcode]->type == phVOWEL)
|
||||
{
|
||||
pl = plist;
|
||||
}
|
||||
else
|
||||
{
|
||||
// consonant, get stress from the following vowel
|
||||
if(phoneme_tab[plist[1].phcode]->type == phVOWEL)
|
||||
{
|
||||
pl = &plist[1];
|
||||
}
|
||||
else
|
||||
return(false); // no stress elevel for this consonant
|
||||
}
|
||||
|
||||
stress_level = pl->stresslevel & 0xf;
|
||||
|
||||
if(tr != NULL)
|
||||
{
|
||||
if((control & 1) && (plist->synthflags & SFLAG_DICTIONARY) && ((tr->langopts.param[LOPT_REDUCE] & 1)==0))
|
||||
{
|
||||
// change phoneme. Don't change phonemes which are given for the word in the dictionary.
|
||||
return(false);
|
||||
}
|
||||
|
||||
if((tr->langopts.param[LOPT_REDUCE] & 0x2) && (stress_level >= pl->wordstress))
|
||||
{
|
||||
// treat the most stressed syllable in an unstressed word as stressed
|
||||
stress_level = 4;
|
||||
}
|
||||
}
|
||||
|
||||
if(condition == 4)
|
||||
{
|
||||
return(stress_level >= pl->wordstress);
|
||||
}
|
||||
|
||||
if(condition == 3)
|
||||
{
|
||||
// if stressed
|
||||
if(stress_level > 3)
|
||||
return(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(stress_level < condition_level[condition])
|
||||
return(true);
|
||||
}
|
||||
return(false);
|
||||
|
||||
} // end of StressCondition
|
||||
|
||||
|
||||
static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, int instn)
|
||||
{//========================================================================================
|
||||
int which;
|
||||
unsigned int data;
|
||||
int instn2;
|
||||
PHONEME_TAB *ph;
|
||||
PHONEME_LIST *plist_this;
|
||||
static int ph_position[7] = {0, 1, 2, 3, 2, 0, 1};
|
||||
|
||||
data = instn & 0xff;
|
||||
instn2 = instn >> 8;
|
||||
|
||||
if(instn2 < 14)
|
||||
{
|
||||
which = (instn2) % 7;
|
||||
|
||||
if(which==4)
|
||||
{
|
||||
// nextPh not word boundary
|
||||
if(plist[1].sourceix)
|
||||
return(false);
|
||||
}
|
||||
if(which==5)
|
||||
{
|
||||
// prevPh, not word boundary
|
||||
if(plist[0].sourceix)
|
||||
return(false);
|
||||
}
|
||||
if(which==6)
|
||||
{
|
||||
// nextVowel, not word boundary
|
||||
for(which=2;;which++)
|
||||
{
|
||||
if(plist[which-1].sourceix)
|
||||
return(false);
|
||||
if(phoneme_tab[plist[which-1].phcode]->type == phVOWEL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
which = ph_position[which];
|
||||
}
|
||||
plist_this = plist;
|
||||
plist = &plist[which-1];
|
||||
|
||||
if(control & 0x100)
|
||||
{
|
||||
// change phonemes pass
|
||||
plist->ph = phoneme_tab[plist->phcode];
|
||||
}
|
||||
ph = plist->ph;
|
||||
|
||||
if(instn2 < 7)
|
||||
{
|
||||
// 'data' is a phoneme number
|
||||
if((phoneme_tab[data]->mnemonic == ph->mnemonic) == true)
|
||||
return(true);
|
||||
if((which == 0) && (ph->type == phVOWEL))
|
||||
return(data == ph->end_type); // prevPh() match on end_type
|
||||
return(data == ph->start_type); // thisPh() or nextPh(), match on start_type
|
||||
}
|
||||
|
||||
data = instn & 0x1f;
|
||||
|
||||
switch(instn & 0xe0)
|
||||
{
|
||||
case 0x00:
|
||||
// phoneme type, vowel, nasal, fricative, etc
|
||||
return(ph->type == data);
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
// place of articulation
|
||||
return(((ph->phflags >> 16) & 0xf) == data);
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
// is a bit set in phoneme flags
|
||||
return((ph->phflags & (1 << data)) != 0);
|
||||
break;
|
||||
|
||||
case 0x80:
|
||||
switch(data)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
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))
|
||||
return((ph->type == phPAUSE) || (plist_this->synthflags & SFLAG_NEXT_PAUSE));
|
||||
|
||||
case 6: // isWordStart
|
||||
return(plist->sourceix != 0);
|
||||
|
||||
case 7: // notWordStart
|
||||
return(plist->sourceix == 0);
|
||||
|
||||
case 8: // isWordEnd
|
||||
return(plist[1].sourceix || (plist[1].ph->type == phPAUSE));
|
||||
break;
|
||||
|
||||
case 9: // isAfterStress
|
||||
if(plist->sourceix != 0)
|
||||
return(false);
|
||||
do {
|
||||
plist--;
|
||||
if((plist->stresslevel & 0xf) >= 4)
|
||||
return(true);
|
||||
|
||||
} while (plist->sourceix == 0);
|
||||
break;
|
||||
|
||||
case 10: // isNotVowel
|
||||
return(ph->type != phVOWEL);
|
||||
|
||||
case 11: // isFinalVowel
|
||||
for(;;)
|
||||
{
|
||||
plist++;
|
||||
plist->ph = phoneme_tab[plist->phcode];
|
||||
if(plist->sourceix != 0)
|
||||
return(true); // start of next word, without finding another vowel
|
||||
if(plist->ph->type == phVOWEL)
|
||||
return(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
if(instn2 == 0xf)
|
||||
{
|
||||
// Other conditions
|
||||
switch(data)
|
||||
{
|
||||
case 1: // PreVoicing
|
||||
return(control & 1);
|
||||
case 2: // KlattSynth
|
||||
return(voice->klattv[0] != 0);
|
||||
}
|
||||
}
|
||||
return(false);
|
||||
} // end of InterpretCondition
|
||||
|
||||
|
||||
static void SwitchVowelType(PHONEME_LIST *plist, PHONEME_DATA *phdata, USHORT **p_prog, int instn_type)
|
||||
{//=====================================================================================================
|
||||
USHORT *prog;
|
||||
int voweltype;
|
||||
signed char x;
|
||||
|
||||
if(instn_type == 2)
|
||||
{
|
||||
phdata->pd_control |= pd_FORNEXTPH;
|
||||
voweltype = plist[1].ph->start_type; // SwitchNextVowelType
|
||||
}
|
||||
else
|
||||
{
|
||||
voweltype = plist[-1].ph->end_type; // SwitchPrevVowelType
|
||||
}
|
||||
|
||||
voweltype -= phonVOWELTYPES;
|
||||
if((voweltype >= 0) && (voweltype < 6))
|
||||
{
|
||||
prog = *p_prog + voweltype*2;
|
||||
phdata->sound_addr[instn_type] = (((prog[1] & 0xf) << 16) + prog[2]) * 4;
|
||||
x = (prog[1] >> 4) & 0xff;
|
||||
phdata->sound_param[instn_type] = x; // sign extend
|
||||
}
|
||||
|
||||
*p_prog += 12;
|
||||
} // end of SwitchVowelType
|
||||
|
||||
|
||||
static int NumInstnWords(USHORT *prog)
|
||||
{//===================================
|
||||
int instn;
|
||||
int instn2;
|
||||
int instn_type;
|
||||
static char n_words[11] = {1,1,1,1,1,1,1,1,1,2,4};
|
||||
|
||||
instn = *prog;
|
||||
instn_type = instn >> 12;
|
||||
if(instn_type < 11)
|
||||
return(n_words[instn_type]);
|
||||
|
||||
// 11 to 15, 2 words
|
||||
instn2 = prog[2];
|
||||
if((instn2 >> 12) == 0xf)
|
||||
{
|
||||
// addWav(), 2 more words
|
||||
return(4);
|
||||
}
|
||||
if(instn2 == i_CONTINUE)
|
||||
{
|
||||
return(3);
|
||||
}
|
||||
return(2);
|
||||
} // end of NumInstnWords
|
||||
|
||||
|
||||
|
||||
void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_DATA *phdata)
|
||||
{//==========================================================================================
|
||||
// control:
|
||||
//bit 0: PreVoicing
|
||||
//bit 8: change phonemes
|
||||
PHONEME_TAB *ph;
|
||||
USHORT *prog;
|
||||
USHORT instn;
|
||||
int instn2;
|
||||
int or_flag;
|
||||
bool truth;
|
||||
int data;
|
||||
int end_flag;
|
||||
int ix;
|
||||
signed char param_sc;
|
||||
|
||||
#define N_RETURN 10
|
||||
int n_return=0;
|
||||
USHORT *return_addr[N_RETURN]; // return address stack
|
||||
|
||||
ph = plist->ph;
|
||||
|
||||
memset(phdata, 0, sizeof(PHONEME_DATA));
|
||||
phdata->pd_param[i_SET_LENGTH] = ph->std_length;
|
||||
phdata->pd_param[i_LENGTH_MOD] = ph->length_mod;
|
||||
|
||||
if(ph->program == 0)
|
||||
return;
|
||||
|
||||
end_flag = 0;
|
||||
|
||||
for(prog = &phoneme_index[ph->program]; end_flag != 1; prog++)
|
||||
{
|
||||
instn = *prog;
|
||||
instn2 = (instn >> 8) & 0xf;
|
||||
or_flag = 0;
|
||||
|
||||
switch(instn >> 12)
|
||||
{
|
||||
case 0:
|
||||
data = instn & 0xff;
|
||||
|
||||
if(instn2 == 0)
|
||||
{
|
||||
// instructions with no operand
|
||||
switch(data)
|
||||
{
|
||||
case i_RETURN:
|
||||
end_flag = 1;
|
||||
break;
|
||||
|
||||
case i_CONTINUE:
|
||||
break;
|
||||
|
||||
default:
|
||||
InvalidInstn(ph,instn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(instn2 == i_APPEND_IFNEXTVOWEL)
|
||||
{
|
||||
if(phoneme_tab[plist[1].phcode]->type == phVOWEL)
|
||||
phdata->pd_param[i_APPEND_PHONEME] = data;
|
||||
}
|
||||
else
|
||||
if(instn2 < N_PHONEME_DATA_PARAM)
|
||||
{
|
||||
if(instn2 == i_CHANGE_PHONEME2)
|
||||
{
|
||||
phdata->pd_param[i_CHANGE_PHONEME] = data; // also set ChangePhoneme
|
||||
}
|
||||
phdata->pd_param[instn2] = data;
|
||||
if((instn2 == i_CHANGE_PHONEME) && (control & 0x100))
|
||||
{
|
||||
// found ChangePhoneme() in PhonemeList mode, exit
|
||||
end_flag = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
InvalidInstn(ph,instn);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if(tr == NULL)
|
||||
break; // ignore if in synthesis stage
|
||||
|
||||
if(instn2 < 8)
|
||||
{
|
||||
// ChangeIf
|
||||
if(StressCondition(tr, plist, instn2 & 7, 1))
|
||||
{
|
||||
phdata->pd_param[i_CHANGE_PHONEME] = instn & 0xff;
|
||||
end_flag = 1; // change phoneme, exit
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
// conditions
|
||||
or_flag = 0;
|
||||
truth = true;
|
||||
while((instn & 0xe000) == 0x2000)
|
||||
{
|
||||
// process a sequence of conditions, using boolean accumulator
|
||||
if(or_flag)
|
||||
truth = (truth || InterpretCondition(tr, control, plist, instn & 0xfff));
|
||||
else
|
||||
truth = (truth && InterpretCondition(tr, control, plist, instn & 0xfff));
|
||||
or_flag = instn & 0x1000;
|
||||
instn = *(++prog);
|
||||
}
|
||||
|
||||
if(truth == false)
|
||||
{
|
||||
if((instn & 0xf800) == i_JUMP_FALSE)
|
||||
{
|
||||
prog += instn & 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
// instruction after a condition is not JUMP_FALSE, so skip the instruction.
|
||||
prog += NumInstnWords(prog);
|
||||
if((prog[0] & 0xfe00) == 0x6000)
|
||||
prog++; // and skip ELSE jump
|
||||
}
|
||||
}
|
||||
prog--;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
// JUMP
|
||||
switch(instn2 >> 1)
|
||||
{
|
||||
case 0:
|
||||
prog += (instn & 0xff) - 1;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// conditional jumps should have been processed in the Condition section
|
||||
break;
|
||||
|
||||
case 5: // NexttVowelStarts
|
||||
SwitchVowelType(plist, phdata, &prog, 2);
|
||||
break;
|
||||
|
||||
case 6: // PrevVowelTypeEndings
|
||||
SwitchVowelType(plist, phdata, &prog, 3);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 9:
|
||||
data = ((instn & 0xf) << 16) + prog[1];
|
||||
switch(instn2)
|
||||
{
|
||||
case 1:
|
||||
// call a procedure or another phoneme
|
||||
if(n_return < N_RETURN)
|
||||
{
|
||||
return_addr[n_return++] = prog+1;
|
||||
prog = &phoneme_index[data] - 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// pitch envelope
|
||||
phdata->pitch_env = data;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// amplitude envelope
|
||||
phdata->amp_env = data;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 10: // Vowelin, Vowelout
|
||||
if(instn2 == 1)
|
||||
ix = 0;
|
||||
else
|
||||
ix = 2;
|
||||
|
||||
phdata->vowel_transition[ix] = ((prog[0] & 0xff) << 16) + prog[1];
|
||||
phdata->vowel_transition[ix+1] = (prog[2] << 16) + prog[3];
|
||||
prog += 3;
|
||||
break;
|
||||
|
||||
case 11: // FMT
|
||||
case 12: // WAV
|
||||
case 13: // VowelStart
|
||||
case 14: // VowelEnd
|
||||
case 15: // addWav
|
||||
instn2 = (instn >> 12) - 11;
|
||||
phdata->sound_addr[instn2] = ((instn & 0xf) << 18) + (prog[1] << 2);
|
||||
param_sc = phdata->sound_param[instn2] = (instn >> 4) & 0xff;
|
||||
prog++;
|
||||
|
||||
if(prog[1] != i_CONTINUE)
|
||||
{
|
||||
if(instn2 < 2)
|
||||
{
|
||||
// FMT() and WAV() imply Return
|
||||
end_flag = 1;
|
||||
if((prog[1] >> 12) == 0xf)
|
||||
{
|
||||
// Return after the following addWav()
|
||||
end_flag = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(instn2 == 4)
|
||||
{
|
||||
// addWav(), return if previous instruction was FMT() or WAV()
|
||||
end_flag--;
|
||||
}
|
||||
|
||||
if((instn2 != 1) && (instn2 != 4))
|
||||
{
|
||||
// FMT, VowelStart or VowelEnding.
|
||||
phdata->sound_param[instn2] = param_sc; // sign extend
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
InvalidInstn(ph,instn);
|
||||
break;
|
||||
}
|
||||
|
||||
if(ph->phflags & phSINGLE_INSTN)
|
||||
{
|
||||
end_flag = 1; // this phoneme has a one-instruction program, with an implicit Return
|
||||
}
|
||||
|
||||
if((end_flag == 1) && (n_return > 0))
|
||||
{
|
||||
// return from called procedure or phoneme
|
||||
end_flag = 0;
|
||||
prog = return_addr[--n_return];
|
||||
}
|
||||
}
|
||||
|
||||
} // end of InterpretPhoneme
|
||||
|
||||
|
||||
void InterpretPhoneme2(int phcode, PHONEME_DATA *phdata)
|
||||
{//=====================================================
|
||||
// Examine the program of a single isolated phoneme
|
||||
int ix;
|
||||
PHONEME_LIST plist[4];
|
||||
memset(plist, 0, sizeof(plist));
|
||||
|
||||
for(ix=0; ix<4; ix++)
|
||||
{
|
||||
plist[ix].phcode = phonPAUSE;
|
||||
plist[ix].ph = phoneme_tab[phonPAUSE];
|
||||
}
|
||||
|
||||
plist[1].phcode = phcode;
|
||||
plist[1].ph = phoneme_tab[phcode];
|
||||
plist[2].sourceix = 1;
|
||||
|
||||
InterpretPhoneme(NULL, 0, &plist[1], phdata);
|
||||
} // end of InterpretPhoneme2
|
||||
|
||||
+308
-136
@@ -219,72 +219,153 @@ static void DoPause(int length, int control)
|
||||
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 length_mod, int amp)
|
||||
{//================================================================
|
||||
static int DoSample2(int index, int which, int std_length, int control, int length_mod, int amp)
|
||||
{//=============================================================================================
|
||||
int length;
|
||||
int length1;
|
||||
int wav_length;
|
||||
int format;
|
||||
int min_length;
|
||||
int start=0;
|
||||
int x;
|
||||
int len4;
|
||||
long *q;
|
||||
unsigned char *p;
|
||||
|
||||
index = index & 0x7fffff;
|
||||
p = &wavefile_data[index];
|
||||
format = p[2];
|
||||
length1 = (p[1] * 256);
|
||||
length1 += p[0]; // length in bytes
|
||||
wav_length = (p[1] * 256);
|
||||
wav_length += p[0]; // length in bytes
|
||||
|
||||
if(seq_len_adjust > 0)
|
||||
{
|
||||
start = (seq_len_adjust * samplerate)/1000;
|
||||
if(format == 0)
|
||||
start *= 2;
|
||||
length1 -= start;
|
||||
index += start;
|
||||
}
|
||||
|
||||
|
||||
if(length_mod > 0)
|
||||
length = (length1 * length_mod) / 256;
|
||||
else
|
||||
length = length1;
|
||||
|
||||
|
||||
length = (length * speed.speed_factor2)/256;
|
||||
min_length = speed.min_sample_len;
|
||||
if(format==0)
|
||||
min_length *= 2;
|
||||
|
||||
if(std_length > 0)
|
||||
{
|
||||
std_length = (std_length * samplerate)/1000;
|
||||
if(format == 0)
|
||||
std_length *= 2;
|
||||
|
||||
x = (min_length * std_length)/wav_length;
|
||||
if(x > min_length)
|
||||
min_length = x;
|
||||
}
|
||||
else
|
||||
{
|
||||
// no length specified, use the length of the stored sound
|
||||
std_length = wav_length;
|
||||
}
|
||||
|
||||
if(length_mod > 0)
|
||||
{
|
||||
std_length = (std_length * length_mod)/256;
|
||||
}
|
||||
|
||||
length = (std_length * speed.speed_factor2)/256;
|
||||
|
||||
if(control & pd_DONTLENGTHEN)
|
||||
{
|
||||
// this option is used for Stops, with short noise bursts.
|
||||
// Don't change their length much.
|
||||
if(length > std_length)
|
||||
{
|
||||
// don't let length exceed std_length
|
||||
length = std_length;
|
||||
}
|
||||
else
|
||||
{
|
||||
// reduce the reduction in length
|
||||
// length = (length + std_length)/2;
|
||||
}
|
||||
}
|
||||
|
||||
if(length < min_length)
|
||||
length = min_length;
|
||||
|
||||
if(length > length1)
|
||||
length = length1; // don't exceed wavefile length
|
||||
|
||||
if(format==0)
|
||||
length /= 2; // 2 byte samples
|
||||
if(format == 0)
|
||||
{
|
||||
// 16 bit samples
|
||||
length /= 2;
|
||||
wav_length /= 2;
|
||||
}
|
||||
|
||||
if(amp < 0)
|
||||
return(length);
|
||||
|
||||
len4 = wav_length / 4;
|
||||
|
||||
index += 4;
|
||||
|
||||
if(amp >= 0)
|
||||
if(which & 0x100)
|
||||
{
|
||||
// mix this with synthesised wave
|
||||
last_wcmdq = wcmdq_tail;
|
||||
q = wcmdq[wcmdq_tail];
|
||||
if(which & 0x100)
|
||||
q[0] = WCMD_WAVE2; // mix this with synthesised wave
|
||||
else
|
||||
q[0] = WCMD_WAVE;
|
||||
q[1] = length; // length in samples
|
||||
q[0] = WCMD_WAVE2;
|
||||
q[1] = length | (wav_length << 16); // length in samples
|
||||
q[2] = long(&wavefile_data[index]);
|
||||
q[3] = format + (amp << 8);
|
||||
WcmdqInc();
|
||||
return(length);
|
||||
}
|
||||
|
||||
if(length > wav_length)
|
||||
{
|
||||
x = len4*3;
|
||||
length -= x;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = length;
|
||||
length = 0;
|
||||
}
|
||||
|
||||
last_wcmdq = wcmdq_tail;
|
||||
q = wcmdq[wcmdq_tail];
|
||||
q[0] = WCMD_WAVE;
|
||||
q[1] = x; // length in samples
|
||||
q[2] = long(&wavefile_data[index]);
|
||||
q[3] = format + (amp << 8);
|
||||
WcmdqInc();
|
||||
|
||||
|
||||
while(length > len4*3)
|
||||
{
|
||||
x = len4;
|
||||
if(format == 0)
|
||||
x *= 2;
|
||||
|
||||
last_wcmdq = wcmdq_tail;
|
||||
q = wcmdq[wcmdq_tail];
|
||||
q[0] = WCMD_WAVE;
|
||||
q[1] = len4*2; // length in samples
|
||||
q[2] = long(&wavefile_data[index+x]);
|
||||
q[3] = format + (amp << 8);
|
||||
WcmdqInc();
|
||||
|
||||
length -= len4*2;
|
||||
}
|
||||
|
||||
if(length > 0)
|
||||
{
|
||||
x = wav_length - length;
|
||||
if(format == 0)
|
||||
x *= 2;
|
||||
last_wcmdq = wcmdq_tail;
|
||||
q = wcmdq[wcmdq_tail];
|
||||
q[0] = WCMD_WAVE;
|
||||
q[1] = length; // length in samples
|
||||
q[2] = long(&wavefile_data[index+x]);
|
||||
q[3] = format + (amp << 8);
|
||||
WcmdqInc();
|
||||
}
|
||||
|
||||
return(length);
|
||||
} // end of Synthesize::DoSample2
|
||||
} // end of DoSample2
|
||||
|
||||
|
||||
#ifdef deleted
|
||||
int DoSample(PHONEME_TAB *ph1, PHONEME_TAB *ph2, int which, int length_mod, int amp)
|
||||
{//====================== ==========================================================
|
||||
int index;
|
||||
@@ -304,10 +385,37 @@ int DoSample(PHONEME_TAB *ph1, PHONEME_TAB *ph2, int which, int length_mod, int
|
||||
if(amp == -1)
|
||||
amp2 = amp;
|
||||
|
||||
result = DoSample2(index,which,length_mod,amp2);
|
||||
result = DoSample2(index,which,length_mod,0,amp2);
|
||||
last_frame = NULL;
|
||||
return(result);
|
||||
} // end of Synthesize::DoSample
|
||||
} // end of DoSample
|
||||
#endif
|
||||
|
||||
|
||||
int DoSample3(PHONEME_DATA *phdata, int length_mod, int amp)
|
||||
{//=========================================================
|
||||
int amp2;
|
||||
int len;
|
||||
EndPitch(1);
|
||||
|
||||
if(amp == -1)
|
||||
{
|
||||
// just get the length, don't produce sound
|
||||
amp2 = amp;
|
||||
}
|
||||
else
|
||||
{
|
||||
amp2 = phdata->sound_param[pd_WAV];
|
||||
if(amp2 == 0)
|
||||
amp2 = 100;
|
||||
amp2 = (amp2 * 32)/100;
|
||||
}
|
||||
|
||||
seq_len_adjust=0;
|
||||
len = DoSample2(phdata->sound_addr[pd_WAV], 2, phdata->pd_param[pd_LENGTHMOD]*2, phdata->pd_control, length_mod, amp2);
|
||||
last_frame = NULL;
|
||||
return(len);
|
||||
} // end of DoSample3
|
||||
|
||||
|
||||
|
||||
@@ -554,7 +662,7 @@ static short vcolouring[N_VCOLOUR][5] = {
|
||||
if(voice->klattv[0])
|
||||
{
|
||||
// fr->klattp[KLATT_AV] = 53; // reduce the amplituide of the start of a vowel
|
||||
fr->klattp[KLATT_AV] = seq[1].frame->klattp[KLATT_AV] - 6;
|
||||
fr->klattp[KLATT_AV] = seq[1].frame->klattp[KLATT_AV] - 4;
|
||||
}
|
||||
if(f2 != 0)
|
||||
{
|
||||
@@ -861,10 +969,10 @@ static void StartSyllable(void)
|
||||
}
|
||||
|
||||
|
||||
int DoSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB *next_ph,
|
||||
int which, PHONEME_LIST *plist, int modulation)
|
||||
{//===================================================================================
|
||||
// which 1 start of phoneme, 2 body and end
|
||||
|
||||
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
|
||||
// length_mod: 256 = 100%
|
||||
// modulation: -1 = don't write to wcmdq
|
||||
|
||||
@@ -877,70 +985,47 @@ int DoSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB *next_ph,
|
||||
int ix;
|
||||
long *q;
|
||||
int len;
|
||||
int min;
|
||||
int match_level;
|
||||
int frame_length;
|
||||
int frame1_length;
|
||||
int frame2_length;
|
||||
int length_factor;
|
||||
int length_mod;
|
||||
int length_mod2; // reduced effect length_mod
|
||||
int total_len = 0;
|
||||
int len_adjust_factor = 256;
|
||||
static int wave_flag = 0;
|
||||
int wcmd_spect = WCMD_SPECT;
|
||||
|
||||
if(fmt_params->fmt_addr == 0)
|
||||
return(0);
|
||||
|
||||
length_mod = plist->length;
|
||||
if(length_mod==0) length_mod=256;
|
||||
|
||||
length_mod2 = (length_mod*(256-speed.speed_factor3) + 256*speed.speed_factor3)/256;
|
||||
|
||||
if(which==1)
|
||||
if(which==1)
|
||||
{
|
||||
// limit the shortening of sonorants before shortened (eg. unstressed vowels)
|
||||
if((this_ph->type==phLIQUID) || (plist[-1].type==phLIQUID) || (plist[-1].type==phNASAL))
|
||||
{
|
||||
// limit the shortening of sonorants before shortened (eg. unstressed vowels)
|
||||
if((this_ph->type==phLIQUID) || (prev_ph->type==phLIQUID) || (prev_ph->type==phNASAL))
|
||||
if(length_mod < (len = translator->langopts.param[LOPT_SONORANT_MIN]))
|
||||
{
|
||||
if(length_mod < (len = translator->langopts.param[LOPT_SONORANT_MIN]))
|
||||
{
|
||||
length_mod = len;
|
||||
}
|
||||
length_mod = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
modn_flags = 0;
|
||||
frames = LookupSpect(this_ph,prev_ph,next_ph,which,&match_level,&n_frames, plist);
|
||||
frames = LookupSpect(this_ph, which, fmt_params, &n_frames, plist);
|
||||
if(frames == NULL)
|
||||
return(0); // not found
|
||||
|
||||
// if((which==2) && (this_ph->phflags & phLONG))
|
||||
if((which==2) && (this_ph->std_length >= 200))
|
||||
{
|
||||
// apply a minimum length for long vowels at fast speeds, to keep the distinction with short vowels
|
||||
total_len = 0;
|
||||
for(frameix=0; frameix<(n_frames-1); frameix++)
|
||||
{
|
||||
length_factor = length_mod;
|
||||
if(frames[frameix].frflags & FRFLAG_LEN_MOD) // reduce effect of length mod
|
||||
{
|
||||
length_factor = length_mod2;
|
||||
}
|
||||
len = (frames[frameix].length * samplerate)/1000;
|
||||
len = (len * length_factor)/256;
|
||||
total_len += len;
|
||||
}
|
||||
|
||||
min = translator->langopts.param[LOPT_MIN_LONG_VOWEL] * (samplerate)/1000;
|
||||
min = (min * length_mod2)/256;
|
||||
if(total_len < min)
|
||||
{
|
||||
len_adjust_factor = (min*256)/total_len;
|
||||
}
|
||||
}
|
||||
|
||||
frame1 = frames[0].frame;
|
||||
frame1_length = frames[0].length;
|
||||
if(voice->klattv[0])
|
||||
wcmd_spect = WCMD_KLATT;
|
||||
|
||||
wavefile_ix = fmt_params->wav_addr;
|
||||
wavefile_amp = (fmt_params->wav_amp * 32)/100;
|
||||
if(wavefile_amp == 0)
|
||||
wavefile_amp = 32;
|
||||
if(wavefile_ix == 0)
|
||||
{
|
||||
if(wave_flag)
|
||||
@@ -990,30 +1075,29 @@ int DoSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB *next_ph,
|
||||
syllable_centre = wcmdq_tail;
|
||||
}
|
||||
|
||||
total_len = 0;
|
||||
frame_length = frame1_length;
|
||||
for(frameix=1; frameix<n_frames; frameix++)
|
||||
{
|
||||
frame2 = frames[frameix].frame;
|
||||
frame2_length = frames[frameix].length;
|
||||
|
||||
if((wavefile_ix != 0) && ((frame1->frflags & FRFLAG_DEFER_WAV)==0))
|
||||
if((fmt_params->wav_addr != 0) && ((frame1->frflags & FRFLAG_DEFER_WAV)==0))
|
||||
{
|
||||
// there is a wave file to play along with this synthesis
|
||||
seq_len_adjust = 0;
|
||||
DoSample2(wavefile_ix,which+0x100,0,wavefile_amp);
|
||||
DoSample2(fmt_params->wav_addr, which+0x100, 0, fmt_params->fmt_control, 0, wavefile_amp);
|
||||
wave_flag = 1;
|
||||
wavefile_ix = 0;
|
||||
fmt_params->wav_addr = 0;
|
||||
}
|
||||
|
||||
length_factor = length_mod;
|
||||
if(frame1->frflags & FRFLAG_LEN_MOD) // reduce effect of length mod
|
||||
{
|
||||
length_factor = length_mod2;
|
||||
length_factor = (length_mod*(256-speed.speed_factor3) + 256*speed.speed_factor3)/256;
|
||||
}
|
||||
len = (frame_length * samplerate)/1000;
|
||||
len = (len * length_factor)/256;
|
||||
len = (len * len_adjust_factor)/256;
|
||||
|
||||
if(modulation >= 0)
|
||||
{
|
||||
@@ -1054,7 +1138,9 @@ int DoSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB *next_ph,
|
||||
}
|
||||
}
|
||||
return(total_len);
|
||||
} // end of Synthesize::DoSpect
|
||||
} // end of DoSpect
|
||||
|
||||
|
||||
|
||||
|
||||
static void DoMarker(int type, int char_posn, int length, int value)
|
||||
@@ -1158,6 +1244,12 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
|
||||
PHONEME_TAB *prev_ph;
|
||||
static int sourceix=0;
|
||||
|
||||
PHONEME_DATA phdata;
|
||||
PHONEME_DATA phdata_prev;
|
||||
PHONEME_DATA phdata_next;
|
||||
PHONEME_DATA phdata_tone;
|
||||
FMT_PARAMS fmtp;
|
||||
|
||||
#ifdef TEST_MBROLA
|
||||
if(mbrola_name[0] != 0)
|
||||
return(MbrolaGenerate(phoneme_list,n_ph,resume));
|
||||
@@ -1252,20 +1344,29 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
|
||||
if(next->type==phLIQUID) released = 1;
|
||||
// if(((p->ph->phflags & phPLACE) == phPLACE_blb) && (next->ph->phflags & phSIBILANT)) released = 1;
|
||||
}
|
||||
if(released == 0)
|
||||
p->synthflags |= SFLAG_NEXT_PAUSE;
|
||||
|
||||
if(released)
|
||||
DoSample(p->ph,next->ph,2,0,0);
|
||||
else
|
||||
DoSample(p->ph,phoneme_tab[phonPAUSE],2,0,0);
|
||||
InterpretPhoneme(NULL, 0, p, &phdata);
|
||||
phdata.pd_control |= pd_DONTLENGTHEN;
|
||||
DoSample3(&phdata, 0, 0);
|
||||
break;
|
||||
|
||||
case phFRICATIVE:
|
||||
InterpretPhoneme(NULL, 0, p, &phdata);
|
||||
|
||||
if(p->synthflags & SFLAG_LENGTHEN)
|
||||
DoSample(p->ph,next->ph,2,p->length,0); // play it twice for [s:] etc.
|
||||
DoSample(p->ph,next->ph,2,p->length,0);
|
||||
{
|
||||
DoSample3(&phdata, p->length, 0); // play it twice for [s:] etc.
|
||||
}
|
||||
DoSample3(&phdata, p->length, 0);
|
||||
break;
|
||||
|
||||
case phVSTOP:
|
||||
ph = p->ph;
|
||||
memset(&fmtp, 0, sizeof(fmtp));
|
||||
fmtp.fmt_control = pd_DONTLENGTHEN;
|
||||
|
||||
pre_voiced = 0;
|
||||
if(next->type==phVOWEL)
|
||||
{
|
||||
@@ -1292,11 +1393,15 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
|
||||
if((prev->type==phVOWEL) || (prev->ph->phflags & phVOWEL2))
|
||||
{
|
||||
// a period of voicing before the release
|
||||
DoSpect(p->ph,phoneme_tab[phonSCHWA],next->ph,1,p,0);
|
||||
InterpretPhoneme(NULL, 0x01, p, &phdata);
|
||||
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
|
||||
fmtp.fmt_length = phdata.sound_param[pd_FMT];
|
||||
|
||||
DoSpect2(ph, 0, &fmtp, p, 0);
|
||||
if(p->synthflags & SFLAG_LENGTHEN)
|
||||
{
|
||||
DoPause(20,0);
|
||||
DoSpect(p->ph,phoneme_tab[phonSCHWA],next->ph,1,p,0);
|
||||
DoSpect2(ph, 0, &fmtp, p, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1311,18 +1416,24 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
|
||||
{
|
||||
// followed by a vowel, or liquid + vowel
|
||||
StartSyllable();
|
||||
DoSpect(p->ph,prev->ph,next->ph,2,p,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoSpect(p->ph,prev->ph,phoneme_tab[phonPAUSE],2,p,0);
|
||||
if((p->newword == 0) && (next2->newword == 0))
|
||||
{
|
||||
if((next->type == phVFRICATIVE) && (p->ph->mnemonic !='d'))
|
||||
DoPause(20,0);
|
||||
if((next->type == phFRICATIVE) || (next->type == phNASAL))
|
||||
DoPause(12,0);
|
||||
}
|
||||
p->synthflags |= SFLAG_NEXT_PAUSE;
|
||||
}
|
||||
InterpretPhoneme(NULL,0, p, &phdata);
|
||||
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
|
||||
fmtp.fmt_length = phdata.sound_param[pd_FMT];
|
||||
fmtp.wav_addr = phdata.sound_addr[pd_ADDWAV];
|
||||
fmtp.wav_amp = phdata.sound_param[pd_ADDWAV];
|
||||
DoSpect2(ph, 0, &fmtp, p, 0);
|
||||
|
||||
if((p->newword == 0) && (next2->newword == 0))
|
||||
{
|
||||
if(next->type == phVFRICATIVE)
|
||||
DoPause(20,0);
|
||||
if(next->type == phFRICATIVE)
|
||||
DoPause(12,0);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1347,22 +1458,29 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
|
||||
}
|
||||
}
|
||||
|
||||
if((next->type==phVOWEL) || ((next->type==phLIQUID) && (next->newword==0))) // ?? test 14.Aug.2007
|
||||
if((next->type==phVOWEL) || ((next->type==phLIQUID)) && (next->newword==0)) // ?? test 14.Aug.2007
|
||||
{
|
||||
StartSyllable();
|
||||
if(p->synthflags & SFLAG_LENGTHEN)
|
||||
DoSpect(p->ph,prev->ph,next->ph,2,p,0);
|
||||
DoSpect(p->ph,prev->ph,next->ph,2,p,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(p->synthflags & SFLAG_LENGTHEN)
|
||||
DoSpect(p->ph,prev->ph,phoneme_tab[phonPAUSE],2,p,0);
|
||||
DoSpect(p->ph,prev->ph,phoneme_tab[phonPAUSE],2,p,0);
|
||||
p->synthflags |= SFLAG_NEXT_PAUSE;
|
||||
}
|
||||
InterpretPhoneme(NULL,0, p, &phdata);
|
||||
memset(&fmtp, 0, sizeof(fmtp));
|
||||
fmtp.std_length = phdata.pd_param[i_SET_LENGTH]*2;
|
||||
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
|
||||
fmtp.fmt_length = phdata.sound_param[pd_FMT];
|
||||
fmtp.wav_addr = phdata.sound_addr[pd_ADDWAV];
|
||||
fmtp.wav_amp = phdata.sound_param[pd_ADDWAV];
|
||||
|
||||
if(p->synthflags & SFLAG_LENGTHEN)
|
||||
DoSpect2(p->ph, 0, &fmtp, p, 0);
|
||||
DoSpect2(p->ph, 0, &fmtp, p, 0);
|
||||
break;
|
||||
|
||||
case phNASAL:
|
||||
memset(&fmtp, 0, sizeof(fmtp));
|
||||
if(!(p->synthflags & SFLAG_SEQCONTINUE))
|
||||
{
|
||||
DoAmplitude(p->amp,NULL);
|
||||
@@ -1374,29 +1492,32 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
|
||||
last_frame = NULL;
|
||||
}
|
||||
|
||||
InterpretPhoneme(NULL,0, p, &phdata);
|
||||
fmtp.std_length = phdata.pd_param[i_SET_LENGTH]*2;
|
||||
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
|
||||
fmtp.fmt_length = phdata.sound_param[pd_FMT];
|
||||
|
||||
if(next->type==phVOWEL)
|
||||
{
|
||||
StartSyllable();
|
||||
DoSpect(p->ph,prev->ph,next->ph,1,p,0);
|
||||
DoSpect2(p->ph, 0, &fmtp, p, 0);
|
||||
}
|
||||
else
|
||||
if(prev->type==phVOWEL && (p->synthflags & SFLAG_SEQCONTINUE))
|
||||
{
|
||||
DoSpect(p->ph,prev->ph,phoneme_tab[phonPAUSE],2,p,0);
|
||||
DoSpect2(p->ph, 0, &fmtp, p, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
last_frame = NULL; // only for nasal ?
|
||||
if(next->type == phLIQUID)
|
||||
DoSpect(p->ph,prev->ph,phoneme_tab[phonSONORANT],2,p,0);
|
||||
else
|
||||
DoSpect(p->ph,prev->ph,phoneme_tab[phonPAUSE],2,p,0);
|
||||
DoSpect2(p->ph, 0, &fmtp, p, 0);
|
||||
last_frame = NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case phLIQUID:
|
||||
memset(&fmtp, 0, sizeof(fmtp));
|
||||
modulation = 0;
|
||||
if(p->ph->phflags & phTRILL)
|
||||
modulation = 5;
|
||||
@@ -1419,17 +1540,14 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
|
||||
if(next->type==phVOWEL)
|
||||
{
|
||||
StartSyllable();
|
||||
DoSpect(p->ph,prev_ph,next->ph,1,p,modulation); // (,)r
|
||||
}
|
||||
else
|
||||
if(prev->type==phVOWEL && (p->synthflags & SFLAG_SEQCONTINUE))
|
||||
{
|
||||
DoSpect(p->ph,prev_ph,next->ph,1,p,modulation);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoSpect(p->ph,prev_ph,next->ph,1,p,modulation);
|
||||
}
|
||||
InterpretPhoneme(NULL, 0, p, &phdata);
|
||||
fmtp.std_length = phdata.pd_param[i_SET_LENGTH]*2;
|
||||
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
|
||||
fmtp.fmt_length = phdata.sound_param[pd_FMT];
|
||||
fmtp.wav_addr = phdata.sound_addr[pd_ADDWAV];
|
||||
fmtp.wav_amp = phdata.sound_param[pd_ADDWAV];
|
||||
DoSpect2(p->ph, 0, &fmtp, p, modulation);
|
||||
|
||||
break;
|
||||
|
||||
@@ -1437,16 +1555,46 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
|
||||
ph = p->ph;
|
||||
stress = p->stresslevel & 0xf;
|
||||
|
||||
// vowel transition from the preceding phoneme
|
||||
vowel_transition0 = vowel_transition[0];
|
||||
vowel_transition1 = vowel_transition[1];
|
||||
memset(&fmtp, 0, sizeof(fmtp));
|
||||
|
||||
InterpretPhoneme(NULL, 0, p, &phdata);
|
||||
fmtp.std_length = phdata.pd_param[i_SET_LENGTH] * 2;
|
||||
|
||||
if(((fmtp.fmt_addr = phdata.sound_addr[pd_VWLSTART]) != 0) && ((phdata.pd_control & pd_FORNEXTPH) == 0))
|
||||
{
|
||||
// a vowel start has been specified by the Vowel program
|
||||
fmtp.fmt_length = phdata.sound_param[pd_VWLSTART];
|
||||
}
|
||||
else
|
||||
if(prev->type != phPAUSE)
|
||||
{
|
||||
// check the previous phoneme
|
||||
InterpretPhoneme(NULL, 0, prev, &phdata_prev);
|
||||
if((fmtp.fmt_addr = phdata_prev.sound_addr[pd_VWLSTART]) != 0)
|
||||
{
|
||||
// a vowel start has been specified by the Vowel program
|
||||
fmtp.fmt2_lenadj = phdata_prev.sound_param[pd_VWLSTART];
|
||||
}
|
||||
fmtp.transition0 = phdata_prev.vowel_transition[0];
|
||||
fmtp.transition1 = phdata_prev.vowel_transition[1];
|
||||
}
|
||||
|
||||
if(fmtp.fmt_addr == 0)
|
||||
{
|
||||
// use the default start for this vowel
|
||||
fmtp.use_vowelin = 1;
|
||||
fmtp.fmt_control = 1;
|
||||
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
|
||||
// fmtp.fmt_length = phdata.sound_param[pd_FMT];
|
||||
}
|
||||
|
||||
pitch_env = envelope_data[p->env];
|
||||
amp_env = NULL;
|
||||
if(p->tone_ph != 0)
|
||||
{
|
||||
pitch_env = LookupEnvelope(phoneme_tab[p->tone_ph]->spect);
|
||||
amp_env = LookupEnvelope(phoneme_tab[p->tone_ph]->after);
|
||||
InterpretPhoneme2(p->tone_ph, &phdata_tone);
|
||||
pitch_env = LookupEnvelope(phdata_tone.pitch_env);
|
||||
amp_env = LookupEnvelope(phdata_tone.amp_env);
|
||||
}
|
||||
|
||||
StartSyllable();
|
||||
@@ -1462,13 +1610,13 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
|
||||
{
|
||||
DoAmplitude(p->amp,amp_env);
|
||||
DoPitch(pitch_env,p->pitch1,p->pitch2); // don't use prevocalic rising tone
|
||||
DoSpect(ph,prev->ph,next->ph,1,p,modulation);
|
||||
DoSpect2(ph, 1, &fmtp, p, modulation);
|
||||
}
|
||||
else
|
||||
if(prev->type==phLIQUID || prev->type==phNASAL)
|
||||
{
|
||||
DoAmplitude(p->amp,amp_env);
|
||||
DoSpect(ph,prev->ph,next->ph,1,p,modulation); // continue with pre-vocalic rising tone
|
||||
DoSpect2(ph, 1, &fmtp, p, modulation); // continue with pre-vocalic rising tone
|
||||
DoPitch(pitch_env,p->pitch1,p->pitch2);
|
||||
}
|
||||
else
|
||||
@@ -1479,7 +1627,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
|
||||
DoPitch(pitch_env,p->pitch1,p->pitch2);
|
||||
}
|
||||
|
||||
DoSpect(ph,prev->ph,next->ph,1,p,modulation);
|
||||
DoSpect2(ph, 1, &fmtp, p, modulation);
|
||||
}
|
||||
|
||||
if(option_phoneme_events)
|
||||
@@ -1487,9 +1635,33 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
|
||||
DoMarker(espeakEVENT_PHONEME, sourceix, 0, p->ph->mnemonic);
|
||||
}
|
||||
|
||||
DoSpect(p->ph,prev->ph,next->ph,2,p,modulation);
|
||||
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
|
||||
fmtp.fmt_length = phdata.sound_param[pd_FMT];
|
||||
fmtp.transition0 = 0;
|
||||
fmtp.transition1 = 0;
|
||||
|
||||
if((fmtp.fmt2_addr = phdata.sound_addr[pd_VWLEND]) != 0)
|
||||
{
|
||||
fmtp.fmt2_lenadj = phdata.sound_param[pd_VWLEND];
|
||||
}
|
||||
else
|
||||
if(next->type != phPAUSE)
|
||||
{
|
||||
fmtp.fmt2_lenadj = 0;
|
||||
InterpretPhoneme(NULL, 0, next, &phdata_next);
|
||||
|
||||
fmtp.use_vowelin = 1;
|
||||
fmtp.transition0 = phdata_next.vowel_transition[2]; // always do vowel_transition, even if ph_VWLEND ?? consider [N]
|
||||
fmtp.transition1 = phdata_next.vowel_transition[3];
|
||||
|
||||
if((fmtp.fmt2_addr = phdata_next.sound_addr[pd_VWLEND]) != 0)
|
||||
{
|
||||
fmtp.fmt2_lenadj = phdata_next.sound_param[pd_VWLEND];
|
||||
}
|
||||
}
|
||||
|
||||
DoSpect2(ph, 2, &fmtp, p, modulation);
|
||||
|
||||
memset(vowel_transition,0,sizeof(vowel_transition));
|
||||
break;
|
||||
}
|
||||
ix++;
|
||||
|
||||
+138
-9
@@ -47,6 +47,9 @@
|
||||
#define SFLAG_SWITCHED_LANG 0x20 // this word uses phonemes from a different language
|
||||
#define SFLAG_PROMOTE_STRESS 0x40 // this unstressed word can be promoted to stressed
|
||||
|
||||
#define SFLAG_PREV_PAUSE 0x1000 // consider previous phoneme as pause
|
||||
#define SFLAG_NEXT_PAUSE 0x2000 // consider next phoneme as pause
|
||||
|
||||
// embedded command numbers
|
||||
#define EMBED_P 1 // pitch
|
||||
#define EMBED_S 2 // speed (used in setlengths)
|
||||
@@ -170,10 +173,11 @@ int n_mix_wavefile; // length in bytes
|
||||
int mix_wave_scale; // 0=2 byte samples
|
||||
int mix_wave_amp;
|
||||
int mix_wavefile_ix;
|
||||
int mix_wavefile_max; // length of available WAV data (in bytes)
|
||||
int mix_wavefile_offset;
|
||||
|
||||
int amplitude;
|
||||
int amplitude_v;
|
||||
int prev_was_synth; // previous sound was synthesized (not a played wave or pause)
|
||||
} WGEN_DATA;
|
||||
|
||||
|
||||
@@ -207,24 +211,147 @@ typedef struct {
|
||||
frame_t *frame;
|
||||
} frameref_t;
|
||||
|
||||
// a clause translated into phoneme codes (first stage)
|
||||
typedef struct {
|
||||
unsigned char phcode;
|
||||
unsigned char stresslevel;
|
||||
unsigned char wordstress;
|
||||
unsigned char tone_ph; // tone phoneme to use with this vowel
|
||||
unsigned short synthflags;
|
||||
unsigned short sourceix; // ix into the original source text string, only set at the start of a word
|
||||
} PHONEME_LIST2;
|
||||
|
||||
|
||||
typedef struct {
|
||||
// The first section is a copy of PHONEME_LIST2
|
||||
unsigned char phcode;
|
||||
unsigned char stresslevel;
|
||||
unsigned char wordstress;
|
||||
unsigned char tone_ph; // tone phoneme to use with this vowel
|
||||
unsigned short synthflags;
|
||||
unsigned short sourceix; // ix into the original source text string, only set at the start of a word
|
||||
|
||||
PHONEME_TAB *ph;
|
||||
unsigned char env; // pitch envelope number
|
||||
unsigned char stresslevel;
|
||||
unsigned char type;
|
||||
unsigned char prepause;
|
||||
unsigned char postpause;
|
||||
unsigned char amp;
|
||||
unsigned char tone_ph; // tone phoneme to use with this vowel
|
||||
unsigned char newword; // bit 0=start of word, bit 1=end of clause, bit 2=start of sentence
|
||||
unsigned char synthflags;
|
||||
short length; // length_mod
|
||||
short pitch1; // pitch, 0-4095 within the Voice's pitch range
|
||||
short pitch2;
|
||||
unsigned short sourceix; // ix into the original source text string, only set at the start of a word
|
||||
} PHONEME_LIST;
|
||||
|
||||
|
||||
#define pd_FMT 0
|
||||
#define pd_WAV 1
|
||||
#define pd_VWLSTART 2
|
||||
#define pd_VWLEND 3
|
||||
#define pd_ADDWAV 4
|
||||
|
||||
#define N_PHONEME_DATA_PARAM 16
|
||||
#define pd_APPENDPHONEME i_APPEND_PHONEME
|
||||
#define pd_CHANGEPHONEME i_CHANGE_PHONEME
|
||||
#define pd_LENGTHMOD i_SET_LENGTH
|
||||
|
||||
#define pd_FORNEXTPH 0x2
|
||||
#define pd_DONTLENGTHEN 0x4
|
||||
#define pd_REDUCELENGTHCHANGE 0x8
|
||||
typedef struct {
|
||||
int pd_control;
|
||||
int pd_param[N_PHONEME_DATA_PARAM]; // set from group 0 instructions
|
||||
int sound_addr[5];
|
||||
int sound_param[5];
|
||||
int vowel_transition[4];
|
||||
int pitch_env;
|
||||
int amp_env;
|
||||
} PHONEME_DATA;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int fmt_control;
|
||||
int use_vowelin;
|
||||
int fmt_addr;
|
||||
int fmt_length;
|
||||
int fmt2_addr;
|
||||
int fmt2_lenadj;
|
||||
int wav_addr;
|
||||
int wav_amp;
|
||||
int transition0;
|
||||
int transition1;
|
||||
int std_length;
|
||||
} FMT_PARAMS;
|
||||
|
||||
|
||||
// instructions
|
||||
|
||||
#define i_RETURN 0x0001
|
||||
#define i_CONTINUE 0x0002
|
||||
|
||||
// Group 0 instrcutions with 8 bit operand. These value go into bits 8-15 if the instruction
|
||||
#define i_CHANGE_PHONEME 0x01
|
||||
#define i_REPLACE_NEXT_PHONEME 0x02
|
||||
#define i_INSERT_PHONEME 0x03
|
||||
#define i_APPEND_PHONEME 0x04
|
||||
#define i_APPEND_IFNEXTVOWEL 0x05
|
||||
#define i_VOICING_SWITCH 0x06
|
||||
#define i_PAUSE_BEFORE 0x07
|
||||
#define i_PAUSE_AFTER 0x08
|
||||
#define i_LENGTH_MOD 0x09
|
||||
#define i_SET_LENGTH 0x0a
|
||||
#define i_LONG_LENGTH 0x0b
|
||||
#define i_CHANGE_PHONEME2 0x0c // not yet used
|
||||
#define i_CHANGE_IF 0x10 // 0x10 to 0x14
|
||||
|
||||
#define i_ADD_LENGTH 0x0c
|
||||
|
||||
|
||||
// conditions and jumps
|
||||
#define i_CONDITION 0x2000
|
||||
#define i_OR 0x1000 // added to i_CONDITION
|
||||
|
||||
#define i_JUMP 0x6000
|
||||
#define i_JUMP_FALSE 0x6800
|
||||
#define i_SWITCH_NEXTVOWEL 0x6a00
|
||||
#define i_SWITCH_PREVVOWEL 0x6c00
|
||||
#define MAX_JUMP 255 // max jump distance
|
||||
|
||||
// multi-word instructions
|
||||
#define i_CALLPH 0x9100
|
||||
#define i_PITCHENV 0x9200
|
||||
#define i_AMPENV 0x9300
|
||||
#define i_VOWELIN 0xa100
|
||||
#define i_VOWELOUT 0xa200
|
||||
#define i_FMT 0xb000
|
||||
#define i_WAV 0xc000
|
||||
#define i_VWLSTART 0xd000
|
||||
#define i_VWLENDING 0xe000
|
||||
#define i_WAVADD 0xf000
|
||||
|
||||
// conditions
|
||||
#define i_isDiminished 0x80
|
||||
#define i_isUnstressed 0x81
|
||||
#define i_isNotStressed 0x82
|
||||
#define i_isStressed 0x83
|
||||
#define i_isMaxStress 0x84
|
||||
|
||||
#define i_isBreak 0x85
|
||||
#define i_isWordStart 0x86
|
||||
#define i_notWordStart 0x87
|
||||
#define i_isWordEnd 0x88
|
||||
#define i_isAfterStress 0x89
|
||||
#define i_isNotVowel 0x8a
|
||||
#define i_isFinalVowel 0x8b
|
||||
|
||||
|
||||
#define i_isPalatal 0x49 // bit 9 in phflags
|
||||
#define i_isRhotic 0x56 // bit 22 in phflags
|
||||
|
||||
#define i_StressLevel 0x800
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
int name;
|
||||
int length;
|
||||
@@ -317,7 +444,7 @@ extern char mbrola_name[20];
|
||||
|
||||
// from synthdata file
|
||||
unsigned int LookupSound(PHONEME_TAB *ph1, PHONEME_TAB *ph2, int which, int *match_level, int control);
|
||||
frameref_t *LookupSpect(PHONEME_TAB *ph1, PHONEME_TAB *prev_ph, PHONEME_TAB *next_ph, int which, int *match_level, 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);
|
||||
|
||||
unsigned char *LookupEnvelope(int ix);
|
||||
int LoadPhData();
|
||||
@@ -365,13 +492,15 @@ espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int
|
||||
void SetParameter(int parameter, int value, int relative);
|
||||
void MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, FILE *f_mbrola);
|
||||
//int MbrolaSynth(char *p_mbrola);
|
||||
int DoSample(PHONEME_TAB *ph1, PHONEME_TAB *ph2, int which, int length_mod, int amp);
|
||||
int DoSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB *next_ph,
|
||||
int which, PHONEME_LIST *plist, int modulation);
|
||||
//int DoSample(PHONEME_TAB *ph1, PHONEME_TAB *ph2, int which, int length_mod, int amp);
|
||||
int DoSample3(PHONEME_DATA *phdata, int length_mod, int amp);
|
||||
int DoSpect2(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, PHONEME_LIST *plist, int modulation);
|
||||
int PauseLength(int pause, int control);
|
||||
int LookupPhonemeTable(const char *name);
|
||||
|
||||
void InitBreath(void);
|
||||
|
||||
void KlattInit();
|
||||
void KlattReset(int control);
|
||||
int Wavegen_Klatt2(int length, int modulation, int resume, frame_t *fr1, frame_t *fr2);
|
||||
|
||||
|
||||
+2
-91
@@ -1183,8 +1183,9 @@ typedef struct {
|
||||
*/
|
||||
|
||||
|
||||
#define RUSSIAN2
|
||||
|
||||
#ifdef RUSSIAN2
|
||||
// This is now done in the phoneme data, ph_russian
|
||||
|
||||
int ChangePhonemes_ru(Translator *tr, PHONEME_LIST2 *phlist, int n_ph, int index, PHONEME_TAB *ph, CHANGEPH *ch)
|
||||
{//=============================================================================================================
|
||||
@@ -1276,96 +1277,6 @@ PH('V','#'),PH('I','3'),PH('I','2'),PH('E','3')};
|
||||
|
||||
return(0);
|
||||
}
|
||||
#else
|
||||
|
||||
|
||||
int ChangePhonemes_ru(Translator *tr, PHONEME_LIST2 *phlist, int n_ph, int index, PHONEME_TAB *ph, CHANGEPH *ch)
|
||||
{//=============================================================================================================
|
||||
// Called for each phoneme in the phoneme list, to allow a language to make changes
|
||||
// flags: bit 0=1 last phoneme in a word
|
||||
// bit 1=1 this is the highest stressed vowel in the current word
|
||||
// bit 2=1 after the highest stressed vowel in the current word
|
||||
// bit 3=1 the phonemes were specified explicitly, or found from an entry in the xx_list dictionary
|
||||
// ph The current phoneme
|
||||
|
||||
int variant;
|
||||
int vowelix;
|
||||
PHONEME_TAB *prev, *next;
|
||||
|
||||
if(ch->flags & 8)
|
||||
return(0); // full phoneme translation has already been given
|
||||
|
||||
// Russian vowel softening and reduction rules
|
||||
if(ph->type == phVOWEL)
|
||||
{
|
||||
#define N_VOWELS_RU 7
|
||||
static unsigned char vowels_ru[N_VOWELS_RU] = {'a','A','o','E','i','u','y'};
|
||||
|
||||
// each line gives: soft, reduced, soft-reduced, post-tonic
|
||||
static unsigned short vowel_replace[N_VOWELS_RU][4] = {
|
||||
{'&', 'V', 'I', 'V'}, // a
|
||||
{'&', 'V', 'I', 'V'}, // A
|
||||
{'8', 'V', 'I', 'V'}, // o
|
||||
{'e', 'I', 'I', 'I'}, // E
|
||||
{'i', 'I', 'I', 'I'}, // i
|
||||
{'u'+('"'<<8), 'U', 'U', 'U'}, // u
|
||||
{'y', 'Y', 'Y', 'Y'}}; // y
|
||||
|
||||
prev = phoneme_tab[phlist[index-1].phcode];
|
||||
next = phoneme_tab[phlist[index+1].phcode];
|
||||
|
||||
if(prev->mnemonic == 'j')
|
||||
return(0);
|
||||
|
||||
// lookup the vowel name to get an index into the vowel_replace[] table
|
||||
for(vowelix=0; vowelix<N_VOWELS_RU; vowelix++)
|
||||
{
|
||||
if(vowels_ru[vowelix] == ph->mnemonic)
|
||||
break;
|
||||
}
|
||||
if(vowelix == N_VOWELS_RU)
|
||||
return(0);
|
||||
|
||||
// do we need a variant of this vowel, depending on the stress and adjacent phonemes ?
|
||||
variant = -1;
|
||||
if(ch->flags & 2)
|
||||
{
|
||||
// a stressed vowel
|
||||
if((prev->phflags & phPALATAL) && ((next->phflags & phPALATAL) || phoneme_tab[phlist[index+2].phcode]->mnemonic == ';'))
|
||||
{
|
||||
// between two palatal consonants, use the soft variant
|
||||
variant = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// an unstressed vowel
|
||||
if(prev->phflags & phPALATAL)
|
||||
{
|
||||
variant = 2; // unstressed soft
|
||||
}
|
||||
else
|
||||
if((ph->mnemonic == 'o') && ((prev->phflags & phPLACE) == phPLACE_pla))
|
||||
{
|
||||
variant = 2; // unstressed soft ([o] vowel following: ш ж
|
||||
}
|
||||
else
|
||||
if(ch->flags & 4)
|
||||
{
|
||||
variant = 3; // post tonic
|
||||
}
|
||||
else
|
||||
{
|
||||
variant = 1; // unstressed
|
||||
}
|
||||
}
|
||||
if(variant >= 0)
|
||||
{
|
||||
phlist[index].phcode = PhonemeCode(vowel_replace[vowelix][variant]);
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+5
-5
@@ -962,7 +962,7 @@ if((wmark > 0) && (wmark < 8))
|
||||
|
||||
if(prefix_type & SUFX_B)
|
||||
{
|
||||
// SUFX_B is used for Turkish, tr_rules contains "(Pb£
|
||||
// SUFX_B is used for Turkish, tr_rules contains "(PbÃÂã
|
||||
// retranslate the prefix part
|
||||
char *wordpf;
|
||||
char prefix_phonemes2[12];
|
||||
@@ -1593,7 +1593,7 @@ static int TranslateWord2(Translator *tr, char *word, WORD_TAB *wtab, int pre_pa
|
||||
|
||||
plist2 = &ph_list2[n_ph_list2];
|
||||
stress = 0;
|
||||
next_stress = 0;
|
||||
next_stress = 1;
|
||||
srcix = 0;
|
||||
max_stress = -1;
|
||||
|
||||
@@ -1663,7 +1663,7 @@ static int TranslateWord2(Translator *tr, char *word, WORD_TAB *wtab, int pre_pa
|
||||
// don't add stress phonemes codes to the list, but give their stress
|
||||
// value to the next vowel phoneme
|
||||
// std_length is used to hold stress number or (if >10) a tone number for a tone language
|
||||
if(ph->spect == 0)
|
||||
if(ph->program == 0)
|
||||
next_stress = ph->std_length;
|
||||
else
|
||||
{
|
||||
@@ -1720,7 +1720,7 @@ static int TranslateWord2(Translator *tr, char *word, WORD_TAB *wtab, int pre_pa
|
||||
if(ph->type == phVOWEL)
|
||||
{
|
||||
stress = next_stress;
|
||||
next_stress = 0;
|
||||
next_stress = 1; // default is 'unstressed'
|
||||
|
||||
if(stress >= 4)
|
||||
{
|
||||
@@ -2272,7 +2272,7 @@ if((c == '/') && (tr->langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(pre
|
||||
if((c == 0x92) || (c == 0xb4) || (c == 0x2019) || (c == 0x2032))
|
||||
c = '\''; // 'microsoft' quote or sexed closing single quote, or prime - possibly used as apostrophe
|
||||
|
||||
if((c == '?') && IsAlpha(prev_out) && IsAlpha(next_in))
|
||||
if(((c == 0x2018) || (c == '?')) && IsAlpha(prev_out) && IsAlpha(next_in))
|
||||
{
|
||||
// ? between two letters may be a smart-quote replaced by ?
|
||||
c = '\'';
|
||||
|
||||
+2
-9
@@ -229,15 +229,6 @@ typedef struct{
|
||||
unsigned char length;
|
||||
} WORD_TAB;
|
||||
|
||||
// a clause translated into phoneme codes (first stage)
|
||||
typedef struct {
|
||||
unsigned char phcode;
|
||||
unsigned char stresslevel;
|
||||
unsigned char tone_ph;
|
||||
unsigned char synthflags;
|
||||
unsigned short sourceix;
|
||||
} PHONEME_LIST2;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
@@ -642,5 +633,7 @@ void *TranslateClause(Translator *tr, FILE *f_text, const void *vp_input, int *t
|
||||
int ReadClause(Translator *tr, FILE *f_in, char *buf, short *charix, int *charix_top, int n_buf, int *tone_type);
|
||||
|
||||
void SetVoiceStack(espeak_VOICE *v);
|
||||
void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_DATA *phdata);
|
||||
void InterpretPhoneme2(int phcode, PHONEME_DATA *phdata);
|
||||
|
||||
extern FILE *f_trans; // for logging
|
||||
|
||||
+10
-6
@@ -511,7 +511,7 @@ void MakeVowelLists(void)
|
||||
SPECT_SEQ *seq;
|
||||
SPECT_SEQK *seqk;
|
||||
frame_t *frame;
|
||||
int match_level;
|
||||
PHONEME_DATA phdata;
|
||||
char dirname[sizeof(path_source)+20];
|
||||
char fname[sizeof(dirname)+40];
|
||||
|
||||
@@ -540,10 +540,12 @@ void MakeVowelLists(void)
|
||||
|
||||
ph = phoneme_tab[phcode];
|
||||
|
||||
if(ph->type != phVOWEL)
|
||||
if((ph==NULL) || (ph->type != phVOWEL))
|
||||
continue;
|
||||
|
||||
if((ix = LookupSound(ph, phoneme_tab[phonPAUSE], 1, &match_level, 0)) == 0)
|
||||
InterpretPhoneme2(phcode, &phdata);
|
||||
|
||||
if((ix = phdata.sound_addr[pd_FMT]) == 0)
|
||||
continue;
|
||||
|
||||
seq = (SPECT_SEQ *)(&spects_data[ix]);
|
||||
@@ -572,9 +574,11 @@ void MakeVowelLists(void)
|
||||
}
|
||||
|
||||
|
||||
extern int n_envelopes;
|
||||
extern char envelope_paths[][80];
|
||||
extern unsigned char envelope_dat[][128];
|
||||
#define N_ENVELOPES 30
|
||||
#define ENV_LEN 128
|
||||
int n_envelopes = 0;
|
||||
char envelope_paths[N_ENVELOPES][80];
|
||||
unsigned char envelope_dat[N_ENVELOPES][ENV_LEN];
|
||||
|
||||
#define HT_ENV 140
|
||||
#define WD_ENV 128*2
|
||||
|
||||
+15
-9
@@ -720,7 +720,6 @@ void WavegenInit(int rate, int wavemult_fact)
|
||||
max_hval = 0;
|
||||
|
||||
wdata.amplitude = 32;
|
||||
wdata.prev_was_synth = 0;
|
||||
|
||||
for(ix=0; ix<N_EMBEDDED_VALUES; ix++)
|
||||
embedded_value[ix] = embedded_default[ix];
|
||||
@@ -1355,17 +1354,20 @@ int Wavegen()
|
||||
if(wdata.mix_wave_scale == 0)
|
||||
{
|
||||
// a 16 bit sample
|
||||
c = wdata.mix_wavefile[wdata.mix_wavefile_ix+1];
|
||||
sample = wdata.mix_wavefile[wdata.mix_wavefile_ix] + (c * 256);
|
||||
c = wdata.mix_wavefile[wdata.mix_wavefile_ix+wdata.mix_wavefile_offset+1];
|
||||
sample = wdata.mix_wavefile[wdata.mix_wavefile_ix+wdata.mix_wavefile_offset] + (c * 256);
|
||||
wdata.mix_wavefile_ix += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// a 8 bit sample, scaled
|
||||
sample = (signed char)wdata.mix_wavefile[wdata.mix_wavefile_ix++] * wdata.mix_wave_scale;
|
||||
sample = (signed char)wdata.mix_wavefile[wdata.mix_wavefile_offset+wdata.mix_wavefile_ix++] * wdata.mix_wave_scale;
|
||||
}
|
||||
z2 = (sample * wdata.amplitude_v) >> 10;
|
||||
z2 = (z2 * wdata.mix_wave_amp)/32;
|
||||
|
||||
if((wdata.mix_wavefile_ix + wdata.mix_wavefile_offset) >= wdata.mix_wavefile_max) // reached the end of available WAV data
|
||||
wdata.mix_wavefile_offset -= (wdata.mix_wavefile_max*3)/4;
|
||||
}
|
||||
|
||||
z1 = z2 + (((total>>8) * amplitude2) >> 13);
|
||||
@@ -1864,14 +1866,14 @@ int WavegenFill(int fill_zeros)
|
||||
echo_complete -= length;
|
||||
}
|
||||
wdata.n_mix_wavefile = 0;
|
||||
wdata.prev_was_synth = 0;
|
||||
KlattReset(1);
|
||||
result = PlaySilence(length,resume);
|
||||
break;
|
||||
|
||||
case WCMD_WAVE:
|
||||
echo_complete = echo_length;
|
||||
wdata.n_mix_wavefile = 0;
|
||||
wdata.prev_was_synth = 0;
|
||||
KlattReset(1);
|
||||
result = PlayWave(length,resume,(unsigned char*)q[2], q[3] & 0xff, q[3] >> 8);
|
||||
break;
|
||||
|
||||
@@ -1879,11 +1881,15 @@ int WavegenFill(int fill_zeros)
|
||||
// wave file to be played at the same time as synthesis
|
||||
wdata.mix_wave_amp = q[3] >> 8;
|
||||
wdata.mix_wave_scale = q[3] & 0xff;
|
||||
wdata.n_mix_wavefile = (length & 0xffff);
|
||||
wdata.mix_wavefile_max = (length >> 16) & 0xffff;
|
||||
if(wdata.mix_wave_scale == 0)
|
||||
wdata.n_mix_wavefile = length*2;
|
||||
else
|
||||
wdata.n_mix_wavefile = length;
|
||||
{
|
||||
wdata.n_mix_wavefile *= 2;
|
||||
wdata.mix_wavefile_max *= 2;
|
||||
}
|
||||
wdata.mix_wavefile_ix = 0;
|
||||
wdata.mix_wavefile_offset = 0;
|
||||
wdata.mix_wavefile = (unsigned char *)q[2];
|
||||
break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user