Program changes to enable audio output from Windows DLL. Language changes: an, de, en, nl, ta. git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@365 d46cf337-b52f-0410-862d-fd96e6ae7743master
.L03 f h j s y z r // allow [B] [D] [Q] before these consonants | .L03 f h j s y z r // allow [B] [D] [Q] before these consonants | ||||
.L04 b v f p // labials, nasals are [m] | .L04 b v f p // labials, nasals are [m] | ||||
.L05 g k // velars, nasals are [N] | .L05 g k // velars, nasals are [N] | ||||
.L06 a e o | |||||
.group a | .group a | ||||
a a | a a | ||||
i) e E | i) e E | ||||
u) e E | u) e E | ||||
y) e E | y) e E | ||||
L06_) e e# // unstressed 'e' silent at start of word after a,e,o | |||||
_) ent' (AP4 ent | _) ent' (AP4 ent | ||||
_) enta' ,ent%a | _) enta' ,ent%a | ||||
&) s (_S1 s | &) s (_S1 s | ||||
_) s' (AP2 s | _) s' (AP2 s | ||||
_) s (C@ %es | |||||
_) s (hA s | |||||
_) s (y s | |||||
A_) s (C s | |||||
.group t | .group t |
teaser _^_EN | teaser _^_EN | ||||
tech _^_EN | tech _^_EN | ||||
terminal _^_EN | terminal _^_EN | ||||
time _^_EN | |||||
trip _^_EN | trip _^_EN | ||||
tuner _^_EN | tuner _^_EN | ||||
unix _^_EN | unix _^_EN | ||||
ersten e:rst@n | ersten e:rst@n | ||||
erstmal e:rstma:l | erstmal e:rstma:l | ||||
erzgebirg e:rtsg@bIrg | erzgebirg e:rtsg@bIrg | ||||
expedient Ekspe:dI'Ent | |||||
extravagant $1 | extravagant $1 | ||||
extrem Ekstr'e:m | extrem Ekstr'e:m | ||||
@t) ien (_ 'i:@n | @t) ien (_ 'i:@n | ||||
&) iens (_ =I;@ns | &) iens (_ =I;@ns | ||||
ient (_ I'Ent | ient (_ I'Ent | ||||
d) ient (_ i:nt | |||||
&) ienz (_ I'Ents | &) ienz (_ I'Ents | ||||
sch) ie (n i: | sch) ie (n i: | ||||
@) ie (reX 'i: | @) ie (reX 'i: |
೮ 8 | ೮ 8 | ||||
೯ 9 | ೯ 9 | ||||
.L01 ಕ ಖ ಗ ಘ ಙ // velar | |||||
.L02 ಚ ಛ ಜ ಝ ಞ // palatal | |||||
.L03 ಟ ಠ ಡ ಢ ಣ // retroflex | |||||
.L04 ತ ಥ ದ ಧ ನ // dental | |||||
.L05 ಪ ಫ ಬ ಭ ಮ // labial | |||||
.group ಕ | .group ಕ | ||||
ಕ ka | ಕ ka | ||||
.group 0xe0b2 // characters which start with UTF-8 bytes: [e0 b2] | .group 0xe0b2 // characters which start with UTF-8 bytes: [e0 b2] | ||||
ಂ m // anusvara (this should nasalize the vowel) | |||||
ಂ(L01 N // anusvara (this should nasalize the vowel) | |||||
ಂ(L02 n^ | |||||
ಂ(L03 n. | |||||
ಂ(L04 n | |||||
ಂ m | |||||
ಃ h // visarga | ಃ h // visarga | ||||
boezemen $alt | boezemen $alt | ||||
ademen $alt | ademen $alt | ||||
bliksemen $alt | bliksemen $alt | ||||
wasemen $alt | |||||
wasemen v#a:s@m@n $alt | |||||
// words where -er is not a stressed verb ending | // words where -er is not a stressed verb ending | ||||
wakker $alt | wakker $alt | ||||
wapper $alt | wapper $alt | ||||
water $alt | water $alt | ||||
wedijver v#Ed'EIv@r $alt | |||||
wedijver v#'EtEIv@r $alt | |||||
weelder $alt | weelder $alt | ||||
wegwijzer $alt | wegwijzer $alt | ||||
weiger $alt | weiger $alt | ||||
vergezicht vErQ@zIxt | vergezicht vErQ@zIxt | ||||
verre vEr@ | verre vEr@ | ||||
verrekijker vEr@kEIk@r | verrekijker vEr@kEIk@r | ||||
versa vErs'a: | |||||
versa v'Erza: | |||||
verste vErst@ | verste vErst@ | ||||
verte vErt@ | verte vErt@ | ||||
volledig $2 | volledig $2 |
_) ge (tenL02 Qe: | _) ge (tenL02 Qe: | ||||
_) geu QY: | _) geu QY: | ||||
_) ge (ven Qe: | _) ge (ven Qe: | ||||
_) ge (ver Qe: | |||||
ge (vend_ Qe: | |||||
ge (ver Qe: | |||||
ge (val Q@ | ge (val Q@ | ||||
_) ge (ving Qe: | |||||
ge (ving Qe: | |||||
ge (sprek Q@ // in compounds | ge (sprek Q@ // in compounds | ||||
&) iko (_ =iko: | &) iko (_ =iko: | ||||
fam) i (lie 'i | fam) i (lie 'i | ||||
_) in (C@P2 'In | _) in (C@P2 'In | ||||
_) in (a@P2 'In | |||||
_) ing (eC_ IN // bewerkingen | _) ing (eC_ IN // bewerkingen | ||||
_) in (do In | _) in (do In | ||||
_) in (forma In | _) in (forma In |
£ libRa | £ libRa | ||||
¤ mena | ¤ mena | ||||
© kopiRajt | © kopiRajt | ||||
® Registrovane: | |||||
® RegistRovane: | |||||
¶ 'oznatSenie||'odseku | |||||
¥ jen | ¥ jen | ||||
− mi:nus | − mi:nus | ||||
± plus||m'i:nus | ± plus||m'i:nus |
_dpt _pul.l.i | _dpt _pul.l.i | ||||
// drop final [U] when followed by an ordinal suffix | |||||
// drop final [U] when followed by an ordinal suffix or thousands | |||||
_1o onR | _1o onR | ||||
_2o irVn.d. | _2o irVn.d. | ||||
_3o mu:nR | _3o mu:nR | ||||
_7Co ;ez.Unu:R | _7Co ;ez.Unu:R | ||||
_8Co ;en.n.u:R | _8Co ;en.n.u:R | ||||
_#ம் a:m // ordinal suffix | _#ம் a:m // ordinal suffix | ||||
_#ல் il | _#ல் il | ||||
_#வது a:vVdU | _#வது a:vVdU | ||||
_#வதும் a:vVdUm | _#வதும் a:vVdUm | ||||
_#வதுமாக a:vVdUma:gV | _#வதுமாக a:vVdUma:gV | ||||
_#ஆம் a:m // including ஆ | |||||
_#ஆவது a:vVdU | |||||
_#ஆவதும் a:vVdUm | |||||
_#ஆவதுமாக a:vVdUma:gV | |||||
_#-ம் a:m // ordinal suffix with hyphen | _#-ம் a:m // ordinal suffix with hyphen | ||||
_#-ல் il | _#-ல் il | ||||
_#-வது a:vVdU | _#-வது a:vVdU | ||||
_#-வதும் a:vVdUm | _#-வதும் a:vVdUm | ||||
_#-வதுமாக a:vVdUma:gV | _#-வதுமாக a:vVdUma:gV | ||||
_#-ஆம் a:m // including ஆ | |||||
_#-ஆவது a:vVdU | |||||
_#-ஆவதும் a:vVdUm | |||||
_#-ஆவதுமாக a:vVdUma:gV | |||||
// English words | // English words | ||||
tamil தமிழ் $text | tamil தமிழ் $text | ||||
பாதிக்காம $alt | பாதிக்காம $alt | ||||
பனியா $alt | பனியா $alt | ||||
பாம் $alt | பாம் $alt | ||||
போத $alt | |||||
// initial த as [d] | // initial த as [d] | ||||
போன் fo:n | போன் fo:n | ||||
போனில் fo:nil | போனில் fo:nil | ||||
//பைலை faIlaI | //பைலை faIlaI | ||||
பாதர் fa:dVr | |||||
பாதரிடம் fa:dVrid.Vm | பாதரிடம் fa:dVrid.Vm | ||||
பாதருடன் fa:dVrUd.Vn | பாதருடன் fa:dVrUd.Vn | ||||
பாதரில்லாமல் fa:dVrilla:mVl | பாதரில்லாமல் fa:dVrilla:mVl |
// endings after போர்ட (board) | // endings after போர்ட (board) | ||||
.L31 ்_ ிங் ின ை ுக்க ில ும | .L31 ்_ ிங் ின ை ுக்க ில ும | ||||
// words after அர்த்த | |||||
.L32 ராத்திரி ஜாம நிசி வேளை | |||||
// consonants | // consonants | ||||
_) க (ால்ஃப் g | _) க (ால்ஃப் g | ||||
_) கால்ப் ga:lf | _) கால்ப் ga:lf | ||||
_) க (ிஃப்ட g | _) க (ிஃப்ட g | ||||
_) கிட (ார git. | |||||
_) க (ிடுகிடு g | _) க (ிடுகிடு g | ||||
_) க (ிண்ணென்ற g | _) க (ிண்ணென்ற g | ||||
_) க (ின்னஸ g | _) க (ின்னஸ g | ||||
_) க் (ளாஸ்_ g | _) க் (ளாஸ்_ g | ||||
_) க்வ (A kw | _) க்வ (A kw | ||||
_) க் (வாலியர g | _) க் (வாலியர g | ||||
_) க (ுட்கா g | |||||
_) கோவர்த்த go:vVrddV# | |||||
_) கோர்க (ாலாந்த go:rk | |||||
_) குருமுக (ி gurumuk | |||||
_) க (ோஸ்வாமி g | |||||
_) க (ோசுவாமி g | |||||
_) க (ிடார் g | |||||
_) க (ிடாரை g | |||||
_) க (ிடாரில g | |||||
_) க (ிடாரின g | |||||
_) க (ிடாரிட g | |||||
//endsort | //endsort | ||||
//sort | //sort | ||||
_முட்) க (டிகார gV | |||||
_தமிழ்) க (ூற k | |||||
_து) க (ாராம k | |||||
_நாகர்) க (ோவில k | |||||
_கோபி) க kV# | _கோபி) க kV# | ||||
_ஸ்டா) க kV# | _ஸ்டா) க kV# | ||||
_ஜமாய்) க kV# | _ஜமாய்) க kV# | ||||
_) ச (ௌஹான tS | _) ச (ௌஹான tS | ||||
_ந) ச் (னு tS | _ந) ச் (னு tS | ||||
_கா) ச்மூச tSmu:tSV# | _கா) ச்மூச tSmu:tSV# | ||||
அ) சு (வமேத s | |||||
அ) சோக (் s.o:k | |||||
_பாஸ்கரா) ச (ாரி tS | |||||
_பரமா) ச (ாரி tS | |||||
_மி) ச (ோராம z | |||||
_) சு (வாதி s | |||||
//endsort | //endsort | ||||
அ) ட்லாண்ட t.la:n.t.V# // atlant | அ) ட்லாண்ட t.la:n.t.V# // atlant | ||||
_) ட்விங்க (ிள t.wiNk | _) ட்விங்க (ிள t.wiNk | ||||
_) ட்வ (ிட்டர t.w | _) ட்வ (ிட்டர t.w | ||||
_ஸ்) டி (ரைக் t. | |||||
_) ட (ூல t. | |||||
//endsort | //endsort | ||||
_) த (ோஹா d | _) த (ோஹா d | ||||
_) தௌலதாப (ாத daUlVd.a:b | _) தௌலதாப (ாத daUlVd.a:b | ||||
_) த (்ராட்சை d | _) த (்ராட்சை d | ||||
_) த (ாவீத d | |||||
_) த (ுரியானந்த d | |||||
_) த (ாவூத d | |||||
//endsort | //endsort | ||||
//sort | //sort | ||||
_அர்) த்த (_L32 ddV# | |||||
_நிசப்) த dV# | _நிசப்) த dV# | ||||
அனந்) த tV# | அனந்) த tV# | ||||
_வசந்) த tV# | _வசந்) த tV# | ||||
_) ப் (ளூஸ b | _) ப் (ளூஸ b | ||||
_) ப் (ளோரிடா f | _) ப் (ளோரிடா f | ||||
_) ப் (ளௌஸ b | _) ப் (ளௌஸ b | ||||
_) புத்த (கய buddV | |||||
_) பாப (ுஜி ba:p | |||||
_) பிக (ார biH | |||||
_) ப (ிஹார b | |||||
_) ப (வ்விய bV | |||||
_) பி (ளட் b | |||||
L03) ப்ப (ூதகண bb | |||||
L03) ப்ப (ூதங்கள bb | |||||
_) புளூடூத் bl.u:t.u:T | |||||
_) ப்ளூடூத் bl.u:t.u:T | |||||
_) பி (ரவுன b | |||||
_) ப் (ரவுன b | |||||
_) ப (ட்டாச்சாரி bV | |||||
_) ப (ிசினச b | |||||
_) ப (ிசினெச b | |||||
_) ப (ூசுக்த b | |||||
_) ப (ேலூர b | |||||
_) பி (ரஷர p | |||||
_) பி (ரத்தியட்ச p | |||||
_) பி (ரத்தியக்ஷ p | |||||
_) ப (ோதத் b | |||||
_) ப (ோதங்கள b | |||||
_ஜுகல்_) ப (ந்தி bV | |||||
_) புத்த (ியக்க putt | |||||
_) ப (ாணம b | |||||
_) ப (ாணத்த b | |||||
//endsort | //endsort | ||||
//sort | //sort | ||||
_சுக) ப (ோக_ b | |||||
_க) ப (ளீகர bV | |||||
_ஜா) ப (ர fV | |||||
_முரண்) ப (ாட p | |||||
_வழி) ப (ார் p | |||||
_வழி) ப (ோட p | |||||
_பழி) ப (ோட p | |||||
_துர்) ப்ப (ுத்தி bb | |||||
அவிர்) ப்ப (ாக bb | |||||
L03) ப்பி (ரேத pp | |||||
L03) ப்பி (ரதே pp | |||||
_துண்டு) ப்பி (ரசுர pp | |||||
_கை) ப்பி (ரசுர pp | |||||
_நீர்) ப pV# | _நீர்) ப pV# | ||||
_ப்ரூ) ப fV# | _ப்ரூ) ப fV# | ||||
இடர்) ப pV# | இடர்) ப pV# | ||||
_) வி (யா v | _) வி (யா v | ||||
வி (யூக v | வி (யூக v | ||||
இண்டர்) வி (யூ v | இண்டர்) வி (யூ v | ||||
L03வ்) வி (யா v | |||||
.group ஶ | .group ஶ | ||||
ஶ SV | ஶ SV | ||||
_ம) ஸ்த (ூர zd | _ம) ஸ்த (ூர zd | ||||
அரி) ஸ (ோன z | அரி) ஸ (ோன z | ||||
_சூய) ஸ zV# | _சூய) ஸ zV# | ||||
_ஹி) ஸ்ப (ுல்லா zb | |||||
.group ஹ | .group ஹ | ||||
ஹ HV | ஹ HV | ||||
இலேக்க (ிய le:gg | இலேக்க (ிய le:gg | ||||
இ (லேச | இ (லேச | ||||
இ (லையோலா | இ (லையோலா | ||||
இ (ராத்_ | |||||
இ (ராப்பகல | |||||
//endsort | //endsort | ||||
.group உ | .group உ |
91 phoneme tables | |||||
93 phoneme tables | |||||
new total | new total | ||||
base 109 109 | base 109 109 | ||||
consonants 11 119 | consonants 11 119 | ||||
et 40 135 | et 40 135 | ||||
fr 64 146 | fr 64 146 | ||||
fr-ca 11 146 | fr-ca 11 146 | ||||
nl 35 130 | |||||
nl 37 131 | |||||
hi 58 149 | hi 58 149 | ||||
bn 12 152 | bn 12 152 | ||||
ne 18 157 | ne 18 157 | ||||
pa 15 151 | pa 15 151 | ||||
ta 24 153 | ta 24 153 | ||||
kn 17 149 | kn 17 149 | ||||
ml 27 152 | |||||
ml 30 152 | |||||
hu 25 124 | hu 25 124 | ||||
lt 44 139 | lt 44 139 | ||||
lv 29 127 | lv 29 127 | ||||
es 15 125 | es 15 125 | ||||
es-la 1 125 | es-la 1 125 | ||||
ca 11 127 | ca 11 127 | ||||
an 4 125 | |||||
an 5 126 | |||||
pt 29 140 | pt 29 140 | ||||
pt-pt 20 140 | pt-pt 20 140 | ||||
ro 36 148 | ro 36 148 | ||||
si 24 155 | si 24 155 | ||||
gu 1 149 | gu 1 149 | ||||
as 12 152 | as 12 152 | ||||
or 12 152 | |||||
mni 11 152 | |||||
tn 27 121 | tn 27 121 | ||||
mt 32 129 | mt 32 129 | ||||
bo 10 153 | bo 10 153 | ||||
ustop/tsh [tS] base | ustop/tsh [tS] base | ||||
[tS#] bn | [tS#] bn | ||||
[c] zhy | [c] zhy | ||||
[tS#] or | |||||
[tS#] mni | |||||
[tS] tn | [tS] tn | ||||
ustop/tsh_ [tS] base | ustop/tsh_ [tS] base | ||||
[c] hi | [c] hi | ||||
[tS#] bn | [tS#] bn | ||||
[c] zhy | [c] zhy | ||||
[tS#] or | |||||
[tS#] mni | |||||
[tS] tn | [tS] tn | ||||
ustop/tsh2 [tS] hr | ustop/tsh2 [tS] hr | ||||
[dZ] hr | [dZ] hr | ||||
[tS] hy | [tS] hy | ||||
[tS`] am | [tS`] am | ||||
ustop/tsh_unasp2 [tS] bn | ustop/tsh_unasp2 [tS] bn | ||||
[tS] or | |||||
[tS] mni | |||||
ustop/ts_pzd [tS;] base | ustop/ts_pzd [tS;] base | ||||
[J#] hi | [J#] hi | ||||
[J#] ml | [J#] ml | ||||
[V] tt | [V] tt | ||||
vowel/&_2 [&] bn | vowel/&_2 [&] bn | ||||
[&] as | [&] as | ||||
[&] or | |||||
[&] mni | |||||
vowel/@_3 [@#] en | vowel/@_3 [@#] en | ||||
[@] en-sc | [@] en-sc | ||||
[I] en-sc | [I] en-sc | ||||
[a] nso | [a] nso | ||||
[a] te | [a] te | ||||
[a] si | [a] si | ||||
[a] or | |||||
[a] mni | |||||
vowel/a_3 [a] en-sc | vowel/a_3 [a] en-sc | ||||
[a/] en-sc | [a/] en-sc | ||||
[A:] en-sc | [A:] en-sc | ||||
[a] ka | [a] ka | ||||
[a:] si | [a:] si | ||||
[a] as | [a] as | ||||
[a] or | |||||
[a] mni | |||||
vowel/a#_3 [a#] en | vowel/a#_3 [a#] en | ||||
[a#] en-n | [a#] en-n | ||||
[a#] en-us | [a#] en-us | ||||
[e:] dv | [e:] dv | ||||
[e:] te | [e:] te | ||||
[e] as | [e] as | ||||
[e] or | |||||
[e] mni | |||||
[E] kl | [E] kl | ||||
vowel/e# [I] en-sc | vowel/e# [I] en-sc | ||||
[e] et | [e] et | ||||
[i] te | [i] te | ||||
[i] si | [i] si | ||||
[i] as | [i] as | ||||
[i] or | |||||
[i] mni | |||||
vowel/i#_6 [i.] zh | vowel/i#_6 [i.] zh | ||||
vowel/i_7 [i:] et | vowel/i_7 [i:] et | ||||
[i] pl | [i] pl | ||||
[o] te | [o] te | ||||
[o:] te | [o:] te | ||||
[o] as | [o] as | ||||
[o] or | |||||
[o] mni | |||||
[o] bo | [o] bo | ||||
[o] kl | [o] kl | ||||
vowel/o_2 [o:] cy | vowel/o_2 [o:] cy | ||||
[O] is | [O] is | ||||
[O] sq | [O] sq | ||||
[O] as | [O] as | ||||
[O] or | |||||
[O] mni | |||||
vowel/oo_en [O] en | vowel/oo_en [O] en | ||||
[O:] en | [O:] en | ||||
[O@] en | [O@] en | ||||
[u] ak | [u] ak | ||||
[u:] wo | [u:] wo | ||||
[u] as | [u] as | ||||
[u] or | |||||
[u] mni | |||||
[u] bo | [u] bo | ||||
[u] tt | [u] tt | ||||
vowel/u# [u:] en-sc | vowel/u# [u:] en-sc |
FMT(vowel/ee_1) | FMT(vowel/ee_1) | ||||
endphoneme | endphoneme | ||||
phoneme e# | |||||
vowel starttype #e endtype #e | |||||
length 200 | |||||
ChangeIfStressed(e) | |||||
ChangePhoneme(NULL) | |||||
endphoneme | |||||
phoneme O | phoneme O | ||||
vowel starttype #o endtype #o | vowel starttype #o endtype #o |
CALL base/z | CALL base/z | ||||
endphoneme | endphoneme | ||||
phoneme l | |||||
import_phoneme en/l | |||||
endphoneme | |||||
phoneme x2 | |||||
import_phoneme af/x2 | |||||
endphoneme |
Vowelin f1=0 f2=1700 -300 300 f3=-100 80 | Vowelin f1=0 f2=1700 -300 300 f3=-100 80 | ||||
Vowelout f1=0 f2=1700 -300 250 f3=-100 80 rms=20 | Vowelout f1=0 f2=1700 -300 250 f3=-100 80 rms=20 | ||||
IF nextPhW(isVowel) AND nextPh(isUnstressed) AND NOT next2PhW(n) THEN | |||||
IF prevPhW(isVowel) THEN | |||||
ChangePhoneme(t#) | |||||
ELIF prevPhW(n) THEN | |||||
WAV(ustop/t, 60) | |||||
IF nextPhW(isVowel) AND nextPh(isUnstressed) THEN | |||||
IF NOT next2PhW(n) OR nextPhW(3:) THEN | |||||
IF prevPhW(isVowel) AND NOT prevPhW(aI@) THEN | |||||
ChangePhoneme(t#) | |||||
ELIF prevPhW(n) THEN | |||||
WAV(ustop/t, 60) | |||||
ENDIF | |||||
ENDIF | ENDIF | ||||
ENDIF | ENDIF | ||||
endphoneme | endphoneme | ||||
// suggested by Prasenjit Sen, but perhaps not needed? | |||||
// ml_rules changes [p], [t], [k] to [b], [d], [g] in non-initial | |||||
// positions | |||||
phoneme p | |||||
import_phoneme consonants/p- | |||||
voicingswitch b | |||||
IF thisPh(isWordStart) THEN | |||||
CALL base/p | |||||
ELIF thisPh(isWordEnd) AND NOT thisPh(isFirstVowel) THEN | |||||
ChangePhoneme(b) | |||||
ENDIF | |||||
endphoneme | |||||
phoneme t | |||||
import_phoneme base/t[ | |||||
voicingswitch d | |||||
IF thisPh(isWordStart) THEN | |||||
CALL base/t | |||||
ELIF thisPh(isWordEnd) AND NOT thisPh(isFirstVowel) THEN | |||||
ChangePhoneme(d) | |||||
ENDIF | |||||
endphoneme | |||||
phoneme k | |||||
import_phoneme consonants/k- | |||||
voicingswitch g | |||||
IF thisPh(isWordStart) THEN | |||||
CALL base/k | |||||
ELIF thisPh(isWordEnd) AND NOT thisPh(isFirstVowel) THEN | |||||
ChangePhoneme(g) | |||||
ENDIF | |||||
endphoneme | |||||
phonemetable as bn | phonemetable as bn | ||||
include ph_assamese | include ph_assamese | ||||
phonemetable or bn | |||||
include ph_oriya | |||||
phonemetable mni bn | |||||
include ph_manipuri | |||||
sprintf(fname_log,"%s%s",path_dsource,"dict_log"); | sprintf(fname_log,"%s%s",path_dsource,"dict_log"); | ||||
log = fopen(fname_log,"w"); | log = fopen(fname_log,"w"); | ||||
if(log != 0) | |||||
{ | |||||
fprintf(log, "%s", utf8_bom); | |||||
} | |||||
sprintf(fname_log,"%s%s",path_dsource,"dict_phonemes"); | sprintf(fname_log,"%s%s",path_dsource,"dict_phonemes"); | ||||
f_phused = fopen(fname_log,"w"); | f_phused = fopen(fname_log,"w"); | ||||
else | else | ||||
{ | { | ||||
error("Unexpected keyword '%s'",item_string); | error("Unexpected keyword '%s'",item_string); | ||||
if((strcmp(item_string, "phoneme") == 0) || (strcmp(item_string, "endphoneme") == 0)) | |||||
return(-1); | |||||
} | } | ||||
// output the word | // output the word |
char *mnemptr; | char *mnemptr; | ||||
unsigned char flag_codes[100]; | unsigned char flag_codes[100]; | ||||
char encoded_ph[200]; | char encoded_ph[200]; | ||||
unsigned char bad_phoneme[4]; | |||||
char bad_phoneme_str[4]; | |||||
int bad_phoneme; | |||||
static char nullstring[] = {0}; | static char nullstring[] = {0}; | ||||
text_not_phonemes = 0; | text_not_phonemes = 0; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
EncodePhonemes(phonetic,encoded_ph,bad_phoneme); | |||||
EncodePhonemes(phonetic,encoded_ph,&bad_phoneme); | |||||
if(strchr(encoded_ph,phonSWITCH) != 0) | if(strchr(encoded_ph,phonSWITCH) != 0) | ||||
{ | { | ||||
flag_codes[n_flag_codes++] = BITNUM_FLAG_ONLY_S; // don't match on suffixes (except 's') when switching languages | flag_codes[n_flag_codes++] = BITNUM_FLAG_ONLY_S; // don't match on suffixes (except 's') when switching languages | ||||
} | } | ||||
// check for errors in the phonemes codes | // check for errors in the phonemes codes | ||||
if(bad_phoneme[0] != 0) | |||||
if(bad_phoneme != 0) | |||||
{ | { | ||||
// unrecognised phoneme, report error | // unrecognised phoneme, report error | ||||
fprintf(f_log,"%5d: Bad phoneme [%c] (0x%x) in: %s %s\n",linenum,bad_phoneme[0],bad_phoneme[0],word,phonetic); | |||||
bad_phoneme_str[utf8_out(bad_phoneme, bad_phoneme_str)] = 0; | |||||
fprintf(f_log,"%5d: Bad phoneme [%s] (U+%x) in: %s %s\n",linenum,bad_phoneme_str,bad_phoneme,word,phonetic); | |||||
error_count++; | error_count++; | ||||
} | } | ||||
} | } | ||||
int finish=0; | int finish=0; | ||||
char buf[80]; | char buf[80]; | ||||
char output[150]; | char output[150]; | ||||
unsigned char bad_phoneme[4]; | |||||
int bad_phoneme; | |||||
char bad_phoneme_str[4]; | |||||
buf[0]=0; | buf[0]=0; | ||||
rule_cond[0]=0; | rule_cond[0]=0; | ||||
return(NULL); | return(NULL); | ||||
} | } | ||||
EncodePhonemes(rule_phonemes,buf,bad_phoneme); | |||||
if(bad_phoneme[0] != 0) | |||||
EncodePhonemes(rule_phonemes,buf,&bad_phoneme); | |||||
if(bad_phoneme != 0) | |||||
{ | { | ||||
fprintf(f_log,"%5d: Bad phoneme [%c] in %s\n",linenum,bad_phoneme[0],input); | |||||
bad_phoneme_str[utf8_out(bad_phoneme, bad_phoneme_str)] = 0; | |||||
fprintf(f_log,"%5d: Bad phoneme [%s] (U+%x) in: %s\n",linenum,bad_phoneme_str,bad_phoneme,input); | |||||
error_count++; | error_count++; | ||||
} | } | ||||
strcpy(output,buf); | strcpy(output,buf); |
const char *EncodePhonemes(const char *p, char *outptr, unsigned char *bad_phoneme) | |||||
/***************************************************************************/ | |||||
const char *EncodePhonemes(const char *p, char *outptr, int *bad_phoneme) | |||||
/******************************************************************/ | |||||
/* Translate a phoneme string from ascii mnemonics to internal phoneme numbers, | /* Translate a phoneme string from ascii mnemonics to internal phoneme numbers, | ||||
from 'p' up to next blank . | from 'p' up to next blank . | ||||
Returns advanced 'p' | Returns advanced 'p' | ||||
unsigned int mnemonic_word; | unsigned int mnemonic_word; | ||||
if(bad_phoneme != NULL) | if(bad_phoneme != NULL) | ||||
bad_phoneme[0] = 0; | |||||
*bad_phoneme = 0; | |||||
// skip initial blanks | // skip initial blanks | ||||
while(isspace(*p)) | while(isspace(*p)) | ||||
// not recognised, report and ignore | // not recognised, report and ignore | ||||
if(bad_phoneme != NULL) | if(bad_phoneme != NULL) | ||||
{ | { | ||||
bad_phoneme[0] = *p; | |||||
bad_phoneme[1] = 0; | |||||
utf8_in(bad_phoneme, p); | |||||
} | } | ||||
*outptr++ = 0; | *outptr++ = 0; | ||||
return(p+1); | return(p+1); |
int debug_flag=0; | int debug_flag=0; | ||||
char fname_log[sizeof(path_dsource)+12]; | char fname_log[sizeof(path_dsource)+12]; | ||||
char err_fname[sizeof(path_home)+15]; | char err_fname[sizeof(path_home)+15]; | ||||
static const char utf8_bom[] = {0xef,0xbb,0xbf,0}; | |||||
switch(event.GetId()) | switch(event.GetId()) | ||||
{ | { | ||||
case MENU_COMPILE_DICT: | case MENU_COMPILE_DICT: | ||||
sprintf(fname_log,"%s%s",path_dsource,"dict_log"); | sprintf(fname_log,"%s%s",path_dsource,"dict_log"); | ||||
log = fopen(fname_log,"w"); | log = fopen(fname_log,"w"); | ||||
if(log != NULL) | |||||
{ | |||||
fprintf(log, "%s", utf8_bom); | |||||
} | |||||
LoadDictionary(translator, translator->dictionary_name, 0); | LoadDictionary(translator, translator->dictionary_name, 0); | ||||
if((err = CompileDictionary(path_dsource,translator->dictionary_name,log,err_fname,debug_flag)) < 0) | if((err = CompileDictionary(path_dsource,translator->dictionary_name,log,err_fname,debug_flag)) < 0) |
//<includes | //<includes | ||||
#ifndef PLATFORM_WINDOWS | |||||
#include <unistd.h> | #include <unistd.h> | ||||
#endif | |||||
#include <assert.h> | #include <assert.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
static sem_t my_sem_stop_is_acknowledged; | static sem_t my_sem_stop_is_acknowledged; | ||||
// my_thread: polls the audio duration and compares it to the duration of the first event. | // my_thread: polls the audio duration and compares it to the duration of the first event. | ||||
static pthread_t my_thread; | static pthread_t my_thread; | ||||
static bool thread_inited; | |||||
static t_espeak_callback* my_callback = NULL; | static t_espeak_callback* my_callback = NULL; | ||||
static int my_event_is_running=0; | static int my_event_is_running=0; | ||||
assert(-1 != sem_init(&my_sem_stop_is_acknowledged, 0, 0)); | assert(-1 != sem_init(&my_sem_stop_is_acknowledged, 0, 0)); | ||||
pthread_attr_t a_attrib; | pthread_attr_t a_attrib; | ||||
if (pthread_attr_init (& a_attrib) | |||||
|| pthread_attr_setdetachstate(&a_attrib, PTHREAD_CREATE_JOINABLE) | |||||
|| pthread_create( &my_thread, | |||||
& a_attrib, | |||||
polling_thread, | |||||
(void*)NULL)) | |||||
{ | |||||
assert(0); | |||||
} | |||||
if (pthread_attr_init (&a_attrib) == 0 | |||||
&& pthread_attr_setdetachstate(&a_attrib, PTHREAD_CREATE_JOINABLE) == 0) | |||||
{ | |||||
thread_inited = (0 == pthread_create(&my_thread, | |||||
&a_attrib, | |||||
polling_thread, | |||||
(void*)NULL)); | |||||
} | |||||
assert(thread_inited); | |||||
pthread_attr_destroy(&a_attrib); | pthread_attr_destroy(&a_attrib); | ||||
} | } | ||||
//> | //> | ||||
"MARK", | "MARK", | ||||
"PLAY", | "PLAY", | ||||
"END", | "END", | ||||
"MSG_TERMINATED" | |||||
"MSG_TERMINATED", | |||||
"PHONEME", | |||||
"SAMPLERATE", | |||||
"??" | |||||
}; | }; | ||||
SHOW("event_display > event=0x%x\n",event); | SHOW("event_display > event=0x%x\n",event); | ||||
{ | { | ||||
ENTER("event_terminate"); | ENTER("event_terminate"); | ||||
if (my_thread) | |||||
if (thread_inited) | |||||
{ | { | ||||
pthread_cancel(my_thread); | pthread_cancel(my_thread); | ||||
pthread_join(my_thread,NULL); | pthread_join(my_thread,NULL); | ||||
sem_destroy(&my_sem_stop_is_required); | sem_destroy(&my_sem_stop_is_required); | ||||
sem_destroy(&my_sem_stop_is_acknowledged); | sem_destroy(&my_sem_stop_is_acknowledged); | ||||
init(); // purge event | init(); // purge event | ||||
thread_inited = 0; | |||||
} | } | ||||
} | } | ||||
//<includes | //<includes | ||||
#ifndef PLATFORM_WINDOWS | |||||
#include <unistd.h> | #include <unistd.h> | ||||
#endif | |||||
#include <assert.h> | #include <assert.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <stdlib.h> | #include <stdlib.h> |
else | else | ||||
{ | { | ||||
// followed by hundreds or thousands etc | // followed by hundreds or thousands etc | ||||
sprintf(string,"_%da",value); | |||||
if(tr->langopts.numbers2 & NUM2_ORDINAL_AND_THOUSANDS) | |||||
sprintf(string, "_%do", value); | |||||
else | |||||
sprintf(string, "_%da", value); | |||||
found = Lookup(tr, string, ph_digits); | found = Lookup(tr, string, ph_digits); | ||||
} | } | ||||
else if(((control & 2) == 0) || ((tr->langopts.numbers & NUM_SWAP_TENS) != 0)) | else if(((control & 2) == 0) || ((tr->langopts.numbers & NUM_SWAP_TENS) != 0)) | ||||
{ | { | ||||
// followed by hundreds or thousands (or tens) | // followed by hundreds or thousands (or tens) | ||||
sprintf(string,"_%da",units); | |||||
if(tr->langopts.numbers2 & NUM2_ORDINAL_AND_THOUSANDS) | |||||
sprintf(string, "_%do", units); | |||||
else | |||||
sprintf(string, "_%da", units); | |||||
found = Lookup(tr, string, ph_digits); | found = Lookup(tr, string, ph_digits); | ||||
} | } | ||||
} | } |
#define phSINGLE_INSTN 0x1000 // this phoneme has a single instruction program, with an implicit Return | #define phSINGLE_INSTN 0x1000 // this phoneme has a single instruction program, with an implicit Return | ||||
#define phBRKAFTER 0x4000 // [*] add a post-pause | #define phBRKAFTER 0x4000 // [*] add a post-pause | ||||
#define phNONSYLLABIC 0x100000 // don't count this vowel as a syllable when finding the stress position | |||||
#define phNONSYLLABIC 0x100000 // don't count this vowel as a syllable when finding the stress position | |||||
#define phLONG 0x200000 | #define phLONG 0x200000 | ||||
#define phLENGTHENSTOP 0x400000 // make the pre-pause slightly longer | #define phLENGTHENSTOP 0x400000 // make the pre-pause slightly longer | ||||
#define phRHOTIC 0x800000 // bit 23 | #define phRHOTIC 0x800000 // bit 23 | ||||
unsigned char end_type; | unsigned char end_type; | ||||
unsigned char std_length; // for vowels, in mS/2; for phSTRESS phonemes, this is the stress/tone type | unsigned char std_length; // for vowels, in mS/2; for phSTRESS phonemes, this is the stress/tone type | ||||
unsigned char length_mod; // a length_mod group number, used to access length_mod_tab | unsigned char length_mod; // a length_mod group number, used to access length_mod_tab | ||||
} PHONEME_TAB; | } PHONEME_TAB; | ||||
#define PH(c1,c2) (c2<<8)+c1 // combine two characters into an integer for phoneme name | |||||
#define PH(c1,c2) (c2<<8)+c1 // combine two characters into an integer for phoneme name | |||||
#define PH3(c1,c2,c3) (c3<<16)+(c2<<8)+c1 | #define PH3(c1,c2,c3) (c3<<16)+(c2<<8)+c1 | ||||
#define PhonemeCode2(c1,c2) PhonemeCode((c2<<8)+c1) | #define PhonemeCode2(c1,c2) PhonemeCode((c2<<8)+c1) | ||||
int LookupPhonemeString(const char *string); | int LookupPhonemeString(const char *string); | ||||
int PhonemeCode(unsigned int mnem); | int PhonemeCode(unsigned int mnem); | ||||
const char *EncodePhonemes(const char *p, char *outptr, unsigned char *bad_phoneme); | |||||
const char *EncodePhonemes(const char *p, char *outptr, int *bad_phoneme); | |||||
void DecodePhonemes(const char *inptr, char *outptr); | void DecodePhonemes(const char *inptr, char *outptr); | ||||
extern const char *WordToString(unsigned int word); | extern const char *WordToString(unsigned int word); |
#include "speech.h" | #include "speech.h" | ||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||
#ifndef PLATFORM_WINDOWS | |||||
#ifdef PLATFORM_WINDOWS | |||||
#include <fcntl.h> | |||||
#include <io.h> | |||||
#include <windows.h> | |||||
#include <winreg.h> | |||||
#else /* PLATFORM_POSIX */ | |||||
#include <unistd.h> | #include <unistd.h> | ||||
#endif | #endif | ||||
"SENTENCE", | "SENTENCE", | ||||
"MARK", | "MARK", | ||||
"PLAY", | "PLAY", | ||||
"END"}; | |||||
"END", | |||||
"MSG_TERMINATED", | |||||
"PHONEME", | |||||
"SAMPLERATE", | |||||
"??" }; | |||||
#endif | #endif | ||||
#include "translate.h" | #include "translate.h" | ||||
#include "wave.h" | #include "wave.h" | ||||
const char *version_string = "1.47.12 23.Sep.13"; | |||||
const char *version_string = "1.47.13 22.Oct.13"; | |||||
const int version_phdata = 0x014709; | const int version_phdata = 0x014709; | ||||
int option_device_number = -1; | int option_device_number = -1; |
SetupTranslator(tr,stress_lengths_ta, NULL); | SetupTranslator(tr,stress_lengths_ta, NULL); | ||||
tr->letter_bits_offset = OFFSET_TAMIL; | tr->letter_bits_offset = OFFSET_TAMIL; | ||||
tr->langopts.numbers = NUM_OMIT_1_THOUSAND ; | tr->langopts.numbers = NUM_OMIT_1_THOUSAND ; | ||||
tr->langopts.numbers2 = NUM2_ORDINAL_AND_THOUSANDS; | |||||
tr->langopts.param[LOPT_WORD_MERGE] = 1; // don't break vowels betwen words | tr->langopts.param[LOPT_WORD_MERGE] = 1; // don't break vowels betwen words | ||||
} | } | ||||
else | else | ||||
break; | break; | ||||
case L('u','r'): // Urdu | case L('u','r'): // Urdu | ||||
case L('s','d'): // Sindhi | |||||
{ | { | ||||
tr->letter_bits_offset = OFFSET_ARABIC; | tr->letter_bits_offset = OFFSET_ARABIC; | ||||
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words | tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words |
prefix_flags = 1; | prefix_flags = 1; | ||||
if(found == 0) | if(found == 0) | ||||
{ | { | ||||
end_type = TranslateRules(tr, wordx, phonemes, N_WORD_PHONEMES, end_phonemes, 0, dictionary_flags); | |||||
end_type = TranslateRules(tr, wordx, phonemes, N_WORD_PHONEMES, end_phonemes, wflags & FLAG_HYPHEN_AFTER, dictionary_flags); | |||||
if(phonemes[0] == phonSWITCH) | if(phonemes[0] == phonSWITCH) | ||||
{ | { | ||||
int ix; | int ix; | ||||
int sylimit; // max. number of syllables in a word to be combined with a preceding preposition | int sylimit; // max. number of syllables in a word to be combined with a preceding preposition | ||||
const char *new_language; | const char *new_language; | ||||
unsigned char bad_phoneme[4]; | |||||
int bad_phoneme; | |||||
int word_flags; | int word_flags; | ||||
int word_copy_len; | int word_copy_len; | ||||
char word_copy[N_WORD_BYTES+1]; | char word_copy[N_WORD_BYTES+1]; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
EncodePhonemes(word,word_phonemes,bad_phoneme); | |||||
EncodePhonemes(word,word_phonemes,&bad_phoneme); | |||||
} | } | ||||
flags = FLAG_FOUND; | flags = FLAG_FOUND; | ||||
} | } |
#define NUM2_ENGLISH_NUMERALS 0x8000 | #define NUM2_ENGLISH_NUMERALS 0x8000 | ||||
#define NUM2_PERCENT_BEFORE 0x10000 | #define NUM2_PERCENT_BEFORE 0x10000 | ||||
#define NUM2_OMIT_1_HUNDRED_ONLY 0x20000 | #define NUM2_OMIT_1_HUNDRED_ONLY 0x20000 | ||||
#define NUM2_ORDINAL_AND_THOUSANDS 0x40000 | |||||
// bits 1-4 use variant form of numbers before thousands,millions,etc. | // bits 1-4 use variant form of numbers before thousands,millions,etc. | ||||
// bits 6-8 use different forms of thousand, million, etc (M MA MB) | // bits 6-8 use different forms of thousand, million, etc (M MA MB) | ||||
// bit9=(LANG=rw) say "thousand" and "million" before its number, not after | // bit9=(LANG=rw) say "thousand" and "million" before its number, not after | ||||
// bit15=(LANG=ne) speak (non-replaced) English numerals in English | // bit15=(LANG=ne) speak (non-replaced) English numerals in English | ||||
// bit16=(LANG=si) say "%" before the number | // bit16=(LANG=si) say "%" before the number | ||||
// bit17=(LANG=ml) omit "one" before hundred only if there are no previous digits | // bit17=(LANG=ml) omit "one" before hundred only if there are no previous digits | ||||
// bit18=(LANG=ta) same variant for ordinals and thousands (#o = #a) | |||||
int numbers2; | int numbers2; | ||||
#define BREAK_THOUSANDS 0x49249248 | #define BREAK_THOUSANDS 0x49249248 |
#include <time.h> | #include <time.h> | ||||
#include "portaudio.h" | #include "portaudio.h" | ||||
#ifndef PLATFORM_WINDOWS | |||||
#ifdef PLATFORM_WINDOWS | |||||
#include <windows.h> | |||||
#else | |||||
#include <unistd.h> | #include <unistd.h> | ||||
#endif | #endif | ||||
#include "wave.h" | #include "wave.h" | ||||
//<Definitions | //<Definitions | ||||
#ifdef NEED_STRUCT_TIMESPEC | |||||
#define HAVE_STRUCT_TIMESPEC 1 | |||||
struct timespec { | |||||
long tv_sec; | |||||
long tv_nsec; | |||||
}; | |||||
#endif /* HAVE_STRUCT_TIMESPEC */ | |||||
enum {ONE_BILLION=1000000000}; | enum {ONE_BILLION=1000000000}; | ||||
#ifdef USE_PORTAUDIO | #ifdef USE_PORTAUDIO | ||||
#endif | #endif | ||||
#ifdef USE_PULSEAUDIO | #ifdef USE_PULSEAUDIO | ||||
// create some wrappers for runtime detection | // create some wrappers for runtime detection | ||||
#define BUFFER_LENGTH (MAX_SAMPLE_RATE*2*sizeof(uint16_t)) | #define BUFFER_LENGTH (MAX_SAMPLE_RATE*2*sizeof(uint16_t)) | ||||
//#define THRESHOLD (BUFFER_LENGTH/5) | //#define THRESHOLD (BUFFER_LENGTH/5) | ||||
static char myBuffer[BUFFER_LENGTH]; | static char myBuffer[BUFFER_LENGTH]; | ||||
static char* myRead=NULL; | |||||
static char* myWrite=NULL; | |||||
static char* myRead=NULL; | |||||
static char* myWrite=NULL; | |||||
static int out_channels=1; | static int out_channels=1; | ||||
static int my_stream_could_start=0; | static int my_stream_could_start=0; | ||||
static int wave_samplerate; | static int wave_samplerate; | ||||
// time measurement | // time measurement | ||||
// The read and write position audio stream in the audio stream are measured in ms. | // The read and write position audio stream in the audio stream are measured in ms. | ||||
// | |||||
// | |||||
// * When the stream is opened, myReadPosition and myWritePosition are cleared. | // * When the stream is opened, myReadPosition and myWritePosition are cleared. | ||||
// * myWritePosition is updated in wave_write. | // * myWritePosition is updated in wave_write. | ||||
// * myReadPosition is updated in pa_callback (+ sample delay). | // * myReadPosition is updated in pa_callback (+ sample delay). | ||||
PaError err; | PaError err; | ||||
SHOW_TIME("start_stream"); | SHOW_TIME("start_stream"); | ||||
my_stream_could_start=0; | |||||
my_stream_could_start=0; | |||||
mInCallbackFinishedState = false; | mInCallbackFinishedState = false; | ||||
err = Pa_StartStream(pa_stream); | err = Pa_StartStream(pa_stream); | ||||
SHOW("start_stream > Pa_StartStream=%d (%s)\n", err, Pa_GetErrorText(err)); | SHOW("start_stream > Pa_StartStream=%d (%s)\n", err, Pa_GetErrorText(err)); | ||||
#if USE_PORTAUDIO == 19 | #if USE_PORTAUDIO == 19 | ||||
if(err == paStreamIsNotStopped) | if(err == paStreamIsNotStopped) | ||||
{ | { | ||||
memcpy(outputBuffer, myRead, aUsedMem); | memcpy(outputBuffer, myRead, aUsedMem); | ||||
} | } | ||||
char* p = (char*)outputBuffer + aUsedMem; | char* p = (char*)outputBuffer + aUsedMem; | ||||
memset(p, 0, n - aUsedMem); | |||||
memset(p, 0, n - aUsedMem); | |||||
// myReadPosition += aUsedMem/(out_channels*sizeof(uint16_t)); | // myReadPosition += aUsedMem/(out_channels*sizeof(uint16_t)); | ||||
myRead = aWrite; | myRead = aWrite; | ||||
} | } | ||||
myRead = myBuffer + aRest; | myRead = myBuffer + aRest; | ||||
} | } | ||||
else | else | ||||
{ | |||||
{ | |||||
SHOW_TIME("pa_callback > underflow"); | SHOW_TIME("pa_callback > underflow"); | ||||
aResult=1; // paComplete; | aResult=1; // paComplete; | ||||
size_t aUsedMem = aTopMem + aRest; | size_t aUsedMem = aTopMem + aRest; | ||||
char* p = (char*)outputBuffer + aUsedMem; | char* p = (char*)outputBuffer + aUsedMem; | ||||
memset(p, 0, n - aUsedMem); | |||||
memset(p, 0, n - aUsedMem); | |||||
// myReadPosition += aUsedMem/(out_channels*sizeof(uint16_t)); | // myReadPosition += aUsedMem/(out_channels*sizeof(uint16_t)); | ||||
myRead = aWrite; | myRead = aWrite; | ||||
} | } | ||||
//paClipOff | paDitherOff, | //paClipOff | paDitherOff, | ||||
paNoFlag, | paNoFlag, | ||||
pa_callback, (void *)userdata); | pa_callback, (void *)userdata); | ||||
SHOW("wave_open_sound > Pa_OpenDefaultStream(1): err=%d (%s)\n",err, Pa_GetErrorText(err)); | |||||
SHOW("wave_open_sound > Pa_OpenDefaultStream(1): err=%d (%s)\n",err, Pa_GetErrorText(err)); | |||||
if(err == paInvalidChannelCount) | if(err == paInvalidChannelCount) | ||||
{ | { | ||||
// paClipOff | paDitherOff, | // paClipOff | paDitherOff, | ||||
pa_callback, | pa_callback, | ||||
(void *)userdata); | (void *)userdata); | ||||
if ((err!=paNoError) | |||||
if ((err!=paNoError) | |||||
&& (err!=paInvalidChannelCount)) //err==paUnanticipatedHostError | && (err!=paInvalidChannelCount)) //err==paUnanticipatedHostError | ||||
{ | { | ||||
fprintf(stderr, "wave_open_sound > Pa_OpenStream : err=%d (%s)\n",err,Pa_GetErrorText(err)); | fprintf(stderr, "wave_open_sound > Pa_OpenStream : err=%d (%s)\n",err,Pa_GetErrorText(err)); | ||||
myOutputParameters.channelCount = 1; | myOutputParameters.channelCount = 1; | ||||
myOutputParameters.sampleFormat = paInt16; | myOutputParameters.sampleFormat = paInt16; | ||||
// Latency greater than 100ms for avoiding glitches | |||||
// Latency greater than 100ms for avoiding glitches | |||||
// (e.g. when moving a window in a graphical desktop) | // (e.g. when moving a window in a graphical desktop) | ||||
// deviceInfo = Pa_GetDeviceInfo(selectedDevice); | // deviceInfo = Pa_GetDeviceInfo(selectedDevice); | ||||
if (deviceInfo) | if (deviceInfo) | ||||
for( i=0; i<numDevices; i++ ) | for( i=0; i<numDevices; i++ ) | ||||
{ | { | ||||
deviceInfo = Pa_GetDeviceInfo( i ); | deviceInfo = Pa_GetDeviceInfo( i ); | ||||
if (deviceInfo == NULL) | if (deviceInfo == NULL) | ||||
{ | { | ||||
break; | break; | ||||
} | } | ||||
const PaHostApiInfo *hostInfo = Pa_GetHostApiInfo( deviceInfo->hostApi ); | const PaHostApiInfo *hostInfo = Pa_GetHostApiInfo( deviceInfo->hostApi ); | ||||
if (hostInfo && hostInfo->type == paALSA) | if (hostInfo && hostInfo->type == paALSA) | ||||
{ | |||||
{ | |||||
// Check (once) the default output device | // Check (once) the default output device | ||||
if (defaultAlsaIndex == numDevices) | if (defaultAlsaIndex == numDevices) | ||||
{ | { | ||||
update_output_parameters(defaultAlsaIndex, deviceInfo); | update_output_parameters(defaultAlsaIndex, deviceInfo); | ||||
if (Pa_IsFormatSupported(NULL, &myOutputParameters, wave_samplerate) == 0) | if (Pa_IsFormatSupported(NULL, &myOutputParameters, wave_samplerate) == 0) | ||||
{ | { | ||||
SHOW( "select_device > ALSA (default), name=%s (#%d)\n", deviceInfo->name, defaultAlsaIndex); | |||||
SHOW( "select_device > ALSA (default), name=%s (#%d)\n", deviceInfo->name, defaultAlsaIndex); | |||||
selectedIndex = defaultAlsaIndex; | selectedIndex = defaultAlsaIndex; | ||||
selectedDeviceInfo = deviceInfo; | selectedDeviceInfo = deviceInfo; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
// if the default output device does not match, | |||||
// look for the device with the highest number of output channels | |||||
// if the default output device does not match, | |||||
// look for the device with the highest number of output channels | |||||
SHOW( "select_device > ALSA, i=%d (numDevices=%d)\n", i, numDevices); | SHOW( "select_device > ALSA, i=%d (numDevices=%d)\n", i, numDevices); | ||||
update_output_parameters(i, deviceInfo); | update_output_parameters(i, deviceInfo); | ||||
if (Pa_IsFormatSupported(NULL, &myOutputParameters, wave_samplerate) == 0) | if (Pa_IsFormatSupported(NULL, &myOutputParameters, wave_samplerate) == 0) | ||||
{ | { | ||||
SHOW( "select_device > ALSA, name=%s (#%d)\n", deviceInfo->name, i); | SHOW( "select_device > ALSA, name=%s (#%d)\n", deviceInfo->name, i); | ||||
if (!selectedDeviceInfo | if (!selectedDeviceInfo | ||||
|| (selectedDeviceInfo->maxOutputChannels < deviceInfo->maxOutputChannels)) | || (selectedDeviceInfo->maxOutputChannels < deviceInfo->maxOutputChannels)) | ||||
{ | { | ||||
{ | { | ||||
update_output_parameters(selectedIndex, selectedDeviceInfo); | update_output_parameters(selectedIndex, selectedDeviceInfo); | ||||
} | } | ||||
else | |||||
else | |||||
{ | { | ||||
i = Pa_GetDefaultOutputDevice(); | i = Pa_GetDefaultOutputDevice(); | ||||
deviceInfo = Pa_GetDeviceInfo( i ); | deviceInfo = Pa_GetDeviceInfo( i ); | ||||
update_output_parameters(i, deviceInfo); | update_output_parameters(i, deviceInfo); | ||||
} | } | ||||
#endif | |||||
#endif | |||||
} | } | ||||
//> | //> | ||||
//<copyBuffer | //<copyBuffer | ||||
static size_t copyBuffer(char* dest, char* src, const size_t theSizeInBytes) | |||||
{ | |||||
static size_t copyBuffer(char* dest, char* src, const size_t theSizeInBytes) | |||||
{ | |||||
size_t bytes_written = 0; | size_t bytes_written = 0; | ||||
unsigned int i = 0; | unsigned int i = 0; | ||||
uint16_t* a_dest = NULL; | uint16_t* a_dest = NULL; | ||||
uint16_t* a_src = NULL; | uint16_t* a_src = NULL; | ||||
if ((src != NULL) && dest != NULL) | if ((src != NULL) && dest != NULL) | ||||
{ | |||||
{ | |||||
// copy for one channel (mono)? | // copy for one channel (mono)? | ||||
if(out_channels==1) | if(out_channels==1) | ||||
{ | |||||
{ | |||||
SHOW("copyBuffer > 1 channel > memcpy %x (%d bytes)\n", (int)myWrite, theSizeInBytes); | SHOW("copyBuffer > 1 channel > memcpy %x (%d bytes)\n", (int)myWrite, theSizeInBytes); | ||||
memcpy(dest, src, theSizeInBytes); | memcpy(dest, src, theSizeInBytes); | ||||
bytes_written = theSizeInBytes; | bytes_written = theSizeInBytes; | ||||
i = 0; | i = 0; | ||||
a_dest = (uint16_t* )dest; | a_dest = (uint16_t* )dest; | ||||
a_src = (uint16_t* )src; | a_src = (uint16_t* )src; | ||||
for(i=0; i<theSizeInBytes/2; i++) | for(i=0; i<theSizeInBytes/2; i++) | ||||
{ | { | ||||
a_dest[2*i] = a_src[i]; | a_dest[2*i] = a_src[i]; | ||||
bytes_written = 2*theSizeInBytes; | bytes_written = 2*theSizeInBytes; | ||||
} // end if(out_channels==1) | } // end if(out_channels==1) | ||||
} // end if ((src != NULL) && dest != NULL) | } // end if ((src != NULL) && dest != NULL) | ||||
return bytes_written; | |||||
return bytes_written; | |||||
} | } | ||||
//> | //> | ||||
// space in ringbuffer for the sample needed: 1x mono channel but 2x for 1 stereo channel | // space in ringbuffer for the sample needed: 1x mono channel but 2x for 1 stereo channel | ||||
size_t bytes_to_write = (out_channels==1) ? theSize : theSize*2; | size_t bytes_to_write = (out_channels==1) ? theSize : theSize*2; | ||||
my_stream_could_start = 0; | my_stream_could_start = 0; | ||||
if(pa_stream == NULL) | if(pa_stream == NULL) | ||||
{ | { | ||||
SHOW_TIME("wave_write > wave_open_sound\n"); | SHOW_TIME("wave_write > wave_open_sound\n"); | ||||
my_stream_could_start = 1; | my_stream_could_start = 1; | ||||
} | } | ||||
assert(BUFFER_LENGTH >= bytes_to_write); | assert(BUFFER_LENGTH >= bytes_to_write); | ||||
if (myWrite >= myBuffer + BUFFER_LENGTH) | if (myWrite >= myBuffer + BUFFER_LENGTH) | ||||
{ | { | ||||
myWrite = myBuffer; | myWrite = myBuffer; | ||||
} // end if (myWrite >= myBuffer + BUFFER_LENGTH) | } // end if (myWrite >= myBuffer + BUFFER_LENGTH) | ||||
size_t aTotalFreeMem=0; | size_t aTotalFreeMem=0; | ||||
char* aRead = myRead; | char* aRead = myRead; | ||||
SHOW("wave_write > aRead=%x, myWrite=%x\n", (int)aRead, (int)myWrite); | SHOW("wave_write > aRead=%x, myWrite=%x\n", (int)aRead, (int)myWrite); | ||||
while (1) | while (1) | ||||
{ | { | ||||
if (my_callback_is_output_enabled && (0==my_callback_is_output_enabled())) | if (my_callback_is_output_enabled && (0==my_callback_is_output_enabled())) | ||||
SHOW_TIME("wave_write > my_callback_is_output_enabled: no!"); | SHOW_TIME("wave_write > my_callback_is_output_enabled: no!"); | ||||
return 0; | return 0; | ||||
} | } | ||||
aRead = myRead; | aRead = myRead; | ||||
// write pointer is before read pointer? | // write pointer is before read pointer? | ||||
if (myWrite >= aRead) | if (myWrite >= aRead) | ||||
{ | { | ||||
{ | { | ||||
aTotalFreeMem = aRead - myWrite; | aTotalFreeMem = aRead - myWrite; | ||||
} // end if (myWrite >= aRead) | } // end if (myWrite >= aRead) | ||||
if (aTotalFreeMem>1) | if (aTotalFreeMem>1) | ||||
{ | { | ||||
// -1 because myWrite must be different of aRead | // -1 because myWrite must be different of aRead | ||||
// otherwise buffer would be considered as empty | // otherwise buffer would be considered as empty | ||||
aTotalFreeMem -= 1; | aTotalFreeMem -= 1; | ||||
} // end if (aTotalFreeMem>1) | } // end if (aTotalFreeMem>1) | ||||
if (aTotalFreeMem >= bytes_to_write) | if (aTotalFreeMem >= bytes_to_write) | ||||
{ | { | ||||
break; | break; | ||||
} // end if (aTotalFreeMem >= bytes_to_write) | } // end if (aTotalFreeMem >= bytes_to_write) | ||||
//SHOW_TIME("wave_write > wait"); | //SHOW_TIME("wave_write > wait"); | ||||
SHOW("wave_write > wait: aTotalFreeMem=%d\n", aTotalFreeMem); | SHOW("wave_write > wait: aTotalFreeMem=%d\n", aTotalFreeMem); | ||||
SHOW("wave_write > aRead=%x, myWrite=%x\n", (int)aRead, (int)myWrite); | SHOW("wave_write > aRead=%x, myWrite=%x\n", (int)aRead, (int)myWrite); | ||||
usleep(10000); | usleep(10000); | ||||
} // end while (1) | } // end while (1) | ||||
aRead = myRead; | aRead = myRead; | ||||
// write pointer is ahead the read pointer? | // write pointer is ahead the read pointer? | ||||
if (myWrite >= aRead) | if (myWrite >= aRead) | ||||
{ | { | ||||
SHOW_TIME("wave_write > myWrite <= aRead"); | SHOW_TIME("wave_write > myWrite <= aRead"); | ||||
myWrite += copyBuffer(myWrite, theMono16BitsWaveBuffer, theSize); | myWrite += copyBuffer(myWrite, theMono16BitsWaveBuffer, theSize); | ||||
} // end if (myWrite >= aRead) | } // end if (myWrite >= aRead) | ||||
bytes_written = bytes_to_write; | bytes_written = bytes_to_write; | ||||
myWritePosition += theSize/sizeof(uint16_t); // add number of samples | myWritePosition += theSize/sizeof(uint16_t); // add number of samples | ||||
if (my_stream_could_start && (get_used_mem() >= out_channels * sizeof(uint16_t) * FRAMES_PER_BUFFER)) | if (my_stream_could_start && (get_used_mem() >= out_channels * sizeof(uint16_t) * FRAMES_PER_BUFFER)) | ||||
{ | { | ||||
start_stream(); | start_stream(); | ||||
} // end if (my_stream_could_start && (get_used_mem() >= out_channels * sizeof(uint16_t) * FRAMES_PER_BUFFER)) | } // end if (my_stream_could_start && (get_used_mem() >= out_channels * sizeof(uint16_t) * FRAMES_PER_BUFFER)) | ||||
SHOW_TIME("wave_write > LEAVE"); | SHOW_TIME("wave_write > LEAVE"); | ||||
return bytes_written; | return bytes_written; | ||||
} | } | ||||
SHOW_TIME("wave_close > LEAVE (NULL stream)"); | SHOW_TIME("wave_close > LEAVE (NULL stream)"); | ||||
return 0; | return 0; | ||||
} | } | ||||
if( Pa_IsStreamStopped( pa_stream ) ) | if( Pa_IsStreamStopped( pa_stream ) ) | ||||
{ | { | ||||
SHOW_TIME("wave_close > LEAVE (stopped)"); | SHOW_TIME("wave_close > LEAVE (stopped)"); | ||||
SHOW_TIME("wave_close > LEAVE (NULL stream)"); | SHOW_TIME("wave_close > LEAVE (NULL stream)"); | ||||
return 0; | return 0; | ||||
} | } | ||||
if( Pa_StreamActive( pa_stream ) == false && mInCallbackFinishedState == false ) | if( Pa_StreamActive( pa_stream ) == false && mInCallbackFinishedState == false ) | ||||
{ | { | ||||
SHOW_TIME("wave_close > LEAVE (not active)"); | SHOW_TIME("wave_close > LEAVE (not active)"); | ||||
SHOW_TIME("wave_close > LEAVE (stopStreamCount)"); | SHOW_TIME("wave_close > LEAVE (stopStreamCount)"); | ||||
return 0; | return 0; | ||||
} | } | ||||
// Comment from Audacity-1.2.4b adapted to the eSpeak context. | |||||
// Comment from Audacity-1.2.4b adapted to the eSpeak context. | |||||
// | // | ||||
// We got here in one of two ways: | // We got here in one of two ways: | ||||
// | // | ||||
// 1. The calling program calls the espeak_Cancel function and we | |||||
// therefore want to stop as quickly as possible. | |||||
// 1. The calling program calls the espeak_Cancel function and we | |||||
// therefore want to stop as quickly as possible. | |||||
// So we use AbortStream(). If this is | // So we use AbortStream(). If this is | ||||
// the case the portaudio stream is still in the Running state | // the case the portaudio stream is still in the Running state | ||||
// (see PortAudio state machine docs). | // (see PortAudio state machine docs). | ||||
// | // | ||||
// 2. The callback told PortAudio to stop the stream since it had | // 2. The callback told PortAudio to stop the stream since it had | ||||
// reached the end of the selection. | |||||
// The event polling thread discovered this by noticing that | |||||
// reached the end of the selection. | |||||
// The event polling thread discovered this by noticing that | |||||
// wave_is_busy() returned false. | // wave_is_busy() returned false. | ||||
// wave_is_busy() (which calls Pa_GetStreamActive()) will not return | // wave_is_busy() (which calls Pa_GetStreamActive()) will not return | ||||
// false until all buffers have finished playing, so we can call | // false until all buffers have finished playing, so we can call | ||||
// call StopStream if the callback brought us here, and AbortStream | // call StopStream if the callback brought us here, and AbortStream | ||||
// if the user brought us here. | // if the user brought us here. | ||||
// | // | ||||
#if (USE_PORTAUDIO == 19) | #if (USE_PORTAUDIO == 19) | ||||
if (pa_stream) | if (pa_stream) | ||||
{ | { | ||||
if (pa_stream) | if (pa_stream) | ||||
{ | { | ||||
#if USE_PORTAUDIO == 18 | #if USE_PORTAUDIO == 18 | ||||
active = Pa_StreamActive(pa_stream) | |||||
active = Pa_StreamActive(pa_stream) | |||||
&& (mInCallbackFinishedState == false); | && (mInCallbackFinishedState == false); | ||||
#else | #else | ||||
active = Pa_IsStreamActive(pa_stream) | active = Pa_IsStreamActive(pa_stream) | ||||
&& (mInCallbackFinishedState == false); | && (mInCallbackFinishedState == false); | ||||
#endif | #endif | ||||
} | } | ||||
SHOW("wave_is_busy: %d\n",active); | SHOW("wave_is_busy: %d\n",active); | ||||
if (!time || !pa_stream) | if (!time || !pa_stream) | ||||
{ | { | ||||
SHOW("event get_remaining_time> %s\n","audio device not available"); | |||||
SHOW("event get_remaining_time> %s\n","audio device not available"); | |||||
return -1; | return -1; | ||||
} | } | ||||
{ | { | ||||
SHOW("event > add_time_in_ms ns: %d sec %Lu nsec \n", ts->tv_sec, t_ns); | SHOW("event > add_time_in_ms ns: %d sec %Lu nsec \n", ts->tv_sec, t_ns); | ||||
ts->tv_sec += 1; | ts->tv_sec += 1; | ||||
t_ns -= ONE_BILLION; | |||||
t_ns -= ONE_BILLION; | |||||
} | } | ||||
ts->tv_nsec = (long int)t_ns; | ts->tv_nsec = (long int)t_ns; | ||||
} | } |