We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Problems with eSpeak NG in NVDA Next Snapshot Version next-15091,d89900a3
When using NVDA version next-15091,d89900a3, speech rate does not work how it should. At rate 100 without rate boost, NVDA speaks much slower than at rate 99. With rate boost, speech slows down above rate 18 and then seems to stay at the same rate regardless of where the slider is moved as long as you stay above rate 18. Words, especially those ending in vowel sounds, also sound as if they are cut off at the ends.
I noticed this first when I updated to this snapshot. During and after the update, speech seemed much slower than I'm used to. Once I noticed this, I tried changing the speech rate and found the results I mentioned above. To reproduce this, make sure you're using eSpeak NG and try changing the rate with and without rate boost. Pay particular attention to the rate values mentioned above.
I'm using NVDA version next-15091,d89900a3 on Windows 10 version 1803 build 17134.5. I also normally use the English America voice and the Klatt4 variant at rate 45 with rate boost turned on. I posted about this in the NVDA Skype group, and others seemed to be having the same issue when they looked into it.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `source/synthDrivers/_espeak.py`
Content:
```
1 # -*- coding: UTF-8 -*-
2 #synthDrivers/_espeak.py
3 #A part of NonVisual Desktop Access (NVDA)
4 #Copyright (C) 2007-2012 NV Access Limited, Peter Vágner
5 #This file is covered by the GNU General Public License.
6 #See the file COPYING for more details.
7 
8 import time
9 import nvwave
10 import threading
11 import Queue
12 from ctypes import *
13 import config
14 import globalVars
15 from logHandler import log
16 import os
17 import codecs
18 
19 isSpeaking = False
20 lastIndex = None
21 bgThread=None
22 bgQueue = None
23 player = None
24 espeakDLL=None
25 
26 #Parameter bounds
27 minRate=80
28 maxRate=450
29 minPitch=0
30 maxPitch=99
31 
32 #event types
33 espeakEVENT_LIST_TERMINATED=0
34 espeakEVENT_WORD=1
35 espeakEVENT_SENTENCE=2
36 espeakEVENT_MARK=3
37 espeakEVENT_PLAY=4
38 espeakEVENT_END=5
39 espeakEVENT_MSG_TERMINATED=6
40 espeakEVENT_PHONEME=7
41 
42 #position types
43 POS_CHARACTER=1
44 POS_WORD=2
45 POS_SENTENCE=3
46 
47 #output types
48 AUDIO_OUTPUT_PLAYBACK=0
49 AUDIO_OUTPUT_RETRIEVAL=1
50 AUDIO_OUTPUT_SYNCHRONOUS=2
51 AUDIO_OUTPUT_SYNCH_PLAYBACK=3
52 
53 #synth flags
54 espeakCHARS_AUTO=0
55 espeakCHARS_UTF8=1
56 espeakCHARS_8BIT=2
57 espeakCHARS_WCHAR=3
58 espeakSSML=0x10
59 espeakPHONEMES=0x100
60 espeakENDPAUSE=0x1000
61 espeakKEEP_NAMEDATA=0x2000
62 
63 #speech parameters
64 espeakSILENCE=0
65 espeakRATE=1
66 espeakVOLUME=2
67 espeakPITCH=3
68 espeakRANGE=4
69 espeakPUNCTUATION=5
70 espeakCAPITALS=6
71 espeakWORDGAP=7
72 espeakOPTIONS=8   # reserved for misc. options.  not yet used
73 espeakINTONATION=9
74 espeakRESERVED1=10
75 espeakRESERVED2=11
76 
77 #error codes
78 EE_OK=0
79 #EE_INTERNAL_ERROR=-1
80 #EE_BUFFER_FULL=1
81 #EE_NOT_FOUND=2
82 
83 class espeak_EVENT_id(Union):
84 	_fields_=[
85 		('number',c_int),
86 		('name',c_char_p),
87 		('string',c_char*8),
88 	]
89 
90 class espeak_EVENT(Structure):
91 	_fields_=[
92 		('type',c_int),
93 		('unique_identifier',c_uint),
94 		('text_position',c_int),
95 		('length',c_int),
96 		('audio_position',c_int),
97 		('sample',c_int),
98 		('user_data',c_void_p),
99 		('id',espeak_EVENT_id),
100 	]
101 
102 class espeak_VOICE(Structure):
103 	_fields_=[
104 		('name',c_char_p),
105 		('languages',c_char_p),
106 		('identifier',c_char_p),
107 		('gender',c_byte),
108 		('age',c_byte),
109 		('variant',c_byte),
110 		('xx1',c_byte),
111 		('score',c_int),
112 		('spare',c_void_p),
113 	]
114 
115 	def __eq__(self, other):
116 		return isinstance(other, type(self)) and addressof(self) == addressof(other)
117 
118 t_espeak_callback=CFUNCTYPE(c_int,POINTER(c_short),c_int,POINTER(espeak_EVENT))
119 
120 @t_espeak_callback
121 def callback(wav,numsamples,event):
122 	try:
123 		global player, isSpeaking, lastIndex
124 		if not isSpeaking:
125 			return 1
126 		for e in event:
127 			if e.type==espeakEVENT_MARK:
128 				lastIndex=int(e.id.name)
129 			elif e.type==espeakEVENT_LIST_TERMINATED:
130 				break
131 		if not wav:
132 			player.idle()
133 			isSpeaking = False
134 			return 0
135 		if numsamples > 0:
136 			try:
137 				player.feed(string_at(wav, numsamples * sizeof(c_short)))
138 			except:
139 				log.debugWarning("Error feeding audio to nvWave",exc_info=True)
140 		return 0
141 	except:
142 		log.error("callback", exc_info=True)
143 
144 class BgThread(threading.Thread):
145 	def __init__(self):
146 		threading.Thread.__init__(self)
147 		self.setDaemon(True)
148 
149 	def run(self):
150 		global isSpeaking
151 		while True:
152 			func, args, kwargs = bgQueue.get()
153 			if not func:
154 				break
155 			try:
156 				func(*args, **kwargs)
157 			except:
158 				log.error("Error running function from queue", exc_info=True)
159 			bgQueue.task_done()
160 
161 def _execWhenDone(func, *args, **kwargs):
162 	global bgQueue
163 	# This can't be a kwarg in the function definition because it will consume the first non-keywor dargument which is meant for func.
164 	mustBeAsync = kwargs.pop("mustBeAsync", False)
165 	if mustBeAsync or bgQueue.unfinished_tasks != 0:
166 		# Either this operation must be asynchronous or There is still an operation in progress.
167 		# Therefore, run this asynchronously in the background thread.
168 		bgQueue.put((func, args, kwargs))
169 	else:
170 		func(*args, **kwargs)
171 
172 def _speak(text):
173 	global isSpeaking
174 	uniqueID=c_int()
175 	isSpeaking = True
176 	flags = espeakCHARS_WCHAR | espeakSSML | espeakPHONEMES
177 	return espeakDLL.espeak_Synth(text,0,0,0,0,flags,byref(uniqueID),0)
178 
179 def speak(text):
180 	global bgQueue
181 	_execWhenDone(_speak, text, mustBeAsync=True)
182 
183 def stop():
184 	global isSpeaking, bgQueue, lastIndex
185 	# Kill all speech from now.
186 	# We still want parameter changes to occur, so requeue them.
187 	params = []
188 	try:
189 		while True:
190 			item = bgQueue.get_nowait()
191 			if item[0] != _speak:
192 				params.append(item)
193 			bgQueue.task_done()
194 	except Queue.Empty:
195 		# Let the exception break us out of this loop, as queue.empty() is not reliable anyway.
196 		pass
197 	for item in params:
198 		bgQueue.put(item)
199 	isSpeaking = False
200 	player.stop()
201 	lastIndex=None
202 
203 def pause(switch):
204 	global player
205 	player.pause(switch)
206 
207 def setParameter(param,value,relative):
208 	_execWhenDone(espeakDLL.espeak_SetParameter,param,value,relative)
209 
210 def getParameter(param,current):
211 	return espeakDLL.espeak_GetParameter(param,current)
212 
213 def getVoiceList():
214 	voices=espeakDLL.espeak_ListVoices(None)
215 	voiceList=[]
216 	for voice in voices:
217 		if not voice: break
218 		voiceList.append(voice.contents)
219 	return voiceList
220 
221 def getCurrentVoice():
222 	voice =  espeakDLL.espeak_GetCurrentVoice()
223 	if voice:
224 		return voice.contents
225 	else:
226 		return None
227 
228 def setVoice(voice):
229 	# For some weird reason, espeak_EspeakSetVoiceByProperties throws an integer divide by zero exception.
230 	setVoiceByName(voice.identifier)
231 
232 def setVoiceByName(name):
233 	_execWhenDone(espeakDLL.espeak_SetVoiceByName,name)
234 
235 def _setVoiceAndVariant(voice=None, variant=None):
236 	res = getCurrentVoice().identifier.split("+")
237 	if not voice:
238 		voice = res[0]
239 	if not variant:
240 		if len(res) == 2:
241 			variant = res[1]
242 		else:
243 			variant = "none"
244 	if variant == "none":
245 		espeakDLL.espeak_SetVoiceByName(voice)
246 	else:
247 		try:
248 			espeakDLL.espeak_SetVoiceByName("%s+%s" % (voice, variant))
249 		except:
250 			espeakDLL.espeak_SetVoiceByName(voice)
251 
252 def setVoiceAndVariant(voice=None, variant=None):
253 	_execWhenDone(_setVoiceAndVariant, voice=voice, variant=variant)
254 
255 def _setVoiceByLanguage(lang):
256 	v=espeak_VOICE()
257 	lang=lang.replace('_','-')
258 	v.languages=lang
259 	try:
260 		espeakDLL.espeak_SetVoiceByProperties(byref(v))
261 	except:
262 		v.languages="en"
263 		espeakDLL.espeak_SetVoiceByProperties(byref(v))
264 
265 def setVoiceByLanguage(lang):
266 	_execWhenDone(_setVoiceByLanguage, lang)
267 
268 def espeak_errcheck(res, func, args):
269 	if res != EE_OK:
270 		raise RuntimeError("%s: code %d" % (func.__name__, res))
271 	return res
272 
273 def initialize():
274 	global espeakDLL, bgThread, bgQueue, player
275 	espeakDLL=cdll.LoadLibrary(r"synthDrivers\espeak.dll")
276 	espeakDLL.espeak_Info.restype=c_char_p
277 	espeakDLL.espeak_Synth.errcheck=espeak_errcheck
278 	espeakDLL.espeak_SetVoiceByName.errcheck=espeak_errcheck
279 	espeakDLL.espeak_SetVoiceByProperties.errcheck=espeak_errcheck
280 	espeakDLL.espeak_SetParameter.errcheck=espeak_errcheck
281 	espeakDLL.espeak_Terminate.errcheck=espeak_errcheck
282 	espeakDLL.espeak_ListVoices.restype=POINTER(POINTER(espeak_VOICE))
283 	espeakDLL.espeak_GetCurrentVoice.restype=POINTER(espeak_VOICE)
284 	espeakDLL.espeak_SetVoiceByName.argtypes=(c_char_p,)
285 	sampleRate=espeakDLL.espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS,300,
286 		os.path.abspath("synthDrivers"),0)
287 	if sampleRate<0:
288 		raise OSError("espeak_Initialize %d"%sampleRate)
289 	player = nvwave.WavePlayer(channels=1, samplesPerSec=sampleRate, bitsPerSample=16, outputDevice=config.conf["speech"]["outputDevice"])
290 	espeakDLL.espeak_SetSynthCallback(callback)
291 	bgQueue = Queue.Queue()
292 	bgThread=BgThread()
293 	bgThread.start()
294 
295 def terminate():
296 	global bgThread, bgQueue, player, espeakDLL 
297 	stop()
298 	bgQueue.put((None, None, None))
299 	bgThread.join()
300 	espeakDLL.espeak_Terminate()
301 	bgThread=None
302 	bgQueue=None
303 	player.close()
304 	player=None
305 	espeakDLL=None
306 
307 def info():
308 	return espeakDLL.espeak_Info()
309 
310 def getVariantDict():
311 	dir='synthDrivers\\espeak-ng-data\\voices\\!v'
312 	# Translators: name of the default espeak varient.
313 	variantDict={"none": pgettext("espeakVarient", "none")}
314 	for fileName in os.listdir(dir):
315 		if os.path.isfile("%s\\%s"%(dir,fileName)):
316 			file=codecs.open("%s\\%s"%(dir,fileName))
317 			for line in file:
318 				if line.startswith('name '):
319 					temp=line.split(" ")
320 					if len(temp) ==2:
321 						name=temp[1].rstrip()
322 						break
323 				name=None
324 			file.close()
325 		if name is not None:
326 			variantDict[fileName]=name
327 	return variantDict
328 
329
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/source/synthDrivers/_espeak.py b/source/synthDrivers/_espeak.py
--- a/source/synthDrivers/_espeak.py
+++ b/source/synthDrivers/_espeak.py
@@ -173,7 +173,9 @@
 	global isSpeaking
 	uniqueID=c_int()
 	isSpeaking = True
-	flags = espeakCHARS_WCHAR | espeakSSML | espeakPHONEMES
+	# eSpeak can only process compound emojis  when using a UTF8 encoding
+	text=text.encode('utf8',errors='ignore')
+	flags = espeakCHARS_UTF8 | espeakSSML | espeakPHONEMES
 	return espeakDLL.espeak_Synth(text,0,0,0,0,flags,byref(uniqueID),0)
 
 def speak(text):

{"golden_diff": "diff --git a/source/synthDrivers/_espeak.py b/source/synthDrivers/_espeak.py\n--- a/source/synthDrivers/_espeak.py\n+++ b/source/synthDrivers/_espeak.py\n@@ -173,7 +173,9 @@\n \tglobal isSpeaking\r\n \tuniqueID=c_int()\r\n \tisSpeaking = True\r\n-\tflags = espeakCHARS_WCHAR | espeakSSML | espeakPHONEMES\r\n+\t# eSpeak can only process compound emojis  when using a UTF8 encoding\r\n+\ttext=text.encode('utf8',errors='ignore')\r\n+\tflags = espeakCHARS_UTF8 | espeakSSML | espeakPHONEMES\r\n \treturn espeakDLL.espeak_Synth(text,0,0,0,0,flags,byref(uniqueID),0)\r\n \r\n def speak(text):\n", "issue": "Problems with eSpeak NG in NVDA Next Snapshot Version next-15091,d89900a3\nWhen using NVDA version next-15091,d89900a3, speech rate does not work how it should. At rate 100 without rate boost, NVDA speaks much slower than at rate 99. With rate boost, speech slows down above rate 18 and then seems to stay at the same rate regardless of where the slider is moved as long as you stay above rate 18. Words, especially those ending in vowel sounds, also sound as if they are cut off at the ends.\r\nI noticed this first when I updated to this snapshot. During and after the update, speech seemed much slower than I'm used to. Once I noticed this, I tried changing the speech rate and found the results I mentioned above. To reproduce this, make sure you're using eSpeak NG and try changing the rate with and without rate boost. Pay particular attention to the rate values mentioned above.\r\nI'm using NVDA version next-15091,d89900a3 on Windows 10 version 1803 build 17134.5. I also normally use the English America voice and the Klatt4 variant at rate 45 with rate boost turned on. I posted about this in the NVDA Skype group, and others seemed to be having the same issue when they looked into it.\n", "before_files": [{"content": "# -*- coding: UTF-8 -*-\r\n#synthDrivers/_espeak.py\r\n#A part of NonVisual Desktop Access (NVDA)\r\n#Copyright (C) 2007-2012 NV Access Limited, Peter V\u00e1gner\r\n#This file is covered by the GNU General Public License.\r\n#See the file COPYING for more details.\r\n\r\nimport time\r\nimport nvwave\r\nimport threading\r\nimport Queue\r\nfrom ctypes import *\r\nimport config\r\nimport globalVars\r\nfrom logHandler import log\r\nimport os\r\nimport codecs\r\n\r\nisSpeaking = False\r\nlastIndex = None\r\nbgThread=None\r\nbgQueue = None\r\nplayer = None\r\nespeakDLL=None\r\n\r\n#Parameter bounds\r\nminRate=80\r\nmaxRate=450\r\nminPitch=0\r\nmaxPitch=99\r\n\r\n#event types\r\nespeakEVENT_LIST_TERMINATED=0\r\nespeakEVENT_WORD=1\r\nespeakEVENT_SENTENCE=2\r\nespeakEVENT_MARK=3\r\nespeakEVENT_PLAY=4\r\nespeakEVENT_END=5\r\nespeakEVENT_MSG_TERMINATED=6\r\nespeakEVENT_PHONEME=7\r\n\r\n#position types\r\nPOS_CHARACTER=1\r\nPOS_WORD=2\r\nPOS_SENTENCE=3\r\n\r\n#output types\r\nAUDIO_OUTPUT_PLAYBACK=0\r\nAUDIO_OUTPUT_RETRIEVAL=1\r\nAUDIO_OUTPUT_SYNCHRONOUS=2\r\nAUDIO_OUTPUT_SYNCH_PLAYBACK=3\r\n\r\n#synth flags\r\nespeakCHARS_AUTO=0\r\nespeakCHARS_UTF8=1\r\nespeakCHARS_8BIT=2\r\nespeakCHARS_WCHAR=3\r\nespeakSSML=0x10\r\nespeakPHONEMES=0x100\r\nespeakENDPAUSE=0x1000\r\nespeakKEEP_NAMEDATA=0x2000\r\n\r\n#speech parameters\r\nespeakSILENCE=0\r\nespeakRATE=1\r\nespeakVOLUME=2\r\nespeakPITCH=3\r\nespeakRANGE=4\r\nespeakPUNCTUATION=5\r\nespeakCAPITALS=6\r\nespeakWORDGAP=7\r\nespeakOPTIONS=8   # reserved for misc. options.  not yet used\r\nespeakINTONATION=9\r\nespeakRESERVED1=10\r\nespeakRESERVED2=11\r\n\r\n#error codes\r\nEE_OK=0\r\n#EE_INTERNAL_ERROR=-1\r\n#EE_BUFFER_FULL=1\r\n#EE_NOT_FOUND=2\r\n\r\nclass espeak_EVENT_id(Union):\r\n\t_fields_=[\r\n\t\t('number',c_int),\r\n\t\t('name',c_char_p),\r\n\t\t('string',c_char*8),\r\n\t]\r\n\r\nclass espeak_EVENT(Structure):\r\n\t_fields_=[\r\n\t\t('type',c_int),\r\n\t\t('unique_identifier',c_uint),\r\n\t\t('text_position',c_int),\r\n\t\t('length',c_int),\r\n\t\t('audio_position',c_int),\r\n\t\t('sample',c_int),\r\n\t\t('user_data',c_void_p),\r\n\t\t('id',espeak_EVENT_id),\r\n\t]\r\n\r\nclass espeak_VOICE(Structure):\r\n\t_fields_=[\r\n\t\t('name',c_char_p),\r\n\t\t('languages',c_char_p),\r\n\t\t('identifier',c_char_p),\r\n\t\t('gender',c_byte),\r\n\t\t('age',c_byte),\r\n\t\t('variant',c_byte),\r\n\t\t('xx1',c_byte),\r\n\t\t('score',c_int),\r\n\t\t('spare',c_void_p),\r\n\t]\r\n\r\n\tdef __eq__(self, other):\r\n\t\treturn isinstance(other, type(self)) and addressof(self) == addressof(other)\r\n\r\nt_espeak_callback=CFUNCTYPE(c_int,POINTER(c_short),c_int,POINTER(espeak_EVENT))\r\n\r\n@t_espeak_callback\r\ndef callback(wav,numsamples,event):\r\n\ttry:\r\n\t\tglobal player, isSpeaking, lastIndex\r\n\t\tif not isSpeaking:\r\n\t\t\treturn 1\r\n\t\tfor e in event:\r\n\t\t\tif e.type==espeakEVENT_MARK:\r\n\t\t\t\tlastIndex=int(e.id.name)\r\n\t\t\telif e.type==espeakEVENT_LIST_TERMINATED:\r\n\t\t\t\tbreak\r\n\t\tif not wav:\r\n\t\t\tplayer.idle()\r\n\t\t\tisSpeaking = False\r\n\t\t\treturn 0\r\n\t\tif numsamples > 0:\r\n\t\t\ttry:\r\n\t\t\t\tplayer.feed(string_at(wav, numsamples * sizeof(c_short)))\r\n\t\t\texcept:\r\n\t\t\t\tlog.debugWarning(\"Error feeding audio to nvWave\",exc_info=True)\r\n\t\treturn 0\r\n\texcept:\r\n\t\tlog.error(\"callback\", exc_info=True)\r\n\r\nclass BgThread(threading.Thread):\r\n\tdef __init__(self):\r\n\t\tthreading.Thread.__init__(self)\r\n\t\tself.setDaemon(True)\r\n\r\n\tdef run(self):\r\n\t\tglobal isSpeaking\r\n\t\twhile True:\r\n\t\t\tfunc, args, kwargs = bgQueue.get()\r\n\t\t\tif not func:\r\n\t\t\t\tbreak\r\n\t\t\ttry:\r\n\t\t\t\tfunc(*args, **kwargs)\r\n\t\t\texcept:\r\n\t\t\t\tlog.error(\"Error running function from queue\", exc_info=True)\r\n\t\t\tbgQueue.task_done()\r\n\r\ndef _execWhenDone(func, *args, **kwargs):\r\n\tglobal bgQueue\r\n\t# This can't be a kwarg in the function definition because it will consume the first non-keywor dargument which is meant for func.\r\n\tmustBeAsync = kwargs.pop(\"mustBeAsync\", False)\r\n\tif mustBeAsync or bgQueue.unfinished_tasks != 0:\r\n\t\t# Either this operation must be asynchronous or There is still an operation in progress.\r\n\t\t# Therefore, run this asynchronously in the background thread.\r\n\t\tbgQueue.put((func, args, kwargs))\r\n\telse:\r\n\t\tfunc(*args, **kwargs)\r\n\r\ndef _speak(text):\r\n\tglobal isSpeaking\r\n\tuniqueID=c_int()\r\n\tisSpeaking = True\r\n\tflags = espeakCHARS_WCHAR | espeakSSML | espeakPHONEMES\r\n\treturn espeakDLL.espeak_Synth(text,0,0,0,0,flags,byref(uniqueID),0)\r\n\r\ndef speak(text):\r\n\tglobal bgQueue\r\n\t_execWhenDone(_speak, text, mustBeAsync=True)\r\n\r\ndef stop():\r\n\tglobal isSpeaking, bgQueue, lastIndex\r\n\t# Kill all speech from now.\r\n\t# We still want parameter changes to occur, so requeue them.\r\n\tparams = []\r\n\ttry:\r\n\t\twhile True:\r\n\t\t\titem = bgQueue.get_nowait()\r\n\t\t\tif item[0] != _speak:\r\n\t\t\t\tparams.append(item)\r\n\t\t\tbgQueue.task_done()\r\n\texcept Queue.Empty:\r\n\t\t# Let the exception break us out of this loop, as queue.empty() is not reliable anyway.\r\n\t\tpass\r\n\tfor item in params:\r\n\t\tbgQueue.put(item)\r\n\tisSpeaking = False\r\n\tplayer.stop()\r\n\tlastIndex=None\r\n\r\ndef pause(switch):\r\n\tglobal player\r\n\tplayer.pause(switch)\r\n\r\ndef setParameter(param,value,relative):\r\n\t_execWhenDone(espeakDLL.espeak_SetParameter,param,value,relative)\r\n\r\ndef getParameter(param,current):\r\n\treturn espeakDLL.espeak_GetParameter(param,current)\r\n\r\ndef getVoiceList():\r\n\tvoices=espeakDLL.espeak_ListVoices(None)\r\n\tvoiceList=[]\r\n\tfor voice in voices:\r\n\t\tif not voice: break\r\n\t\tvoiceList.append(voice.contents)\r\n\treturn voiceList\r\n\r\ndef getCurrentVoice():\r\n\tvoice =  espeakDLL.espeak_GetCurrentVoice()\r\n\tif voice:\r\n\t\treturn voice.contents\r\n\telse:\r\n\t\treturn None\r\n\r\ndef setVoice(voice):\r\n\t# For some weird reason, espeak_EspeakSetVoiceByProperties throws an integer divide by zero exception.\r\n\tsetVoiceByName(voice.identifier)\r\n\r\ndef setVoiceByName(name):\r\n\t_execWhenDone(espeakDLL.espeak_SetVoiceByName,name)\r\n\r\ndef _setVoiceAndVariant(voice=None, variant=None):\r\n\tres = getCurrentVoice().identifier.split(\"+\")\r\n\tif not voice:\r\n\t\tvoice = res[0]\r\n\tif not variant:\r\n\t\tif len(res) == 2:\r\n\t\t\tvariant = res[1]\r\n\t\telse:\r\n\t\t\tvariant = \"none\"\r\n\tif variant == \"none\":\r\n\t\tespeakDLL.espeak_SetVoiceByName(voice)\r\n\telse:\r\n\t\ttry:\r\n\t\t\tespeakDLL.espeak_SetVoiceByName(\"%s+%s\" % (voice, variant))\r\n\t\texcept:\r\n\t\t\tespeakDLL.espeak_SetVoiceByName(voice)\r\n\r\ndef setVoiceAndVariant(voice=None, variant=None):\r\n\t_execWhenDone(_setVoiceAndVariant, voice=voice, variant=variant)\r\n\r\ndef _setVoiceByLanguage(lang):\r\n\tv=espeak_VOICE()\r\n\tlang=lang.replace('_','-')\r\n\tv.languages=lang\r\n\ttry:\r\n\t\tespeakDLL.espeak_SetVoiceByProperties(byref(v))\r\n\texcept:\r\n\t\tv.languages=\"en\"\r\n\t\tespeakDLL.espeak_SetVoiceByProperties(byref(v))\r\n\r\ndef setVoiceByLanguage(lang):\r\n\t_execWhenDone(_setVoiceByLanguage, lang)\r\n\r\ndef espeak_errcheck(res, func, args):\r\n\tif res != EE_OK:\r\n\t\traise RuntimeError(\"%s: code %d\" % (func.__name__, res))\r\n\treturn res\r\n\r\ndef initialize():\r\n\tglobal espeakDLL, bgThread, bgQueue, player\r\n\tespeakDLL=cdll.LoadLibrary(r\"synthDrivers\\espeak.dll\")\r\n\tespeakDLL.espeak_Info.restype=c_char_p\r\n\tespeakDLL.espeak_Synth.errcheck=espeak_errcheck\r\n\tespeakDLL.espeak_SetVoiceByName.errcheck=espeak_errcheck\r\n\tespeakDLL.espeak_SetVoiceByProperties.errcheck=espeak_errcheck\r\n\tespeakDLL.espeak_SetParameter.errcheck=espeak_errcheck\r\n\tespeakDLL.espeak_Terminate.errcheck=espeak_errcheck\r\n\tespeakDLL.espeak_ListVoices.restype=POINTER(POINTER(espeak_VOICE))\r\n\tespeakDLL.espeak_GetCurrentVoice.restype=POINTER(espeak_VOICE)\r\n\tespeakDLL.espeak_SetVoiceByName.argtypes=(c_char_p,)\r\n\tsampleRate=espeakDLL.espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS,300,\r\n\t\tos.path.abspath(\"synthDrivers\"),0)\r\n\tif sampleRate<0:\r\n\t\traise OSError(\"espeak_Initialize %d\"%sampleRate)\r\n\tplayer = nvwave.WavePlayer(channels=1, samplesPerSec=sampleRate, bitsPerSample=16, outputDevice=config.conf[\"speech\"][\"outputDevice\"])\r\n\tespeakDLL.espeak_SetSynthCallback(callback)\r\n\tbgQueue = Queue.Queue()\r\n\tbgThread=BgThread()\r\n\tbgThread.start()\r\n\r\ndef terminate():\r\n\tglobal bgThread, bgQueue, player, espeakDLL \r\n\tstop()\r\n\tbgQueue.put((None, None, None))\r\n\tbgThread.join()\r\n\tespeakDLL.espeak_Terminate()\r\n\tbgThread=None\r\n\tbgQueue=None\r\n\tplayer.close()\r\n\tplayer=None\r\n\tespeakDLL=None\r\n\r\ndef info():\r\n\treturn espeakDLL.espeak_Info()\r\n\r\ndef getVariantDict():\r\n\tdir='synthDrivers\\\\espeak-ng-data\\\\voices\\\\!v'\r\n\t# Translators: name of the default espeak varient.\r\n\tvariantDict={\"none\": pgettext(\"espeakVarient\", \"none\")}\r\n\tfor fileName in os.listdir(dir):\r\n\t\tif os.path.isfile(\"%s\\\\%s\"%(dir,fileName)):\r\n\t\t\tfile=codecs.open(\"%s\\\\%s\"%(dir,fileName))\r\n\t\t\tfor line in file:\r\n\t\t\t\tif line.startswith('name '):\r\n\t\t\t\t\ttemp=line.split(\" \")\r\n\t\t\t\t\tif len(temp) ==2:\r\n\t\t\t\t\t\tname=temp[1].rstrip()\r\n\t\t\t\t\t\tbreak\r\n\t\t\t\tname=None\r\n\t\t\tfile.close()\r\n\t\tif name is not None:\r\n\t\t\tvariantDict[fileName]=name\r\n\treturn variantDict\r\n\r\n", "path": "source/synthDrivers/_espeak.py"}], "after_files": [{"content": "# -*- coding: UTF-8 -*-\r\n#synthDrivers/_espeak.py\r\n#A part of NonVisual Desktop Access (NVDA)\r\n#Copyright (C) 2007-2012 NV Access Limited, Peter V\u00e1gner\r\n#This file is covered by the GNU General Public License.\r\n#See the file COPYING for more details.\r\n\r\nimport time\r\nimport nvwave\r\nimport threading\r\nimport Queue\r\nfrom ctypes import *\r\nimport config\r\nimport globalVars\r\nfrom logHandler import log\r\nimport os\r\nimport codecs\r\n\r\nisSpeaking = False\r\nlastIndex = None\r\nbgThread=None\r\nbgQueue = None\r\nplayer = None\r\nespeakDLL=None\r\n\r\n#Parameter bounds\r\nminRate=80\r\nmaxRate=450\r\nminPitch=0\r\nmaxPitch=99\r\n\r\n#event types\r\nespeakEVENT_LIST_TERMINATED=0\r\nespeakEVENT_WORD=1\r\nespeakEVENT_SENTENCE=2\r\nespeakEVENT_MARK=3\r\nespeakEVENT_PLAY=4\r\nespeakEVENT_END=5\r\nespeakEVENT_MSG_TERMINATED=6\r\nespeakEVENT_PHONEME=7\r\n\r\n#position types\r\nPOS_CHARACTER=1\r\nPOS_WORD=2\r\nPOS_SENTENCE=3\r\n\r\n#output types\r\nAUDIO_OUTPUT_PLAYBACK=0\r\nAUDIO_OUTPUT_RETRIEVAL=1\r\nAUDIO_OUTPUT_SYNCHRONOUS=2\r\nAUDIO_OUTPUT_SYNCH_PLAYBACK=3\r\n\r\n#synth flags\r\nespeakCHARS_AUTO=0\r\nespeakCHARS_UTF8=1\r\nespeakCHARS_8BIT=2\r\nespeakCHARS_WCHAR=3\r\nespeakSSML=0x10\r\nespeakPHONEMES=0x100\r\nespeakENDPAUSE=0x1000\r\nespeakKEEP_NAMEDATA=0x2000\r\n\r\n#speech parameters\r\nespeakSILENCE=0\r\nespeakRATE=1\r\nespeakVOLUME=2\r\nespeakPITCH=3\r\nespeakRANGE=4\r\nespeakPUNCTUATION=5\r\nespeakCAPITALS=6\r\nespeakWORDGAP=7\r\nespeakOPTIONS=8   # reserved for misc. options.  not yet used\r\nespeakINTONATION=9\r\nespeakRESERVED1=10\r\nespeakRESERVED2=11\r\n\r\n#error codes\r\nEE_OK=0\r\n#EE_INTERNAL_ERROR=-1\r\n#EE_BUFFER_FULL=1\r\n#EE_NOT_FOUND=2\r\n\r\nclass espeak_EVENT_id(Union):\r\n\t_fields_=[\r\n\t\t('number',c_int),\r\n\t\t('name',c_char_p),\r\n\t\t('string',c_char*8),\r\n\t]\r\n\r\nclass espeak_EVENT(Structure):\r\n\t_fields_=[\r\n\t\t('type',c_int),\r\n\t\t('unique_identifier',c_uint),\r\n\t\t('text_position',c_int),\r\n\t\t('length',c_int),\r\n\t\t('audio_position',c_int),\r\n\t\t('sample',c_int),\r\n\t\t('user_data',c_void_p),\r\n\t\t('id',espeak_EVENT_id),\r\n\t]\r\n\r\nclass espeak_VOICE(Structure):\r\n\t_fields_=[\r\n\t\t('name',c_char_p),\r\n\t\t('languages',c_char_p),\r\n\t\t('identifier',c_char_p),\r\n\t\t('gender',c_byte),\r\n\t\t('age',c_byte),\r\n\t\t('variant',c_byte),\r\n\t\t('xx1',c_byte),\r\n\t\t('score',c_int),\r\n\t\t('spare',c_void_p),\r\n\t]\r\n\r\n\tdef __eq__(self, other):\r\n\t\treturn isinstance(other, type(self)) and addressof(self) == addressof(other)\r\n\r\nt_espeak_callback=CFUNCTYPE(c_int,POINTER(c_short),c_int,POINTER(espeak_EVENT))\r\n\r\n@t_espeak_callback\r\ndef callback(wav,numsamples,event):\r\n\ttry:\r\n\t\tglobal player, isSpeaking, lastIndex\r\n\t\tif not isSpeaking:\r\n\t\t\treturn 1\r\n\t\tfor e in event:\r\n\t\t\tif e.type==espeakEVENT_MARK:\r\n\t\t\t\tlastIndex=int(e.id.name)\r\n\t\t\telif e.type==espeakEVENT_LIST_TERMINATED:\r\n\t\t\t\tbreak\r\n\t\tif not wav:\r\n\t\t\tplayer.idle()\r\n\t\t\tisSpeaking = False\r\n\t\t\treturn 0\r\n\t\tif numsamples > 0:\r\n\t\t\ttry:\r\n\t\t\t\tplayer.feed(string_at(wav, numsamples * sizeof(c_short)))\r\n\t\t\texcept:\r\n\t\t\t\tlog.debugWarning(\"Error feeding audio to nvWave\",exc_info=True)\r\n\t\treturn 0\r\n\texcept:\r\n\t\tlog.error(\"callback\", exc_info=True)\r\n\r\nclass BgThread(threading.Thread):\r\n\tdef __init__(self):\r\n\t\tthreading.Thread.__init__(self)\r\n\t\tself.setDaemon(True)\r\n\r\n\tdef run(self):\r\n\t\tglobal isSpeaking\r\n\t\twhile True:\r\n\t\t\tfunc, args, kwargs = bgQueue.get()\r\n\t\t\tif not func:\r\n\t\t\t\tbreak\r\n\t\t\ttry:\r\n\t\t\t\tfunc(*args, **kwargs)\r\n\t\t\texcept:\r\n\t\t\t\tlog.error(\"Error running function from queue\", exc_info=True)\r\n\t\t\tbgQueue.task_done()\r\n\r\ndef _execWhenDone(func, *args, **kwargs):\r\n\tglobal bgQueue\r\n\t# This can't be a kwarg in the function definition because it will consume the first non-keywor dargument which is meant for func.\r\n\tmustBeAsync = kwargs.pop(\"mustBeAsync\", False)\r\n\tif mustBeAsync or bgQueue.unfinished_tasks != 0:\r\n\t\t# Either this operation must be asynchronous or There is still an operation in progress.\r\n\t\t# Therefore, run this asynchronously in the background thread.\r\n\t\tbgQueue.put((func, args, kwargs))\r\n\telse:\r\n\t\tfunc(*args, **kwargs)\r\n\r\ndef _speak(text):\r\n\tglobal isSpeaking\r\n\tuniqueID=c_int()\r\n\tisSpeaking = True\r\n\t# eSpeak can only process compound emojis  when using a UTF8 encoding\r\n\ttext=text.encode('utf8',errors='ignore')\r\n\tflags = espeakCHARS_UTF8 | espeakSSML | espeakPHONEMES\r\n\treturn espeakDLL.espeak_Synth(text,0,0,0,0,flags,byref(uniqueID),0)\r\n\r\ndef speak(text):\r\n\tglobal bgQueue\r\n\t_execWhenDone(_speak, text, mustBeAsync=True)\r\n\r\ndef stop():\r\n\tglobal isSpeaking, bgQueue, lastIndex\r\n\t# Kill all speech from now.\r\n\t# We still want parameter changes to occur, so requeue them.\r\n\tparams = []\r\n\ttry:\r\n\t\twhile True:\r\n\t\t\titem = bgQueue.get_nowait()\r\n\t\t\tif item[0] != _speak:\r\n\t\t\t\tparams.append(item)\r\n\t\t\tbgQueue.task_done()\r\n\texcept Queue.Empty:\r\n\t\t# Let the exception break us out of this loop, as queue.empty() is not reliable anyway.\r\n\t\tpass\r\n\tfor item in params:\r\n\t\tbgQueue.put(item)\r\n\tisSpeaking = False\r\n\tplayer.stop()\r\n\tlastIndex=None\r\n\r\ndef pause(switch):\r\n\tglobal player\r\n\tplayer.pause(switch)\r\n\r\ndef setParameter(param,value,relative):\r\n\t_execWhenDone(espeakDLL.espeak_SetParameter,param,value,relative)\r\n\r\ndef getParameter(param,current):\r\n\treturn espeakDLL.espeak_GetParameter(param,current)\r\n\r\ndef getVoiceList():\r\n\tvoices=espeakDLL.espeak_ListVoices(None)\r\n\tvoiceList=[]\r\n\tfor voice in voices:\r\n\t\tif not voice: break\r\n\t\tvoiceList.append(voice.contents)\r\n\treturn voiceList\r\n\r\ndef getCurrentVoice():\r\n\tvoice =  espeakDLL.espeak_GetCurrentVoice()\r\n\tif voice:\r\n\t\treturn voice.contents\r\n\telse:\r\n\t\treturn None\r\n\r\ndef setVoice(voice):\r\n\t# For some weird reason, espeak_EspeakSetVoiceByProperties throws an integer divide by zero exception.\r\n\tsetVoiceByName(voice.identifier)\r\n\r\ndef setVoiceByName(name):\r\n\t_execWhenDone(espeakDLL.espeak_SetVoiceByName,name)\r\n\r\ndef _setVoiceAndVariant(voice=None, variant=None):\r\n\tres = getCurrentVoice().identifier.split(\"+\")\r\n\tif not voice:\r\n\t\tvoice = res[0]\r\n\tif not variant:\r\n\t\tif len(res) == 2:\r\n\t\t\tvariant = res[1]\r\n\t\telse:\r\n\t\t\tvariant = \"none\"\r\n\tif variant == \"none\":\r\n\t\tespeakDLL.espeak_SetVoiceByName(voice)\r\n\telse:\r\n\t\ttry:\r\n\t\t\tespeakDLL.espeak_SetVoiceByName(\"%s+%s\" % (voice, variant))\r\n\t\texcept:\r\n\t\t\tespeakDLL.espeak_SetVoiceByName(voice)\r\n\r\ndef setVoiceAndVariant(voice=None, variant=None):\r\n\t_execWhenDone(_setVoiceAndVariant, voice=voice, variant=variant)\r\n\r\ndef _setVoiceByLanguage(lang):\r\n\tv=espeak_VOICE()\r\n\tlang=lang.replace('_','-')\r\n\tv.languages=lang\r\n\ttry:\r\n\t\tespeakDLL.espeak_SetVoiceByProperties(byref(v))\r\n\texcept:\r\n\t\tv.languages=\"en\"\r\n\t\tespeakDLL.espeak_SetVoiceByProperties(byref(v))\r\n\r\ndef setVoiceByLanguage(lang):\r\n\t_execWhenDone(_setVoiceByLanguage, lang)\r\n\r\ndef espeak_errcheck(res, func, args):\r\n\tif res != EE_OK:\r\n\t\traise RuntimeError(\"%s: code %d\" % (func.__name__, res))\r\n\treturn res\r\n\r\ndef initialize():\r\n\tglobal espeakDLL, bgThread, bgQueue, player\r\n\tespeakDLL=cdll.LoadLibrary(r\"synthDrivers\\espeak.dll\")\r\n\tespeakDLL.espeak_Info.restype=c_char_p\r\n\tespeakDLL.espeak_Synth.errcheck=espeak_errcheck\r\n\tespeakDLL.espeak_SetVoiceByName.errcheck=espeak_errcheck\r\n\tespeakDLL.espeak_SetVoiceByProperties.errcheck=espeak_errcheck\r\n\tespeakDLL.espeak_SetParameter.errcheck=espeak_errcheck\r\n\tespeakDLL.espeak_Terminate.errcheck=espeak_errcheck\r\n\tespeakDLL.espeak_ListVoices.restype=POINTER(POINTER(espeak_VOICE))\r\n\tespeakDLL.espeak_GetCurrentVoice.restype=POINTER(espeak_VOICE)\r\n\tespeakDLL.espeak_SetVoiceByName.argtypes=(c_char_p,)\r\n\tsampleRate=espeakDLL.espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS,300,\r\n\t\tos.path.abspath(\"synthDrivers\"),0)\r\n\tif sampleRate<0:\r\n\t\traise OSError(\"espeak_Initialize %d\"%sampleRate)\r\n\tplayer = nvwave.WavePlayer(channels=1, samplesPerSec=sampleRate, bitsPerSample=16, outputDevice=config.conf[\"speech\"][\"outputDevice\"])\r\n\tespeakDLL.espeak_SetSynthCallback(callback)\r\n\tbgQueue = Queue.Queue()\r\n\tbgThread=BgThread()\r\n\tbgThread.start()\r\n\r\ndef terminate():\r\n\tglobal bgThread, bgQueue, player, espeakDLL \r\n\tstop()\r\n\tbgQueue.put((None, None, None))\r\n\tbgThread.join()\r\n\tespeakDLL.espeak_Terminate()\r\n\tbgThread=None\r\n\tbgQueue=None\r\n\tplayer.close()\r\n\tplayer=None\r\n\tespeakDLL=None\r\n\r\ndef info():\r\n\treturn espeakDLL.espeak_Info()\r\n\r\ndef getVariantDict():\r\n\tdir='synthDrivers\\\\espeak-ng-data\\\\voices\\\\!v'\r\n\t# Translators: name of the default espeak varient.\r\n\tvariantDict={\"none\": pgettext(\"espeakVarient\", \"none\")}\r\n\tfor fileName in os.listdir(dir):\r\n\t\tif os.path.isfile(\"%s\\\\%s\"%(dir,fileName)):\r\n\t\t\tfile=codecs.open(\"%s\\\\%s\"%(dir,fileName))\r\n\t\t\tfor line in file:\r\n\t\t\t\tif line.startswith('name '):\r\n\t\t\t\t\ttemp=line.split(\" \")\r\n\t\t\t\t\tif len(temp) ==2:\r\n\t\t\t\t\t\tname=temp[1].rstrip()\r\n\t\t\t\t\t\tbreak\r\n\t\t\t\tname=None\r\n\t\t\tfile.close()\r\n\t\tif name is not None:\r\n\t\t\tvariantDict[fileName]=name\r\n\treturn variantDict\r\n\r\n", "path": "source/synthDrivers/_espeak.py"}]}