Mercurial > hg > svcore
comparison base/Pitch.cpp @ 1025:88b54a185a0a
Use double instead of float for frequencies in Pitch, just for confidence
author | Chris Cannam |
---|---|
date | Mon, 08 Dec 2014 15:37:12 +0000 |
parents | d1ce7a4a920b |
children | cc27f35aa75c |
comparison
equal
deleted
inserted
replaced
1024:d1ce7a4a920b | 1025:88b54a185a0a |
---|---|
17 #include "Preferences.h" | 17 #include "Preferences.h" |
18 #include "system/System.h" | 18 #include "system/System.h" |
19 | 19 |
20 #include <cmath> | 20 #include <cmath> |
21 | 21 |
22 float | 22 double |
23 Pitch::getFrequencyForPitch(int midiPitch, | 23 Pitch::getFrequencyForPitch(int midiPitch, |
24 float centsOffset, | 24 double centsOffset, |
25 float concertA) | 25 double concertA) |
26 { | 26 { |
27 if (concertA <= 0.0) { | 27 if (concertA <= 0.0) { |
28 concertA = Preferences::getInstance()->getTuningFrequency(); | 28 concertA = Preferences::getInstance()->getTuningFrequency(); |
29 } | 29 } |
30 float p = float(midiPitch) + (centsOffset / 100); | 30 double p = double(midiPitch) + (centsOffset / 100); |
31 return concertA * powf(2.0, (p - 69.0) / 12.0); | 31 return concertA * pow(2.0, (p - 69.0) / 12.0); |
32 } | 32 } |
33 | 33 |
34 int | 34 int |
35 Pitch::getPitchForFrequency(float frequency, | 35 Pitch::getPitchForFrequency(double frequency, |
36 float *centsOffsetReturn, | 36 double *centsOffsetReturn, |
37 float concertA) | 37 double concertA) |
38 { | 38 { |
39 if (concertA <= 0.0) { | 39 if (concertA <= 0.0) { |
40 concertA = Preferences::getInstance()->getTuningFrequency(); | 40 concertA = Preferences::getInstance()->getTuningFrequency(); |
41 } | 41 } |
42 float p = 12.0 * (log(frequency / (concertA / 2.0)) / log(2.0)) + 57.0; | 42 double p = 12.0 * (log(frequency / (concertA / 2.0)) / log(2.0)) + 57.0; |
43 | 43 |
44 int midiPitch = int(p + 0.00001); | 44 int midiPitch = int(round(p)); |
45 float centsOffset = (p - midiPitch) * 100.0; | 45 double centsOffset = (p - midiPitch) * 100.0; |
46 | 46 |
47 if (centsOffset >= 50.0) { | 47 if (centsOffset >= 50.0) { |
48 midiPitch = midiPitch + 1; | 48 midiPitch = midiPitch + 1; |
49 centsOffset = -(100.0 - centsOffset); | 49 centsOffset = -(100.0 - centsOffset); |
50 } | 50 } |
51 if (centsOffset < -50.0) { | |
52 midiPitch = midiPitch - 1; | |
53 centsOffset = (100.0 + centsOffset); | |
54 } | |
51 | 55 |
52 if (centsOffsetReturn) *centsOffsetReturn = centsOffset; | 56 if (centsOffsetReturn) *centsOffsetReturn = centsOffset; |
53 return midiPitch; | 57 return midiPitch; |
54 } | 58 } |
55 | 59 |
56 int | 60 int |
57 Pitch::getPitchForFrequencyDifference(float frequencyA, | 61 Pitch::getPitchForFrequencyDifference(double frequencyA, |
58 float frequencyB, | 62 double frequencyB, |
59 float *centsOffsetReturn, | 63 double *centsOffsetReturn, |
60 float concertA) | 64 double concertA) |
61 { | 65 { |
62 if (concertA <= 0.0) { | 66 if (concertA <= 0.0) { |
63 concertA = Preferences::getInstance()->getTuningFrequency(); | 67 concertA = Preferences::getInstance()->getTuningFrequency(); |
64 } | 68 } |
65 | 69 |
66 if (frequencyA > frequencyB) { | 70 if (frequencyA > frequencyB) { |
67 std::swap(frequencyA, frequencyB); | 71 std::swap(frequencyA, frequencyB); |
68 } | 72 } |
69 | 73 |
70 float pA = 12.0 * (log(frequencyA / (concertA / 2.0)) / log(2.0)) + 57.0; | 74 double pA = 12.0 * (log(frequencyA / (concertA / 2.0)) / log(2.0)) + 57.0; |
71 float pB = 12.0 * (log(frequencyB / (concertA / 2.0)) / log(2.0)) + 57.0; | 75 double pB = 12.0 * (log(frequencyB / (concertA / 2.0)) / log(2.0)) + 57.0; |
72 | 76 |
73 float p = pB - pA; | 77 double p = pB - pA; |
74 | 78 |
75 int midiPitch = int(p + 0.00001); | 79 int midiPitch = int(p + 0.00001); |
76 float centsOffset = (p - midiPitch) * 100.0; | 80 double centsOffset = (p - midiPitch) * 100.0; |
77 | 81 |
78 if (centsOffset >= 50.0) { | 82 if (centsOffset >= 50.0) { |
79 midiPitch = midiPitch + 1; | 83 midiPitch = midiPitch + 1; |
80 centsOffset = -(100.0 - centsOffset); | 84 centsOffset = -(100.0 - centsOffset); |
81 } | 85 } |
127 note = midiPitch % 12; | 131 note = midiPitch % 12; |
128 } | 132 } |
129 | 133 |
130 QString | 134 QString |
131 Pitch::getPitchLabel(int midiPitch, | 135 Pitch::getPitchLabel(int midiPitch, |
132 float centsOffset, | 136 double centsOffset, |
133 bool useFlats) | 137 bool useFlats) |
134 { | 138 { |
135 int note, octave; | 139 int note, octave; |
136 getNoteAndOctaveForPitch(midiPitch, note, octave); | 140 getNoteAndOctaveForPitch(midiPitch, note, octave); |
137 | 141 |
138 QString plain = (useFlats ? flatNotes : notes)[note].arg(octave); | 142 QString plain = (useFlats ? flatNotes : notes)[note].arg(octave); |
139 | 143 |
140 int ic = lrintf(centsOffset); | 144 int ic = lrint(centsOffset); |
141 if (ic == 0) return plain; | 145 if (ic == 0) return plain; |
142 else if (ic > 0) return QString("%1+%2c").arg(plain).arg(ic); | 146 else if (ic > 0) return QString("%1+%2c").arg(plain).arg(ic); |
143 else return QString("%1%2c").arg(plain).arg(ic); | 147 else return QString("%1%2c").arg(plain).arg(ic); |
144 } | 148 } |
145 | 149 |
146 QString | 150 QString |
147 Pitch::getPitchLabelForFrequency(float frequency, | 151 Pitch::getPitchLabelForFrequency(double frequency, |
148 float concertA, | 152 double concertA, |
149 bool useFlats) | 153 bool useFlats) |
150 { | 154 { |
151 if (concertA <= 0.0) { | 155 if (concertA <= 0.0) { |
152 concertA = Preferences::getInstance()->getTuningFrequency(); | 156 concertA = Preferences::getInstance()->getTuningFrequency(); |
153 } | 157 } |
154 float centsOffset = 0.0; | 158 double centsOffset = 0.0; |
155 int midiPitch = getPitchForFrequency(frequency, ¢sOffset, concertA); | 159 int midiPitch = getPitchForFrequency(frequency, ¢sOffset, concertA); |
156 return getPitchLabel(midiPitch, centsOffset, useFlats); | 160 return getPitchLabel(midiPitch, centsOffset, useFlats); |
157 } | 161 } |
158 | 162 |
159 QString | 163 QString |
160 Pitch::getLabelForPitchRange(int semis, float cents) | 164 Pitch::getLabelForPitchRange(int semis, double cents) |
161 { | 165 { |
162 if (semis > 0) { | 166 if (semis > 0) { |
163 while (cents < 0.f) { | 167 while (cents < 0.0) { |
164 --semis; | 168 --semis; |
165 cents += 100.f; | 169 cents += 100.0; |
166 } | 170 } |
167 } | 171 } |
168 if (semis < 0) { | 172 if (semis < 0) { |
169 while (cents > 0.f) { | 173 while (cents > 0.0) { |
170 ++semis; | 174 ++semis; |
171 cents -= 100.f; | 175 cents -= 100.0; |
172 } | 176 } |
173 } | 177 } |
174 | 178 |
175 int ic = lrintf(cents); | 179 int ic = lrint(cents); |
176 | 180 |
177 if (ic == 0) { | 181 if (ic == 0) { |
178 if (semis >= 12) { | 182 if (semis >= 12) { |
179 return QString("%1'%2").arg(semis/12).arg(semis - 12*(semis/12)); | 183 return QString("%1'%2").arg(semis/12).arg(semis - 12*(semis/12)); |
180 } else { | 184 } else { |
196 } | 200 } |
197 } | 201 } |
198 } | 202 } |
199 | 203 |
200 bool | 204 bool |
201 Pitch::isFrequencyInMidiRange(float frequency, | 205 Pitch::isFrequencyInMidiRange(double frequency, |
202 float concertA) | 206 double concertA) |
203 { | 207 { |
204 float centsOffset = 0.0; | 208 double centsOffset = 0.0; |
205 int midiPitch = getPitchForFrequency(frequency, ¢sOffset, concertA); | 209 int midiPitch = getPitchForFrequency(frequency, ¢sOffset, concertA); |
206 return (midiPitch >= 0 && midiPitch < 128); | 210 return (midiPitch >= 0 && midiPitch < 128); |
207 } | 211 } |
208 | 212 |