@@ -2,6 +2,272 @@ use crate::Error;
22use core:: convert:: TryFrom ;
33use core:: fmt;
44
5+ /// Precomputed frequencies (Hz) for all 128 MIDI notes using standard A440 tuning.
6+ /// Formula: 2^((n + 36.37631656229591) / 12)
7+ const FREQ_F64 : [ f64 ; 128 ] = [
8+ 8.175798915643707e+00 , // 0 CMinus1
9+ 8.661957218027251e+00 , // 1 DbMinus1
10+ 9.177023997418985e+00 , // 2 DMinus1
11+ 9.722718241315027e+00 , // 3 EbMinus1
12+ 1.030086115352718e+01 , // 4 EMinus1
13+ 1.091338223228137e+01 , // 5 FMinus1
14+ 1.156232570973857e+01 , // 6 GbMinus1
15+ 1.224985737442966e+01 , // 7 GMinus1
16+ 1.297827179937328e+01 , // 8 AbMinus1
17+ 1.375000000000000e+01 , // 9 AMinus1
18+ 1.456761754744030e+01 , // 10 BbMinus1
19+ 1.543385316425388e+01 , // 11 BMinus1
20+ 1.635159783128741e+01 , // 12 C0
21+ 1.732391443605450e+01 , // 13 Db0
22+ 1.835404799483797e+01 , // 14 D0
23+ 1.944543648263005e+01 , // 15 Eb0
24+ 2.060172230705437e+01 , // 16 E0
25+ 2.182676446456274e+01 , // 17 F0
26+ 2.312465141947714e+01 , // 18 Gb0
27+ 2.449971474885933e+01 , // 19 G0
28+ 2.595654359874657e+01 , // 20 Ab0
29+ 2.749999999999999e+01 , // 21 A0
30+ 2.913523509488062e+01 , // 22 Bb0
31+ 3.086770632850775e+01 , // 23 B0
32+ 3.270319566257481e+01 , // 24 C1
33+ 3.464782887210901e+01 , // 25 Db1
34+ 3.670809598967594e+01 , // 26 D1
35+ 3.889087296526010e+01 , // 27 Eb1
36+ 4.120344461410874e+01 , // 28 E1
37+ 4.365352892912548e+01 , // 29 F1
38+ 4.624930283895428e+01 , // 30 Gb1
39+ 4.899942949771867e+01 , // 31 G1
40+ 5.191308719749313e+01 , // 32 Ab1
41+ 5.499999999999998e+01 , // 33 A1
42+ 5.827047018976124e+01 , // 34 Bb1
43+ 6.173541265701550e+01 , // 35 B1
44+ 6.540639132514963e+01 , // 36 C2
45+ 6.929565774421802e+01 , // 37 Db2
46+ 7.341619197935188e+01 , // 38 D2
47+ 7.778174593052020e+01 , // 39 Eb2
48+ 8.240688922821748e+01 , // 40 E2
49+ 8.730705785825096e+01 , // 41 F2
50+ 9.249860567790856e+01 , // 42 Gb2
51+ 9.799885899543733e+01 , // 43 G2
52+ 1.038261743949863e+02 , // 44 Ab2
53+ 1.100000000000000e+02 , // 45 A2
54+ 1.165409403795225e+02 , // 46 Bb2
55+ 1.234708253140310e+02 , // 47 B2
56+ 1.308127826502993e+02 , // 48 C3
57+ 1.385913154884360e+02 , // 49 Db3
58+ 1.468323839587038e+02 , // 50 D3
59+ 1.555634918610404e+02 , // 51 Eb3
60+ 1.648137784564350e+02 , // 52 E3
61+ 1.746141157165019e+02 , // 53 F3
62+ 1.849972113558171e+02 , // 54 Gb3
63+ 1.959977179908747e+02 , // 55 G3
64+ 2.076523487899725e+02 , // 56 Ab3
65+ 2.199999999999999e+02 , // 57 A3
66+ 2.330818807590450e+02 , // 58 Bb3
67+ 2.469416506280620e+02 , // 59 B3
68+ 2.616255653005987e+02 , // 60 C4
69+ 2.771826309768719e+02 , // 61 Db4
70+ 2.936647679174075e+02 , // 62 D4
71+ 3.111269837220810e+02 , // 63 Eb4
72+ 3.296275569128697e+02 , // 64 E4
73+ 3.492282314330038e+02 , // 65 F4
74+ 3.699944227116345e+02 , // 66 Gb4
75+ 3.919954359817490e+02 , // 67 G4
76+ 4.153046975799451e+02 , // 68 Ab4
77+ 4.400000000000001e+02 , // 69 A4
78+ 4.661637615180896e+02 , // 70 Bb4
79+ 4.938833012561240e+02 , // 71 B4
80+ 5.232511306011974e+02 , // 72 C5
81+ 5.543652619537438e+02 , // 73 Db5
82+ 5.873295358348150e+02 , // 74 D5
83+ 6.222539674441620e+02 , // 75 Eb5
84+ 6.592551138257395e+02 , // 76 E5
85+ 6.984564628660077e+02 , // 77 F5
86+ 7.399888454232689e+02 , // 78 Gb5
87+ 7.839908719634981e+02 , // 79 G5
88+ 8.306093951598901e+02 , // 80 Ab5
89+ 8.800000000000002e+02 , // 81 A5
90+ 9.323275230361793e+02 , // 82 Bb5
91+ 9.877666025122480e+02 , // 83 B5
92+ 1.046502261202395e+03 , // 84 C6
93+ 1.108730523907488e+03 , // 85 Db6
94+ 1.174659071669630e+03 , // 86 D6
95+ 1.244507934888324e+03 , // 87 Eb6
96+ 1.318510227651479e+03 , // 88 E6
97+ 1.396912925732015e+03 , // 89 F6
98+ 1.479977690846538e+03 , // 90 Gb6
99+ 1.567981743926996e+03 , // 91 G6
100+ 1.661218790319782e+03 , // 92 Ab6
101+ 1.760000000000000e+03 , // 93 A6
102+ 1.864655046072361e+03 , // 94 Bb6
103+ 1.975533205024499e+03 , // 95 B6
104+ 2.093004522404789e+03 , // 96 C7
105+ 2.217461047814978e+03 , // 97 Db7
106+ 2.349318143339263e+03 , // 98 D7
107+ 2.489015869776648e+03 , // 99 Eb7
108+ 2.637020455302961e+03 , // 100 E7
109+ 2.793825851464034e+03 , // 101 F7
110+ 2.959955381693076e+03 , // 102 Gb7
111+ 3.135963487853996e+03 , // 103 G7
112+ 3.322437580639565e+03 , // 104 Ab7
113+ 3.520000000000001e+03 , // 105 A7
114+ 3.729310092144722e+03 , // 106 Bb7
115+ 3.951066410048997e+03 , // 107 B7
116+ 4.186009044809579e+03 , // 108 C8
117+ 4.434922095629956e+03 , // 109 Db8
118+ 4.698636286678526e+03 , // 110 D8
119+ 4.978031739553296e+03 , // 111 Eb8
120+ 5.274040910605922e+03 , // 112 E8
121+ 5.587651702928068e+03 , // 113 F8
122+ 5.919910763386151e+03 , // 114 Gb8
123+ 6.271926975707993e+03 , // 115 G8
124+ 6.644875161279129e+03 , // 116 Ab8
125+ 7.040000000000002e+03 , // 117 A8
126+ 7.458620184289443e+03 , // 118 Bb8
127+ 7.902132820097994e+03 , // 119 B8
128+ 8.372018089619158e+03 , // 120 C9
129+ 8.869844191259912e+03 , // 121 Db9
130+ 9.397272573357051e+03 , // 122 D9
131+ 9.956063479106591e+03 , // 123 Eb9
132+ 1.054808182121184e+04 , // 124 E9
133+ 1.117530340585614e+04 , // 125 F9
134+ 1.183982152677230e+04 , // 126 Gb9
135+ 1.254385395141599e+04 , // 127 G9
136+ ] ;
137+
138+ /// Precomputed frequencies (Hz) for all 128 MIDI notes using standard A440 tuning.
139+ /// Formula: 2^((n + 36.376316) / 12)
140+ const FREQ_F32 : [ f32 ; 128 ] = [
141+ 8.1757987e+00_f32 , // 0 CMinus1
142+ 8.6619569e+00_f32 , // 1 DbMinus1
143+ 9.1770237e+00_f32 , // 2 DMinus1
144+ 9.7227179e+00_f32 , // 3 EbMinus1
145+ 1.0300861e+01_f32 , // 4 EMinus1
146+ 1.0913382e+01_f32 , // 5 FMinus1
147+ 1.1562325e+01_f32 , // 6 GbMinus1
148+ 1.2249857e+01_f32 , // 7 GMinus1
149+ 1.2978271e+01_f32 , // 8 AbMinus1
150+ 1.3750000e+01_f32 , // 9 AMinus1
151+ 1.4567617e+01_f32 , // 10 BbMinus1
152+ 1.5433853e+01_f32 , // 11 BMinus1
153+ 1.6351597e+01_f32 , // 12 C0
154+ 1.7323914e+01_f32 , // 13 Db0
155+ 1.8354047e+01_f32 , // 14 D0
156+ 1.9445436e+01_f32 , // 15 Eb0
157+ 2.0601722e+01_f32 , // 16 E0
158+ 2.1826764e+01_f32 , // 17 F0
159+ 2.3124651e+01_f32 , // 18 Gb0
160+ 2.4499714e+01_f32 , // 19 G0
161+ 2.5956543e+01_f32 , // 20 Ab0
162+ 2.7499999e+01_f32 , // 21 A0
163+ 2.9135234e+01_f32 , // 22 Bb0
164+ 3.0867705e+01_f32 , // 23 B0
165+ 3.2703195e+01_f32 , // 24 C1
166+ 3.4647828e+01_f32 , // 25 Db1
167+ 3.6708095e+01_f32 , // 26 D1
168+ 3.8890872e+01_f32 , // 27 Eb1
169+ 4.1203443e+01_f32 , // 28 E1
170+ 4.3653528e+01_f32 , // 29 F1
171+ 4.6249301e+01_f32 , // 30 Gb1
172+ 4.8999428e+01_f32 , // 31 G1
173+ 5.1913086e+01_f32 , // 32 Ab1
174+ 5.4999998e+01_f32 , // 33 A1
175+ 5.8270468e+01_f32 , // 34 Bb1
176+ 6.1735411e+01_f32 , // 35 B1
177+ 6.5406389e+01_f32 , // 36 C2
178+ 6.9295655e+01_f32 , // 37 Db2
179+ 7.3416190e+01_f32 , // 38 D2
180+ 7.7781743e+01_f32 , // 39 Eb2
181+ 8.2406887e+01_f32 , // 40 E2
182+ 8.7307055e+01_f32 , // 41 F2
183+ 9.2498603e+01_f32 , // 42 Gb2
184+ 9.7998856e+01_f32 , // 43 G2
185+ 1.0382617e+02_f32 , // 44 Ab2
186+ 1.1000000e+02_f32 , // 45 A2
187+ 1.1654094e+02_f32 , // 46 Bb2
188+ 1.2347082e+02_f32 , // 47 B2
189+ 1.3081278e+02_f32 , // 48 C3
190+ 1.3859131e+02_f32 , // 49 Db3
191+ 1.4683238e+02_f32 , // 50 D3
192+ 1.5556349e+02_f32 , // 51 Eb3
193+ 1.6481377e+02_f32 , // 52 E3
194+ 1.7461411e+02_f32 , // 53 F3
195+ 1.8499721e+02_f32 , // 54 Gb3
196+ 1.9599771e+02_f32 , // 55 G3
197+ 2.0765234e+02_f32 , // 56 Ab3
198+ 2.1999999e+02_f32 , // 57 A3
199+ 2.3308187e+02_f32 , // 58 Bb3
200+ 2.4694164e+02_f32 , // 59 B3
201+ 2.6162556e+02_f32 , // 60 C4
202+ 2.7718262e+02_f32 , // 61 Db4
203+ 2.9366476e+02_f32 , // 62 D4
204+ 3.1112697e+02_f32 , // 63 Eb4
205+ 3.2962755e+02_f32 , // 64 E4
206+ 3.4922822e+02_f32 , // 65 F4
207+ 3.6999441e+02_f32 , // 66 Gb4
208+ 3.9199542e+02_f32 , // 67 G4
209+ 4.1530468e+02_f32 , // 68 Ab4
210+ 4.3999999e+02_f32 , // 69 A4
211+ 4.6616375e+02_f32 , // 70 Bb4
212+ 4.9388329e+02_f32 , // 71 B4
213+ 5.2325111e+02_f32 , // 72 C5
214+ 5.5436524e+02_f32 , // 73 Db5
215+ 5.8732952e+02_f32 , // 74 D5
216+ 6.2225395e+02_f32 , // 75 Eb5
217+ 6.5925509e+02_f32 , // 76 E5
218+ 6.9845644e+02_f32 , // 77 F5
219+ 7.3998882e+02_f32 , // 78 Gb5
220+ 7.8399085e+02_f32 , // 79 G5
221+ 8.3060937e+02_f32 , // 80 Ab5
222+ 8.7999997e+02_f32 , // 81 A5
223+ 9.3232749e+02_f32 , // 82 Bb5
224+ 9.8776657e+02_f32 , // 83 B5
225+ 1.0465022e+03_f32 , // 84 C6
226+ 1.1087305e+03_f32 , // 85 Db6
227+ 1.1746590e+03_f32 , // 86 D6
228+ 1.2445079e+03_f32 , // 87 Eb6
229+ 1.3185102e+03_f32 , // 88 E6
230+ 1.3969129e+03_f32 , // 89 F6
231+ 1.4799776e+03_f32 , // 90 Gb6
232+ 1.5679817e+03_f32 , // 91 G6
233+ 1.6612187e+03_f32 , // 92 Ab6
234+ 1.7599999e+03_f32 , // 93 A6
235+ 1.8646550e+03_f32 , // 94 Bb6
236+ 1.9755331e+03_f32 , // 95 B6
237+ 2.0930045e+03_f32 , // 96 C7
238+ 2.2174610e+03_f32 , // 97 Db7
239+ 2.3493181e+03_f32 , // 98 D7
240+ 2.4890158e+03_f32 , // 99 Eb7
241+ 2.6370204e+03_f32 , // 100 E7
242+ 2.7938258e+03_f32 , // 101 F7
243+ 2.9599553e+03_f32 , // 102 Gb7
244+ 3.1359634e+03_f32 , // 103 G7
245+ 3.3224375e+03_f32 , // 104 Ab7
246+ 3.5199999e+03_f32 , // 105 A7
247+ 3.7293100e+03_f32 , // 106 Bb7
248+ 3.9510663e+03_f32 , // 107 B7
249+ 4.1860089e+03_f32 , // 108 C8
250+ 4.4349220e+03_f32 , // 109 Db8
251+ 4.6986361e+03_f32 , // 110 D8
252+ 4.9780316e+03_f32 , // 111 Eb8
253+ 5.2740407e+03_f32 , // 112 E8
254+ 5.5876515e+03_f32 , // 113 F8
255+ 5.9199106e+03_f32 , // 114 Gb8
256+ 6.2719268e+03_f32 , // 115 G8
257+ 6.6448749e+03_f32 , // 116 Ab8
258+ 7.0399998e+03_f32 , // 117 A8
259+ 7.4586199e+03_f32 , // 118 Bb8
260+ 7.9021326e+03_f32 , // 119 B8
261+ 8.3720178e+03_f32 , // 120 C9
262+ 8.8698439e+03_f32 , // 121 Db9
263+ 9.3972723e+03_f32 , // 122 D9
264+ 9.9560632e+03_f32 , // 123 Eb9
265+ 1.0548081e+04_f32 , // 124 E9
266+ 1.1175303e+04_f32 , // 125 F9
267+ 1.1839821e+04_f32 , // 126 Gb9
268+ 1.2543854e+04_f32 , // 127 G9
269+ ] ;
270+
5271/// A midi note.
6272///
7273/// The format for the enum is `$NOTE` `$MODIFIER?` `$OCTAVE`. Note can be a note from `A` to `G`.
@@ -242,11 +508,9 @@ impl Note {
242508 /// let note = wmidi::Note::A3;
243509 /// sing(note.to_freq_f32());
244510 /// ```
245- #[ cfg( feature = "std" ) ]
246511 #[ inline( always) ]
247512 pub fn to_freq_f32 ( self ) -> f32 {
248- let exp = ( f32:: from ( self as u8 ) + 36.376_316 ) / 12.0 ;
249- 2_f32 . powf ( exp)
513+ FREQ_F32 [ self as usize ]
250514 }
251515
252516 /// The frequency using the standard 440Hz tuning.
@@ -257,11 +521,9 @@ impl Note {
257521 /// let note = wmidi::Note::A3;
258522 /// sing(note.to_freq_f64());
259523 /// ```
260- #[ cfg( feature = "std" ) ]
261524 #[ inline( always) ]
262525 pub fn to_freq_f64 ( self ) -> f64 {
263- let exp = ( f64:: from ( self as u8 ) + 36.376_316_562_295_91 ) / 12.0 ;
264- 2_f64 . powf ( exp)
526+ FREQ_F64 [ self as usize ]
265527 }
266528
267529 /// Get the note relative to `self`.
@@ -484,12 +746,50 @@ mod test {
484746
485747 #[ cfg( feature = "std" ) ]
486748 #[ test]
487- fn note_to_frequency ( ) {
749+ fn note_to_frequency_a440 ( ) {
488750 let a440_f64 = Note :: A4 . to_freq_f64 ( ) ;
489751 assert ! ( ( a440_f64 - 440.0 ) . abs( ) < 1E-10 , "{} != 440" , a440_f64) ;
490752
491753 let a440_f32 = Note :: A4 . to_freq_f32 ( ) ;
492- assert ! ( ( a440_f32 - 440.0 ) . abs( ) < 1E-10 , "{} != 440" , a440_f32) ;
754+ assert ! ( ( a440_f32 - 440.0 ) . abs( ) < 1E-3 , "{} != 440" , a440_f32) ;
755+ }
756+
757+ #[ cfg( feature = "std" ) ]
758+ #[ test]
759+ fn note_to_frequency_f64 ( ) {
760+ for midi in 0u8 ..=127 {
761+ let note = Note :: from_u8_lossy ( midi) ;
762+ let expected = {
763+ let exp = ( f64:: from ( midi) + 36.376_316_562_295_91 ) / 12.0 ;
764+ 2.0_f64 . powf ( exp)
765+ } ;
766+ let got = note. to_freq_f64 ( ) ;
767+ let rel_err = ( got - expected) . abs ( ) / expected;
768+ assert ! (
769+ rel_err < 1e-4 ,
770+ "note={}: got {} expected {} rel_err={}" ,
771+ midi, got, expected, rel_err
772+ ) ;
773+ }
774+ }
775+
776+ #[ cfg( feature = "std" ) ]
777+ #[ test]
778+ fn note_to_frequency_f32 ( ) {
779+ for midi in 0u8 ..=127 {
780+ let note = Note :: from_u8_lossy ( midi) ;
781+ let expected = {
782+ let exp = ( f32:: from ( midi) + 36.376_316_f32 ) / 12.0 ;
783+ 2.0_f32 . powf ( exp)
784+ } ;
785+ let got = note. to_freq_f32 ( ) ;
786+ let rel_err = ( got - expected) . abs ( ) / expected;
787+ assert ! (
788+ rel_err < 1e-4 ,
789+ "note={}: got {} expected {} rel_err={}" ,
790+ midi, got, expected, rel_err
791+ ) ;
792+ }
493793 }
494794
495795 #[ test]
0 commit comments