1
2
3
4
5
6
7 import time
8 import nvwave
9 import threading
10 import Queue
11 from ctypes import *
12 import config
13 import globalVars
14 from logHandler import log
15 import os
16 import codecs
17
18 isSpeaking = False
19 lastIndex = None
20 bgThread=None
21 bgQueue = None
22 player = None
23 espeakDLL=None
24
25
26 minRate=80
27 maxRate=450
28 minPitch=0
29 maxPitch=99
30
31
32 espeakEVENT_LIST_TERMINATED=0
33 espeakEVENT_WORD=1
34 espeakEVENT_SENTENCE=2
35 espeakEVENT_MARK=3
36 espeakEVENT_PLAY=4
37 espeakEVENT_END=5
38 espeakEVENT_MSG_TERMINATED=6
39 espeakEVENT_PHONEME=7
40
41
42 POS_CHARACTER=1
43 POS_WORD=2
44 POS_SENTENCE=3
45
46
47 AUDIO_OUTPUT_PLAYBACK=0
48 AUDIO_OUTPUT_RETRIEVAL=1
49 AUDIO_OUTPUT_SYNCHRONOUS=2
50 AUDIO_OUTPUT_SYNCH_PLAYBACK=3
51
52
53 espeakCHARS_AUTO=0
54 espeakCHARS_UTF8=1
55 espeakCHARS_8BIT=2
56 espeakCHARS_WCHAR=3
57 espeakSSML=0x10
58 espeakPHONEMES=0x100
59 espeakENDPAUSE=0x1000
60 espeakKEEP_NAMEDATA=0x2000
61
62
63 espeakSILENCE=0
64 espeakRATE=1
65 espeakVOLUME=2
66 espeakPITCH=3
67 espeakRANGE=4
68 espeakPUNCTUATION=5
69 espeakCAPITALS=6
70 espeakWORDGAP=7
71 espeakOPTIONS=8
72 espeakINTONATION=9
73 espeakRESERVED1=10
74 espeakRESERVED2=11
75
76
77 EE_OK=0
83 _fields_=[
84 ('number',c_int),
85 ('name',c_char_p),
86 ]
87
89 _fields_=[
90 ('type',c_int),
91 ('unique_identifier',c_uint),
92 ('text_position',c_int),
93 ('length',c_int),
94 ('audio_position',c_int),
95 ('sample',c_int),
96 ('user_data',c_void_p),
97 ('id',espeak_EVENT_id),
98 ]
99
101 _fields_=[
102 ('name',c_char_p),
103 ('languages',c_char_p),
104 ('identifier',c_char_p),
105 ('gender',c_byte),
106 ('age',c_byte),
107 ('variant',c_byte),
108 ('xx1',c_byte),
109 ('score',c_int),
110 ('spare',c_void_p),
111 ]
112
114 return isinstance(other, type(self)) and addressof(self) == addressof(other)
115
116 t_espeak_callback=CFUNCTYPE(c_int,POINTER(c_short),c_int,POINTER(espeak_EVENT))
117
118 @t_espeak_callback
119 -def callback(wav,numsamples,event):
141
144 threading.Thread.__init__(self)
145 self.setDaemon(True)
146
148 global isSpeaking
149 while True:
150 func, args, kwargs = bgQueue.get()
151 if not func:
152 break
153 try:
154 func(*args, **kwargs)
155 except:
156 log.error("Error running function from queue", exc_info=True)
157 bgQueue.task_done()
158
160 global bgQueue
161
162 mustBeAsync = kwargs.pop("mustBeAsync", False)
163 if mustBeAsync or bgQueue.unfinished_tasks != 0:
164
165
166 bgQueue.put((func, args, kwargs))
167 else:
168 func(*args, **kwargs)
169
176
180
200
204
207
209 return espeakDLL.espeak_GetParameter(param,current)
210
212 voices=espeakDLL.espeak_ListVoices(None)
213 voiceList=[]
214 for voice in voices:
215 if not voice: break
216 voiceList.append(voice.contents)
217 return voiceList
218
220 voice = espeakDLL.espeak_GetCurrentVoice()
221 if voice:
222 return voice.contents
223 else:
224 return None
225
229
232
234 res = getCurrentVoice().identifier.split("+")
235 if not voice:
236 voice = res[0]
237 if not variant:
238 if len(res) == 2:
239 variant = res[1]
240 else:
241 variant = "none"
242 if variant == "none":
243 espeakDLL.espeak_SetVoiceByName(voice)
244 else:
245 try:
246 espeakDLL.espeak_SetVoiceByName("%s+%s" % (voice, variant))
247 except:
248 espeakDLL.espeak_SetVoiceByName(voice)
249
252
254 v=espeak_VOICE()
255 lang=lang.replace('_','-')
256 v.languages=lang
257 try:
258 espeakDLL.espeak_SetVoiceByProperties(byref(v))
259 except:
260 v.languages="en"
261 espeakDLL.espeak_SetVoiceByProperties(byref(v))
262
265
267 if res != EE_OK:
268 raise RuntimeError("%s: code %d" % (func.__name__, res))
269 return res
270
272 global espeakDLL, bgThread, bgQueue, player
273 espeakDLL=cdll.LoadLibrary(r"synthDrivers\espeak.dll")
274 espeakDLL.espeak_Info.restype=c_char_p
275 espeakDLL.espeak_Synth.errcheck=espeak_errcheck
276 espeakDLL.espeak_SetVoiceByName.errcheck=espeak_errcheck
277 espeakDLL.espeak_SetVoiceByProperties.errcheck=espeak_errcheck
278 espeakDLL.espeak_SetParameter.errcheck=espeak_errcheck
279 espeakDLL.espeak_Terminate.errcheck=espeak_errcheck
280 espeakDLL.espeak_ListVoices.restype=POINTER(POINTER(espeak_VOICE))
281 espeakDLL.espeak_GetCurrentVoice.restype=POINTER(espeak_VOICE)
282 espeakDLL.espeak_SetVoiceByName.argtypes=(c_char_p,)
283 sampleRate=espeakDLL.espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS,300,"synthDrivers",0)
284 if sampleRate<0:
285 raise OSError("espeak_Initialize %d"%sampleRate)
286 player = nvwave.WavePlayer(channels=1, samplesPerSec=sampleRate, bitsPerSample=16, outputDevice=config.conf["speech"]["outputDevice"])
287 espeakDLL.espeak_SetSynthCallback(callback)
288 bgQueue = Queue.Queue()
289 bgThread=BgThread()
290 bgThread.start()
291
303
306
308 dir='synthDrivers\\espeak-data\\voices\\!v'
309 variantDict={"none":_("none")}
310 for fileName in os.listdir(dir):
311 if os.path.isfile("%s\\%s"%(dir,fileName)):
312 file=codecs.open("%s\\%s"%(dir,fileName))
313 for line in file:
314 if line.startswith('name '):
315 temp=line.split(" ")
316 if len(temp) ==2:
317 name=temp[1].rstrip()
318 break
319 name=None
320 file.close()
321 if name is not None:
322 variantDict[fileName]=name
323 return variantDict
324