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 }
|