mirror of
https://github.com/lightsoutgames/godot-tts
synced 2024-11-25 05:05:56 +00:00
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.
This commit is contained in:
parent
91faf9197c
commit
495c5eddad
|
@ -9,4 +9,4 @@ crate-type = ["cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
gdnative = "0.8"
|
gdnative = "0.8"
|
||||||
tts = "0.2"
|
tts = { git = "https://gitlab.com/ndarilek/tts-rs" }
|
||||||
|
|
69
TTS.gd
69
TTS.gd
|
@ -17,13 +17,49 @@ func _ready():
|
||||||
else:
|
else:
|
||||||
print_debug("TTS not available!")
|
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
|
var javascript_rate = 50
|
||||||
|
|
||||||
func set_rate(rate):
|
func set_rate(rate):
|
||||||
if rate < 0:
|
if rate < self.min_rate:
|
||||||
rate = 0
|
rate = self.min_rate
|
||||||
elif rate > 100:
|
elif rate > self.max_rate:
|
||||||
rate = 100
|
rate = self.max_rate
|
||||||
if tts != null:
|
if tts != null:
|
||||||
tts.rate = rate
|
tts.rate = rate
|
||||||
elif OS.has_feature('JavaScript'):
|
elif OS.has_feature('JavaScript'):
|
||||||
|
@ -39,20 +75,27 @@ func get_rate():
|
||||||
|
|
||||||
var rate setget set_rate, 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):
|
func speak(text, interrupt := true):
|
||||||
if tts != null:
|
if tts != null:
|
||||||
tts.speak(text, interrupt)
|
tts.speak(text, interrupt)
|
||||||
elif OS.has_feature('JavaScript'):
|
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 = """
|
var code = """
|
||||||
let utterance = new SpeechSynthesisUtterance("%s")
|
let utterance = new SpeechSynthesisUtterance("%s")
|
||||||
utterance.rate = %s
|
utterance.rate = %s
|
||||||
""" % [text.replace("\n", " "), scaled_rate]
|
""" % [text.replace("\n", " "), javascript_rate]
|
||||||
if interrupt:
|
if interrupt:
|
||||||
code += """
|
code += """
|
||||||
window.speechSynthesis.cancel()
|
window.speechSynthesis.cancel()
|
||||||
|
@ -69,8 +112,8 @@ func stop():
|
||||||
JavaScript.eval("window.speechSynthesis.cancel()")
|
JavaScript.eval("window.speechSynthesis.cancel()")
|
||||||
|
|
||||||
func get_is_rate_supported():
|
func get_is_rate_supported():
|
||||||
if Engine.get_singleton("AndroidTTS"):
|
if Engine.has_singleton("AndroidTTS"):
|
||||||
return false
|
return true
|
||||||
elif OS.has_feature('JavaScript'):
|
elif OS.has_feature('JavaScript'):
|
||||||
return true
|
return true
|
||||||
elif tts != null:
|
elif tts != null:
|
||||||
|
|
68
src/lib.rs
68
src/lib.rs
|
@ -1,5 +1,3 @@
|
||||||
use std::u8;
|
|
||||||
|
|
||||||
use gdnative::init::*;
|
use gdnative::init::*;
|
||||||
use gdnative::*;
|
use gdnative::*;
|
||||||
use tts::{Features, TTS as Tts};
|
use tts::{Features, TTS as Tts};
|
||||||
|
@ -18,27 +16,69 @@ impl TTS {
|
||||||
|
|
||||||
fn register_properties(builder: &ClassBuilder<Self>) {
|
fn register_properties(builder: &ClassBuilder<Self>) {
|
||||||
builder
|
builder
|
||||||
.add_property::<u8>("rate")
|
.add_property("rate")
|
||||||
.with_default(50)
|
|
||||||
.with_getter(|this: &TTS, _| match this.0.get_rate() {
|
.with_getter(|this: &TTS, _| match this.0.get_rate() {
|
||||||
Ok(rate) => rate / u8::MAX * 100,
|
Ok(rate) => rate,
|
||||||
_ => 0,
|
_ => 0.,
|
||||||
})
|
})
|
||||||
.with_setter(|this: &mut TTS, _, mut v: u8| {
|
.with_setter(|this: &mut TTS, _, v: f32| {
|
||||||
if v > 100 {
|
|
||||||
v = 100;
|
|
||||||
}
|
|
||||||
let mut v = v as f32;
|
|
||||||
v = v * u8::MAX as f32 / 100.;
|
|
||||||
let Features {
|
let Features {
|
||||||
rate: rate_supported,
|
rate: rate_supported,
|
||||||
..
|
..
|
||||||
} = this.0.supported_features();
|
} = this.0.supported_features();
|
||||||
if rate_supported {
|
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]
|
#[export]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user