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 {