1use anyhow::{ensure, Result};
4unsafe extern "C" {
5 fn aw_silk_encode(
6 pcm: *const i16,
7 samples: i32,
8 out: *mut u8,
9 capacity: i32,
10 length: *mut i32,
11 ) -> i32;
12 fn aw_silk_decode(
13 input: *const u8,
14 length: i32,
15 pcm: *mut i16,
16 capacity: i32,
17 samples: *mut i32,
18 ) -> i32;
19}
20pub const SAMPLE_RATE: u32 = 16000;
21pub const BIT_RATE: u32 = 16000;
23pub const FRAME_MS: u32 = 20;
25pub const MAX_NOTE_MS: u32 = 60_000;
27pub const MAX_SAMPLES: usize = (MAX_NOTE_MS / 1000 * SAMPLE_RATE) as usize;
28pub const MAX_STREAM_BYTES: usize = 200 * 1024;
30pub const MAX_NOTE_BYTES: usize = 10
36 + (MAX_NOTE_MS / FRAME_MS) as usize * (2 + (BIT_RATE / 8 * FRAME_MS / 1000) as usize * 3 / 2);
37const _: () = assert!(MAX_NOTE_BYTES <= MAX_STREAM_BYTES);
38pub fn encode(pcm: &[i16]) -> Result<Vec<u8>> {
39 ensure!(
40 !pcm.is_empty() && pcm.len() <= MAX_SAMPLES,
41 "voice_duration_limit"
42 );
43 let mut out = vec![0u8; MAX_STREAM_BYTES];
44 let mut length = 0i32;
45 let status = unsafe {
48 aw_silk_encode(
49 pcm.as_ptr(),
50 pcm.len() as i32,
51 out.as_mut_ptr(),
52 out.len() as i32,
53 &mut length,
54 )
55 };
56 ensure!(
57 status == 0 && length >= 12 && length as usize <= out.len(),
58 "silk_encode_failed"
59 );
60 out.truncate(length as usize);
61 validate_framing(&out)?;
62 Ok(out)
63}
64pub fn validate_framing(input: &[u8]) -> Result<u32> {
65 ensure!(
66 input.len() >= 12
67 && input.len() <= MAX_STREAM_BYTES
68 && input[0] <= 3
69 && input[1..10] == *b"#!SILK_V3",
70 "invalid_silk_stream"
71 );
72 let mut p = 10;
73 let mut packets = 0u32;
74 while p < input.len() {
75 ensure!(p + 2 <= input.len(), "invalid_silk_packet");
76 let n = i16::from_le_bytes(input[p..p + 2].try_into()?) as i32;
77 p += 2;
78 ensure!(
79 n > 0 && n <= 5120 && n as usize <= input.len() - p,
80 "invalid_silk_packet"
81 );
82 p += n as usize;
83 packets += 1;
84 ensure!(packets <= MAX_NOTE_MS / FRAME_MS, "voice_duration_limit");
85 }
86 ensure!(packets > 0, "empty_silk_stream");
87 Ok(packets * FRAME_MS)
88}
89pub fn decode(input: &[u8]) -> Result<Vec<i16>> {
90 validate_framing(input)?;
91 let mut pcm = vec![0i16; MAX_SAMPLES];
92 let mut samples = 0i32;
93 let status = unsafe {
96 aw_silk_decode(
97 input.as_ptr(),
98 input.len() as i32,
99 pcm.as_mut_ptr(),
100 pcm.len() as i32,
101 &mut samples,
102 )
103 };
104 ensure!(
105 status == 0 && samples > 0 && samples as usize <= pcm.len(),
106 "silk_decode_failed"
107 );
108 pcm.truncate(samples as usize);
109 Ok(pcm)
110}
111pub fn wav(pcm: &[i16]) -> Result<Vec<u8>> {
112 ensure!(pcm.len() <= MAX_SAMPLES, "voice_duration_limit");
113 let n = u32::try_from(pcm.len() * 2)?;
114 let mut out = Vec::with_capacity(44 + n as usize);
115 out.extend(b"RIFF");
116 out.extend((36 + n).to_le_bytes());
117 out.extend(b"WAVEfmt ");
118 out.extend(16u32.to_le_bytes());
119 out.extend(1u16.to_le_bytes());
120 out.extend(1u16.to_le_bytes());
121 out.extend(SAMPLE_RATE.to_le_bytes());
122 out.extend((SAMPLE_RATE * 2).to_le_bytes());
123 out.extend(2u16.to_le_bytes());
124 out.extend(16u16.to_le_bytes());
125 out.extend(b"data");
126 out.extend(n.to_le_bytes());
127 for s in pcm {
128 out.extend(s.to_le_bytes());
129 }
130 Ok(out)
131}
132#[cfg(test)]
133mod tests {
134 use super::*;
135 #[test]
136 fn independent_fresh_tones_encode_decode() {
137 let pcm = (0..16000)
138 .map(|i| ((i as f64 * 440.0 * std::f64::consts::TAU / 16000.0).sin() * 10000.0) as i16)
139 .collect::<Vec<_>>();
140 let encoded = encode(&pcm).unwrap();
141 assert_eq!(validate_framing(&encoded).unwrap(), 1000);
142 let decoded = decode(&encoded).unwrap();
143 assert_eq!(decoded.len(), pcm.len());
144 assert!(decoded.iter().any(|s| s.abs() > 1000));
145 assert_eq!(&wav(&decoded).unwrap()[..4], b"RIFF");
146 }
147 #[test]
148 fn maximum_note_stays_within_derived_byte_bound() {
149 assert_eq!(MAX_SAMPLES, 960_000);
150 assert_eq!(MAX_NOTE_BYTES, 186_010);
151 let mut seed = 0x9e37_79b9_7f4a_7c15u64;
154 let noise = (0..MAX_SAMPLES)
155 .map(|_| {
156 seed = seed
157 .wrapping_mul(6364136223846793005)
158 .wrapping_add(1442695040888963407);
159 (seed >> 48) as u16 as i16
160 })
161 .collect::<Vec<_>>();
162 let harmonic = (0..MAX_SAMPLES)
163 .map(|i| {
164 let t = i as f64 / SAMPLE_RATE as f64;
165 let f0 = 120.0 + 40.0 * (t * 3.0).sin();
166 let v = (1..30)
167 .map(|h| (t * f0 * h as f64 * std::f64::consts::TAU).sin() / h as f64)
168 .sum::<f64>();
169 (v * (t * 4.0).sin().abs() * 8000.0) as i16
170 })
171 .collect::<Vec<_>>();
172 for pcm in [noise, harmonic] {
173 let encoded = encode(&pcm).unwrap();
174 assert!(encoded.len() <= MAX_NOTE_BYTES, "{}", encoded.len());
175 assert_eq!(validate_framing(&encoded).unwrap(), MAX_NOTE_MS);
176 }
177 let too_long = vec![0i16; MAX_SAMPLES + 1];
178 assert!(encode(&too_long).is_err());
179 }
180 #[test]
181 fn malformed_packet_refused_before_ffi() {
182 for input in [
183 vec![],
184 [vec![2], b"#!SILK_V3".to_vec(), vec![0, 0]].concat(),
185 [vec![2], b"#!SILK_V3".to_vec(), vec![255, 255]].concat(),
186 ] {
187 assert!(decode(&input).is_err());
188 }
189 }
190}