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