win_wrap/
tts.rs

1/*
2 * Copyright (c) 2024. The RigelA open source project team and
3 * its contributors reserve all rights.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software distributed under the
10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and limitations under the License.
12 */
13
14use std::sync::Arc;
15
16use windows::{
17    core::HSTRING, Media::SpeechSynthesis::SpeechSynthesizer, Storage::Streams::DataReader,
18};
19
20#[derive(Clone, Debug)]
21pub struct Sapi5TtsSynthesizer {
22    synth: Arc<SpeechSynthesizer>,
23}
24
25impl Sapi5TtsSynthesizer {
26    /**
27    创建一个TTS对象(语音合成,SAPI5)
28    */
29    pub fn new() -> Self {
30        // 创建语音合成器
31        let synth = SpeechSynthesizer::new().expect("Can't create the speech synthesizer.");
32        Self {
33            synth: synth.into(),
34        }
35    }
36
37    /**
38    设置语速。
39    某些语音的最低语速快于 0.5,最大语速低于 6.0。
40    说话率不能直接转换为每分钟单词数,因为每种语音和语言的默认语速可能不同。
41    <https://learn.microsoft.com/zh-cn/uwp/api/windows.media.speechsynthesis.speechsynthesizeroptions.speakingrate?view=winrt-22621#windows-media-speechsynthesis-speechsynthesizeroptions-speakingrate>
42    */
43    pub fn set_speed(&self, speed: f64) {
44        let options = self.synth.Options().unwrap();
45        options
46            .SetSpeakingRate(speed)
47            .expect("Can't set the speed value.");
48    }
49
50    /// 设置语调
51    pub fn set_pitch(&self, pitch: f64) {
52        let options = self.synth.Options().unwrap();
53        options
54            .SetAudioPitch(pitch)
55            .expect("Can't set the pitch value.");
56    }
57
58    /// 设置音量
59    pub fn set_volume(&self, volume: f64) {
60        let options = self.synth.Options().unwrap();
61        options
62            .SetAudioVolume(volume)
63            .expect("Can't set the volume value.");
64    }
65
66    /**
67    获取所有已安装的语音合成发音人。
68    */
69    pub fn get_voice_list(&self) -> Vec<(String, String)> {
70        let mut v: Vec<(String, String)> = vec![];
71        for x in SpeechSynthesizer::AllVoices().unwrap() {
72            v.push((
73                x.Id().unwrap().to_string(),
74                x.DisplayName().unwrap().to_string(),
75            ))
76        }
77        v
78    }
79
80    /**
81    设置发音人。
82    `voice` 发音人id。
83    */
84    pub fn set_voice(&self, voice: String) {
85        for x in SpeechSynthesizer::AllVoices().unwrap() {
86            if x.Id().unwrap().to_string() == voice {
87                self.synth.SetVoice(&x).unwrap_or(());
88                return;
89            }
90        }
91    }
92
93    /**
94    合成语音。
95    此函数是异步函数,需要使用.await。
96    `text` 要朗读的文字。
97    */
98    pub fn synth(&self, text: &str, recv: impl Fn(Vec<u8>) -> bool) -> Option<[u8; 44]> {
99        let Ok(stream) = self.synth.SynthesizeTextToStreamAsync(&HSTRING::from(text)) else {
100            return None;
101        };
102        let Ok(stream) = stream.get() else {
103            return None;
104        };
105
106        let Ok(size) = stream.Size() else {
107            return None;
108        };
109        let Ok(reader) = DataReader::CreateDataReader(&stream) else {
110            return None;
111        };
112        let _ = reader.LoadAsync(size as u32);
113
114        // 跳过音频文件头的44个字节
115        let mut head: [u8; 44] = [0; 44];
116        reader.ReadBytes(&mut head).unwrap();
117        let mut last_len = size as u32 - 44;
118        let mut buffer: [u8; 3200] = [0; 3200];
119        loop {
120            if reader.ReadBytes(&mut buffer).is_err() {
121                break;
122            }
123            match reader.UnconsumedBufferLength() {
124                Ok(len) if last_len != len => {
125                    if !recv(buffer[0..(last_len - len) as usize].to_vec()) {
126                        break;
127                    }
128                    last_len = len;
129                }
130                _ => continue,
131            }
132        }
133        Some(head)
134    }
135}
136
137#[cfg(test)]
138mod test_tts {
139    use crate::tts::Sapi5TtsSynthesizer;
140
141    #[test]
142    fn main() {
143        let synth = Sapi5TtsSynthesizer::new();
144        let (tx, rx) = std::sync::mpsc::channel();
145        synth.synth("你好呀,我们是一群追求梦想的人。", move |data| {
146            for i in data {
147                let _ = tx.send(i);
148            }
149            true
150        }).unwrap();
151        let v = rx.iter().collect::<Vec<_>>();
152        dbg!(v.len());
153    }
154}