Mercurial > hg > svgui
comparison layer/SpectrogramLayer.cpp @ 1058:9a13bc339fa9 spectrogram-minor-refactor
Mid-refactor to pull out the bulk of paintDrawBuffer into chunks
| author | Chris Cannam |
|---|---|
| date | Mon, 13 Jun 2016 16:17:44 +0100 |
| parents | b4fd6c67fce5 |
| children | e1c2dcc7790e |
comparison
equal
deleted
inserted
replaced
| 1057:218be6cf2d4f | 1058:9a13bc339fa9 |
|---|---|
| 2350 } | 2350 } |
| 2351 | 2351 |
| 2352 return columnCount; | 2352 return columnCount; |
| 2353 } | 2353 } |
| 2354 | 2354 |
| 2355 void | |
| 2356 SpectrogramLayer::normalise(vector<float> &values, Normalization norm) const | |
| 2357 { | |
| 2358 if (norm == NormalizeColumns || | |
| 2359 norm == NormalizeHybrid) { | |
| 2360 | |
| 2361 float max = 0.f; | |
| 2362 for (int i = 0; in_range_for(i, values); ++i) { | |
| 2363 if (i == 0 || values[i] > max) { | |
| 2364 max = values[i]; | |
| 2365 } | |
| 2366 } | |
| 2367 if (max > 0.f) { | |
| 2368 float scale = 1.f / max; | |
| 2369 if (norm == NormalizeHybrid) { | |
| 2370 scale = scale * log10f(max + 1.f); | |
| 2371 } | |
| 2372 for (int i = 0; in_range_for(i, values); ++i) { | |
| 2373 values[i] *= scale; | |
| 2374 } | |
| 2375 } | |
| 2376 } | |
| 2377 } | |
| 2378 | |
| 2379 vector<float> | |
| 2380 SpectrogramLayer::getColumnFromFFTModel(FFTModel *fft, | |
| 2381 int sx, // column number in model | |
| 2382 int minbin, | |
| 2383 int bincount) const | |
| 2384 { | |
| 2385 vector<float> values(bincount, 0.f); | |
| 2386 | |
| 2387 if (m_colourScale == PhaseColourScale) { | |
| 2388 fft->getPhasesAt(sx, values.data(), minbin, bincount); | |
| 2389 } else { | |
| 2390 fft->getMagnitudesAt(sx, values.data(), minbin, bincount); | |
| 2391 } | |
| 2392 | |
| 2393 return move(values); | |
| 2394 } | |
| 2395 | |
| 2396 vector<float> | |
| 2397 SpectrogramLayer::getColumnFromGenericModel(DenseThreeDimensionalModel *model, | |
| 2398 int sx, // column number in model | |
| 2399 int minbin, | |
| 2400 int bincount) const | |
| 2401 { | |
| 2402 if (m_colourScale == PhaseColourScale) { | |
| 2403 throw std::logic_error("can't use phase scale with generic 3d model"); | |
| 2404 } | |
| 2405 | |
| 2406 auto col = model->getColumn(sx); | |
| 2407 | |
| 2408 return move(vector<float>(col.data() + minbin, | |
| 2409 col.data() + minbin + bincount)); | |
| 2410 } | |
| 2411 | |
| 2412 void | |
| 2413 SpectrogramLayer::scaleColumn(vector<float> &col) | |
| 2414 { | |
| 2415 if (m_normalization != NormalizeColumns && | |
| 2416 m_normalization != NormalizeHybrid) { | |
| 2417 float scale = 2.f / float(m_fftSize); | |
| 2418 int n = int(col.size()); | |
| 2419 for (int i = 0; i < n; ++i) { | |
| 2420 col[i] *= scale; | |
| 2421 } | |
| 2422 } | |
| 2423 } | |
| 2424 | |
| 2425 static bool | |
| 2426 is_peak(const vector<float> &values, int ix) | |
| 2427 { | |
| 2428 if (!in_range_for(ix-1, values)) return false; | |
| 2429 if (!in_range_for(ix+1, values)) return false; | |
| 2430 if (values[ix] < values[ix+1]) return false; | |
| 2431 if (values[ix] < values[ix-1]) return false; | |
| 2432 return true; | |
| 2433 } | |
| 2434 | |
| 2435 vector<float> | |
| 2436 SpectrogramLayer::distributeColumn(const vector<float> &in, | |
| 2437 int h, | |
| 2438 const vector<double> &binfory, | |
| 2439 int minbin, | |
| 2440 bool interpolate) | |
| 2441 { | |
| 2442 vector<float> out(h, 0.f); | |
| 2443 int bins = int(in.size()); | |
| 2444 | |
| 2445 for (int y = 0; y < h; ++y) { | |
| 2446 | |
| 2447 double sy0 = binfory[y] - minbin; | |
| 2448 double sy1 = sy0 + 1; | |
| 2449 if (y+1 < h) { | |
| 2450 sy1 = binfory[y+1] - minbin; | |
| 2451 } | |
| 2452 | |
| 2453 if (interpolate && fabs(sy1 - sy0) < 1.0) { | |
| 2454 | |
| 2455 double centre = (sy0 + sy1) / 2; | |
| 2456 double dist = (centre - 0.5) - rint(centre - 0.5); | |
| 2457 int bin = int(centre); | |
| 2458 | |
| 2459 int other = (dist < 0 ? (bin-1) : (bin+1)); | |
| 2460 | |
| 2461 if (bin < 0) bin = 0; | |
| 2462 if (bin >= bins) bin = bins-1; | |
| 2463 | |
| 2464 if (other < 0 || other >= bins) { | |
| 2465 other = bin; | |
| 2466 } | |
| 2467 | |
| 2468 if (m_binDisplay == PeakBins) { | |
| 2469 | |
| 2470 if (is_peak(in, bin)) { | |
| 2471 out[y] = in[bin]; | |
| 2472 } else if (other != bin && is_peak(in, other)) { | |
| 2473 out[y] = in[other]; | |
| 2474 } | |
| 2475 | |
| 2476 } else { | |
| 2477 | |
| 2478 double prop = 1.0 - fabs(dist); | |
| 2479 | |
| 2480 double v0 = in[bin]; | |
| 2481 double v1 = in[other]; | |
| 2482 | |
| 2483 out[y] = float(prop * v0 + (1.0 - prop) * v1); | |
| 2484 } | |
| 2485 | |
| 2486 } else { // not interpolating this one | |
| 2487 | |
| 2488 int by0 = int(sy0 + 0.0001); | |
| 2489 int by1 = int(sy1 + 0.0001); | |
| 2490 if (by1 < by0 + 1) by1 = by0 + 1; | |
| 2491 | |
| 2492 for (int bin = by0; bin < by1; ++bin) { | |
| 2493 | |
| 2494 if (m_binDisplay == PeakBins && !is_peak(in, bin)) { | |
| 2495 continue; | |
| 2496 } | |
| 2497 | |
| 2498 float value = in[bin]; | |
| 2499 | |
| 2500 if (value > out[y] || m_colourScale == PhaseColourScale) { | |
| 2501 out[y] = value; | |
| 2502 } | |
| 2503 } | |
| 2504 } | |
| 2505 } | |
| 2506 | |
| 2507 return out; | |
| 2508 } | |
| 2509 | |
| 2510 void | |
| 2511 SpectrogramLayer::recordColumnExtents(const vector<float> &col, | |
| 2512 int sx, // column index, for m_columnMags | |
| 2513 MagnitudeRange &overallMag, | |
| 2514 bool &overallMagChanged) | |
| 2515 { | |
| 2516 //!!! this differs from previous logic when in peak mode - as the | |
| 2517 //!!! zeros between peaks are now sampled, where they were not | |
| 2518 //!!! before | |
| 2519 | |
| 2520 if (!in_range_for(sx, m_columnMags)) { | |
| 2521 throw logic_error("sx out of range for m_columnMags"); | |
| 2522 } | |
| 2523 MagnitudeRange mr; | |
| 2524 for (auto v: col) { | |
| 2525 mr.sample(v); | |
| 2526 } | |
| 2527 m_columnMags[sx] = mr; | |
| 2528 if (overallMag.sample(mr)) { | |
| 2529 overallMagChanged = true; | |
| 2530 } | |
| 2531 } | |
| 2532 | |
| 2533 // order: | |
| 2534 // get column -> scale -> distribute/interpolate -> record extents -> normalise -> apply display gain | |
| 2535 | |
| 2355 int | 2536 int |
| 2356 SpectrogramLayer::paintDrawBuffer(LayerGeometryProvider *v, | 2537 SpectrogramLayer::paintDrawBuffer(LayerGeometryProvider *v, |
| 2357 int w, | 2538 int w, |
| 2358 int h, | 2539 int h, |
| 2359 const vector<int> &binforx, | 2540 const vector<int> &binforx, |
