Added runtime detection of pulseaudio, with fallback to portaudio if pulse is not running. Use build option "AUDIO=runtime" in the makefile. Phoneme programs. Added condition "isTranslationGiven" to test whether a phoneme has been specified explicitly for a word in *_list. *_rules files. Suffix rules are now considered only if there is a previous vowel in the word. git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@274 d46cf337-b52f-0410-862d-fd96e6ae7743master
@@ -66,7 +66,7 @@ R3 s S t T tS v w | |||
x z Z | |||
Dictionary hu_dict 2011-09-07 | |||
Dictionary hu_dict 2011-09-15 | |||
a A a: E e: i i: o | |||
o: u u: Y y y: Y: | |||
@@ -102,7 +102,7 @@ p Q r R s s; t T | |||
ts v x z | |||
Dictionary en_dict 2011-09-07 | |||
Dictionary en_dict 2011-09-08 | |||
0 3 3: @ @- @2 @5 @L | |||
a a# A: A@ aa aI aI@ aU | |||
@@ -202,7 +202,7 @@ q r r. s S s. t T | |||
t. th th. v w x z | |||
Dictionary ta_dict 2011-09-07 | |||
Dictionary ta_dict 2011-09-13 | |||
a a: aI aU e E e: i | |||
I i: o o: u U u2 u: | |||
@@ -327,7 +327,7 @@ k l m n p R s S | |||
t tS v w x | |||
Dictionary nl_dict 2011-08-26 | |||
Dictionary nl_dict 2011-09-12 | |||
8 @ @- a A a: A~ e | |||
E e# E2 e: EI eU i I | |||
@@ -476,7 +476,7 @@ p R R^ s S t tS ts | |||
v w x z Z | |||
Dictionary tr_dict 2011-04-22 | |||
Dictionary tr_dict 2011-09-16 | |||
@ a e E i I o O | |||
u U W y Y |
@@ -1967,6 +1967,24 @@ használatáról $unstressend | |||
gyártót $unstressend | |||
bírja $unstressend | |||
azon $unstressend | |||
kultúráját $unstressend | |||
célja $unstressend | |||
hirdeti $unstressend | |||
munkához $unstressend | |||
teremtsen $unstressend | |||
munkát $unstressend | |||
programmal $unstressend | |||
alkotott $unstressend | |||
válaszokat $unstressend | |||
környezetben $unstressend | |||
elfogadtak $unstressend | |||
érkezik $unstressend | |||
kiállításon $unstressend | |||
területén $unstressend | |||
gyengén $unstressend | |||
jelentőségű $unstressend | |||
elárulta $unstressend | |||
bolygón $unstressend | |||
// word pairs | |||
@@ -124,6 +124,7 @@ szanité) c (cs ts | |||
bohó) c (sipk ts | |||
kilen) c (sáv ts | |||
cszs tSZ | |||
kilen) c (schill ts | |||
.group ch | |||
anar) ch (i h | |||
@@ -1178,6 +1179,14 @@ gaboná) szs (ák SZ | |||
para) szt (segg st | |||
azbe) szt (sisak st | |||
nyu) szt (süveg st | |||
serté) szs (ír SZ | |||
szere) szs (ák SZ | |||
rizse) szs (ák SZ | |||
tá) szs (in SZ | |||
ruhá) szs (ák SZ | |||
ro) szs (ák SZ | |||
va) szs (ír SZ | |||
széná) szs (ák SZ | |||
.group t | |||
t t |
@@ -93,33 +93,33 @@ __ ,alttSIzg'I | |||
€ avRO | |||
_0 s@f@R | |||
_1 biR | |||
_2 ici | |||
_3 YtS | |||
_4 dWRt | |||
_5 beS | |||
_6 alt@ | |||
_7 jedi | |||
_8 seciz | |||
_9 dokuz | |||
_10 on | |||
_0 s@f'@R | |||
_1 b'iR | |||
_2 ic'i | |||
_3 'ytS | |||
_4 d'WRt | |||
_5 b'ES | |||
_6 alt'@ | |||
_7 jed'i | |||
_8 sec'Iz | |||
_9 d'okuz | |||
_10 'on | |||
_11 'onbiR | |||
_12 'onici | |||
_1X on | |||
_2X jiRmi | |||
_3X otuz | |||
_4X k@Rk | |||
_5X elli | |||
_6X altm@S | |||
_7X jetmiS | |||
_8X seksEn | |||
_9X doksan | |||
_0C jyz | |||
_1X 'on | |||
_2X jiRm'i | |||
_3X ot'uz | |||
_4X k'@Rk | |||
_5X ell'i | |||
_6X altm'@S | |||
_7X jetm'iS | |||
_8X seks'En | |||
_9X doks'an | |||
_0C 'jyz | |||
_2C 'icijyz | |||
_0M1 bIn | |||
_0M2 miljon | |||
_0M3 miljar | |||
_0M1 b'in | |||
_0M2 milj'on | |||
_0M3 milj'ar | |||
_dpt _viRg,Yl_| | |||
@@ -394,8 +394,8 @@ l/l_ [l] base | |||
[l/] fr | |||
l/l_@ [l/3] base | |||
[l/] fr | |||
l/l@ [l#] base | |||
[”¦] base | |||
l/l@ [hÖq] base | |||
[l#] base | |||
[l] fr | |||
[l/2] fr | |||
[K] nso | |||
@@ -428,16 +428,16 @@ l/L2_oL [l/2] base | |||
l/L2_uL [l/2] base | |||
l/l_3 [l/] de | |||
l/l_4 [ll] sq | |||
l/la [l#] base | |||
[”¦] base | |||
l/la [hÖq] base | |||
[l#] base | |||
[l] fr | |||
[l/2] fr | |||
[K] nso | |||
[K] tn | |||
l/l_a [l/3] base | |||
[l/] fr | |||
l/le [l#] base | |||
[”¦] base | |||
l/le [hÖq] base | |||
[l#] base | |||
[l] fr | |||
[l/2] fr | |||
[K] nso | |||
@@ -448,8 +448,8 @@ l/L_eL_af [&] af | |||
[&:] af | |||
l/l_front [L] sq | |||
l/l_front_ [l/4] sq | |||
l/li [l#] base | |||
[”¦] base | |||
l/li [hÖq] base | |||
[l#] base | |||
[l] fr | |||
[l/2] fr | |||
[l] zh | |||
@@ -462,8 +462,8 @@ ll/ll [L] bg | |||
ll/_ll [L] bg | |||
l/l_long [l] base | |||
[l] fr | |||
l/lo [l#] base | |||
[”¦] base | |||
l/lo [hÖq] base | |||
[l#] base | |||
[l/2] fr | |||
[K] nso | |||
[K] tn | |||
@@ -472,8 +472,8 @@ l/l_o [l/3] base | |||
l^/l_rfx [l.] base | |||
[l] ru | |||
[l^] ru | |||
l/lu [l#] base | |||
[”¦] base | |||
l/lu [hÖq] base | |||
[l#] base | |||
[l] fr | |||
[l/2] fr | |||
[K] nso | |||
@@ -1870,7 +1870,6 @@ vowel/ii_3 [I] cy | |||
[I] hr | |||
[I] sv | |||
[I] no | |||
[I] tr | |||
[I] pa | |||
[i] sl | |||
vowel/ii#_3 [I2] en-us | |||
@@ -1882,6 +1881,7 @@ vowel/ii_5 [i1] et | |||
[i] bg | |||
[I] la | |||
[i] zh | |||
[I] tr | |||
[i] az | |||
[i] am | |||
vowel/ii_6 [I] en-wm |
@@ -3,11 +3,15 @@ | |||
phoneme i | |||
vowel starttype #i endtype #i | |||
length 150 | |||
IF thisPh(isFinalVowel) THEN | |||
ChangePhoneme(I) | |||
ENDIF | |||
IF nextPh(isNotVowel) AND next2Ph(isNotVowel) THEN | |||
ChangePhoneme(I) | |||
IF thisPh(isTranslationGiven) THEN | |||
// don't reduce the vowel if phonemes are explicitly given | |||
ELSE | |||
IF thisPh(isFinalVowel) THEN | |||
ChangePhoneme(I) | |||
ENDIF | |||
IF nextPh(isNotVowel) AND next2Ph(isNotVowel) THEN | |||
ChangePhoneme(I) | |||
ENDIF | |||
ENDIF | |||
FMT(vowel/i_6) | |||
endphoneme | |||
@@ -15,17 +19,22 @@ endphoneme | |||
phoneme I | |||
vowel starttype #i endtype #i | |||
length 150 | |||
FMT(vowel/ii_3) | |||
FMT(vowel/ii_5) | |||
endphoneme | |||
phoneme y | |||
vowel starttype #u endtype #u | |||
length 155 | |||
IF thisPh(isFinalVowel) THEN | |||
ChangePhoneme(Y) | |||
ENDIF | |||
IF nextPh(isNotVowel) AND next2Ph(isNotVowel) THEN | |||
ChangePhoneme(Y) | |||
IF thisPh(isTranslationGiven) THEN | |||
// don't reduce the vowel if phonemes are explicitly given | |||
ELSE | |||
IF thisPh(isFinalVowel) THEN | |||
ChangePhoneme(Y) | |||
ENDIF | |||
IF nextPh(isNotVowel) AND next2Ph(isNotVowel) THEN | |||
ChangePhoneme(Y) | |||
ENDIF | |||
ENDIF | |||
FMT(vowel/y_5) | |||
endphoneme | |||
@@ -41,11 +50,15 @@ endphoneme | |||
phoneme e | |||
vowel starttype #e endtype #e | |||
length 180 | |||
IF thisPh(isFinalVowel) THEN | |||
ChangePhoneme(E) | |||
ENDIF | |||
IF nextPh(isNotVowel) AND next2Ph(isNotVowel) THEN | |||
ChangePhoneme(E) | |||
IF thisPh(isTranslationGiven) THEN | |||
// don't reduce the vowel if phonemes are explicitly given | |||
ELSE | |||
IF thisPh(isFinalVowel) THEN | |||
ChangePhoneme(E) | |||
ENDIF | |||
IF nextPh(isNotVowel) AND next2Ph(isNotVowel) THEN | |||
ChangePhoneme(E) | |||
ENDIF | |||
ENDIF | |||
FMT(vowel/e_mid2) | |||
endphoneme | |||
@@ -56,6 +69,7 @@ phoneme E | |||
FMT(vowel/e_mid) | |||
endphoneme | |||
phoneme W | |||
vowel starttype #@ endtype #@ | |||
length 180 | |||
@@ -63,7 +77,6 @@ phoneme W | |||
endphoneme | |||
phoneme a | |||
vowel starttype #a endtype #a | |||
length 190 | |||
@@ -75,16 +88,19 @@ endphoneme | |||
phoneme u | |||
vowel starttype #u endtype #u | |||
length 150 | |||
IF thisPh(isFinalVowel) THEN | |||
ChangePhoneme(U) | |||
ENDIF | |||
IF nextPh(isNotVowel) AND next2Ph(isNotVowel) THEN | |||
ChangePhoneme(U) | |||
IF thisPh(isTranslationGiven) THEN | |||
// don't reduce the vowel if phonemes are explicitly given | |||
ELSE | |||
IF thisPh(isFinalVowel) THEN | |||
ChangePhoneme(U) | |||
ENDIF | |||
IF nextPh(isNotVowel) AND next2Ph(isNotVowel) THEN | |||
ChangePhoneme(U) | |||
ENDIF | |||
ENDIF | |||
FMT(vowel/u_2) | |||
endphoneme | |||
phoneme U | |||
vowel starttype #u endtype #u | |||
length 150 | |||
@@ -104,11 +120,15 @@ endphoneme | |||
phoneme o | |||
vowel starttype #o endtype #o | |||
length 190 | |||
IF thisPh(isFinalVowel) THEN | |||
ChangePhoneme(O) | |||
ENDIF | |||
IF nextPh(isNotVowel) AND next2Ph(isNotVowel) THEN | |||
ChangePhoneme(O) | |||
IF thisPh(isTranslationGiven) THEN | |||
// don't reduce the vowel if phonemes are explicitly given | |||
ELSE | |||
IF thisPh(isFinalVowel) THEN | |||
ChangePhoneme(O) | |||
ENDIF | |||
IF nextPh(isNotVowel) AND next2Ph(isNotVowel) THEN | |||
ChangePhoneme(O) | |||
ENDIF | |||
ENDIF | |||
FMT(vowel/o_mid) | |||
endphoneme |
@@ -25,12 +25,19 @@ INSTALL = install | |||
LN_SF = /bin/ln -sf | |||
MKDIR = mkdir -p | |||
# 'runtime' uses pulseaudio if it is running, else uses portaudio | |||
#AUDIO = runtime | |||
AUDIO = portaudio | |||
#AUDIO = portaudio0 | |||
#AUDIO = portaudio2 | |||
#AUDIO = pulseaudio | |||
#AUDIO = sada | |||
ifeq ($(AUDIO),runtime) | |||
WAVE=wave.cpp wave_pulse.cpp | |||
LIB_AUDIO=-lpulse -lpulse-simple -lportaudio | |||
USE_AUDIO=-DUSE_PULSEAUDIO -DUSE_PORTAUDIO | |||
else | |||
ifeq ($(AUDIO),pulseaudio) | |||
WAVE=wave_pulse.cpp | |||
LIB_AUDIO=-lpulse | |||
@@ -61,6 +68,7 @@ endif | |||
endif | |||
endif | |||
endif | |||
endif | |||
speak_SOURCES = speak.cpp compiledict.cpp dictionary.cpp intonation.cpp \ | |||
readclause.cpp setlengths.cpp numbers.cpp synth_mbrola.cpp \ |
@@ -20,7 +20,7 @@ CPPFLAGS = -Wall -g -fexceptions -I/usr/lib/wx/include/gtk2-unicode-release-2.6 | |||
-DGTK_NO_CHECK_CASTS -D__WXGTK__ -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES | |||
-D_LARGEFILE_SOURCE=1 -DNO_GCC_PRAGMA -D_ESPEAKEDIT | |||
CXXFLAGS = -O2 -g0 -Wall -g -fexceptions -I/usr/lib/wx/include/gtk2-unicode-release-2.6 -I/usr/include/wx-2.6 \ | |||
CXXFLAGS = -O2 -Wall -fexceptions -I/usr/lib/wx/include/gtk2-unicode-release-2.6 -I/usr/include/wx-2.6 \ | |||
-DGTK_NO_CHECK_CASTS -D__WXGTK__ -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES -D_LARGEFILE_SOURCE=1 -DNO_GCC_PRAGMA -D_ESPEAKEDIT | |||
all: espeakedit |
@@ -95,8 +95,8 @@ static keywtab_t k_conditions[] = { | |||
{"nextPh", tWHICH_PHONEME, 0x200}, | |||
{"next2Ph", tWHICH_PHONEME, 0x300}, | |||
{"nextPhW", tWHICH_PHONEME, 0x400}, | |||
{"next2PhW", tWHICH_PHONEME, 0x700}, | |||
{"nextVowel",tWHICH_PHONEME, 0x600}, | |||
// {"next2PhW", tWHICH_PHONEME, 0x700}, | |||
// {"numVowels", tTEST, 0x000}, | |||
// {"afterStress", tTEST, 0x000}, | |||
@@ -144,6 +144,7 @@ static keywtab_t k_properties[] = { | |||
{"isFirstVowel", 0, i_isFirstVowel}, | |||
{"isSecondVowel", 0, i_isSecondVowel}, | |||
{"isSeqFlag1", 0, i_isSeqFlag1}, | |||
{"isTranslationGiven", 0, i_IsTranslationGiven}, // phoneme translation given in **_list or as [[...]] | |||
{NULL, 0, 0} | |||
}; |
@@ -2161,9 +2161,19 @@ static void MatchRule(Translator *tr, char *word[], char *word_start, int group_ | |||
break; | |||
case RULE_ENDING: | |||
// next 3 bytes are a (non-zero) ending type. 2 bytes of flags + suffix length | |||
match.end_type = (rule[0] << 16) + ((rule[1] & 0x7f) << 8) + (rule[2] & 0x7f); | |||
rule += 3; | |||
{ | |||
int end_type; | |||
// next 3 bytes are a (non-zero) ending type. 2 bytes of flags + suffix length | |||
end_type = (rule[0] << 16) + ((rule[1] & 0x7f) << 8) + (rule[2] & 0x7f); | |||
if((tr->word_vowel_count == 0) && !(end_type & SUFX_P)) | |||
failed = 1; // don't match a suffix rule if there are no previous syllables (needed for lang=tr). | |||
else | |||
{ | |||
match.end_type = end_type; | |||
rule += 3; | |||
} | |||
} | |||
break; | |||
case RULE_NO_SUFFIX: |
@@ -448,50 +448,6 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
} | |||
} | |||
#ifdef deleted | |||
while((ph->reduce_to != 0) && (!(plist3->synthflags & SFLAG_DICTIONARY) || (tr->langopts.param[LOPT_REDUCE] & 1))) | |||
{ | |||
int reduce_level; | |||
int stress_level; | |||
int reduce = 0; | |||
reduce_level = (ph->phflags >> 28) & 7; | |||
if(ph->type == phVOWEL) | |||
{ | |||
stress_level = plist3->stress; | |||
} | |||
else | |||
{ | |||
// consonant, get stress from the following vowel | |||
if(next->type == phVOWEL) | |||
stress_level = (plist3+1)->stress; | |||
else | |||
break; | |||
} | |||
if((stress_level == 1) && (first_vowel)) | |||
stress_level = 0; // ignore 'dimished' stress on first syllable | |||
if(stress_level == 1) | |||
reduce = 1; // stress = 'reduced' | |||
if(stress_level < reduce_level) | |||
reduce =1; | |||
if((word_stress < 4) && (tr->langopts.param[LOPT_REDUCE] & 0x2) && (stress_level >= word_stress)) | |||
{ | |||
// don't reduce the most stressed syllable in an unstressed word | |||
reduce = 0; | |||
} | |||
if(reduce) | |||
ph = phoneme_tab[ph->reduce_to]; | |||
else | |||
break; | |||
} | |||
#endif | |||
if(ph->type == phVOWEL) | |||
first_vowel = 0; | |||
@@ -1192,6 +1192,7 @@ ESPEAK_API espeak_ERROR espeak_Synchronize(void) | |||
extern void FreePhData(void); | |||
extern void FreeVoiceList(void); | |||
ESPEAK_API espeak_ERROR espeak_Terminate(void) | |||
{//=========================================== | |||
@@ -1214,6 +1215,7 @@ ESPEAK_API espeak_ERROR espeak_Terminate(void) | |||
Free(outbuf); | |||
outbuf = NULL; | |||
FreePhData(); | |||
FreeVoiceList(); | |||
if(f_logespeak) | |||
{ |
@@ -35,7 +35,7 @@ | |||
#include "translate.h" | |||
#include "wave.h" | |||
const char *version_string = "1.45.41 07.Sep.11"; | |||
const char *version_string = "1.45.43 16.Sep.11"; | |||
const int version_phdata = 0x014500; | |||
int option_device_number = -1; | |||
@@ -172,6 +172,7 @@ void FreePhData(void) | |||
Free(phoneme_tab_data); | |||
Free(phoneme_index); | |||
Free(phondata_ptr); | |||
Free(tunes); | |||
phoneme_tab_data=NULL; | |||
phoneme_index=NULL; | |||
phondata_ptr=NULL; | |||
@@ -613,7 +614,16 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, | |||
int count; | |||
PHONEME_TAB *ph; | |||
PHONEME_LIST *plist_this; | |||
static int ph_position[8] = {0, 1, 2, 3, 2, 0, 1, 3}; // prevPh, thisPh, nextPh, next2Ph, nextPhW, prevPhW, nextVowel, next2PhW | |||
static int ph_position[8] = {0, 1, 2, 3, 2, 0, 1, 3}; // prevPh, thisPh, nextPh, next2Ph, nextPhW, prevPhW, nextVowel, (other conditions) | |||
// instruction: 2xxx, 3xxx | |||
// bits 8-10 = 0 to 6, which phoneme | |||
// bit 11 = 0, bits 0-7 are a phoneme code | |||
// bit 11 = 1, bits 5-7 type of data, bits 0-4 data value | |||
// bits 8-10 = 7, other conditions | |||
data = instn & 0xff; | |||
instn2 = instn >> 8; | |||
@@ -634,12 +644,12 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, | |||
if(plist[0].sourceix) | |||
return(false); | |||
} | |||
if(which==7) | |||
{ | |||
// nextPh2 not word boundary | |||
if((plist[1].sourceix) || (plist[2].sourceix)) | |||
return(false); | |||
} | |||
// if(which==7) | |||
// { | |||
// // nextPh2 not word boundary | |||
// if((plist[1].sourceix) || (plist[2].sourceix)) | |||
// return(false); | |||
// } | |||
if(which==6) | |||
{ | |||
@@ -676,7 +686,7 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, | |||
} | |||
ph = plist->ph; | |||
if(instn2 < 7) | |||
if(instn2 < 8) | |||
{ | |||
// 'data' is a phoneme number | |||
if((phoneme_tab[data]->mnemonic == ph->mnemonic) == true) | |||
@@ -783,6 +793,9 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, | |||
break; | |||
} | |||
return(count > 0); | |||
case 0x10: // isTranslationGiven | |||
return((plist->synthflags & SFLAG_DICTIONARY) != 0); | |||
} | |||
break; | |||
@@ -903,7 +916,7 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_ | |||
switch(instn >> 12) | |||
{ | |||
case 0: | |||
case 0: // 0xxx | |||
data = instn & 0xff; | |||
if(instn2 == 0) |
@@ -329,6 +329,8 @@ typedef struct { | |||
#define i_isFirstVowel 0x8d | |||
#define i_isSecondVowel 0x8e | |||
#define i_isSeqFlag1 0x8f | |||
#define i_IsTranslationGiven 0x90 | |||
// place of articulation | |||
#define i_isVel 0x28 |
@@ -122,7 +122,7 @@ | |||
#define SUFX_I 0x0200 // y may have been changed to i | |||
#define SUFX_P 0x0400 // prefix | |||
#define SUFX_V 0x0800 // suffix means use the verb form pronunciation | |||
#define SUFX_D 0x1000 // previous letter may have been doubles | |||
#define SUFX_D 0x1000 // previous letter may have been doubled | |||
#define SUFX_F 0x2000 // verb follows | |||
#define SUFX_Q 0x4000 // don't retranslate | |||
#define SUFX_T 0x10000 // don't affect the stress position in the stem |
@@ -1745,6 +1745,18 @@ espeak_ERROR SetVoiceByProperties(espeak_VOICE *voice_selector) | |||
} // end of SetVoiceByProperties | |||
void FreeVoiceList() | |||
{//================= | |||
for(int ix=0; ix<n_voices_list; ix++) | |||
{ | |||
if(voices_list[ix] != NULL) | |||
{ | |||
free(voices_list[ix]); | |||
voices_list[ix] = NULL; | |||
} | |||
} | |||
n_voices_list = 0; | |||
} | |||
//======================================================================= | |||
@@ -1763,13 +1775,7 @@ ESPEAK_API const espeak_VOICE **espeak_ListVoices(espeak_VOICE *voice_spec) | |||
char path_voices[sizeof(path_home)+12]; | |||
// free previous voice list data | |||
for(ix=0; ix<n_voices_list; ix++) | |||
{ | |||
if(voices_list[ix] != NULL) | |||
free(voices_list[ix]); | |||
} | |||
n_voices_list = 0; | |||
FreeVoiceList(); | |||
sprintf(path_voices,"%s%cvoices",path_home,PATHSEP); | |||
len_path_voices = strlen(path_voices)+1; |
@@ -53,6 +53,148 @@ enum {ONE_BILLION=1000000000}; | |||
#endif | |||
#ifdef USE_PULSEAUDIO | |||
// create some wrappers for runtime detection | |||
// checked on wave_init | |||
static int pulse_running; | |||
// wave.cpp (this file) | |||
void wave_port_init(int); | |||
void* wave_port_open(const char* the_api); | |||
size_t wave_port_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize); | |||
int wave_port_close(void* theHandler); | |||
int wave_port_is_busy(void* theHandler); | |||
void wave_port_terminate(); | |||
uint32_t wave_port_get_read_position(void* theHandler); | |||
uint32_t wave_port_get_write_position(void* theHandler); | |||
void wave_port_flush(void* theHandler); | |||
void wave_port_set_callback_is_output_enabled(t_wave_callback* cb); | |||
void* wave_port_test_get_write_buffer(); | |||
int wave_port_get_remaining_time(uint32_t sample, uint32_t* time); | |||
// wave_pulse.cpp | |||
int is_pulse_running(); | |||
void wave_pulse_init(int); | |||
void* wave_pulse_open(const char* the_api); | |||
size_t wave_pulse_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize); | |||
int wave_pulse_close(void* theHandler); | |||
int wave_pulse_is_busy(void* theHandler); | |||
void wave_pulse_terminate(); | |||
uint32_t wave_pulse_get_read_position(void* theHandler); | |||
uint32_t wave_pulse_get_write_position(void* theHandler); | |||
void wave_pulse_flush(void* theHandler); | |||
void wave_pulse_set_callback_is_output_enabled(t_wave_callback* cb); | |||
void* wave_pulse_test_get_write_buffer(); | |||
int wave_pulse_get_remaining_time(uint32_t sample, uint32_t* time); | |||
// wrappers | |||
void wave_init(int srate) { | |||
pulse_running = is_pulse_running(); | |||
if (pulse_running) | |||
wave_pulse_init(srate); | |||
else | |||
wave_port_init(srate); | |||
} | |||
void* wave_open(const char* the_api) { | |||
if (pulse_running) | |||
return wave_pulse_open(the_api); | |||
else | |||
return wave_port_open(the_api); | |||
} | |||
size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize) { | |||
if (pulse_running) | |||
return wave_pulse_write(theHandler, theMono16BitsWaveBuffer, theSize); | |||
else | |||
return wave_port_write(theHandler, theMono16BitsWaveBuffer, theSize); | |||
} | |||
int wave_close(void* theHandler) { | |||
if (pulse_running) | |||
return wave_pulse_close(theHandler); | |||
else | |||
return wave_port_close(theHandler); | |||
} | |||
int wave_is_busy(void* theHandler) { | |||
if (pulse_running) | |||
return wave_pulse_is_busy(theHandler); | |||
else | |||
return wave_port_is_busy(theHandler); | |||
} | |||
void wave_terminate() { | |||
if (pulse_running) | |||
wave_pulse_terminate(); | |||
else | |||
wave_port_terminate(); | |||
} | |||
uint32_t wave_get_read_position(void* theHandler) { | |||
if (pulse_running) | |||
return wave_pulse_get_read_position(theHandler); | |||
else | |||
return wave_port_get_read_position(theHandler); | |||
} | |||
uint32_t wave_get_write_position(void* theHandler) { | |||
if (pulse_running) | |||
return wave_pulse_get_write_position(theHandler); | |||
else | |||
return wave_port_get_write_position(theHandler); | |||
} | |||
void wave_flush(void* theHandler) { | |||
if (pulse_running) | |||
wave_pulse_flush(theHandler); | |||
else | |||
wave_port_flush(theHandler); | |||
} | |||
void wave_set_callback_is_output_enabled(t_wave_callback* cb) { | |||
if (pulse_running) | |||
wave_pulse_set_callback_is_output_enabled(cb); | |||
else | |||
wave_port_set_callback_is_output_enabled(cb); | |||
} | |||
void* wave_test_get_write_buffer() { | |||
if (pulse_running) | |||
return wave_pulse_test_get_write_buffer(); | |||
else | |||
return wave_port_test_get_write_buffer(); | |||
} | |||
int wave_get_remaining_time(uint32_t sample, uint32_t* time) | |||
{ | |||
if (pulse_running) | |||
return wave_pulse_get_remaining_time(sample, time); | |||
else | |||
return wave_port_get_remaining_time(sample, time); | |||
} | |||
// rename functions to be wrapped | |||
#define wave_init wave_port_init | |||
#define wave_open wave_port_open | |||
#define wave_write wave_port_write | |||
#define wave_close wave_port_close | |||
#define wave_is_busy wave_port_is_busy | |||
#define wave_terminate wave_port_terminate | |||
#define wave_get_read_position wave_port_get_read_position | |||
#define wave_get_write_position wave_port_get_write_position | |||
#define wave_flush wave_port_flush | |||
#define wave_set_callback_is_output_enabled wave_port_set_callback_is_output_enabled | |||
#define wave_test_get_write_buffer wave_port_test_get_write_buffer | |||
#define wave_get_remaining_time wave_port_get_remaining_time | |||
#endif // USE_PULSEAUDIO | |||
static t_wave_callback* my_callback_is_output_enabled=NULL; | |||
#define N_WAV_BUF 10 |
@@ -65,6 +65,7 @@ enum { | |||
static t_wave_callback* my_callback_is_output_enabled=NULL; | |||
#define SAMPLE_RATE 22050 | |||
#define ESPEAK_FORMAT PA_SAMPLE_S16LE | |||
#define ESPEAK_CHANNEL 1 | |||
@@ -74,6 +75,39 @@ static t_wave_callback* my_callback_is_output_enabled=NULL; | |||
#define MINREQ 880 | |||
#define FRAGSIZE 0 | |||
#ifdef USE_PORTAUDIO | |||
// rename functions to be wrapped | |||
#define wave_init wave_pulse_init | |||
#define wave_open wave_pulse_open | |||
#define wave_write wave_pulse_write | |||
#define wave_close wave_pulse_close | |||
#define wave_is_busy wave_pulse_is_busy | |||
#define wave_terminate wave_pulse_terminate | |||
#define wave_get_read_position wave_pulse_get_read_position | |||
#define wave_get_write_position wave_pulse_get_write_position | |||
#define wave_flush wave_pulse_flush | |||
#define wave_set_callback_is_output_enabled wave_pulse_set_callback_is_output_enabled | |||
#define wave_test_get_write_buffer wave_pulse_test_get_write_buffer | |||
#define wave_get_remaining_time wave_pulse_get_remaining_time | |||
// check whether we can connect to PulseAudio | |||
#include <pulse/simple.h> | |||
int is_pulse_running() | |||
{ | |||
pa_sample_spec ss; | |||
ss.format = ESPEAK_FORMAT; | |||
ss.rate = SAMPLE_RATE; | |||
ss.channels = ESPEAK_CHANNEL; | |||
pa_simple *s = pa_simple_new(NULL, "eSpeak", PA_STREAM_PLAYBACK, NULL, "is_pulse_running", &ss, NULL, NULL, NULL); | |||
if (s) { | |||
pa_simple_free(s); | |||
return 1; | |||
} else | |||
return 0; | |||
} | |||
#endif // USE_PORTAUDIO | |||
static pthread_mutex_t pulse_mutex; | |||
static pa_context *context = NULL; | |||
@@ -843,8 +877,9 @@ int wave_get_remaining_time(uint32_t sample, uint32_t* time) | |||
return 0; | |||
} | |||
#endif // of USE_PORTAUDIO | |||
#endif // of USE_PULSEAUDIO | |||
#ifndef USE_PORTAUDIO | |||
//> | |||
//<clock_gettime2, add_time_in_ms | |||
@@ -878,6 +913,7 @@ void add_time_in_ms(struct timespec *ts, int time_in_ms) | |||
} | |||
ts->tv_nsec = (long int)t_ns; | |||
} | |||
#endif // ifndef USE_PORTAUDIO | |||
#endif // USE_ASYNC |