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}