1mod stft;
4pub mod window;
5
6pub use stft::StftHelper;
7
8pub const MINUS_INFINITY_DB: f32 = -100.0;
9pub const MINUS_INFINITY_GAIN: f32 = 1e-5; pub const NOTES: [&str; 12] = [
11 "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B",
12];
13
14#[cfg(all(debug_assertions, feature = "assert_process_allocs"))]
17pub fn permit_alloc<T, F: FnOnce() -> T>(func: F) -> T {
18 nice_assert_no_alloc::permit_alloc(func)
19}
20
21#[cfg(not(all(debug_assertions, feature = "assert_process_allocs")))]
24pub fn permit_alloc<T, F: FnOnce() -> T>(func: F) -> T {
25 func()
26}
27
28#[inline]
30pub fn db_to_gain(dbs: f32) -> f32 {
31 if dbs > MINUS_INFINITY_DB {
32 10.0f32.powf(dbs * 0.05)
33 } else {
34 0.0
35 }
36}
37
38#[inline]
41pub fn gain_to_db(gain: f32) -> f32 {
42 f32::max(gain, MINUS_INFINITY_GAIN).log10() * 20.0
43}
44
45#[inline]
50pub fn db_to_gain_fast(dbs: f32) -> f32 {
51 const CONVERSION_FACTOR: f32 = std::f32::consts::LN_10 / 20.0;
52 (dbs * CONVERSION_FACTOR).exp()
53}
54
55#[inline]
58pub fn db_to_gain_fast_branching(dbs: f32) -> f32 {
59 if dbs > MINUS_INFINITY_DB {
60 db_to_gain_fast(dbs)
61 } else {
62 0.0
63 }
64}
65
66#[inline]
69pub fn gain_to_db_fast(gain: f32) -> f32 {
70 const CONVERSION_FACTOR: f32 = std::f32::consts::LOG10_E * 20.0;
71 f32::max(gain, MINUS_INFINITY_GAIN).ln() * CONVERSION_FACTOR
72}
73
74#[inline]
77pub fn gain_to_db_fast_epsilon(gain: f32) -> f32 {
78 const CONVERSION_FACTOR: f32 = std::f32::consts::LOG10_E * 20.0;
79 f32::max(gain, MINUS_INFINITY_GAIN).ln() * CONVERSION_FACTOR
80}
81
82#[inline]
85pub fn midi_note_to_freq(note: u8) -> f32 {
86 f32_midi_note_to_freq(note as f32)
87}
88
89#[inline]
93pub fn f32_midi_note_to_freq(note: f32) -> f32 {
94 2.0f32.powf((note - 69.0) / 12.0) * 440.0
95}
96
97#[inline]
101pub fn freq_to_midi_note(freq: f32) -> f32 {
102 ((freq / 440.0).log2() * 12.0) + 69.0
103}
104
105#[cfg(test)]
106mod tests {
107 mod db_gain_conversion {
108 use super::super::*;
109
110 #[test]
111 fn test_db_to_gain_positive() {
112 assert_eq!(db_to_gain(3.0), 1.4125376);
113 }
114
115 #[test]
116 fn test_db_to_gain_negative() {
117 assert_eq!(db_to_gain(-3.0), 1.4125376f32.recip());
118 }
119
120 #[test]
121 fn test_db_to_gain_minus_infinity() {
122 assert_eq!(db_to_gain(-100.0), 0.0);
123 }
124
125 #[test]
126 fn test_gain_to_db_positive() {
127 assert_eq!(gain_to_db(4.0), 12.041201);
128 }
129
130 #[test]
131 fn test_gain_to_db_negative() {
132 assert_eq!(gain_to_db(0.25), -12.041201);
133 }
134
135 #[test]
136 fn test_gain_to_db_minus_infinity_zero() {
137 assert_eq!(gain_to_db(0.0), MINUS_INFINITY_DB);
138 }
139
140 #[test]
141 fn test_gain_to_db_minus_infinity_negative() {
142 assert_eq!(gain_to_db(-2.0), MINUS_INFINITY_DB);
143 }
144 }
145
146 mod fast_db_gain_conversion {
147 use super::super::*;
148
149 #[test]
150 fn test_db_to_gain_positive() {
151 approx::assert_relative_eq!(
152 db_to_gain(3.0),
153 db_to_gain_fast_branching(3.0),
154 epsilon = 1e-7
155 );
156 }
157
158 #[test]
159 fn test_db_to_gain_negative() {
160 approx::assert_relative_eq!(
161 db_to_gain(-3.0),
162 db_to_gain_fast_branching(-3.0),
163 epsilon = 1e-7
164 );
165 }
166
167 #[test]
168 fn test_db_to_gain_minus_infinity() {
169 approx::assert_relative_eq!(
170 db_to_gain(-100.0),
171 db_to_gain_fast_branching(-100.0),
172 epsilon = 1e-7
173 );
174 }
175
176 #[test]
177 fn test_gain_to_db_positive() {
178 approx::assert_relative_eq!(gain_to_db(4.0), gain_to_db_fast(4.0), epsilon = 1e-7);
179 }
180
181 #[test]
182 fn test_gain_to_db_negative() {
183 approx::assert_relative_eq!(gain_to_db(0.25), gain_to_db_fast(0.25), epsilon = 1e-7);
184 }
185
186 #[test]
187 fn test_gain_to_db_minus_infinity_zero() {
188 approx::assert_relative_eq!(gain_to_db(0.0), gain_to_db_fast(0.0), epsilon = 1e-7);
189 }
190
191 #[test]
192 fn test_gain_to_db_minus_infinity_negative() {
193 approx::assert_relative_eq!(gain_to_db(-2.0), gain_to_db_fast(-2.0), epsilon = 1e-7);
194 }
195 }
196}