annotate base/ColumnOp.cpp @ 1267:1d8418cca63a 3.0-integration

Further column op tests and fixes
author Chris Cannam
date Thu, 17 Nov 2016 14:46:03 +0000
parents
children 2f468f43c02c
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@1267 22 using namespace std;
Chris@1267 23
Chris@1267 24 ColumnOp::Column
Chris@1267 25 ColumnOp::fftScale(const Column &in, int fftSize)
Chris@1267 26 {
Chris@1267 27 return applyGain(in, 2.0 / fftSize);
Chris@1267 28 }
Chris@1267 29
Chris@1267 30 ColumnOp::Column
Chris@1267 31 ColumnOp::peakPick(const Column &in)
Chris@1267 32 {
Chris@1267 33 vector<float> out(in.size(), 0.f);
Chris@1267 34
Chris@1267 35 for (int i = 0; in_range_for(in, i); ++i) {
Chris@1267 36 if (isPeak(in, i)) {
Chris@1267 37 out[i] = in[i];
Chris@1267 38 }
Chris@1267 39 }
Chris@1267 40
Chris@1267 41 return out;
Chris@1267 42 }
Chris@1267 43
Chris@1267 44 ColumnOp::Column
Chris@1267 45 ColumnOp::normalize(const Column &in, ColumnNormalization n) {
Chris@1267 46
Chris@1267 47 if (n == ColumnNormalization::None || in.empty()) {
Chris@1267 48 return in;
Chris@1267 49 }
Chris@1267 50
Chris@1267 51 float scale = 1.f;
Chris@1267 52
Chris@1267 53 if (n == ColumnNormalization::Sum1) {
Chris@1267 54
Chris@1267 55 float sum = 0.f;
Chris@1267 56
Chris@1267 57 for (auto v: in) {
Chris@1267 58 sum += fabsf(v);
Chris@1267 59 }
Chris@1267 60
Chris@1267 61 if (sum != 0.f) {
Chris@1267 62 scale = 1.f / sum;
Chris@1267 63 }
Chris@1267 64
Chris@1267 65 } else {
Chris@1267 66
Chris@1267 67 float max = 0.f;
Chris@1267 68
Chris@1267 69 for (auto v: in) {
Chris@1267 70 v = fabsf(v);
Chris@1267 71 if (v > max) {
Chris@1267 72 max = v;
Chris@1267 73 }
Chris@1267 74 }
Chris@1267 75
Chris@1267 76 if (n == ColumnNormalization::Max1) {
Chris@1267 77 if (max != 0.f) {
Chris@1267 78 scale = 1.f / max;
Chris@1267 79 }
Chris@1267 80 } else if (n == ColumnNormalization::Hybrid) {
Chris@1267 81 if (max > 0.f) {
Chris@1267 82 scale = log10f(max + 1.f) / max;
Chris@1267 83 }
Chris@1267 84 }
Chris@1267 85 }
Chris@1267 86
Chris@1267 87 return applyGain(in, scale);
Chris@1267 88 }
Chris@1267 89
Chris@1267 90 ColumnOp::Column
Chris@1267 91 ColumnOp::distribute(const Column &in,
Chris@1267 92 int h,
Chris@1267 93 const vector<double> &binfory,
Chris@1267 94 int minbin,
Chris@1267 95 bool interpolate)
Chris@1267 96 {
Chris@1267 97 vector<float> out(h, 0.f);
Chris@1267 98 int bins = int(in.size());
Chris@1267 99
Chris@1267 100 for (int y = 0; y < h; ++y) {
Chris@1267 101
Chris@1267 102 if (interpolate && h > bins) {
Chris@1267 103
Chris@1267 104 double sy = binfory[y] - minbin - 0.5;
Chris@1267 105 double syf = floor(sy);
Chris@1267 106
Chris@1267 107 int mainbin = int(syf);
Chris@1267 108 int other = mainbin;
Chris@1267 109 if (sy > syf) {
Chris@1267 110 other = mainbin + 1;
Chris@1267 111 } else if (sy < syf) {
Chris@1267 112 other = mainbin - 1;
Chris@1267 113 }
Chris@1267 114
Chris@1267 115 if (mainbin < 0) {
Chris@1267 116 mainbin = 0;
Chris@1267 117 }
Chris@1267 118 if (mainbin >= bins) {
Chris@1267 119 mainbin = bins - 1;
Chris@1267 120 }
Chris@1267 121
Chris@1267 122 if (other < 0) {
Chris@1267 123 other = 0;
Chris@1267 124 }
Chris@1267 125 if (other >= bins) {
Chris@1267 126 other = bins - 1;
Chris@1267 127 }
Chris@1267 128
Chris@1267 129 double prop = 1.0 - fabs(sy - syf);
Chris@1267 130
Chris@1267 131 double v0 = in[mainbin];
Chris@1267 132 double v1 = in[other];
Chris@1267 133
Chris@1267 134 out[y] = float(prop * v0 + (1.0 - prop) * v1);
Chris@1267 135
Chris@1267 136 } else {
Chris@1267 137
Chris@1267 138 double sy0 = binfory[y] - minbin;
Chris@1267 139
Chris@1267 140 double sy1;
Chris@1267 141 if (y+1 < h) {
Chris@1267 142 sy1 = binfory[y+1] - minbin;
Chris@1267 143 } else {
Chris@1267 144 sy1 = bins;
Chris@1267 145 }
Chris@1267 146
Chris@1267 147 int by0 = int(sy0 + 0.0001);
Chris@1267 148 int by1 = int(sy1 + 0.0001);
Chris@1267 149
Chris@1267 150 for (int bin = by0; bin == by0 || bin < by1; ++bin) {
Chris@1267 151
Chris@1267 152 float value = in[bin];
Chris@1267 153
Chris@1267 154 if (bin == by0 || value > out[y]) {
Chris@1267 155 out[y] = value;
Chris@1267 156 }
Chris@1267 157 }
Chris@1267 158 }
Chris@1267 159 }
Chris@1267 160
Chris@1267 161 return out;
Chris@1267 162 }