Sweeper February 2016

How to make speech synthesiser speak a bunch of utterances, one after another?

I am building an app that will speak the sentences/words that is stored in a playlist one by one. Both the playlists and the items in them are stored inside Core Data.

I added a play/stop button in the storyboard. Here is the event handler for it:

@IBAction func playClick(sender: UIBarButtonItem) {
    if isPlaying {
        synthesizer.stopSpeakingAtBoundary(.Immediate)
        isPlaying = false
        sender.image = UIImage(named: "play")
    } else {
        sender.image = UIImage(named: "stop")
        isPlaying = true
        for string in playlist.utterrances! {
            let utterance = UserSettings.getPrefUtterance((string as! Utterance).string!)
            utterance.postUtteranceDelay = 2
            synthesizer.speakUtterance(utterance)
        }
        isPlaying = false
        sender.image = UIImage(named: "play")
    }
}

isPlaying (type Bool), synthesizer (type AVSpeechSynthesizer) and playlist (type Playlists, an entity description) are class-level variables.

I think the code here is pretty clear. First I decide whether the button should stop or start the synthesizer. If it is the latter, loop through the items in the playlist and synthesise them. Then switch the images and mutate isPlaying

But when I run the app and press the button, nothing at all happens. No sound, no image change, no nothing. I think this is because of the last two lines in the method, so I deleted them. This time, the image of the button changes but still no sound.

I think that this must be because I am telling the synthesiser to start speaking before the last utterance is finished. Or I need to know when the synthesiser stops speaking and start another utterance.

"But why don't you just join the strings and synthesise it just for once?", you asked. Because I want to have a two-second delay between each item in

Answers


Fogmeister February 2016

The best way to do this is using the AVSpeechSynthesizerDelegate.

It has a method... speechSynthesizer(_:didFinishSpeechUtterance:) which is called when an utterance finishes.

You can keep track of the utterance that is currently being spoken and when the delegate gets informed of it being finished then start the next one.

If you want them to only play when the button is clicked then disable the button when the delegate gets informed of didStartSpeechUtterance and then enable the button on didFinish....

Post Status

Asked in February 2016
Viewed 1,515 times
Voted 4
Answered 1 times

Search




Leave an answer