augmented_audio_volume/
lib.rs

1// Augmented Audio: Audio libraries and applications
2// Copyright (c) 2022 Pedro Tacla Yamada
3//
4// The MIT License (MIT)
5//
6// Permission is hereby granted, free of charge, to any person obtaining a copy
7// of this software and associated documentation files (the "Software"), to deal
8// in the Software without restriction, including without limitation the rights
9// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10// copies of the Software, and to permit persons to whom the Software is
11// furnished to do so, subject to the following conditions:
12//
13// The above copyright notice and this permission notice shall be included in
14// all copies or substantial portions of the Software.
15//
16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22// THE SOFTWARE.
23//! Data-types for representing volume in:
24//!
25//! * [`Decibels`]
26//! * [`Amplitude`]
27//!
28//! And conversions between the two.
29use std::ops::Mul;
30
31#[cfg(not(feature = "f64"))]
32pub type Float = f32;
33
34#[cfg(feature = "f64")]
35pub type Float = f64;
36
37/// Represents a reference-less dB value.
38#[derive(Default, PartialEq, PartialOrd, Debug, Clone, Copy)]
39pub struct Decibels {
40    decibels: Float,
41}
42
43impl Decibels {
44    /// Constructs [`Decibels`] from a number
45    pub fn from_db(decibels: Float) -> Self {
46        Decibels { decibels }
47    }
48
49    /// Constructs [`Decibels`] from an amplitude and reference
50    pub fn from_amplitude(amplitude: Float, reference_amplitude: Float) -> Self {
51        Decibels::from_db(amplitude_to_db(amplitude, reference_amplitude))
52    }
53
54    /// Changes this [`Decibels`] internal dB value to match `amplitude`
55    pub fn set_amplitude(&mut self, amplitude: Float, reference_amplitude: Float) {
56        self.decibels = amplitude_to_db(amplitude, reference_amplitude)
57    }
58
59    /// Changes this [`Decibels`] internal dB value
60    pub fn set_db(&mut self, db: Float) {
61        self.decibels = db;
62    }
63
64    /// Converts this [`Decibels`] to `amplitude`
65    pub fn as_amplitude(&self, reference_amplitude: Float) -> Float {
66        db_to_amplitude(self.decibels, reference_amplitude)
67    }
68
69    /// Returns this [`Decibels`] inner value
70    pub fn as_db(&self) -> Float {
71        self.decibels
72    }
73
74    /// Converts this [`Decibels`] to amplitude
75    pub fn amplitude(&self, reference_amplitude: Float) -> Amplitude {
76        Amplitude::from_db(self.decibels, reference_amplitude)
77    }
78}
79
80impl From<Float> for Decibels {
81    fn from(db: Float) -> Self {
82        Self::from_db(db)
83    }
84}
85
86impl From<Decibels> for Float {
87    fn from(db: Decibels) -> Self {
88        db.as_db()
89    }
90}
91
92impl Mul for Decibels {
93    type Output = Self;
94
95    fn mul(self, rhs: Self) -> Self::Output {
96        Self::from_db(self.decibels * rhs.decibels)
97    }
98}
99
100/// Represents an amplitude measurement or constant.
101#[derive(Default, PartialEq, PartialOrd, Debug, Clone, Copy)]
102pub struct Amplitude {
103    amplitude: Float,
104}
105
106impl Amplitude {
107    /// Constructs an [`Amplitude`]
108    pub fn from_amplitude(amplitude: Float) -> Self {
109        Amplitude { amplitude }
110    }
111
112    /// Constructs an [`Amplitude`] from a dB measurement and a reference value
113    pub fn from_db(db: Float, reference_amplitude: Float) -> Self {
114        Amplitude::from_amplitude(db_to_amplitude(db, reference_amplitude))
115    }
116
117    /// Changes this [`Amplitude`] inner value
118    pub fn set_amplitude(&mut self, amplitude: Float) {
119        self.amplitude = amplitude;
120    }
121
122    /// Changes this [`Amplitude`] inner value to match dB
123    pub fn set_db(&mut self, db: Float, reference_amplitude: Float) {
124        self.amplitude = db_to_amplitude(db, reference_amplitude);
125    }
126
127    /// Gets this [`Amplitude`] inner value
128    pub fn as_amplitude(&self) -> Float {
129        self.amplitude
130    }
131
132    /// Gets this [`Amplitude`] inner value as dB
133    pub fn as_db(&self, reference_amplitude: Float) -> Float {
134        amplitude_to_db(self.amplitude, reference_amplitude)
135    }
136
137    /// Converts this [`Amplitude`] to [`Decibels`]
138    pub fn decibels(&self, reference_amplitude: Float) -> Decibels {
139        Decibels::from_amplitude(self.amplitude, reference_amplitude)
140    }
141}
142
143impl From<Float> for Amplitude {
144    fn from(volume: Float) -> Self {
145        Self::from_amplitude(volume)
146    }
147}
148
149impl From<Amplitude> for Float {
150    fn from(amp: Amplitude) -> Self {
151        amp.as_amplitude()
152    }
153}
154
155impl Mul for Amplitude {
156    type Output = Self;
157
158    fn mul(self, rhs: Self) -> Self::Output {
159        Self::from_amplitude(self.amplitude * rhs.amplitude)
160    }
161}
162
163impl Mul<Float> for Amplitude {
164    type Output = Self;
165
166    fn mul(self, rhs: Float) -> Self::Output {
167        Self::from_amplitude(self.amplitude * rhs)
168    }
169}
170
171/// Convert decibels to amplitude
172pub fn db_to_amplitude(db: Float, reference_amplitude: Float) -> Float {
173    Float::powf(10.0, db / 20.0) * reference_amplitude
174}
175
176/// Convert amplitude to decibels
177pub fn amplitude_to_db(volume: Float, reference_amplitude: Float) -> Float {
178    20.0 * (volume / reference_amplitude).log10()
179}
180
181#[cfg(test)]
182mod tests {
183    use audio_processor_testing_helpers::assert_f_eq;
184
185    use super::*;
186
187    #[test]
188    fn test_decibels_can_be_created_from_db() {
189        let db = Decibels::from_db(0.0);
190        assert_eq!(db.as_db(), 0.0);
191    }
192
193    #[test]
194    fn test_decibels_set_db() {
195        let mut db = Decibels::from_db(0.0);
196        db.set_db(-0.1);
197        assert_eq!(db.as_db(), -0.1);
198    }
199
200    #[test]
201    fn test_decibels_set_amplitude() {
202        let mut db = Decibels::from_db(3.0);
203        db.set_amplitude(1.0, 1.0);
204        assert_eq!(db.as_db(), 0.0);
205    }
206
207    #[test]
208    fn test_decibels_as_amplitude() {
209        let db = Decibels::from_db(0.0);
210        let amp = db.as_amplitude(1.0);
211        assert_eq!(amp, 1.0);
212    }
213
214    #[test]
215    fn test_decibels_amplitude() {
216        let db = Decibels::from_db(0.0);
217        let amp = db.amplitude(1.0);
218        let amp = amp.as_amplitude();
219        assert_eq!(amp, 1.0);
220    }
221
222    #[test]
223    fn test_decibels_from_float() {
224        let db = Decibels::from(0.0);
225        let db = db.as_db();
226        assert_eq!(db, 0.0);
227    }
228
229    #[test]
230    fn test_amplitude_from_amplitude() {
231        let amp = Amplitude::from_amplitude(1.0);
232        assert_eq!(amp.as_amplitude(), 1.0);
233    }
234
235    #[test]
236    fn test_amplitude_from_db() {
237        let amp = Amplitude::from_db(0.0, 1.0);
238        assert_eq!(amp.as_amplitude(), 1.0);
239    }
240
241    #[test]
242    fn test_amplitude_set_amplitude() {
243        let mut amp = Amplitude::from_amplitude(10.0);
244        amp.set_amplitude(2.0);
245        assert_eq!(amp.as_amplitude(), 2.0);
246    }
247
248    #[test]
249    fn test_amplitude_set_db() {
250        let mut amp = Amplitude::from_amplitude(10.0);
251        amp.set_db(0.0, 1.0);
252        assert_eq!(amp.as_amplitude(), 1.0);
253    }
254
255    #[test]
256    fn test_amplitude_as_db() {
257        let amp = Amplitude::from_amplitude(10.0);
258        let db = amp.as_db(1.0);
259        assert_eq!(db, 20.0);
260    }
261
262    #[test]
263    fn test_amplitude_decibels() {
264        let amp = Amplitude::from_amplitude(1.0);
265        let db = amp.decibels(1.0);
266        assert_eq!(db.as_amplitude(1.0), 1.0);
267    }
268
269    #[test]
270    fn test_amplitude_roundtrip() {
271        let amp = Amplitude::from_amplitude(1.0);
272        let db = amp.decibels(1.0);
273        let amp2 = db.amplitude(1.0);
274        assert_eq!(amp, amp2);
275    }
276
277    #[test]
278    fn test_amplitude_from_float() {
279        let amp = Amplitude::from(1.0);
280        assert_eq!(amp.as_amplitude(), 1.0);
281    }
282
283    #[test]
284    fn test_float_from_amplitude() {
285        let amp: f32 = Amplitude::from(1.0).into();
286        assert_eq!(amp, 1.0);
287    }
288
289    #[test]
290    fn test_amplitude_mult() {
291        let amp1 = Amplitude::from(3.0);
292        let amp2 = Amplitude::from(2.0);
293        let amp = amp1 * amp2;
294        assert_eq!(amp.as_amplitude(), 6.0);
295    }
296
297    #[test]
298    fn test_amplitude_mult_float() {
299        let amp1 = Amplitude::from(3.0);
300        let amp2 = 2.0;
301        let amp = amp1 * amp2;
302        assert_eq!(amp.as_amplitude(), 6.0);
303    }
304
305    #[test]
306    fn test_it_can_be_created() {
307        let volume = Amplitude::from_amplitude(1.0);
308        assert_f_eq!(volume.as_amplitude(), 1.0);
309    }
310
311    #[test]
312    fn test_it_can_be_converted_to_db() {
313        let volume = Amplitude::from_amplitude(1.0);
314        let db = volume.decibels(1.0);
315        assert_f_eq!(db.as_db(), 0.0);
316    }
317}