1use std::mem::size_of;
2use include_data::include_data;
3
4const BYTE_SIZE: usize = 20810;
7
8type PcmSample = i16;
9
10const SAMPLE_SIZE: usize = size_of::<PcmSample>();
12
13const MAX_LETTERS: usize = 32;
15
16const LETTER_SAMPLES: usize = BYTE_SIZE/SAMPLE_SIZE;
18
19const MAX_BUFFER_SIZE: usize = BYTE_SIZE * MAX_LETTERS;
21
22macro_rules! import_raw {
27 ($var_name:ident, $file_name:literal) => {
28 const $var_name: [PcmSample; BYTE_SIZE/2] = include_data!($file_name);
29 }
30}
31
32import_raw!(A, "../data/a.raw");
33import_raw!(B, "../data/b.raw");
34import_raw!(C, "../data/c.raw");
35import_raw!(D, "../data/d.raw");
36import_raw!(E, "../data/e.raw");
37import_raw!(F, "../data/f.raw");
38import_raw!(G, "../data/g.raw");
39import_raw!(H, "../data/h.raw");
40import_raw!(I, "../data/i.raw");
41import_raw!(J, "../data/j.raw");
42import_raw!(K, "../data/k.raw");
43import_raw!(L, "../data/l.raw");
44import_raw!(M, "../data/m.raw");
45import_raw!(N, "../data/n.raw");
46import_raw!(O, "../data/o.raw");
47import_raw!(P, "../data/p.raw");
48import_raw!(Q, "../data/q.raw");
49import_raw!(R, "../data/r.raw");
50import_raw!(S, "../data/s.raw");
51import_raw!(T, "../data/t.raw");
52import_raw!(U, "../data/u.raw");
53import_raw!(V, "../data/v.raw");
54import_raw!(W, "../data/w.raw");
55import_raw!(X, "../data/x.raw");
56import_raw!(Y, "../data/y.raw");
57import_raw!(Z, "../data/z.raw");
58import_raw!(SPACE, "../data/space.raw");
59
60const fn letter_to_pcm(c: char) -> Option<[PcmSample; BYTE_SIZE/2]> {
61 match c {
62 'a' => Some(A),
63 'b' => Some(B),
64 'c' => Some(C),
65 'd' => Some(D),
66 'e' => Some(E),
67 'f' => Some(F),
68 'g' => Some(G),
69 'h' => Some(H),
70 'i' => Some(I),
71 'j' => Some(J),
72 'k' => Some(K),
73 'l' => Some(L),
74 'm' => Some(M),
75 'n' => Some(N),
76 'o' => Some(O),
77 'p' => Some(P),
78 'q' => Some(Q),
79 'r' => Some(R),
80 's' => Some(S),
81 't' => Some(T),
82 'u' => Some(U),
83 'v' => Some(V),
84 'w' => Some(W),
85 'x' => Some(X),
86 'y' => Some(Y),
87 'z' => Some(Z),
88 ' ' => Some(SPACE),
89 _ => None
90 }
91}
92
93pub fn tts<S: AsRef<str>>(s: S, buf: &mut [PcmSample; MAX_BUFFER_SIZE]) -> Option<usize> {
103 if s.as_ref().len() > MAX_LETTERS {
104 return None;
105 }
106 Some(
107 s
108 .as_ref()
109 .chars()
110 .fold(0, |offset: usize, ch| {
111 letter_to_pcm(ch).unwrap()
112 .iter()
113 .enumerate()
114 .for_each(|(i, pcm)| buf[(offset*BYTE_SIZE)+i] = *pcm);
115 offset+1
116 })
117 )
118}
119
120#[cfg(test)]
121mod tests {
122 use super::MAX_BUFFER_SIZE;
123 use super::tts;
124 use super::BYTE_SIZE;
125 use super::A;
126 use super::PcmSample;
127 use super::LETTER_SAMPLES;
128
129 #[test]
130 fn check_one_letter_str() {
131 let mut buf: [PcmSample; MAX_BUFFER_SIZE] = [0; MAX_BUFFER_SIZE];
132 let conv = String::from("a");
133 let bytes = tts(conv, &mut buf);
134 assert_eq!(bytes.unwrap(), 1);
135 let created_slice = &buf[0..LETTER_SAMPLES];
136 assert_eq!(created_slice.len(), A.len());
137 assert_eq!(created_slice, A);
138 }
139 #[test]
140 fn check_one_word_str() {
141 let mut buf: [PcmSample; MAX_BUFFER_SIZE] = [0; MAX_BUFFER_SIZE];
142 let conv = String::from("hello");
143 let bytes = tts(conv, &mut buf);
144 assert_eq!(bytes.unwrap(), 5);
145 }
146 #[test]
147 fn check_multi_word() {
148 let mut buf: [PcmSample; MAX_BUFFER_SIZE] = [0; MAX_BUFFER_SIZE];
149 let conv = String::from("hello world");
150 let bytes = tts(conv, &mut buf);
151 assert_eq!(bytes.unwrap(), 11);
152 }
153}