1 use super::player::db_to_ratio;
2 use crate::convert::i24;
3 pub use crate::dither::{mk_ditherer, DithererBuilder, TriangularDitherer};
4 
5 use std::mem;
6 use std::str::FromStr;
7 use std::time::Duration;
8 
9 #[derive(Clone, Copy, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]
10 pub enum Bitrate {
11     Bitrate96,
12     Bitrate160,
13     Bitrate320,
14 }
15 
16 impl FromStr for Bitrate {
17     type Err = ();
from_str(s: &str) -> Result<Self, Self::Err>18     fn from_str(s: &str) -> Result<Self, Self::Err> {
19         match s {
20             "96" => Ok(Self::Bitrate96),
21             "160" => Ok(Self::Bitrate160),
22             "320" => Ok(Self::Bitrate320),
23             _ => Err(()),
24         }
25     }
26 }
27 
28 impl Default for Bitrate {
default() -> Self29     fn default() -> Self {
30         Self::Bitrate160
31     }
32 }
33 
34 #[derive(Clone, Copy, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]
35 pub enum AudioFormat {
36     F64,
37     F32,
38     S32,
39     S24,
40     S24_3,
41     S16,
42 }
43 
44 impl FromStr for AudioFormat {
45     type Err = ();
from_str(s: &str) -> Result<Self, Self::Err>46     fn from_str(s: &str) -> Result<Self, Self::Err> {
47         match s.to_uppercase().as_ref() {
48             "F64" => Ok(Self::F64),
49             "F32" => Ok(Self::F32),
50             "S32" => Ok(Self::S32),
51             "S24" => Ok(Self::S24),
52             "S24_3" => Ok(Self::S24_3),
53             "S16" => Ok(Self::S16),
54             _ => Err(()),
55         }
56     }
57 }
58 
59 impl Default for AudioFormat {
default() -> Self60     fn default() -> Self {
61         Self::S16
62     }
63 }
64 
65 impl AudioFormat {
66     // not used by all backends
67     #[allow(dead_code)]
size(&self) -> usize68     pub fn size(&self) -> usize {
69         match self {
70             Self::F64 => mem::size_of::<f64>(),
71             Self::F32 => mem::size_of::<f32>(),
72             Self::S24_3 => mem::size_of::<i24>(),
73             Self::S16 => mem::size_of::<i16>(),
74             _ => mem::size_of::<i32>(), // S32 and S24 are both stored in i32
75         }
76     }
77 }
78 
79 #[derive(Clone, Debug, PartialEq)]
80 pub enum NormalisationType {
81     Album,
82     Track,
83     Auto,
84 }
85 
86 impl FromStr for NormalisationType {
87     type Err = ();
from_str(s: &str) -> Result<Self, Self::Err>88     fn from_str(s: &str) -> Result<Self, Self::Err> {
89         match s.to_lowercase().as_ref() {
90             "album" => Ok(Self::Album),
91             "track" => Ok(Self::Track),
92             "auto" => Ok(Self::Auto),
93             _ => Err(()),
94         }
95     }
96 }
97 
98 impl Default for NormalisationType {
default() -> Self99     fn default() -> Self {
100         Self::Auto
101     }
102 }
103 
104 #[derive(Clone, Debug, PartialEq)]
105 pub enum NormalisationMethod {
106     Basic,
107     Dynamic,
108 }
109 
110 impl FromStr for NormalisationMethod {
111     type Err = ();
from_str(s: &str) -> Result<Self, Self::Err>112     fn from_str(s: &str) -> Result<Self, Self::Err> {
113         match s.to_lowercase().as_ref() {
114             "basic" => Ok(Self::Basic),
115             "dynamic" => Ok(Self::Dynamic),
116             _ => Err(()),
117         }
118     }
119 }
120 
121 impl Default for NormalisationMethod {
default() -> Self122     fn default() -> Self {
123         Self::Dynamic
124     }
125 }
126 
127 #[derive(Clone)]
128 pub struct PlayerConfig {
129     pub bitrate: Bitrate,
130     pub gapless: bool,
131     pub passthrough: bool,
132 
133     pub normalisation: bool,
134     pub normalisation_type: NormalisationType,
135     pub normalisation_method: NormalisationMethod,
136     pub normalisation_pregain: f64,
137     pub normalisation_threshold: f64,
138     pub normalisation_attack: Duration,
139     pub normalisation_release: Duration,
140     pub normalisation_knee: f64,
141 
142     // pass function pointers so they can be lazily instantiated *after* spawning a thread
143     // (thereby circumventing Send bounds that they might not satisfy)
144     pub ditherer: Option<DithererBuilder>,
145 }
146 
147 impl Default for PlayerConfig {
default() -> Self148     fn default() -> Self {
149         Self {
150             bitrate: Bitrate::default(),
151             gapless: true,
152             normalisation: false,
153             normalisation_type: NormalisationType::default(),
154             normalisation_method: NormalisationMethod::default(),
155             normalisation_pregain: 0.0,
156             normalisation_threshold: db_to_ratio(-2.0),
157             normalisation_attack: Duration::from_millis(5),
158             normalisation_release: Duration::from_millis(100),
159             normalisation_knee: 1.0,
160             passthrough: false,
161             ditherer: Some(mk_ditherer::<TriangularDitherer>),
162         }
163     }
164 }
165 
166 // fields are intended for volume control range in dB
167 #[derive(Clone, Copy, Debug)]
168 pub enum VolumeCtrl {
169     Cubic(f64),
170     Fixed,
171     Linear,
172     Log(f64),
173 }
174 
175 impl FromStr for VolumeCtrl {
176     type Err = ();
from_str(s: &str) -> Result<Self, Self::Err>177     fn from_str(s: &str) -> Result<Self, Self::Err> {
178         Self::from_str_with_range(s, Self::DEFAULT_DB_RANGE)
179     }
180 }
181 
182 impl Default for VolumeCtrl {
default() -> VolumeCtrl183     fn default() -> VolumeCtrl {
184         VolumeCtrl::Log(Self::DEFAULT_DB_RANGE)
185     }
186 }
187 
188 impl VolumeCtrl {
189     pub const MAX_VOLUME: u16 = u16::MAX;
190 
191     // Taken from: https://www.dr-lex.be/info-stuff/volumecontrols.html
192     pub const DEFAULT_DB_RANGE: f64 = 60.0;
193 
from_str_with_range(s: &str, db_range: f64) -> Result<Self, <Self as FromStr>::Err>194     pub fn from_str_with_range(s: &str, db_range: f64) -> Result<Self, <Self as FromStr>::Err> {
195         use self::VolumeCtrl::*;
196         match s.to_lowercase().as_ref() {
197             "cubic" => Ok(Cubic(db_range)),
198             "fixed" => Ok(Fixed),
199             "linear" => Ok(Linear),
200             "log" => Ok(Log(db_range)),
201             _ => Err(()),
202         }
203     }
204 }
205