-
-
Save ryanlintott/e1284682216d4e4a90fa474a676fb453 to your computer and use it in GitHub Desktop.
import Foundation | |
import AVFoundation | |
@available(iOS 10.0, *) | |
extension AVSpeechSynthesizer { | |
func speakIPA(_ ipaString: String, voiceIdentifier: String, willSpeak: ((String) -> Void)? = nil) { | |
//Set the audio session to playback to ignore mute switch on device | |
do { | |
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback, options: [.interruptSpokenAudioAndMixWithOthers, .duckOthers]) | |
} catch { | |
print("Error: \(error.localizedDescription)") | |
} | |
let mutableAttributedString = NSMutableAttributedString(string: ipaString) | |
let range = NSString(string: ipaString).range(of: ipaString) | |
let pronunciationKey = NSAttributedString.Key(rawValue: AVSpeechSynthesisIPANotationAttribute) | |
mutableAttributedString.setAttributes([pronunciationKey: ipaString], range: range) | |
let utterance = AVSpeechUtterance(attributedString: mutableAttributedString) | |
let voice = AVSpeechSynthesisVoice(identifier: voiceIdentifier) | |
utterance.voice = voice | |
// Pausing first is safer and may prevent bugs | |
self.pauseSpeaking(at: .immediate) | |
self.stopSpeaking(at: .immediate) | |
// Run some code just before speaking | |
willSpeak?(utterance.speechString) | |
print("speakIPA: \(ipaString) voice: \(voice?.identifier ?? "?")") | |
self.speak(utterance) | |
} | |
} |
This code is a bit older and I found a few bugs since. Mainly if you have a different region set on your phone the IPA might sound very strange. The latest version that works better is included in this package > OEVoice
Apple's version of IPA is quite limited. Each voice is mostly limited to the sounds used in the language and accent it was created for. I started with the voice that worked best initially then used a bunch of substitutions to alter the base OE IPA pronunciations and fix various errors as I found them. Often combinations of symbols just wouldn't work so I would swap with similar sounds until I got something close enough. If you check out this file you'll see all the substitutions I used to fine tune the pronunciation. OEVoice.swift
The only way to ensure your pronunciations are correct would be to add IPA pronunciations to each word. You need to use IPA symbols (I find this helpful: https://ipa.typeit.org) and there will be some combinations that Apple might not pronounce correctly. If Toki Pona is purely phonetic then maybe you could do a substitution swapping letters for IPA symbols. If however it's more like English where letters may sound different depending on the context you'll probably need to translate each word as the rules would be too complex to code. Either way, once you have IPA pronunciations you think are accurate, then I would try testing with voices, finding one that is the closest fit, then testing with words and making any voice-specific adjustments to IPA characters (like I've done with Old English).
When picking IPA symbols I found this app very helpful as you could hear the different sounds:
https://apps.apple.com/app/id869642260
Also this web app was helpful for testing even though it's using non-Apple voices as it's pretty accurate.
http://ipa-reader.xyz
Ive been trying to do something similar and neither my attempt or this seems to be obeying any ipa