1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
//! # Sample Format //! //! Module containing different output formats like stereo, 2.1, 5.1, 7.1, etc. //! //! All functions that deal with converting raw bytes to numeric types assume //! the bytes are in little-endian format. //! //! As there is no i24 built-in type, i32 is used in it's place where //! applicable. In most cases where a 24-bit sample is stored in a 32-bit data //! type, the upper byte is ignored or explicitly set to 0. use super::*; pub mod mono; pub mod stereo; pub use mono::*; pub use stereo::*; use std::convert::TryFrom; use std::ops::*; /// Trait implementing the ability to perform math operations with a polyphonic /// sample format and a monophonic sample. /// /// # Dependencies: /// /// * Default - A good default value for audio samples is 0. /// * Most mathematical operators are required to be implemented to be able to /// perform common operations on sample values. /// * [`Mul`]/[`MulAssign`] is defined for both [`MathT`] as well as [`SampleT`] /// for the convenience of common audio operations. /// * [`From`]/[`Into`] implemented for [`SampleT`] - These functions should be /// simple calls to [`from_sample`] and [`into_sample`] respectively. /// * [`TryFrom`]/[`Into`] implemented for [`Vec<_>`] - These functions should /// convert the sample values to the given standard integer types. As [`Vec`]s /// are generic types, it cannot be assumed that any attempted conversions of /// [`Vec`]s to a given sample format will succeed. Therefore those conversions /// use [`TryFrom`] to indicate when there is an issue, which can be /// communicated with the given [`String`] used for the error type. An example /// of such an error could be (for the [`Stereo`] type): /// /// ``` /// # let v: Vec<f32> = vec![]; /// format!("ERROR: Given vector was length {}. This function requires length 2.", v.len()); /// ``` /// /// [`Mul`]: https://doc.rust-lang.org/std/ops/trait.Mul.html /// [`MulAssign`]: https://doc.rust-lang.org/std/ops/trait.MulAssign.html /// [`MathT`]: ../type.MathT.html /// [`SampleT`]: ../type.SampleT.html /// [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html /// [`Into`]: https://doc.rust-lang.org/std/convert/trait.Into.html /// [`from_sample`]: #tymethod.from_sample /// [`into_sample`]: #tymethod.into_sample /// [`TryFrom`]: https://doc.rust-lang.org/std/convert/trait.TryFrom.html /// [`Vec<_>`]: https://doc.rust-lang.org/std/vec/struct.Vec.html /// [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html /// [`String`]: https://doc.rust-lang.org/std/convert/trait.From.html /// [`Stereo`]: stereo/struct.Stereo.html pub trait SampleFormat: Default + Neg<Output=Self> + Add< Self, Output=Self> + AddAssign< Self> + Sub< Self, Output=Self> + SubAssign< Self> + Mul< Self, Output=Self> + MulAssign< Self> + Mul< SampleT, Output=Self> + MulAssign<SampleT> + Mul< MathT, Output=Self> + MulAssign< MathT> + From< SampleT> + Into< SampleT> + TryFrom<Vec< u8>, Error=String> + Into< Vec< u8>> + TryFrom<Vec<i16>, Error=String> + Into< Vec<i16>> + TryFrom<Vec<i32>, Error=String> + Into< Vec<i32>> { /// Creates an object from a single monophonic sample. fn from_sample(x:SampleT) -> Self; /// Converts the given polyphonic sample to a monophonic sample. fn into_sample(self) -> SampleT; /// Returns the number of [`SampleT`] values held within a given /// [`SampleFormat`]. A common use for this would be for ensuring [`Vec`]s /// given to [`try_from`] have the correct size. /// /// [`SampleT`]: ../type.SampleT.html /// [`SampleFormat`]: trait.SampleFormat.html /// [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html /// [`try_from`]: https://doc.rust-lang.org/std/convert/trait.TryFrom.html#tymethod.try_from fn num_samples() -> usize; } /// Trait implementing the ability to pan a monophonic sample into a polyphonic /// sample. This is generic for the polyphonic type and the type that defines /// how it is panned. To see an implementation, see /// [`Stereo::to_sample_format`]. /// /// [`Stereo::to_sample_format`]: stereo/struct.Stereo.html#method.to_sample_format pub trait Panner<G>: SampleFormat { /// Converts the monophonic sample into a polyphonic sample. fn to_sample_format(s: SampleT, g: G) -> Self; } /// Converts a u8 8-bit sample to a `SampleT`. pub fn sample_from_u8(v: u8) -> SampleT { (v as SampleT - 128.0) / 128.0 } /// Converts a raw byte to a `SampleT`. pub fn sample_from_u8_bytes(v:[u8;1]) -> SampleT { (v[0] as SampleT - 128.0) / 128.0 } /// Converts a `SampleT` to an `u8`. pub fn sample_to_u8(s: SampleT) -> u8 { (s * 128.0 + 128.0).round() as u8 } /// Converts a `SampleT` to a raw little-endian byte. pub fn sample_to_u8_bytes(s: SampleT) -> [u8;1] { [sample_to_u8(s)] } /// Converts an i16 16-bit sample to a `SampleT`. pub fn sample_from_i16(v: i16) -> SampleT { v as SampleT / ((1 << 15) as SampleT - 1.0) } /// Converts raw bytes to a `SampleT`. pub fn sample_from_i16_bytes(v:[u8;2]) -> SampleT { (i16::from_le_bytes(v) as SampleT) / ((1 << 15) as SampleT - 1.0) } /// Converts a `SampleT` to an `i16`. pub fn sample_to_i16(s: SampleT) -> i16 { (s * ((1<<15) as SampleT - 1.0)).round() as i16 } /// Converts a `SampleT` to raw little-endian bytes. pub fn sample_to_i16_bytes(s: SampleT) -> [u8; 2] { sample_to_i16(s).to_le_bytes() } /// Converts an i32 24-bit sample to a `SampleT`. pub fn sample_from_i24(v: i32) -> SampleT { v as SampleT / ((1 << 23) as SampleT - 1.0) } /// Converts raw bytes to a `SampleT`. pub fn sample_from_i24_bytes(v:[u8;3]) -> SampleT { (i32::from_le_bytes([v[0],v[1],v[2],0]) as SampleT) / ((1 << 23) as SampleT - 1.0) } /// Converts a `SampleT` to an `i24`. pub fn sample_to_i24(s: SampleT) -> i32 { (s * ((1<<23) as SampleT - 1.0)).round() as i32 } /// Converts a `SampleT` to raw little-endian bytes. pub fn sample_to_i24_bytes(s: SampleT) -> [u8; 3] { let i = sample_to_i24(s).to_le_bytes(); [i[0],i[1],i[2]] }