def test_convertComplex(self): """Test converting a complex speech sequence to SSML. XML generation is already tested by TestXmlBalancer. However, SSML is what callers expect at the end of the day, so test converting a complex speech sequence to SSML. Depends on behavior tested by TestXmlBalancer. """ converter = speechXml.SsmlConverter("en_US") xml = converter.convertToXml([ "t1", PitchCommand(multiplier=2), VolumeCommand(multiplier=2), "t2", PitchCommand(), LangChangeCommand("de_DE"), CharacterModeCommand(True), IndexCommand(1), "c", CharacterModeCommand(False), PhonemeCommand("phIpa", text="phText") ]) self.assertEqual( xml, '<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">' 't1' '<prosody pitch="200%" volume="200%">t2</prosody>' '<prosody volume="200%"><voice xml:lang="de-DE">' '<mark name="1"/><say-as interpret-as="characters">c</say-as>' '<phoneme alphabet="ipa" ph="phIpa">phText</phoneme>' '</voice></prosody></speak>')
def test3(self): """Change pitch, text, end utterance, text. wx.CallLater(500, speech.speak, [ PitchCommand(offset=50), u"This is the first utterance in a higher pitch", EndUtteranceCommand(), u"And this is the second" ]) Expected: All should be higher pitch. """ smi = SpeechManagerInteractions(self) sequence = [ PitchCommand(offset=50), u"This is the first utterance in a higher pitch", # EndUtterance effectively splits the sequence, two sequence numbers are returned # from smi.speak for ease of adding expectations. smi.create_EndUtteranceCommand(expectedToBecomeIndex=1), smi.create_ExpectedProsodyCommand(PitchCommand(offset=50)), u"And this is the second", smi.create_ExpectedIndex(expectedToBecomeIndex=2), ] with smi.expectation(): smi.speak(sequence) smi.expect_synthSpeak(0) with smi.expectation(): smi.indexReached(1) smi.pumpAll() smi.expect_synthSpeak(1)
def test_pitchNotifications(self): expected = repr([PitchCommand(offset=30), 'A', PitchCommand()]) output = _getSpellingCharAddCapNotification( speakCharAs='A', sayCapForCapitals=False, capPitchChange=30, beepForCapitals=False, ) self.assertEqual(repr(list(output)), expected)
def test_allNotifications(self): expected = repr([ PitchCommand(offset=30), BeepCommand(2000, 50, left=50, right=50), 'cap ', 'A', PitchCommand() ]) output = _getSpellingCharAddCapNotification( speakCharAs='A', sayCapForCapitals=True, capPitchChange=30, beepForCapitals=True, ) self.assertEqual(repr(list(output)), expected)
def test_13_SPRI_interruptBeforeIndexReached(self, mock_BeepCommand_run): """The same as the other test_13, but the first index is not reached before the interruption. In this cases speech manager is expected to finish the first utterance before interrupting. """ smi = SpeechManagerInteractions(self) smi.addMockCallMonitoring([mock_BeepCommand_run]) firstSeq = [ PitchCommand(offset=100), "Text before the beep ", smi.create_BeepCommand(440, 10, expectedToBecomeIndex=1), "text after the beep, text, text, text, text", smi.create_ExpectedIndex(expectedToBecomeIndex=2), ] with smi.expectation(): first = smi.speak(priority=speech.Spri.NORMAL, seq=firstSeq) smi.expect_synthSpeak(first) with smi.expectation(): interrupt = smi.speak( priority=speech.Spri.NOW, seq=[ "This is an interruption", smi.create_ExpectedIndex(expectedToBecomeIndex=3) ]) smi.expect_synthSpeak(interrupt) smi.expect_synthCancel() with smi.expectation(): # the first sequence was canceled, after reaching the end of the interruption sequence expect to return # to the first sequence. Note that it speaks the whole first utterance again. smi.indexReached(3) smi.pumpAll() smi.expect_synthSpeak(first)
def test_cap(self): expected = repr([ PitchCommand(offset=30), BeepCommand(2000, 50, left=50, right=50), 'cap ', 'A', PitchCommand(), EndUtteranceCommand(), ]) output = _getSpellingSpeechWithoutCharMode( text='A', locale=None, useCharacterDescriptions=False, sayCapForCapitals=True, capPitchChange=30, beepForCapitals=True, ) self.assertEqual(repr(list(output)), expected)
def generateBalancerCommands(self, speechSequence): commands = super(_OcPreAPI5SsmlConverter, self).generateBalancerCommands(speechSequence) # The EncloseAllCommand from SSML must be first. yield next(commands) # OneCore didn't provide a way to set base prosody values before API version 5. # Therefore, the base values need to be set using SSML. yield self.convertRateCommand(RateCommand(multiplier=1)) yield self.convertVolumeCommand(VolumeCommand(multiplier=1)) yield self.convertPitchCommand(PitchCommand(multiplier=1)) for command in commands: yield command
def test_13_SPRI_interruptAfterIndexReached(self, mock_BeepCommand_run): """Utterance at SPRI_NORMAL including a pitch change and beep. Utterance at SPRI_NOW. Manual Test (in NVDA python console): wx.CallLater(500, speech.speak, [ speech.PitchCommand(offset=100), u"Text before the beep ", speech.BeepCommand(440, 10), u"text after the beep, text, text, text, text" ]) wx.CallLater(1500, speech.speak, [u"This is an interruption"], priority=speech.SPRI_NOW) Expected: Text speaks with higher pitch, beep, text gets interrupted, interruption speaks with normal pitch, text after the beep speaks again with higher pitch """ smi = SpeechManagerInteractions(self) smi.addMockCallMonitoring([mock_BeepCommand_run]) firstSeq = [ PitchCommand(offset=100), "Text before the beep ", smi.create_BeepCommand(440, 10, expectedToBecomeIndex=1), "text after the beep, text, text, text, text", smi.create_ExpectedIndex(expectedToBecomeIndex=2), ] with smi.expectation(): first = smi.speak(priority=speech.Spri.NORMAL, seq=firstSeq) smi.expect_synthSpeak(first) with smi.expectation(): smi.indexReached(1) smi.pumpAll() smi.expect_mockCall(mock_BeepCommand_run) with smi.expectation(): interrupt = smi.speak( priority=speech.Spri.NOW, seq=[ "This is an interruption", smi.create_ExpectedIndex(expectedToBecomeIndex=3) ]) smi.expect_synthSpeak(interrupt) smi.expect_synthCancel() with smi.expectation(): smi.indexReached(3) smi.pumpAll() resume = [ smi.create_ExpectedProsodyCommand(firstSeq[0]), *firstSeq[3:] ] smi.expect_synthSpeak(sequence=resume)
def test_1(self, mock_BeepCommand_run, mock_WaveFileCommand_run): r"""Text, beep, beep, sound, text. Manual Test (in NVDA python console): wx.CallLater(500, speech.speak, [ u"This is some speech and then comes a", BeepCommand(440, 10), u"beep. If you liked that, let's ", BeepCommand(880, 10), u"beep again. I'll speak the rest of this in a ", PitchCommand(offset=50), u"higher pitch. And for the finale, let's ", WaveFileCommand(r"waves\browseMode.wav"), u"play a sound." ]) """ smi = SpeechManagerInteractions(self) smi.addMockCallMonitoring( [mock_BeepCommand_run, mock_WaveFileCommand_run]) _beepCommand = smi.create_BeepCommand _waveFileCommand = smi.create_WaveFileCommand sequence = [ "This is some speech and then comes a", _beepCommand(440, 10, expectedToBecomeIndex=1), "beep. If you liked that, let's ", _beepCommand(880, 10, expectedToBecomeIndex=2), "beep again. I'll speak the rest of this in a ", PitchCommand(offset=50), "higher pitch. And for the finale, let's ", _waveFileCommand(r"waves\browseMode.wav", expectedToBecomeIndex=3), "play a sound.", smi.create_ExpectedIndex(expectedToBecomeIndex=4) ] with smi.expectation(): smi.speak(sequence) smi.expect_synthSpeak(0) for i in range(1, 5): with smi.expectation(): smi.indexReached(i) smi.pumpAll() if i in [ 1, 2, ]: smi.expect_mockCall(mock_BeepCommand_run) if i in [ 3, ]: smi.expect_mockCall(mock_WaveFileCommand_run)
def test_4_profiles(self): """Text, pitch, text, enter profile1, enter profile2, text, exit profile1, text. Manual Test (in NVDA python console): from speech import sayAll, appModuleHandler t1 = sayAll.SayAllProfileTrigger() t2 = appModuleHandler.AppProfileTrigger("notepad") wx.CallLater(500, speech.speak, [ u"Testing testing ", PitchCommand(offset=100), "1 2 3 4", ConfigProfileTriggerCommand(t1, True), ConfigProfileTriggerCommand(t2, True), u"5 6 7 8", ConfigProfileTriggerCommand(t1, False), u"9 10 11 12" ]) Expected: All text after 1 2 3 4 should be higher pitch. 5 6 7 8 should have profile 1 and 2. 9 10 11 12 should be just profile 2. """ t1 = InitialDevelopmentTests.FakeProfileTrigger("t1") t2 = InitialDevelopmentTests.FakeProfileTrigger("t2") smi = SpeechManagerInteractions(self) smi.addMockCallMonitoring([t1.enter, t1.exit, t2.enter, t2.exit]) seq = [ "Testing testing ", PitchCommand(offset=100), "1 2 3 4", smi.create_ExpectedIndex(1), # The preceeding index is expected, # as the following profile trigger commands will cause the utterance to be split here. ConfigProfileTriggerCommand(t1, True), ConfigProfileTriggerCommand(t2, True), "5 6 7 8", smi.create_ExpectedIndex(2), # The preceeding index is expected, # as the following profile trigger commands will cause the utterance to be split here. ConfigProfileTriggerCommand(t1, False), "9 10 11 12" ] with smi.expectation(): smi.speak(seq) smi.expect_synthSpeak(sequence=seq[:4]) with smi.expectation(): smi.indexReached(1) smi.pumpAll() with smi.expectation(): smi.doneSpeaking() smi.pumpAll() smi.expect_synthCancel() smi.expect_mockCall(t1.enter) smi.expect_synthCancel() smi.expect_mockCall(t2.enter) smi.expect_synthSpeak(sequence=[ seq[1], # PitchCommand '5 6 7 8', seq[7], # IndexCommand index=2 (due to a ConfigProfileTriggerCommand following it) ]) with smi.expectation(): smi.indexReached(2) smi.pumpAll() with smi.expectation(): smi.doneSpeaking() smi.pumpAll() smi.expect_synthCancel() smi.expect_synthSpeak(sequence=[ seq[1], # PitchCommand '9 10 11 12', smi.create_ExpectedIndex(expectedToBecomeIndex=3) ]) smi.expect_mockCall(t1.exit) with smi.expectation(): smi.indexReached(3) smi.pumpAll() with smi.expectation(): smi.doneSpeaking() smi.pumpAll() smi.expect_synthCancel() smi.expect_mockCall(t2.exit)
def test_expectedProsodyNotMatching(self): p = PitchCommand(offset=2) e = ExpectedProsody(PitchCommand(offset=5)) self.assertNotEqual(p, e)