Instead of reflexively asking for code when someone simply doesn't know how to do something, it's more helpful to tell them how to do it.
For example, there's something called duckmode that lowers the sound of music in the background. I did not know this, so there was no code.
It lowers music played using Musickit played in the same program, but it does not lower music played by AvAudioPlayer.
Before playing a sentence through the synthesizer, I call setDuckMode(), and when the sentence is complete, I set the active audio session back to mix mode.
This works, except there are timing problems when you want to play apple music, speak through the synth, and play a sound effect through AvAudioPlay all at the same time, which is something I need to do.
You can't switch modes while AvAudioPlayer is still playing audio, so you can't go into duck to hear the voice over Apple music. Trying to do so causes an error and interrupts the audio being played through AvAudioPlayer.
You can set a session to be in both duck and mix mode at the same time, but that keeps the music low the entire time.
Ideally, you want to schedule speaking through the synthesizer when audio is not being played through AvAudioPlayer.
func setDuckMode() {
do {
try AVAudioSession.sharedInstance().setActive(false)
try AVAudioSession.sharedInstance().setCategory(
.playback,
mode: .default,
options: [.duckOthers])
try AVAudioSession.sharedInstance().setActive(true)
} catch {
Logger.sm.debug("Could not init sound duck. \(error)")
}
}
func setMixMode() {
do {
try AVAudioSession.sharedInstance().setActive(false)
try AVAudioSession.sharedInstance().setCategory(
.playback,
mode: .default,
options: .mixWithOthers)
try AVAudioSession.sharedInstance().setActive(true)
} catch {
Logger.sm.debug("Could not init sound mixed. \(error)")
}
}
extension SoundManager: AVSpeechSynthesizerDelegate {
func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
setMixMode()
}
}