Skip to main content

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