1use crate::error::{CodecError, Result};
4use crate::types::{CodecType, SampleRate};
5
6pub fn validate_samples(samples: &[i16]) -> Result<()> {
8 if samples.is_empty() {
9 return Err(CodecError::invalid_format("Input samples cannot be empty"));
10 }
11 Ok(())
14}
15
16pub fn validate_encoded_data(data: &[u8]) -> Result<()> {
18 if data.is_empty() {
19 return Err(CodecError::invalid_format("Encoded data cannot be empty"));
20 }
21
22 if data.len() > 1024 * 1024 {
24 return Err(CodecError::invalid_format(format!(
25 "Encoded data too large: {} bytes",
26 data.len()
27 )));
28 }
29
30 Ok(())
31}
32
33pub fn validate_frame_size(codec_type: CodecType, frame_size: usize) -> Result<()> {
35 let expected_sizes = match codec_type {
36 CodecType::G711Pcmu | CodecType::G711Pcma => {
37 vec![80, 160, 240, 320]
39 }
40
41 CodecType::G729 | CodecType::G729A | CodecType::G729BA => {
42 vec![80]
44 }
45 CodecType::Opus => {
46 vec![120, 240, 480, 960, 1920, 2880]
48 }
49 };
50
51 if !expected_sizes.contains(&frame_size) {
52 return Err(CodecError::InvalidFrameSize {
53 expected: expected_sizes[0],
54 actual: frame_size,
55 });
56 }
57
58 Ok(())
59}
60
61pub fn validate_sample_rate(codec_type: CodecType, sample_rate: SampleRate) -> Result<()> {
63 let supported_rates = codec_type.supported_sample_rates();
64 let rate_hz = sample_rate.hz();
65
66 if !supported_rates.contains(&rate_hz) {
67 return Err(CodecError::InvalidSampleRate {
68 rate: rate_hz,
69 supported: supported_rates.to_vec(),
70 });
71 }
72
73 Ok(())
74}
75
76pub fn validate_channels(codec_type: CodecType, channels: u8) -> Result<()> {
78 let supported_channels = codec_type.supported_channels();
79
80 if !supported_channels.contains(&channels) {
81 return Err(CodecError::InvalidChannelCount {
82 channels,
83 supported: supported_channels.to_vec(),
84 });
85 }
86
87 Ok(())
88}
89
90pub fn validate_bitrate(codec_type: CodecType, bitrate: u32) -> Result<()> {
92 let (min_bitrate, max_bitrate) = codec_type.bitrate_range();
93
94 if bitrate < min_bitrate || bitrate > max_bitrate {
95 return Err(CodecError::InvalidBitrate {
96 bitrate,
97 min: min_bitrate,
98 max: max_bitrate,
99 });
100 }
101
102 Ok(())
103}
104
105pub fn validate_buffer_sizes(
107 input_size: usize,
108 output_size: usize,
109 expected_ratio: f32,
110) -> Result<()> {
111 let expected_output_size = (input_size as f32 * expected_ratio) as usize;
112
113 if output_size < expected_output_size {
114 return Err(CodecError::BufferTooSmall {
115 needed: expected_output_size,
116 actual: output_size,
117 });
118 }
119
120 Ok(())
121}
122
123pub fn validate_channel_alignment(samples: &[i16], channels: u8) -> Result<()> {
125 if samples.len() % channels as usize != 0 {
126 return Err(CodecError::invalid_format(format!(
127 "Sample count {} not divisible by channel count {}",
128 samples.len(),
129 channels
130 )));
131 }
132
133 Ok(())
134}
135
136pub fn validate_g711_frame(samples: &[i16], expected_frame_size: usize) -> Result<()> {
138 validate_samples(samples)?;
139
140 if samples.len() != expected_frame_size {
141 return Err(CodecError::InvalidFrameSize {
142 expected: expected_frame_size,
143 actual: samples.len(),
144 });
145 }
146
147 Ok(())
148}
149
150pub fn validate_g722_frame(samples: &[i16], expected_frame_size: usize) -> Result<()> {
152 validate_samples(samples)?;
153
154 if samples.len() != expected_frame_size {
155 return Err(CodecError::InvalidFrameSize {
156 expected: expected_frame_size,
157 actual: samples.len(),
158 });
159 }
160
161 if samples.len() % 2 != 0 {
163 return Err(CodecError::invalid_format(
164 "G.722 requires even number of samples for QMF processing",
165 ));
166 }
167
168 Ok(())
169}
170
171pub fn validate_g729_frame(samples: &[i16]) -> Result<()> {
173 validate_samples(samples)?;
174
175 if samples.len() != 80 {
177 return Err(CodecError::InvalidFrameSize {
178 expected: 80,
179 actual: samples.len(),
180 });
181 }
182
183 Ok(())
184}
185
186pub fn validate_opus_frame(samples: &[i16], sample_rate: SampleRate) -> Result<()> {
188 validate_samples(samples)?;
189
190 let rate_hz = sample_rate.hz();
191 let frame_size = samples.len();
192
193 let valid_frame_sizes = match rate_hz {
195 8000 => vec![20, 40, 80, 160, 320, 480],
196 12000 => vec![30, 60, 120, 240, 480, 720],
197 16000 => vec![40, 80, 160, 320, 640, 960],
198 24000 => vec![60, 120, 240, 480, 960, 1440],
199 48000 => vec![120, 240, 480, 960, 1920, 2880],
200 _ => {
201 return Err(CodecError::InvalidSampleRate {
202 rate: rate_hz,
203 supported: vec![8000, 12000, 16000, 24000, 48000],
204 })
205 }
206 };
207
208 if !valid_frame_sizes.contains(&frame_size) {
209 return Err(CodecError::InvalidFrameSize {
210 expected: valid_frame_sizes[0],
211 actual: frame_size,
212 });
213 }
214
215 Ok(())
216}
217
218pub fn validate_buffer_compatibility(
220 input: &[i16],
221 output: &[u8],
222 compression_ratio: f32,
223) -> Result<()> {
224 let expected_output_size = (input.len() as f32 * compression_ratio) as usize;
225
226 if output.len() < expected_output_size {
227 return Err(CodecError::BufferTooSmall {
228 needed: expected_output_size,
229 actual: output.len(),
230 });
231 }
232
233 Ok(())
234}
235
236pub fn validate_simd_alignment(data: &[i16]) -> Result<()> {
238 let ptr = data.as_ptr() as usize;
239
240 if ptr % 16 != 0 {
242 tracing::debug!("Data not aligned for SIMD operations, falling back to scalar");
243 }
244
245 Ok(())
246}
247
248#[cfg(test)]
249mod tests {
250 use super::*;
251 use crate::types::SampleRate;
252
253 #[test]
254 fn test_validate_samples() {
255 let valid_samples = vec![0, 1000, -1000, 16000, -16000];
256 assert!(validate_samples(&valid_samples).is_ok());
257
258 let empty_samples: Vec<i16> = vec![];
259 assert!(validate_samples(&empty_samples).is_err());
260 }
261
262 #[test]
263 fn test_validate_encoded_data() {
264 let valid_data = vec![0u8, 127, 255, 64, 192];
265 assert!(validate_encoded_data(&valid_data).is_ok());
266
267 let empty_data: Vec<u8> = vec![];
268 assert!(validate_encoded_data(&empty_data).is_err());
269
270 let too_large_data = vec![0u8; 2 * 1024 * 1024]; assert!(validate_encoded_data(&too_large_data).is_err());
272 }
273
274 #[test]
275 fn test_validate_frame_size() {
276 assert!(validate_frame_size(CodecType::G711Pcmu, 160).is_ok());
278 assert!(validate_frame_size(CodecType::G711Pcmu, 123).is_err());
279
280 assert!(validate_frame_size(CodecType::G729, 80).is_ok());
282 assert!(validate_frame_size(CodecType::G729, 160).is_err());
283 }
284
285 #[test]
286 fn test_validate_sample_rate() {
287 assert!(validate_sample_rate(CodecType::G711Pcmu, SampleRate::Rate8000).is_ok());
289 assert!(validate_sample_rate(CodecType::G711Pcmu, SampleRate::Rate48000).is_err());
290
291 assert!(validate_sample_rate(CodecType::Opus, SampleRate::Rate8000).is_ok());
293 assert!(validate_sample_rate(CodecType::Opus, SampleRate::Rate48000).is_ok());
294 }
295
296 #[test]
297 fn test_validate_channels() {
298 assert!(validate_channels(CodecType::G711Pcmu, 1).is_ok());
300 assert!(validate_channels(CodecType::G711Pcmu, 2).is_err());
301
302 assert!(validate_channels(CodecType::Opus, 1).is_ok());
304 assert!(validate_channels(CodecType::Opus, 2).is_ok());
305 assert!(validate_channels(CodecType::Opus, 3).is_err());
306 }
307
308 #[test]
309 fn test_validate_bitrate() {
310 assert!(validate_bitrate(CodecType::G711Pcmu, 64000).is_ok());
312 assert!(validate_bitrate(CodecType::G711Pcmu, 128000).is_err());
313
314 assert!(validate_bitrate(CodecType::Opus, 32000).is_ok());
316 assert!(validate_bitrate(CodecType::Opus, 600000).is_err());
317 }
318
319 #[test]
320 fn test_validate_buffer_sizes() {
321 assert!(validate_buffer_sizes(160, 80, 0.5).is_ok());
323 assert!(validate_buffer_sizes(160, 40, 0.5).is_err());
324 }
325
326 #[test]
327 fn test_validate_channel_alignment() {
328 let mono_samples = vec![0, 1, 2, 3, 4]; assert!(validate_channel_alignment(&mono_samples, 1).is_ok());
330 assert!(validate_channel_alignment(&mono_samples, 2).is_err());
331
332 let stereo_samples = vec![0, 1, 2, 3]; assert!(validate_channel_alignment(&stereo_samples, 2).is_ok());
334 }
335
336 #[test]
337 fn test_codec_specific_validation() {
338 let g711_frame = vec![0i16; 160];
340 assert!(validate_g711_frame(&g711_frame, 160).is_ok());
341 assert!(validate_g711_frame(&g711_frame, 80).is_err());
342
343 let g729_frame = vec![0i16; 80];
345 assert!(validate_g729_frame(&g729_frame).is_ok());
346
347 let wrong_g729_frame = vec![0i16; 160];
348 assert!(validate_g729_frame(&wrong_g729_frame).is_err());
349 }
350
351 #[test]
352 fn test_buffer_compatibility() {
353 let input = vec![0i16; 160];
354 let output = vec![0u8; 80];
355
356 assert!(validate_buffer_compatibility(&input, &output, 0.5).is_ok());
358
359 let small_output = vec![0u8; 40];
360 assert!(validate_buffer_compatibility(&input, &small_output, 0.5).is_err());
361 }
362}