From 446317bdd4604cc32fff4fcd8d671b4e7ee90016 Mon Sep 17 00:00:00 2001 From: bunnie Date: Wed, 9 Mar 2022 03:48:12 +0800 Subject: [PATCH] add speech rate library call and default setting 350 wpm was the requested default! --- Cargo.lock | 5 +++-- services/gam/Cargo.toml | 3 +++ services/gam/src/menu.rs | 14 ++++++++++++++ services/tts/Cargo.toml | 2 +- services/tts/src/api.rs | 2 ++ services/tts/src/lib.rs | 7 ++++++- services/tts/src/main.rs | 14 +++++++++++++- xtask/src/main.rs | 36 +++++++++++++++++++++--------------- 8 files changed, 63 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index adb379d75..8327da6e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -947,6 +947,7 @@ dependencies = [ "susres", "ticktimer-server", "trng", + "tts-frontend", "utralib", "xous", "xous-ipc 0.9.7", @@ -3099,9 +3100,9 @@ dependencies = [ [[package]] name = "xous-tts-backend" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b895859a53d60cf076ce5af2b0520390a5fada412fa5dd6e9b92e4c1b4020ce7" +checksum = "a2d0fd1ceeb73a0eb226efc0f772dd643c25bc59b04db4bb593b4273d7253624" dependencies = [ "log", "num-derive", diff --git a/services/gam/Cargo.toml b/services/gam/Cargo.toml index fff731b12..dbb7691b5 100644 --- a/services/gam/Cargo.toml +++ b/services/gam/Cargo.toml @@ -30,10 +30,13 @@ susres = {path = "../susres"} # used for the sleep now menu item enum_dispatch = "0.3.7" # used for trait-based dispatch off of multiple layout objects. locales = {path = "../../locales"} +tts-frontend = {path="../tts"} + [target.'cfg(not(any(windows,unix)))'.dependencies] utralib = {path = "../../utralib"} [features] debugprint = [] +tts = [] # default = ["debugprint"] # "debugprint" default = [] diff --git a/services/gam/src/menu.rs b/services/gam/src/menu.rs index 727ed5770..ad42125a5 100644 --- a/services/gam/src/menu.rs +++ b/services/gam/src/menu.rs @@ -11,6 +11,8 @@ use num_traits::*; use graphics_server::api::{PixelColor, TextBounds, DrawStyle, GlyphStyle}; +#[cfg(feature = "tts")] +use tts_frontend::*; #[derive(Debug)] pub struct Menu<'a> { pub sid: xous::SID, @@ -26,6 +28,8 @@ pub struct Menu<'a> { pub canvas_width: Option, pub helper_data: Option>, pub name: std::string::String, + #[cfg(feature = "tts")] + pub tts: TtsFrontend, } #[derive(Debug, num_derive::FromPrimitive, num_derive::ToPrimitive)] @@ -57,6 +61,8 @@ impl<'a> Menu<'a> { log::debug!("requesting content canvas for menu"); let canvas = gam.request_content_canvas(authtoken.unwrap()).expect("couldn't get my content canvas from GAM"); let line_height = gam.glyph_height_hint(GlyphStyle::Cjk).expect("couldn't get glyph height hint") as i16 + 2; + #[cfg(feature="tts")] + let tts = TtsFrontend::new(&xns).unwrap(); Menu { sid, gam, @@ -71,6 +77,8 @@ impl<'a> Menu<'a> { canvas_width: None, helper_data: None, name: std::string::String::from(name), + #[cfg(feature="tts")] + tts, } } pub fn activate(&self) { @@ -164,6 +172,8 @@ impl<'a> Menu<'a> { if with_marker { write!(item_tv.text, "\u{25B6}").unwrap(); + #[cfg(feature="tts")] + self.tts.tts_simple(item.name.as_str().unwrap()).unwrap(); } else { write!(item_tv.text, "\t").unwrap(); } @@ -269,6 +279,10 @@ impl<'a> Menu<'a> { } log::trace!("menu redraw##"); self.gam.redraw().unwrap(); + #[cfg(feature="tts")] + { + // self.tts.tts_simple(&self.name).unwrap(); + } } fn num_items(&self) -> usize { self.items.len() diff --git a/services/tts/Cargo.toml b/services/tts/Cargo.toml index 5da8d4957..bf158787a 100644 --- a/services/tts/Cargo.toml +++ b/services/tts/Cargo.toml @@ -17,7 +17,7 @@ num-derive = {version = "0.3.3", default-features = false} num-traits = {version = "0.2.14", default-features = false} rkyv = {version = "0.4.3", default-features = false, features = ["const_generics"]} # xous-tts-backend = {path="../../../tts-backend"} -xous-tts-backend = "0.1.2" +xous-tts-backend = "0.1.3" codec = {path = "../codec"} [target.'cfg(not(any(windows,unix)))'.dependencies] diff --git a/services/tts/src/api.rs b/services/tts/src/api.rs index b16dfec5c..41e093513 100644 --- a/services/tts/src/api.rs +++ b/services/tts/src/api.rs @@ -8,6 +8,8 @@ pub(crate) enum Opcode { CodecCb, /// Stops audio playback immediately. Does not stop wave generation. CodecStop, + /// Set words per minute + SetWordsPerMinute, /// Exits the server Quit, } diff --git a/services/tts/src/lib.rs b/services/tts/src/lib.rs index c78091c57..13c9e8228 100644 --- a/services/tts/src/lib.rs +++ b/services/tts/src/lib.rs @@ -2,7 +2,7 @@ pub mod api; pub use api::*; -use xous::CID; +use xous::{CID, send_message, Message}; use xous_ipc::Buffer; use num_traits::ToPrimitive; @@ -27,6 +27,11 @@ impl TtsFrontend { let buf = Buffer::into_buf(msg).or(Err(xous::Error::InternalError))?; buf.lend(self.conn, Opcode::TextToSpeech.to_u32().unwrap()).map(|_| ()) } + pub fn set_words_per_minute(&self, wpm: u32) -> Result<(), xous::Error> { + send_message(self.conn, + Message::new_scalar(Opcode::SetWordsPerMinute.to_usize().unwrap(), wpm as usize, 0, 0, 0) + ).map(|_| ()) + } } use core::sync::atomic::{AtomicU32, Ordering}; diff --git a/services/tts/src/main.rs b/services/tts/src/main.rs index 0552e73c6..430b3e8b8 100644 --- a/services/tts/src/main.rs +++ b/services/tts/src/main.rs @@ -13,6 +13,8 @@ use std::sync::{Arc, Mutex}; use std::sync::atomic::{AtomicBool, Ordering}; use std::collections::VecDeque; +const DEFAULT_WPM: u32 = 350; + #[derive(num_derive::FromPrimitive, num_derive::ToPrimitive, Debug)] pub(crate) enum WaveOp { Return, @@ -90,7 +92,13 @@ fn xmain() -> ! { } } }); - tts_be.tts_config(wav_sid.to_array(), WaveOp::Return.to_u32().unwrap(), None).unwrap(); + let mut wpm = DEFAULT_WPM; + tts_be.tts_config( + wav_sid.to_array(), + WaveOp::Return.to_u32().unwrap(), + None, + Some(wpm) + ).unwrap(); let mut just_initiated = false; loop { let msg = xous::receive_message(tts_sid).unwrap(); @@ -158,6 +166,10 @@ fn xmain() -> ! { log::info!("stop called. Immediate stop and loss of audio data."); codec.abort().unwrap(); } + Some(Opcode::SetWordsPerMinute) => msg_scalar_unpack!(msg, wpm_arg, _, _, _, { + wpm = wpm_arg as u32; + tts_be.tts_config(wav_sid.to_array(), WaveOp::Return.to_u32().unwrap(), None, Some(wpm)).unwrap(); + }), Some(Opcode::Quit) => { send_message(wav_cid, Message::new_blocking_scalar(WaveOp::Quit.to_usize().unwrap(), 0, 0, 0, 0) diff --git a/xtask/src/main.rs b/xtask/src/main.rs index cae3e4ae9..398d49905 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -199,21 +199,27 @@ fn main() -> Result<(), Box> { renode_image(false, &cbtest_pkgs, &[], None, None)? }, Some("tts") => { - println!("Fetching tts executable from build server..."); - let tmp_dir = tempfile::Builder::new().prefix("bins").tempdir()?; - let tts_exec_name = tmp_dir.path().join("espeak-embedded"); - let tts_exec_string = tts_exec_name.clone().into_os_string().into_string().unwrap(); - let mut tts_exec_file = OpenOptions::new() - .read(true) - .write(true) - .create(true) - .truncate(true) - .open(tts_exec_name).expect("Can't open our version file for writing"); - let mut freader = ureq::get("https://ci.betrusted.io/job/espeak-embedded/lastSuccessfulBuild/artifact/target/riscv32imac-unknown-xous-elf/release/espeak-embedded") - .call()? - .into_reader(); - std::io::copy(&mut freader, &mut tts_exec_file)?; - println!("TTS exec is {} bytes", tts_exec_file.metadata().unwrap().len()); + let tts_exec_string = if false { + println!("Fetching tts executable from build server..."); + let tmp_dir = tempfile::Builder::new().prefix("bins").tempdir()?; + let tts_exec_name = tmp_dir.path().join("espeak-embedded"); + let tts_exec_string = tts_exec_name.clone().into_os_string().into_string().unwrap(); + let mut tts_exec_file = OpenOptions::new() + .read(true) + .write(true) + .create(true) + .truncate(true) + .open(tts_exec_name).expect("Can't open our version file for writing"); + let mut freader = ureq::get("https://ci.betrusted.io/job/espeak-embedded/lastSuccessfulBuild/artifact/target/riscv32imac-unknown-xous-elf/release/espeak-embedded") + .call()? + .into_reader(); + std::io::copy(&mut freader, &mut tts_exec_file)?; + println!("TTS exec is {} bytes", tts_exec_file.metadata().unwrap().len()); + tts_exec_string + } else { + println!("****** WARNING: using local dev image. Do not check this configuration in! ******"); + "../espeak-embedded/target/riscv32imac-unknown-xous-elf/release/espeak-embedded".to_string() + }; let mut args = env::args(); args.nth(1);