def background_thread_func(self): bytes_sent=ctypes.c_int16() out_buffer=ctypes.create_string_buffer(OUT_BUFFER_SIZE) bytes_received=ctypes.c_int16() data_type=ctypes.c_int16() while True: data, index = self.queue.get() if data is None: break synthIndexReached.notify(synth=self, index=index) remaining=len(data)+1 while remaining and self.isSpeaking: self.dll.pico_putTextUtf8(self.pico_engine, data, remaining, ctypes.byref(bytes_sent)) remaining-=bytes_sent.value data=data[bytes_sent.value:] status=PICO_STEP_BUSY buf=BytesIO() while self.isSpeaking and status==PICO_STEP_BUSY: status=self.dll.pico_getData(self.pico_engine, out_buffer, OUT_BUFFER_SIZE, ctypes.byref(bytes_received), ctypes.byref(data_type)) if status==PICO_STEP_BUSY: buf.write(ctypes.string_at(out_buffer, bytes_received.value)) if buf.tell() >= 4096: self.player.feed(buf.getvalue()) buf.seek(0) buf.truncate(0) else: if buf.tell(): self.player.feed(buf.getvalue()) synthDoneSpeaking.notify(synth=self) self.player.idle() if not self.isSpeaking: #stop requested during playback self.dll.pico_resetEngine(self.pico_engine,0) self.lastIndex=None self.queue.task_done()
def EndStream(self, streamNum, pos): synth = self.synthRef() if synth is None: log.debugWarning( "Called Bookmark method on EndStream while driver is dead") return synthDoneSpeaking.notify(synth=synth)
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() synthDoneSpeaking.notify(synth=self) while self._queuedSpeech: item = self._queuedSpeech.pop(0) if isinstance(item, tuple): # Parameter change. # Note that, if prosody otions aren't supported, this code will never be executed. func, value = item value = ctypes.c_double(value) func(self._handle, value) continue self._wasCancelled = False log.debug("Begin processing speech") self._isProcessing = True # ocSpeech_speak is async. # It will call _callback in a background thread once done, # which will eventually process the queue again. self._dll.ocSpeech_speak(self._handle, item) return log.debug("Queue empty, done processing") self._isProcessing = False
def run(self): try: self.wavePlayer = nvwave.WavePlayer( channels=1, samplesPerSec=self.sampleRate, bitsPerSample=16, outputDevice=config.conf["speech"]["outputDevice"]) self.synthEvent = threading.Event() finally: self.initializeEvent.set() while self.keepAlive: self.synthEvent.wait() self.synthEvent.clear() lastIndex = None while self.keepAlive: data = self.speechPlayer.synthesize(8192) if self.isSpeaking and data: indexNum = self.speechPlayer.getLastIndex() self.wavePlayer.feed( ctypes.string_at(data, data.length * 2), onDone=lambda indexNum=indexNum: synthIndexReached. notify(synth=self.synthRef(), index=indexNum) if indexNum >= 0 else False) lastIndex = indexNum else: indexNum = self.speechPlayer.getLastIndex() if indexNum > 0 and indexNum != lastIndex: synthIndexReached.notify(synth=self.synthRef(), index=indexNum) self.wavePlayer.idle() synthDoneSpeaking.notify(synth=self.synthRef()) break self.initializeEvent.set()
def ITTSBufNotifySink_BookMark(self, this, qTimeStamp, dwMarkNum): synth = self.synthRef() if synth is None: log.debugWarning("Called ITTSBufNotifySink_BookMark method on ITTSBufNotifySink while driver is dead") return synthIndexReached.notify(synth=synth, index=dwMarkNum) if synth._finalIndex == dwMarkNum: synth._finalIndex = None synthDoneSpeaking.notify(synth=synth)
def EndStream(self, streamNum, pos): synth = self.synthRef() if synth is None: log.debugWarning("Called Bookmark method on EndStream while driver is dead") return synthDoneSpeaking.notify(synth=synth) if synth._audioDucker: if audioDucking._isDebug(): log.debug("Disabling audio ducking due to speech stream end") synth._audioDucker.disable()
def _processQueue(self): if not self._queuedSpeech and self._player is None: # If oneCore speech has not been successful yet the player will not have initialised. (#11544) # We can't sync the player in this instance. log.debugWarning( "Cannot process speech queue as player not set and no speech queued" ) return if not self._queuedSpeech: # There are no more queued utterances at this point, so call sync. # This blocks while waiting for the final chunk to play, # so by the time this is done, there might be something queued. # #10721: We use sync instead of idle because idle closes the audio # device. If there's something in the queue after playing the final chunk, # that will result in WaveOutOpen being called in the callback when we # push the next chunk of audio. We *really* don't want this because calling # WaveOutOpen blocks for ~100 ms if called from the callback when the SSML # includes marks, resulting in lag between utterances. if isDebugForSynthDriver(): log.debug("Calling sync on audio player") self._player.sync() if not self._queuedSpeech: # There's still nothing in the queue, so it's okay to call idle now. if isDebugForSynthDriver(): log.debug("Calling idle on audio player") self._player.idle() synthDoneSpeaking.notify(synth=self) while self._queuedSpeech: item = self._queuedSpeech.pop(0) if isinstance(item, tuple): # Parameter change. # Note that, if prosody otions aren't supported, this code will never be executed. func, value = item value = ctypes.c_double(value) func(self._ocSpeechToken, value) continue self._wasCancelled = False if isDebugForSynthDriver(): log.debug("Begin processing speech") self._isProcessing = True # ocSpeech_speak is async. # It will call _callback in a background thread once done, # which will eventually process the queue again. self._dll.ocSpeech_speak(self._ocSpeechToken, item) return if isDebugForSynthDriver(): log.debug("Queue empty, done processing") self._isProcessing = False
def _onDoneSpeaking(self): synthDoneSpeaking.notify(synth=self) def resub(dct, s):
def _onDoneSpeaking(self): synthDoneSpeaking.notify(synth=self)
def ITTSBufNotifySink_BookMark(self, this, qTimeStamp, dwMarkNum): synthIndexReached.notify(synth=self._synthDriver,index=dwMarkNum) if self._synthDriver._finalIndex==dwMarkNum: self._synthDriver._finalIndex=None synthDoneSpeaking.notify(synth=self._synthDriver)
def _onIndexReached(self, index): if index is not None: synthIndexReached.notify(synth=self, index=index) else: synthDoneSpeaking.notify(synth=self)