audioadapter_sample/
readwrite.rs

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