novel_tts/queue/
queue_output.rs1use super::{Signal, SoundOrSilence, THRESHOLD, TTSQueueInput};
7use anyhow::{Result, anyhow};
8use rodio::{Sample, Source, source::Zero};
9use std::sync::Arc;
10
11pub struct TTSQueueOutput<T>
19where
20 T: Source + Send + Clone,
21{
22 pub current: SoundOrSilence<T>,
24
25 pub current_signal: Signal,
28
29 pub index: usize,
31
32 pub input: Arc<TTSQueueInput<T>>,
34
35 pub is_initial: bool,
38}
39
40impl<T> TTSQueueOutput<T>
41where
42 T: Source + Send + Clone,
43{
44 pub fn new(input: Arc<TTSQueueInput<T>>, index: usize) -> Self {
53 let (sound, signal, is_initial) =
55 if let Some((sound, signal)) = input.sounds.lock().unwrap().get(index) {
56 (SoundOrSilence::Sound(sound.clone()), signal.clone(), false)
58 } else {
59 let silence = Zero::new_samples(1, 44100, THRESHOLD);
61 (SoundOrSilence::Silence(silence), None, true)
62 };
63
64 Self {
65 current: sound,
66 current_signal: signal,
67 index,
68 input,
69 is_initial,
70 }
71 }
72
73 pub fn go_next(&mut self) -> Result<()> {
82 if let Some(sender) = self.current_signal.take() {
84 sender.try_send(true).ok();
86 }
87
88 let next_index = if self.is_initial {
90 self.index
92 } else {
93 self.index + 1
95 };
96
97 if let Some((sound, signal)) = self.input.sounds.lock().unwrap().get(next_index) {
99 self.current = SoundOrSilence::Sound(sound.clone());
101 self.current_signal = signal.clone();
102 self.index = next_index;
103 self.is_initial = false;
104 } else {
105 if self.input.is_finished() {
107 return Err(anyhow!("No more sounds in the queue"));
109 }
110 let silence = Zero::new_samples(1, 44100, THRESHOLD);
112 self.current = SoundOrSilence::Silence(silence);
113 }
114
115 if let Some(sender) = &self.current_signal {
117 sender.try_send(false).ok();
119 }
120
121 Ok(())
122 }
123}
124
125impl<T> Iterator for TTSQueueOutput<T>
126where
127 T: Source + Send + Clone,
128{
129 type Item = Sample;
130
131 fn next(&mut self) -> Option<Self::Item> {
132 loop {
134 if let Some(sample) = self.current.next() {
136 return Some(sample);
137 }
138
139 if self.go_next().is_err() {
141 return None;
143 }
144 }
145 }
146
147 fn size_hint(&self) -> (usize, Option<usize>) {
148 (self.current.size_hint().0, None)
150 }
151}
152
153impl<T> Source for TTSQueueOutput<T>
154where
155 T: Source + Send + Clone,
156{
157 fn current_span_len(&self) -> Option<usize> {
171 if let Some(val) = self.current.current_span_len() {
173 if val != 0 {
174 return Some(val);
175 } else if !self.input.is_finished() && self.input.sounds.lock().unwrap().is_empty() {
176 return Some(THRESHOLD);
178 }
179 }
180
181 let (lower_bound, _) = self.current.size_hint();
183 if lower_bound > 0 {
185 return Some(lower_bound);
186 }
187
188 Some(THRESHOLD)
190 }
191
192 fn channels(&self) -> rodio::ChannelCount {
194 self.current.channels()
195 }
196
197 fn sample_rate(&self) -> rodio::SampleRate {
199 self.current.sample_rate()
200 }
201
202 fn total_duration(&self) -> Option<std::time::Duration> {
204 None
205 }
206}