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