annotate base/ColumnOp.cpp @ 1301:6681027ff2ff 3.0-integration

Interpolate always, when interpolation requested. Previous test failed to take into account varying bin height in log-scale modes, which meant interpolation might be necessary even when more bins than pixels.
author Chris Cannam <cannam@all-day-breakfast.com>
date Mon, 28 Nov 2016 14:40:45 +0000
parents 2f468f43c02c
children 47ee4706055c
rev   line source
Chris@1267 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@1267 2
Chris@1267 3 /*
Chris@1267 4 Sonic Visualiser
Chris@1267 5 An audio file viewer and annotation editor.
Chris@1267 6 Centre for Digital Music, Queen Mary, University of London.
Chris@1267 7 This file copyright 2006-2016 Chris Cannam and QMUL.
Chris@1267 8
Chris@1267 9 This program is free software; you can redistribute it and/or
Chris@1267 10 modify it under the terms of the GNU General Public License as
Chris@1267 11 published by the Free Software Foundation; either version 2 of the
Chris@1267 12 License, or (at your option) any later version. See the file
Chris@1267 13 COPYING included with this distribution for more information.
Chris@1267 14 */
Chris@1267 15
Chris@1267 16 #include "ColumnOp.h"
Chris@1267 17
Chris@1267 18 #include <cmath>
Chris@1267 19 #include <algorithm>
Chris@1267 20 #include <iostream>
Chris@1267 21
Chris@1283 22 #include "base/Debug.h"
Chris@1283 23
Chris@1267 24 using namespace std;
Chris@1267 25
Chris@1267 26 ColumnOp::Column
Chris@1267 27 ColumnOp::fftScale(const Column &in, int fftSize)
Chris@1267 28 {
Chris@1267 29 return applyGain(in, 2.0 / fftSize);
Chris@1267 30 }
Chris@1267 31
Chris@1267 32 ColumnOp::Column
Chris@1267 33 ColumnOp::peakPick(const Column &in)
Chris@1267 34 {
Chris@1267 35 vector<float> out(in.size(), 0.f);
Chris@1267 36
Chris@1267 37 for (int i = 0; in_range_for(in, i); ++i) {
Chris@1267 38 if (isPeak(in, i)) {
Chris@1267 39 out[i] = in[i];
Chris@1267 40 }
Chris@1267 41 }
Chris@1267 42
Chris@1267 43 return out;
Chris@1267 44 }
Chris@1267 45
Chris@1267 46 ColumnOp::Column
Chris@1267 47 ColumnOp::normalize(const Column &in, ColumnNormalization n) {
Chris@1267 48
Chris@1267 49 if (n == ColumnNormalization::None || in.empty()) {
Chris@1267 50 return in;
Chris@1267 51 }
Chris@1267 52
Chris@1267 53 float scale = 1.f;
Chris@1267 54
Chris@1267 55 if (n == ColumnNormalization::Sum1) {
Chris@1267 56
Chris@1267 57 float sum = 0.f;
Chris@1267 58
Chris@1267 59 for (auto v: in) {
Chris@1267 60 sum += fabsf(v);
Chris@1267 61 }
Chris@1267 62
Chris@1267 63 if (sum != 0.f) {
Chris@1267 64 scale = 1.f / sum;
Chris@1267 65 }
Chris@1267 66
Chris@1267 67 } else {
Chris@1267 68
Chris@1267 69 float max = 0.f;
Chris@1267 70
Chris@1267 71 for (auto v: in) {
Chris@1267 72 v = fabsf(v);
Chris@1267 73 if (v > max) {
Chris@1267 74 max = v;
Chris@1267 75 }
Chris@1267 76 }
Chris@1267 77
Chris@1267 78 if (n == ColumnNormalization::Max1) {
Chris@1267 79 if (max != 0.f) {
Chris@1267 80 scale = 1.f / max;
Chris@1267 81 }
Chris@1267 82 } else if (n == ColumnNormalization::Hybrid) {
Chris@1267 83 if (max > 0.f) {
Chris@1267 84 scale = log10f(max + 1.f) / max;
Chris@1267 85 }
Chris@1267 86 }
Chris@1267 87 }
Chris@1267 88
Chris@1267 89 return applyGain(in, scale);
Chris@1267 90 }
Chris@1267 91
Chris@1267 92 ColumnOp::Column
Chris@1267 93 ColumnOp::distribute(const Column &in,
Chris@1267 94 int h,
Chris@1267 95 const vector<double> &binfory,
Chris@1267 96 int minbin,
Chris@1267 97 bool interpolate)
Chris@1267 98 {
Chris@1267 99 vector<float> out(h, 0.f);
Chris@1267 100 int bins = int(in.size());
Chris@1267 101
Chris@1267 102 for (int y = 0; y < h; ++y) {
Chris@1267 103
cannam@1301 104 if (interpolate) {
Chris@1267 105
Chris@1267 106 double sy = binfory[y] - minbin - 0.5;
Chris@1267 107 double syf = floor(sy);
Chris@1267 108
Chris@1267 109 int mainbin = int(syf);
Chris@1267 110 int other = mainbin;
Chris@1267 111 if (sy > syf) {
Chris@1267 112 other = mainbin + 1;
Chris@1267 113 } else if (sy < syf) {
Chris@1267 114 other = mainbin - 1;
Chris@1267 115 }
Chris@1267 116
Chris@1267 117 if (mainbin < 0) {
Chris@1267 118 mainbin = 0;
Chris@1267 119 }
Chris@1267 120 if (mainbin >= bins) {
Chris@1267 121 mainbin = bins - 1;
Chris@1267 122 }
Chris@1267 123
Chris@1267 124 if (other < 0) {
Chris@1267 125 other = 0;
Chris@1267 126 }
Chris@1267 127 if (other >= bins) {
Chris@1267 128 other = bins - 1;
Chris@1267 129 }
Chris@1267 130
Chris@1267 131 double prop = 1.0 - fabs(sy - syf);
Chris@1267 132
Chris@1267 133 double v0 = in[mainbin];
Chris@1267 134 double v1 = in[other];
Chris@1267 135
Chris@1267 136 out[y] = float(prop * v0 + (1.0 - prop) * v1);
Chris@1267 137
Chris@1267 138 } else {
Chris@1267 139
Chris@1267 140 double sy0 = binfory[y] - minbin;
Chris@1267 141
Chris@1267 142 double sy1;
Chris@1267 143 if (y+1 < h) {
Chris@1267 144 sy1 = binfory[y+1] - minbin;
Chris@1267 145 } else {
Chris@1267 146 sy1 = bins;
Chris@1267 147 }
Chris@1267 148
Chris@1267 149 int by0 = int(sy0 + 0.0001);
Chris@1267 150 int by1 = int(sy1 + 0.0001);
Chris@1283 151
Chris@1283 152 if (by0 < 0 || by0 >= bins || by1 > bins) {
Chris@1283 153 SVCERR << "ERROR: bin index out of range in ColumnOp::distribute: by0 = " << by0 << ", by1 = " << by1 << ", sy0 = " << sy0 << ", sy1 = " << sy1 << ", y = " << y << ", binfory[y] = " << binfory[y] << ", minbin = " << minbin << ", bins = " << bins << endl;
Chris@1283 154 continue;
Chris@1283 155 }
Chris@1267 156
Chris@1267 157 for (int bin = by0; bin == by0 || bin < by1; ++bin) {
Chris@1267 158
Chris@1267 159 float value = in[bin];
Chris@1267 160
Chris@1267 161 if (bin == by0 || value > out[y]) {
Chris@1267 162 out[y] = value;
Chris@1267 163 }
Chris@1267 164 }
Chris@1267 165 }
Chris@1267 166 }
Chris@1267 167
Chris@1267 168 return out;
Chris@1267 169 }