annotate base/ColumnOp.cpp @ 1346:75ad55315db4 3.0-integration

More work on getting tests (especially file encoding ones) running on Windows. Various problems here to do with interaction with test filenames in Hg repos
author Chris Cannam
date Fri, 06 Jan 2017 15:44:55 +0000
parents 47ee4706055c
children 9ef1cc26024c
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@1303 102 if (interpolate) {
Chris@1303 103 // If the bins are all closer together than the target y
Chris@1303 104 // coordinate increments, then we don't want to interpolate
Chris@1303 105 // after all. But because the binfory mapping isn't
Chris@1303 106 // necessarily linear, just checking e.g. whether bins > h is
Chris@1303 107 // not enough -- the bins could still be spaced more widely at
Chris@1303 108 // either end of the scale. We are prepared to assume however
Chris@1303 109 // that if the bins are closer at both ends of the scale, they
Chris@1303 110 // aren't going to diverge mysteriously in the middle.
Chris@1303 111 if (h > 1 &&
Chris@1303 112 fabs(binfory[1] - binfory[0]) >= 1.0 &&
Chris@1303 113 fabs(binfory[h-1] - binfory[h-2]) >= 1.0) {
Chris@1303 114 interpolate = false;
Chris@1303 115 }
Chris@1303 116 }
Chris@1303 117
Chris@1267 118 for (int y = 0; y < h; ++y) {
Chris@1267 119
cannam@1301 120 if (interpolate) {
Chris@1267 121
Chris@1267 122 double sy = binfory[y] - minbin - 0.5;
Chris@1267 123 double syf = floor(sy);
Chris@1267 124
Chris@1267 125 int mainbin = int(syf);
Chris@1267 126 int other = mainbin;
Chris@1267 127 if (sy > syf) {
Chris@1267 128 other = mainbin + 1;
Chris@1267 129 } else if (sy < syf) {
Chris@1267 130 other = mainbin - 1;
Chris@1267 131 }
Chris@1267 132
Chris@1267 133 if (mainbin < 0) {
Chris@1267 134 mainbin = 0;
Chris@1267 135 }
Chris@1267 136 if (mainbin >= bins) {
Chris@1267 137 mainbin = bins - 1;
Chris@1267 138 }
Chris@1267 139
Chris@1267 140 if (other < 0) {
Chris@1267 141 other = 0;
Chris@1267 142 }
Chris@1267 143 if (other >= bins) {
Chris@1267 144 other = bins - 1;
Chris@1267 145 }
Chris@1267 146
Chris@1267 147 double prop = 1.0 - fabs(sy - syf);
Chris@1267 148
Chris@1267 149 double v0 = in[mainbin];
Chris@1267 150 double v1 = in[other];
Chris@1267 151
Chris@1267 152 out[y] = float(prop * v0 + (1.0 - prop) * v1);
Chris@1267 153
Chris@1267 154 } else {
Chris@1267 155
Chris@1267 156 double sy0 = binfory[y] - minbin;
Chris@1267 157
Chris@1267 158 double sy1;
Chris@1267 159 if (y+1 < h) {
Chris@1267 160 sy1 = binfory[y+1] - minbin;
Chris@1267 161 } else {
Chris@1267 162 sy1 = bins;
Chris@1267 163 }
Chris@1267 164
Chris@1267 165 int by0 = int(sy0 + 0.0001);
Chris@1267 166 int by1 = int(sy1 + 0.0001);
Chris@1283 167
Chris@1283 168 if (by0 < 0 || by0 >= bins || by1 > bins) {
Chris@1283 169 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 170 continue;
Chris@1283 171 }
Chris@1267 172
Chris@1267 173 for (int bin = by0; bin == by0 || bin < by1; ++bin) {
Chris@1267 174
Chris@1267 175 float value = in[bin];
Chris@1267 176
Chris@1267 177 if (bin == by0 || value > out[y]) {
Chris@1267 178 out[y] = value;
Chris@1267 179 }
Chris@1267 180 }
Chris@1267 181 }
Chris@1267 182 }
Chris@1267 183
Chris@1267 184 return out;
Chris@1267 185 }