audioadapter_sample/readwrite.rs
1use crate::sample::*;
2use num_traits::{ToPrimitive, float::FloatCore};
3use std::io;
4
5/// A trait that extends [std::io::Read] with methods for reading samples directly.
6pub trait ReadSamples: io::Read {
7 /// Read a single sample from the underlying reader.
8 ///
9 /// This method reads a chunk of bytes from the underlying reader,
10 /// and interprets it as a sample of type `T`.
11 ///
12 /// # Type Parameters
13 ///
14 /// * `T`: A type implementing the `BytesSample` trait, defining the format of the sample to read.
15 ///
16 /// # Returns
17 ///
18 /// * `io::Result<T>`: The read sample, or an error if reading failed.
19 ///
20 /// # Errors
21 ///
22 /// This function will return an error if:
23 ///
24 /// * The underlying reader returns an error.
25 /// * The number of bytes read is not sufficient to represent a complete sample.
26 fn read_sample<T: BytesSample>(&mut self) -> io::Result<T> {
27 let mut sample: T = unsafe { std::mem::zeroed() };
28 self.read_exact(sample.as_mut_slice())?;
29 Ok(sample)
30 }
31
32 /// Read a single sample and return it as a numeric type.
33 ///
34 /// This method reads a chunk of bytes from the underlying reader,
35 /// interprets it as a sample of type `T`, and returns the sample
36 /// converted to its associated `NumericType`.
37 ///
38 /// # Type Parameters
39 ///
40 /// * `T`: A type implementing the `BytesSample` trait, defining the format of the sample to read.
41 ///
42 /// # Returns
43 ///
44 /// * `io::Result<T::NumericType>`: The sample as a number, or an error if reading failed.
45 ///
46 /// # Errors
47 ///
48 /// This function will return an error if:
49 ///
50 /// * The underlying reader returns an error.
51 /// * The number of bytes read is not sufficient to represent a complete sample.
52 fn read_number<T: BytesSample>(&mut self) -> io::Result<T::NumericType> {
53 let sample = self.read_sample::<T>()?;
54 Ok(sample.to_number())
55 }
56
57 /// Read a single sample and convert it to a floating-point number.
58 ///
59 /// This method reads a chunk of bytes from the underlying reader,
60 /// interprets it as a sample of type `T`, and returns the sample
61 /// converted to a floating-point number of type `U`. The conversion
62 /// uses the `to_scaled_float` method from the `RawSample` trait,
63 /// ensuring that the float is scaled between -1.0 and 1.0.
64 ///
65 /// # Type Parameters
66 ///
67 /// * `T`: A type implementing both `RawSample` and `BytesSample`, defining the format of the sample to read.
68 /// * `U`: A floating-point type implementing `FloatCore` and `ToPrimitive`, representing the desired output format.
69 ///
70 /// # Returns
71 ///
72 /// * `io::Result<U>`: The converted sample as a float, or an error if reading failed.
73 ///
74 /// # Errors
75 ///
76 /// This function will return an error if:
77 ///
78 /// * The underlying reader returns an error.
79 /// * The number of bytes read is not sufficient to represent a complete sample.
80 fn read_converted<T: RawSample + BytesSample, U: FloatCore + ToPrimitive>(
81 &mut self,
82 ) -> io::Result<U> {
83 let sample = self.read_sample::<T>()?;
84 Ok(sample.to_scaled_float::<U>())
85 }
86
87 /// Read multiple samples into a slice.
88 ///
89 /// This method attempts to read enough bytes from the underlying reader to
90 /// fill the buffer `buf` with samples of type `T`. It reads samples one at a time,
91 /// populating the buffer in order.
92 ///
93 /// # Type Parameters
94 ///
95 /// * `T`: A type implementing the `BytesSample` trait, defining the format of the samples to read.
96 ///
97 /// # Arguments
98 ///
99 /// * `buf`: A mutable slice where the samples will be stored.
100 ///
101 /// # Errors
102 ///
103 /// This function will return an error if:
104 ///
105 /// * The underlying reader returns an error.
106 /// * The number of bytes read is not sufficient to represent a complete sample.
107 /// * The end of the reader is reached before all samples have been read.
108 fn read_samples_exact<T: BytesSample>(&mut self, buf: &mut [T]) -> io::Result<()> {
109 for sample in buf.iter_mut() {
110 *sample = self.read_sample()?;
111 }
112 Ok(())
113 }
114
115 /// Read multiple samples and store them as numeric types in a provided buffer.
116 ///
117 /// This method reads a sequence of samples from the underlying reader and
118 /// stores them in the provided buffer `buf`. Each sample is read and
119 /// interpreted as a type `T`, then converted to its associated `NumericType`
120 /// before being stored in the buffer.
121 ///
122 /// # Type Parameters
123 ///
124 /// * `T`: A type implementing the `BytesSample` trait, defining the format of the samples to read.
125 ///
126 /// # Arguments
127 ///
128 /// * `buf`: A mutable slice where the samples will be stored. The length of the slice determines how many samples are read.
129 ///
130 /// # Returns
131 ///
132 /// * `io::Result<()>`: Ok(()) if all samples were read successfully.
133 ///
134 /// # Errors
135 ///
136 /// This function will return an error if:
137 ///
138 /// * The underlying reader returns an error.
139 /// * The number of bytes read is not sufficient to represent a complete sample.
140 /// * The end of the reader is reached before all samples have been read.
141 fn read_numbers_exact<T: BytesSample>(&mut self, buf: &mut [T::NumericType]) -> io::Result<()> {
142 for sample in buf.iter_mut() {
143 *sample = self.read_number::<T>()?;
144 }
145 Ok(())
146 }
147
148 /// Read multiple samples, convert them to floats, and store them in a provided buffer.
149 ///
150 /// This method reads a sequence of samples from the underlying reader,
151 /// converts each sample to a floating-point number of type `U`, and
152 /// stores the results in the provided buffer `buf`.
153 ///
154 /// # Type Parameters
155 ///
156 /// * `T`: A type implementing both `RawSample` and `BytesSample`, defining the format of the samples to read.
157 /// * `U`: A floating-point type implementing `FloatCore` and `ToPrimitive`, representing the desired output format.
158 ///
159 /// # Arguments
160 ///
161 /// * `buf`: A mutable slice where the converted samples will be stored. The length of the slice determines how many samples are read.
162 ///
163 /// # Returns
164 ///
165 /// * `io::Result<()>`: Ok(()) if all samples were read and converted successfully.
166 ///
167 /// # Errors
168 ///
169 /// This function will return an error if:
170 ///
171 /// * The underlying reader returns an error.
172 /// * The number of bytes read is not sufficient to represent a complete sample.
173 /// * The end of the reader is reached before all samples have been read.
174 fn read_converted_exact<T: RawSample + BytesSample, U: FloatCore + ToPrimitive>(
175 &mut self,
176 buf: &mut [U],
177 ) -> io::Result<()> {
178 for sample in buf.iter_mut() {
179 *sample = self.read_converted::<T, U>()?;
180 }
181 Ok(())
182 }
183
184 /// Read samples until the end of the stream, storing them in a vector.
185 ///
186 /// This method reads samples from the underlying reader until reaching
187 /// the end of the stream, the optional limit, or encountering an error.
188 /// Each sample is read and interpreted as a type `T`
189 /// before being appended to the provided vector `buf`.
190 ///
191 /// Only complete samples are read. If the last bytes at the end of the stream
192 /// are too few to make up a complete sample, then they are ignored.
193 ///
194 /// # Type Parameters
195 ///
196 /// * `T`: A type implementing the `BytesSample` trait, defining the format of the samples to read.
197 ///
198 /// # Arguments
199 ///
200 /// * `buf`: A mutable vector where the samples will be appended.
201 /// * `limit`: An optional limit for how many samples to read.
202 ///
203 /// # Returns
204 /// The number of samples read.
205 ///
206 /// # Errors
207 ///
208 /// * The underlying reader returns an error (except for EOF).
209 fn read_samples_to_limit_or_end<T: BytesSample>(
210 &mut self,
211 buf: &mut Vec<T>,
212 limit: Option<usize>,
213 ) -> io::Result<usize> {
214 let mut count = 0;
215 loop {
216 match self.read_sample::<T>() {
217 Ok(sample) => {
218 buf.push(sample);
219 count += 1;
220 }
221 Err(ref e) if e.kind() == io::ErrorKind::UnexpectedEof => {
222 break;
223 }
224 Err(e) => return Err(e),
225 }
226 if let Some(limit) = limit {
227 if count >= limit {
228 break;
229 }
230 }
231 }
232 Ok(count)
233 }
234
235 /// Read samples until the end of the stream, storing them as numeric types in a vector.
236 ///
237 /// This method reads samples from the underlying reader until reaching
238 /// the end of the stream, the optional limit, or encountering an error.
239 /// Each sample is read and interpreted as
240 /// a type `T`, then converted to its associated `NumericType` before being
241 /// appended to the provided vector `buf`.
242 ///
243 /// Only complete samples are read. If the last bytes at the end of the stream
244 /// are too few to make up a complete sample, then they are ignored.
245 ///
246 /// # Type Parameters
247 ///
248 /// * `T`: A type implementing the `BytesSample` trait, defining the format of the samples to read.
249 ///
250 /// # Arguments
251 ///
252 /// * `buf`: A mutable vector where the samples will be appended.
253 /// * `limit`: An optional limit for how many samples to read.
254 ///
255 /// # Returns
256 ///
257 /// * `io::Result<usize>`: The number of samples read, or an error if reading failed.
258 ///
259 /// # Errors
260 ///
261 /// This function will return an error if:
262 ///
263 /// * The underlying reader returns an error (except for EOF).
264 fn read_numbers_to_limit_or_end<T: BytesSample>(
265 &mut self,
266 buf: &mut Vec<T::NumericType>,
267 limit: Option<usize>,
268 ) -> io::Result<usize> {
269 let mut count = 0;
270 loop {
271 match self.read_number::<T>() {
272 Ok(sample) => {
273 buf.push(sample);
274 count += 1;
275 }
276 Err(ref e) if e.kind() == io::ErrorKind::UnexpectedEof => {
277 break;
278 }
279 Err(e) => return Err(e),
280 }
281 if let Some(limit) = limit {
282 if count >= limit {
283 break;
284 }
285 }
286 }
287 Ok(count)
288 }
289
290 /// Read samples until the end of the stream, converting them to floats, and store in a vector.
291 ///
292 /// This method reads samples from the underlying reader until reaching
293 /// the end of the stream, the optional limit, or encountering an error.
294 /// Each sample is read, converted to a
295 /// floating-point number of type `U`, and appended to the provided vector `buf`.
296 ///
297 /// Only complete samples are read. If the last bytes at the end of the stream
298 /// are too few to make up a complete sample, then they are ignored.
299 ///
300 /// # Type Parameters
301 ///
302 /// * `T`: A type implementing both `RawSample` and `BytesSample`, defining the format of the samples to read.
303 /// * `U`: A floating-point type implementing `FloatCore` and `ToPrimitive`, representing the desired output format.
304 ///
305 /// # Arguments
306 ///
307 /// * `buf`: A mutable vector where the converted samples will be appended.
308 /// * `limit`: An optional limit for how many samples to read.
309 ///
310 /// # Returns
311 ///
312 /// * `io::Result<usize>`: The number of samples read and converted, or an error if reading failed.
313 ///
314 /// # Errors
315 ///
316 /// This function will return an error if:
317 ///
318 /// * The underlying reader returns an error (except for EOF).
319 fn read_converted_to_limit_or_end<T: RawSample + BytesSample, U: FloatCore + ToPrimitive>(
320 &mut self,
321 buf: &mut Vec<U>,
322 limit: Option<usize>,
323 ) -> io::Result<usize> {
324 let mut count = 0;
325 loop {
326 match self.read_converted::<T, U>() {
327 Ok(sample) => {
328 buf.push(sample);
329 count += 1;
330 }
331 Err(ref e) if e.kind() == io::ErrorKind::UnexpectedEof => {
332 break;
333 }
334 Err(e) => return Err(e),
335 }
336 if let Some(limit) = limit {
337 if count >= limit {
338 break;
339 }
340 }
341 }
342 Ok(count)
343 }
344}
345
346impl<R: io::Read + ?Sized> ReadSamples for R {}
347
348/// A trait that extends [std::io::Write] with methods for writing samples directly.
349pub trait WriteSamples: io::Write {
350 /// Write a single sample to the underlying writer.
351 ///
352 /// This method takes a reference to a sample of type `T`,
353 /// gets its raw byte representation using the `as_slice` method,
354 /// and writes it to the underlying writer.
355 ///
356 /// # Type Parameters
357 ///
358 /// * `T`: A type implementing the `BytesSample` trait, defining the format of the sample to write.
359 /// # Returns
360 ///
361 /// * `io::Result<()>`: Ok(()) if the sample was written successfully.
362 /// # Errors
363 ///
364 /// This function will return an error if:
365 ///
366 /// * The underlying writer returns an error.
367 fn write_sample<T: BytesSample>(&mut self, sample: &T) -> io::Result<()> {
368 self.write_all(sample.as_slice())
369 }
370
371 /// Write a single sample from a numeric type to the underlying writer.
372 ///
373 /// This method takes a sample represented by its `NumericType`,
374 /// converts it to a raw byte representation using the provided `T`,
375 /// and writes it to the underlying writer.
376 ///
377 /// # Type Parameters
378 ///
379 /// * `T`: A type implementing the `BytesSample` trait, defining the format of the sample to write.
380 ///
381 /// # Arguments
382 ///
383 /// * `value`: The sample to write.
384 ///
385 /// # Returns
386 ///
387 /// * `io::Result<()>`: Ok(()) if the sample was written successfully.
388 ///
389 /// # Errors
390 ///
391 /// This function will return an error if:
392 ///
393 /// * The underlying writer returns an error.
394 fn write_number<T: BytesSample>(&mut self, value: T::NumericType) -> io::Result<()> {
395 self.write_all(T::from_number(value).as_slice())
396 }
397
398 /// Write a single converted sample to the underlying writer.
399 ///
400 /// This method takes a floating-point sample of type `U`, converts it to
401 /// the raw byte representation of type `T` and then writes it to the underlying writer.
402 ///
403 /// # Type Parameters
404 ///
405 /// * `T`: A type implementing both `RawSample` and `BytesSample`, defining the format of the sample to write.
406 /// * `U`: A floating-point type implementing `FloatCore` and `ToPrimitive`, representing the sample to write.
407 ///
408 /// # Arguments
409 ///
410 /// * `value`: The sample to write.
411 ///
412 /// # Returns
413 ///
414 /// * `io::Result<bool>`: Ok(true) if the value was clipped during conversion, Ok(false) otherwise.
415 ///
416 /// # Errors
417 ///
418 /// This function will return an error if:
419 ///
420 /// * The underlying writer returns an error.
421 fn write_converted<T: RawSample + BytesSample, U: FloatCore + ToPrimitive>(
422 &mut self,
423 value: U,
424 ) -> io::Result<bool> {
425 let converted = T::from_scaled_float(value);
426 self.write_all(converted.value.as_slice())?;
427 Ok(converted.clipped)
428 }
429
430 /// Write multiple samples to the underlying writer.
431 ///
432 /// This method takes a slice of samples, gets the raw byte representation of each sample,
433 /// and then writes it to the underlying writer.
434 ///
435 /// # Type Parameters
436 ///
437 /// * `T`: A type implementing the `BytesSample` trait, defining the format of the samples to write.
438 /// # Arguments
439 ///
440 /// * `samples`: The samples to write.
441 /// # Returns
442 ///
443 /// * `io::Result<()>`: Ok(()) if all samples were written successfully.
444 /// # Errors
445 ///
446 /// This function will return an error if:
447 ///
448 /// * The underlying writer returns an error.
449 fn write_all_samples<T: BytesSample>(&mut self, samples: &[T]) -> io::Result<()> {
450 for sample in samples {
451 self.write_sample::<T>(sample)?;
452 }
453 Ok(())
454 }
455
456 /// Write multiple samples from a numeric slice to the underlying writer.
457 ///
458 /// This method takes a slice of samples represented by their `NumericType`,
459 /// converts each sample to its raw byte representation using the provided `T`,
460 /// and writes them to the underlying writer.
461 ///
462 /// # Type Parameters
463 ///
464 /// * `T`: A type implementing the `BytesSample` trait, defining the format of the samples to write.
465 ///
466 /// # Arguments
467 ///
468 /// * `values`: The samples to write.
469 ///
470 /// # Returns
471 ///
472 /// * `io::Result<()>`: Ok(()) if all samples were written successfully.
473 ///
474 /// # Errors
475 ///
476 /// This function will return an error if:
477 ///
478 /// * The underlying writer returns an error.
479 fn write_all_numbers<T: BytesSample>(&mut self, values: &[T::NumericType]) -> io::Result<()> {
480 for value in values {
481 self.write_number::<T>(*value)?;
482 }
483 Ok(())
484 }
485
486 /// Write multiple converted samples from a float slice to the underlying writer.
487 ///
488 /// This method takes a slice of floating-point samples of type `U`, converts each sample
489 /// to its raw byte representation of type `T`, and then writes them to the underlying writer.
490 ///
491 /// # Type Parameters
492 ///
493 /// * `T`: A type implementing both `RawSample` and `BytesSample`, defining the format of the samples to write.
494 /// * `U`: A floating-point type implementing `FloatCore` and `ToPrimitive`, representing the samples to write.
495 ///
496 /// # Arguments
497 ///
498 /// * `values`: The samples to write.
499 ///
500 /// # Returns
501 ///
502 /// * `io::Result<usize>`: The number of samples that were clipped during conversion.
503 ///
504 /// # Errors
505 ///
506 /// This function will return an error if:
507 ///
508 /// * The underlying writer returns an error.
509 fn write_all_converted<T: RawSample + BytesSample, U: FloatCore + ToPrimitive>(
510 &mut self,
511 values: &[U],
512 ) -> io::Result<usize> {
513 let mut nbr_clipped = 0;
514 for value in values {
515 let clipped = self.write_converted::<T, U>(*value)?;
516 if clipped {
517 nbr_clipped += 1;
518 }
519 }
520 Ok(nbr_clipped)
521 }
522}
523
524impl<W: io::Write + ?Sized> WriteSamples for W {}
525
526#[cfg(test)]
527mod tests {
528 extern crate alloc;
529
530 use super::*;
531 use crate::readwrite::ReadSamples;
532 use crate::readwrite::WriteSamples;
533
534 #[test]
535 fn test_read_number_i16() {
536 let data: Vec<u8> = vec![0, 1, 2, 3];
537 let mut slice = &data[..];
538 assert_eq!(slice.read_number::<I16_LE>().unwrap(), 256);
539 assert_eq!(slice.read_number::<I16_LE>().unwrap(), 3 * 256 + 2);
540 assert!(slice.read_number::<I16_LE>().is_err());
541 }
542
543 #[test]
544 fn test_read_converted_i16() {
545 let data: Vec<u8> = vec![0, 64, 0, 32];
546 let mut slice = &data[..];
547 assert_eq!(slice.read_converted::<I16_LE, f32>().unwrap(), 0.5);
548 assert_eq!(slice.read_converted::<I16_LE, f32>().unwrap(), 0.25);
549 assert!(slice.read_converted::<I16_LE, f32>().is_err());
550 }
551
552 #[test]
553 fn test_read_number_exact_i16() {
554 let data: Vec<u8> = vec![0, 1, 2, 3];
555 let mut slice = &data[..];
556 let mut buf = [0; 2];
557 slice.read_numbers_exact::<I16_LE>(&mut buf).unwrap();
558 assert_eq!(buf, [256, 3 * 256 + 2]);
559 assert!(slice.read_numbers_exact::<I16_LE>(&mut buf).is_err());
560 }
561
562 #[test]
563 fn test_read_converted_exact_i16() {
564 let data: Vec<u8> = vec![0, 64, 0, 32];
565 let mut slice = &data[..];
566 let mut buf = [0.0; 2];
567 slice.read_converted_exact::<I16_LE, f32>(&mut buf).unwrap();
568 assert_eq!(buf, [0.5, 0.25]);
569 assert!(slice.read_converted_exact::<I16_LE, f32>(&mut buf).is_err());
570 }
571
572 #[test]
573 fn test_read_numbers_to_end_i16() {
574 // four complete samples, and one extra byte at the end
575 let data: Vec<u8> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8];
576 let mut slice = &data[..];
577 let mut buf = Vec::new();
578 slice
579 .read_numbers_to_limit_or_end::<I16_LE>(&mut buf, None)
580 .unwrap();
581 assert_eq!(buf, [256, 3 * 256 + 2, 5 * 256 + 4, 7 * 256 + 6]);
582 let mut slice2 = &data[..];
583 let mut buf2 = Vec::new();
584 slice2
585 .read_numbers_to_limit_or_end::<I16_LE>(&mut buf2, Some(2))
586 .unwrap();
587 assert_eq!(buf2, [256, 3 * 256 + 2]);
588 }
589
590 #[test]
591 fn test_read_converted_to_end_i16() {
592 // four complete samples, and one extra byte at the end
593 let data: Vec<u8> = vec![0, 64, 0, 32, 0, 16, 0, 8, 0];
594 let mut slice = &data[..];
595 let mut buf = Vec::new();
596 slice
597 .read_converted_to_limit_or_end::<I16_LE, f32>(&mut buf, None)
598 .unwrap();
599 assert_eq!(buf, [0.5, 0.25, 0.125, 0.0625]);
600 let mut slice2 = &data[..];
601 let mut buf2 = Vec::new();
602 slice2
603 .read_converted_to_limit_or_end::<I16_LE, f32>(&mut buf2, Some(2))
604 .unwrap();
605 assert_eq!(buf2, [0.5, 0.25]);
606 }
607
608 #[test]
609 fn test_write_number_i16() {
610 let mut buf = Vec::new();
611 buf.write_number::<I16_LE>(256).unwrap();
612 buf.write_number::<I16_LE>(3 * 256 + 2).unwrap();
613 assert_eq!(buf, [0, 1, 2, 3]);
614 }
615
616 #[test]
617 fn test_write_converted_i16() {
618 let mut buf = Vec::new();
619 buf.write_converted::<I16_LE, f32>(0.5).unwrap();
620 buf.write_converted::<I16_LE, f32>(0.25).unwrap();
621 assert_eq!(buf, [0, 64, 0, 32]);
622 }
623
624 #[test]
625 fn test_write_all_numbers_i16() {
626 let mut buf = Vec::new();
627 buf.write_all_numbers::<I16_LE>(&[256, 3 * 256 + 2])
628 .unwrap();
629 assert_eq!(buf, [0, 1, 2, 3]);
630 }
631
632 #[test]
633 fn test_write_all_converted_i16() {
634 let mut buf = Vec::new();
635 buf.write_all_converted::<I16_LE, f32>(&[0.5, 0.25])
636 .unwrap();
637 assert_eq!(buf, [0, 64, 0, 32]);
638 }
639}