From ffa71c7c3533e03ad37f6980c36440c86422f2bc Mon Sep 17 00:00:00 2001 From: James Teh Date: Tue, 15 Aug 2017 12:24:18 +1000 Subject: [PATCH] OneCore Voices: Fix lag when reporting characters. (#7495) When we speak characters, we include indexes, which get translated to SSML marks. Unfortunately, calling WaveOutOpen blocks for ~100 ms if called from the callback when the SSML includes marks. We're not quite sure why. To work around this, open the device before queuing. Move the call to player.idle to _processQueue so that it gets called (thus closing the audio device) even if the UWP code encounters an exception. --- source/synthDrivers/oneCore.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/source/synthDrivers/oneCore.py b/source/synthDrivers/oneCore.py index 1cbfe1933b1..8a7e9f2d8c4 100644 --- a/source/synthDrivers/oneCore.py +++ b/source/synthDrivers/oneCore.py @@ -142,6 +142,11 @@ def cancel(self): def speak(self, speechSequence): conv = _OcSsmlConverter(self.language, self.rate, self.pitch, self.volume) text = conv.convertToXml(speechSequence) + # #7495: Calling WaveOutOpen blocks for ~100 ms if called from the callback + # when the SSML includes marks. + # We're not quite sure why. + # To work around this, open the device before queuing. + self._player.open() self._queueSpeech(text) def _queueSpeech(self, item): @@ -151,6 +156,12 @@ def _queueSpeech(self, item): self._processQueue() def _processQueue(self): + if not self._queuedSpeech: + # There are no more queued utterances at this point, so call idle. + # This blocks while waiting for the final chunk to play, + # so by the time this is done, there might be something queued. + log.debug("Calling idle on audio player") + self._player.idle() if self._queuedSpeech: item = self._queuedSpeech.pop(0) self._wasCancelled = False @@ -208,13 +219,6 @@ def _callback(self, bytes, len, markers): if prevMarker: self.lastIndex = prevMarker log.debug("Done pushing audio") - if not self._queuedSpeech: - # There are no more queued utterances at this point, so call idle. - # This blocks while waiting for the final chunk to play, - # so by the time this is done, there might be something queued. - # The call to _processQueue will take care of this. - log.debug("Calling idle on audio player") - self._player.idle() self._processQueue() def _getAvailableVoices(self, onlyValid=True):