Mercurial > hg > svgui
comparison layer/SliceLayer.cpp @ 1386:fc3d89f88690 spectrogramparam
Use log-frequency rather than log-bin for calculating x coord in spectrum. This has the advantage that frequency positions don't move when we change the window size or oversampling ratio, but it does give us an unhelpfully large amount of space for very low frequencies - to be considered
author | Chris Cannam |
---|---|
date | Mon, 12 Nov 2018 11:34:34 +0000 |
parents | 413e09f303ba |
children | bca9870301b7 |
comparison
equal
deleted
inserted
replaced
1385:37e9d6a1e00c | 1386:fc3d89f88690 |
---|---|
191 } | 191 } |
192 | 192 |
193 double | 193 double |
194 SliceLayer::getXForBin(const LayerGeometryProvider *v, double bin) const | 194 SliceLayer::getXForBin(const LayerGeometryProvider *v, double bin) const |
195 { | 195 { |
196 return getXForScalePoint(v, bin, m_minbin, m_maxbin); | |
197 } | |
198 | |
199 double | |
200 SliceLayer::getXForScalePoint(const LayerGeometryProvider *v, | |
201 double p, double pmin, double pmax) const | |
202 { | |
196 double x = 0; | 203 double x = 0; |
197 | 204 |
198 bin -= m_minbin; | 205 p -= pmin; |
199 if (bin < 0) bin = 0; | 206 if (p < 0) p = 0; |
200 | 207 |
201 double count = m_maxbin - m_minbin; | 208 double extent = pmax - pmin; |
202 if (count < 0) count = 0; | 209 if (extent < 0) extent = 0; |
203 | 210 |
204 int pw = v->getPaintWidth(); | 211 int pw = v->getPaintWidth(); |
205 int origin = m_xorigins[v->getId()]; | 212 int origin = m_xorigins[v->getId()]; |
206 int w = pw - origin; | 213 int w = pw - origin; |
207 if (w < 1) w = 1; | 214 if (w < 1) w = 1; |
208 | 215 |
209 switch (m_binScale) { | 216 switch (m_binScale) { |
210 | 217 |
211 case LinearBins: | 218 case LinearBins: |
212 x = (w * bin) / count; | 219 x = (w * p) / extent; |
213 break; | 220 break; |
214 | 221 |
215 case LogBins: | 222 case LogBins: |
216 // The 0.8 here is an awkward compromise. Our x-coord is | 223 // The 0.8 here is an awkward compromise. Our x-coord is |
217 // proportional to log of bin number, with the x-coord "of a | 224 // proportional to log of bin number, with the x-coord "of a |
223 // for that bin is in the middle of it. Yet in some modes | 230 // for that bin is in the middle of it. Yet in some modes |
224 // we'll still want it. A compromise is to count our first bin | 231 // we'll still want it. A compromise is to count our first bin |
225 // as "a bit less than 1", so that most of it is visible but a | 232 // as "a bit less than 1", so that most of it is visible but a |
226 // bit is tactfully cropped at the left edge so it doesn't | 233 // bit is tactfully cropped at the left edge so it doesn't |
227 // take up so much space. | 234 // take up so much space. |
228 x = (w * log10(bin + 0.8)) / log10(count + 0.8); | 235 x = (w * log10(p + 0.8)) / log10(extent + 0.8); |
229 break; | 236 break; |
230 | 237 |
231 case InvertedLogBins: | 238 case InvertedLogBins: |
232 x = w - (w * log10(count - bin - 1)) / log10(count); | 239 x = w - (w * log10(extent - p - 1)) / log10(extent); |
233 break; | 240 break; |
234 } | 241 } |
235 | 242 |
236 return x + origin; | 243 return x + origin; |
237 } | 244 } |
238 | 245 |
239 double | 246 double |
240 SliceLayer::getBinForX(const LayerGeometryProvider *v, double x) const | 247 SliceLayer::getBinForX(const LayerGeometryProvider *v, double x) const |
241 { | 248 { |
242 double bin = 0; | 249 return getScalePointForX(v, x, m_minbin, m_maxbin); |
243 | 250 } |
244 double count = m_maxbin - m_minbin; | 251 |
245 if (count < 0) count = 0; | 252 double |
253 SliceLayer::getScalePointForX(const LayerGeometryProvider *v, | |
254 double x, double pmin, double pmax) const | |
255 { | |
256 double p = 0; | |
257 | |
258 double extent = pmax - pmin; | |
259 if (extent < 0) extent = 0; | |
246 | 260 |
247 int pw = v->getPaintWidth(); | 261 int pw = v->getPaintWidth(); |
248 int origin = m_xorigins[v->getId()]; | 262 int origin = m_xorigins[v->getId()]; |
249 | 263 |
250 int w = pw - origin; | 264 int w = pw - origin; |
256 double eps = 1e-10; | 270 double eps = 1e-10; |
257 | 271 |
258 switch (m_binScale) { | 272 switch (m_binScale) { |
259 | 273 |
260 case LinearBins: | 274 case LinearBins: |
261 bin = (x * count) / w + eps; | 275 p = (x * extent) / w + eps; |
262 break; | 276 break; |
263 | 277 |
264 case LogBins: | 278 case LogBins: |
265 // See comment in getXForBin | 279 // See comment in getXForScalePoint |
266 bin = pow(10.0, (x * log10(count + 0.8)) / w) - 0.8 + eps; | 280 p = pow(10.0, (x * log10(extent + 0.8)) / w) - 0.8 + eps; |
267 break; | 281 break; |
268 | 282 |
269 case InvertedLogBins: | 283 case InvertedLogBins: |
270 bin = count + 1 - pow(10.0, (log10(count) * (w - x)) / double(w)) + eps; | 284 p = extent + 1 - pow(10.0, (log10(extent) * (w - x)) / double(w)) + eps; |
271 break; | 285 break; |
272 } | 286 } |
273 | 287 |
274 return bin + m_minbin; | 288 return p + pmin; |
275 } | 289 } |
276 | 290 |
277 double | 291 double |
278 SliceLayer::getYForValue(const LayerGeometryProvider *v, double value, double &norm) const | 292 SliceLayer::getYForValue(const LayerGeometryProvider *v, double value, double &norm) const |
279 { | 293 { |