From 495c5eddadff6ef947cca6ad26199178801acc44 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Tue, 19 May 2020 07:49:28 -0500 Subject: [PATCH] Major `tts-rs` update. * Initial WinRT driver, used when no Windows screen reader is detected. * Enhanced rate support, tracking min/max/normal rate per synthesizer. * `rate_percentage` properties make working with differing rate ranges easier. --- Cargo.toml | 2 +- TTS.gd | 69 ++++++++++++++++++++++++++++++++++++++++++++---------- src/lib.rs | 68 ++++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 111 insertions(+), 28 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 90b7a61..c572450 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,4 +9,4 @@ crate-type = ["cdylib"] [dependencies] gdnative = "0.8" -tts = "0.2" +tts = { git = "https://gitlab.com/ndarilek/tts-rs" } diff --git a/TTS.gd b/TTS.gd index 14f704c..8497a5d 100644 --- a/TTS.gd +++ b/TTS.gd @@ -17,13 +17,49 @@ func _ready(): else: print_debug("TTS not available!") +func _get_min_rate(): + if OS.has_feature('JavaScript'): + return 0.1 + elif Engine.has_singleton("AndroidTTS"): + return 0.1 + elif tts != null: + return tts.min_rate + else: + return 0 + +var min_rate setget , _get_min_rate + +func _get_max_rate(): + if OS.has_feature('JavaScript'): + return 10 + elif Engine.has_singleton("AndroidTTS"): + return 10.0 + elif tts != null: + return tts.max_rate + else: + return 0 + +var max_rate setget , _get_max_rate + +func _get_normal_rate(): + if OS.has_feature('JavaScript'): + return 1 + elif Engine.has_singleton("AndroidTTS"): + return 1.0 + elif tts != null: + return tts.normal_rate + else: + return 0 + +var normal_rate setget , _get_normal_rate + var javascript_rate = 50 func set_rate(rate): - if rate < 0: - rate = 0 - elif rate > 100: - rate = 100 + if rate < self.min_rate: + rate = self.min_rate + elif rate > self.max_rate: + rate = self.max_rate if tts != null: tts.rate = rate elif OS.has_feature('JavaScript'): @@ -39,20 +75,27 @@ func get_rate(): var rate setget set_rate, get_rate +func _get_rate_percentage(): + return range_lerp(self.rate, self.min_rate, self.max_rate, 0, 100) + +func _set_rate_percentage(v): + self.rate = range_lerp(v, 0, 100, self.min_rate, self.max_rate) + +var rate_percentage setget _set_rate_percentage, _get_rate_percentage + +func _get_normal_rate_percentage(): + return range_lerp(self.normal_rate, self.min_rate, self.max_rate, 0, 100) + +var normal_rate_percentage setget , _get_rate_percentage + func speak(text, interrupt := true): if tts != null: tts.speak(text, interrupt) elif OS.has_feature('JavaScript'): - var scaled_rate: float - if javascript_rate <= 50: - scaled_rate = javascript_rate / 50.0 - else: - scaled_rate = javascript_rate - 50 - scaled_rate = 1 + (scaled_rate / 5.0) var code = """ let utterance = new SpeechSynthesisUtterance("%s") utterance.rate = %s - """ % [text.replace("\n", " "), scaled_rate] + """ % [text.replace("\n", " "), javascript_rate] if interrupt: code += """ window.speechSynthesis.cancel() @@ -69,8 +112,8 @@ func stop(): JavaScript.eval("window.speechSynthesis.cancel()") func get_is_rate_supported(): - if Engine.get_singleton("AndroidTTS"): - return false + if Engine.has_singleton("AndroidTTS"): + return true elif OS.has_feature('JavaScript'): return true elif tts != null: diff --git a/src/lib.rs b/src/lib.rs index 786b783..91ad464 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,3 @@ -use std::u8; - use gdnative::init::*; use gdnative::*; use tts::{Features, TTS as Tts}; @@ -18,27 +16,69 @@ impl TTS { fn register_properties(builder: &ClassBuilder) { builder - .add_property::("rate") - .with_default(50) + .add_property("rate") .with_getter(|this: &TTS, _| match this.0.get_rate() { - Ok(rate) => rate / u8::MAX * 100, - _ => 0, + Ok(rate) => rate, + _ => 0., }) - .with_setter(|this: &mut TTS, _, mut v: u8| { - if v > 100 { - v = 100; - } - let mut v = v as f32; - v = v * u8::MAX as f32 / 100.; + .with_setter(|this: &mut TTS, _, v: f32| { let Features { rate: rate_supported, .. } = this.0.supported_features(); if rate_supported { - this.0.set_rate(v as u8).unwrap(); + let mut v = v; + if v < this.0.min_rate() { + v = this.0.min_rate(); + } else if v > this.0.max_rate() { + v = this.0.max_rate(); + } + this.0.set_rate(v).unwrap(); } }) - .done() + .done(); + builder + .add_property("min_rate") + .with_getter(|this: &TTS, _| { + let Features { + rate: rate_supported, + .. + } = this.0.supported_features(); + if rate_supported { + this.0.min_rate() + } else { + 0. + } + }) + .done(); + builder + .add_property("max_rate") + .with_getter(|this: &TTS, _| { + let Features { + rate: rate_supported, + .. + } = this.0.supported_features(); + if rate_supported { + this.0.max_rate() + } else { + 0. + } + }) + .done(); + builder + .add_property("normal_rate") + .with_getter(|this: &TTS, _| { + let Features { + rate: rate_supported, + .. + } = this.0.supported_features(); + if rate_supported { + this.0.normal_rate() + } else { + 0. + } + }) + .done(); } #[export]