TextToSpeech - Add way to control Speak Rate
Speak rate proved to be exceedingly difficult to get right in cross platform setting. Basically, Android and UWP are absolutely fine and predictable, but the speak rate value for iOS is wildly different between iOS versions, and doesn't seem to be based on a linear scale in terms of the value you set.
This really meant there's no easy way to take a common value range for a cross platform API (let's say 0.0x to 2.0x speed) and apply that in a meaningful way to iOS.
Not suggesting we won't or can't do this, it just requires quite bit more work and research than you'd expect, due to how iOS implements this.
I find some code can to do that.
https://github.com/jamesmontemagno/TextToSpeechPlugin/blob/master/src/TextToSpeech.Plugin/TextToSpeech.apple.cs#L113
We discussed that code previously and decided it wasn't exhaustive enough of all possibilities... We've also investigated how other platforms approach it, and the only consistencies we've found is that it's terribly unreliable and inconsistent.
If someone wants to do the work of analyzing a bunch of different iOS devices and OS versions, we can continue the dialogue, but this one's unfortunately pretty low on our priority list at this point in time given the constraints.
add this
So one possibility here is to not allow for a double SpeechRate to be set, but instead make an enum with a number of practical choices: Min, Slow, Default, Fast, Max and then choose what those values might be on Android and UWP. On iOS this would allow us to do something like:
var osMin = AVSpeechUtteranceMinimumSpeechRate;
var osDefault = AVSpeechUtteranceDefaultSpeechRate;
var osMax = AVSpeechUtteranceMaximumSpeechRate;
switch (speechRate) {
case SpeechRate.Minimum:
return osMin;
case SpeechRate.Slow:
return osMin + ((osDefault - osMin) / 2.0f);
case SpeechRate.Default:
return osDefault;
case SpeechRate.Fast:
return osDefault + ((osMax - osDefault) / 2.0f);
case SpeechRate.Maximum:
return osMax;
default:
return osDefault;
}
It still wouldn't be quite consistent between platforms since Android / UWP don't really have a 'minimum' that corresponds to what iOS's min might be, and we'd just have to guess (maybe on Android / UWP the max is 4.0x and that roughly matches what iOS considers maximum).
One way for us to maybe seed these values is to get some long text and measure the speech length in seconds and see if we can get it sort of the same.
My concern here is that AVSpeechUtteranceMinimumSpeechRate might be lower or higher on a given iOS version and not just in terms of the value itself, but the resulting speed of speech.
So that might be the first test, see if AVSpeechUtteranceMinimumSpeechRate is roughly the same speed on iOS 10 and 11 (if we can even get something to test back that far). If it IS, then we can probably seed multiplier values to use in my previous pseudo code that sound roughly the same speed as the other platforms.
Hoping you can come up with a solution or even partial solution for this soon. As it stands this feature doesn't work good on Android so I will go back to trying the plug in.
Thanks for moving to Needs triage. Perhaps this works on a very fast phone but on the Android phone that I have the speech rate is so slow that I can hardly understand the English words the phone is trying to say. As a temporary measure I am going to try the TTS plugin and give up using the Xamarin Essentials one for now.
SpeakRate is very userful, please, add this feature! Thanks
+1 would be very helpful