annotate base/ColumnOp.h @ 1187:fd40a5335968 spectrogram-minor-refactor

Pull out column ops into ColumnOp
author Chris Cannam
date Mon, 20 Jun 2016 11:30:15 +0100
parents
children d9698ee93659
rev   line source
Chris@1187 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@1187 2
Chris@1187 3 /*
Chris@1187 4 Sonic Visualiser
Chris@1187 5 An audio file viewer and annotation editor.
Chris@1187 6 Centre for Digital Music, Queen Mary, University of London.
Chris@1187 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@1187 8
Chris@1187 9 This program is free software; you can redistribute it and/or
Chris@1187 10 modify it under the terms of the GNU General Public License as
Chris@1187 11 published by the Free Software Foundation; either version 2 of the
Chris@1187 12 License, or (at your option) any later version. See the file
Chris@1187 13 COPYING included with this distribution for more information.
Chris@1187 14 */
Chris@1187 15
Chris@1187 16 #ifndef COLUMN_OP_H
Chris@1187 17 #define COLUMN_OP_H
Chris@1187 18
Chris@1187 19 #include "BaseTypes.h"
Chris@1187 20
Chris@1187 21 #include <cmath>
Chris@1187 22
Chris@1187 23 class ColumnOp
Chris@1187 24 {
Chris@1187 25 public:
Chris@1187 26 typedef std::vector<float> Column;
Chris@1187 27
Chris@1187 28 enum Normalization {
Chris@1187 29 NoNormalization,
Chris@1187 30 NormalizeColumns,
Chris@1187 31 NormalizeVisibleArea,
Chris@1187 32 NormalizeHybrid
Chris@1187 33 };
Chris@1187 34
Chris@1187 35 static Column fftScale(const Column &in, int fftSize) {
Chris@1187 36
Chris@1187 37 Column out;
Chris@1187 38 out.reserve(in.size());
Chris@1187 39 float scale = 2.f / float(fftSize);
Chris@1187 40 for (auto v: in) {
Chris@1187 41 out.push_back(v * scale);
Chris@1187 42 }
Chris@1187 43
Chris@1187 44 return out;
Chris@1187 45 }
Chris@1187 46
Chris@1187 47 static bool isPeak(const Column &in, int ix) {
Chris@1187 48
Chris@1187 49 if (!in_range_for(in, ix-1)) return false;
Chris@1187 50 if (!in_range_for(in, ix+1)) return false;
Chris@1187 51 if (in[ix] < in[ix+1]) return false;
Chris@1187 52 if (in[ix] < in[ix-1]) return false;
Chris@1187 53
Chris@1187 54 return true;
Chris@1187 55 }
Chris@1187 56
Chris@1187 57 static Column peakPick(const Column &in) {
Chris@1187 58
Chris@1187 59 std::vector<float> out(in.size(), 0.f);
Chris@1187 60 for (int i = 0; in_range_for(in, i); ++i) {
Chris@1187 61 if (isPeak(in, i)) {
Chris@1187 62 out[i] = in[i];
Chris@1187 63 }
Chris@1187 64 }
Chris@1187 65
Chris@1187 66 return out;
Chris@1187 67 }
Chris@1187 68
Chris@1187 69 static Column normalize(const Column &in, Normalization n) {
Chris@1187 70
Chris@1187 71 if (n == NoNormalization || n == NormalizeVisibleArea) {
Chris@1187 72 return in;
Chris@1187 73 }
Chris@1187 74
Chris@1187 75 float max = *max_element(in.begin(), in.end());
Chris@1187 76
Chris@1187 77 if (n == NormalizeColumns && max == 0.f) {
Chris@1187 78 return in;
Chris@1187 79 }
Chris@1187 80
Chris@1187 81 if (n == NormalizeHybrid && max <= 0.f) {
Chris@1187 82 return in;
Chris@1187 83 }
Chris@1187 84
Chris@1187 85 std::vector<float> out;
Chris@1187 86 out.reserve(in.size());
Chris@1187 87
Chris@1187 88 float scale;
Chris@1187 89 if (n == NormalizeHybrid) {
Chris@1187 90 scale = log10f(max + 1.f) / max;
Chris@1187 91 } else {
Chris@1187 92 scale = 1.f / max;
Chris@1187 93 }
Chris@1187 94
Chris@1187 95 for (auto v: in) {
Chris@1187 96 out.push_back(v * scale);
Chris@1187 97 }
Chris@1187 98 return out;
Chris@1187 99 }
Chris@1187 100
Chris@1187 101 static Column applyGain(const Column &in, float gain) {
Chris@1187 102
Chris@1187 103 if (gain == 1.f) {
Chris@1187 104 return in;
Chris@1187 105 }
Chris@1187 106 Column out;
Chris@1187 107 out.reserve(in.size());
Chris@1187 108 for (auto v: in) {
Chris@1187 109 out.push_back(v * gain);
Chris@1187 110 }
Chris@1187 111 return out;
Chris@1187 112 }
Chris@1187 113
Chris@1187 114 static Column distribute(const Column &in,
Chris@1187 115 int h,
Chris@1187 116 const std::vector<double> &binfory,
Chris@1187 117 int minbin,
Chris@1187 118 bool interpolate) {
Chris@1187 119
Chris@1187 120 std::vector<float> out(h, 0.f);
Chris@1187 121 int bins = int(in.size());
Chris@1187 122
Chris@1187 123 for (int y = 0; y < h; ++y) {
Chris@1187 124
Chris@1187 125 double sy0 = binfory[y] - minbin;
Chris@1187 126 double sy1 = sy0 + 1;
Chris@1187 127 if (y+1 < h) {
Chris@1187 128 sy1 = binfory[y+1] - minbin;
Chris@1187 129 }
Chris@1187 130
Chris@1187 131 if (interpolate && fabs(sy1 - sy0) < 1.0) {
Chris@1187 132
Chris@1187 133 double centre = (sy0 + sy1) / 2;
Chris@1187 134 double dist = (centre - 0.5) - rint(centre - 0.5);
Chris@1187 135 int bin = int(centre);
Chris@1187 136
Chris@1187 137 int other = (dist < 0 ? (bin-1) : (bin+1));
Chris@1187 138
Chris@1187 139 if (bin < 0) bin = 0;
Chris@1187 140 if (bin >= bins) bin = bins-1;
Chris@1187 141
Chris@1187 142 if (other < 0 || other >= bins) {
Chris@1187 143 other = bin;
Chris@1187 144 }
Chris@1187 145
Chris@1187 146 double prop = 1.0 - fabs(dist);
Chris@1187 147
Chris@1187 148 double v0 = in[bin];
Chris@1187 149 double v1 = in[other];
Chris@1187 150
Chris@1187 151 out[y] = float(prop * v0 + (1.0 - prop) * v1);
Chris@1187 152
Chris@1187 153 } else { // not interpolating this one
Chris@1187 154
Chris@1187 155 int by0 = int(sy0 + 0.0001);
Chris@1187 156 int by1 = int(sy1 + 0.0001);
Chris@1187 157 if (by1 < by0 + 1) by1 = by0 + 1;
Chris@1187 158
Chris@1187 159 for (int bin = by0; bin < by1; ++bin) {
Chris@1187 160
Chris@1187 161 float value = in[bin];
Chris@1187 162
Chris@1187 163 if (value > out[y]) {
Chris@1187 164 out[y] = value;
Chris@1187 165 }
Chris@1187 166 }
Chris@1187 167 }
Chris@1187 168 }
Chris@1187 169
Chris@1187 170 return out;
Chris@1187 171 }
Chris@1187 172
Chris@1187 173 };
Chris@1187 174
Chris@1187 175 #endif
Chris@1187 176