11import Foundation
2+ import MediaPlayer
23import ReadiumNavigator
34import ReadiumShared
45import ReadiumInternal
56
7+ func clamp< T> ( _ value: T , minValue: T , maxValue: T ) -> T where T : Comparable {
8+ return min ( max ( value, minValue) , maxValue)
9+ }
10+
611extension Resource {
712 var propertiesSync : ResourceProperties {
813 let semaphore = DispatchSemaphore ( value: 0 )
@@ -179,11 +184,11 @@ extension EPUBPreferences {
179184}
180185
181186public struct TTSPreferences {
182- /// Rate at which utterances should be spoken. Defaults to 1.0
183- public var rate : Double ?
187+ /// Rate at which utterances should be spoken. Defaults to 0.5
188+ public var rate : Float ?
184189
185- /// Pitch at which utterances should be spoken. Defaults to 1.0
186- public var pitch : Double ?
190+ /// Pitch at which utterances should be spoken. Defaults to 1.0 and should be in range 0.5 to 2.0
191+ public var pitch : Float ?
187192
188193 /// Language overriding the publication one.
189194 public var overrideLanguage : Language ?
@@ -192,8 +197,8 @@ public struct TTSPreferences {
192197 public var voiceIdentifier : String ?
193198
194199 public init (
195- rate: Double ? = nil ,
196- pitch: Double ? = nil ,
200+ rate: Float ? = nil ,
201+ pitch: Float ? = nil ,
197202 overrideLanguage: Language ? = nil ,
198203 voiceIdentifier: String ? = nil
199204 ) {
@@ -205,11 +210,21 @@ public struct TTSPreferences {
205210
206211 init ( fromMap jsonMap: Dictionary < String , Any > ) throws {
207212 let map = jsonMap,
208- rate = map [ " speed " ] as? Double ,
209- pitch = map [ " pitch " ] as? Double ,
213+ rate = map [ " speed " ] as? Double ?? 1.0 ,
214+ pitch = map [ " pitch " ] as? Double ?? 1.0 ,
210215 langCode = map [ " languageOverride " ] as? String ,
211216 overrideLanguage = langCode != nil ? Language ( stringLiteral: langCode!) : nil ,
212217 voiceIdentifier = map [ " voiceIdentifier " ] as? String
213- self . init ( rate: rate, pitch: pitch, overrideLanguage: overrideLanguage, voiceIdentifier: voiceIdentifier)
218+
219+ /// Rate is normalized on iOS, since AVSpeechUtterance has a default rate of 0.5 (see AVSpeechUtteranceDefaultSpeechRate)
220+ /// Rate is also clamped between allowed values.
221+ let avRate = clamp ( Float ( rate) * AVSpeechUtteranceDefaultSpeechRate,
222+ minValue: AVSpeechUtteranceMinimumSpeechRate,
223+ maxValue: AVSpeechUtteranceMaximumSpeechRate)
224+ /// Pitch is clamped between allowed values according to AVSpeechUtterance docs.
225+ let avPitch = clamp ( Float ( pitch) ,
226+ minValue: 0.5 ,
227+ maxValue: 2.0 )
228+ self . init ( rate: avRate, pitch: avPitch, overrideLanguage: overrideLanguage, voiceIdentifier: voiceIdentifier)
214229 }
215230}
0 commit comments