annotate base/ColumnOp.cpp @ 1290:fa574c909c3d 3.0-integration

Add MAD_BUFFER_GUARD padding at end of mp3 buffer, in order to ensure last frame is decoded successfully (otherwise the decoded audio is truncated). Another thing learned from madplay.
author Chris Cannam
date Thu, 24 Nov 2016 17:06:31 +0000
parents 2f468f43c02c
children 6681027ff2ff
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@1267 102 for (int y = 0; y < h; ++y) {
Chris@1267 103
Chris@1267 104 if (interpolate && h > bins) {
Chris@1267 105
Chris@1267 106 double sy = binfory[y] - minbin - 0.5;
Chris@1267 107 double syf = floor(sy);
Chris@1267 108
Chris@1267 109 int mainbin = int(syf);
Chris@1267 110 int other = mainbin;
Chris@1267 111 if (sy > syf) {
Chris@1267 112 other = mainbin + 1;
Chris@1267 113 } else if (sy < syf) {
Chris@1267 114 other = mainbin - 1;
Chris@1267 115 }
Chris@1267 116
Chris@1267 117 if (mainbin < 0) {
Chris@1267 118 mainbin = 0;
Chris@1267 119 }
Chris@1267 120 if (mainbin >= bins) {
Chris@1267 121 mainbin = bins - 1;
Chris@1267 122 }
Chris@1267 123
Chris@1267 124 if (other < 0) {
Chris@1267 125 other = 0;
Chris@1267 126 }
Chris@1267 127 if (other >= bins) {
Chris@1267 128 other = bins - 1;
Chris@1267 129 }
Chris@1267 130
Chris@1267 131 double prop = 1.0 - fabs(sy - syf);
Chris@1267 132
Chris@1267 133 double v0 = in[mainbin];
Chris@1267 134 double v1 = in[other];
Chris@1267 135
Chris@1267 136 out[y] = float(prop * v0 + (1.0 - prop) * v1);
Chris@1267 137
Chris@1267 138 } else {
Chris@1267 139
Chris@1267 140 double sy0 = binfory[y] - minbin;
Chris@1267 141
Chris@1267 142 double sy1;
Chris@1267 143 if (y+1 < h) {
Chris@1267 144 sy1 = binfory[y+1] - minbin;
Chris@1267 145 } else {
Chris@1267 146 sy1 = bins;
Chris@1267 147 }
Chris@1267 148
Chris@1267 149 int by0 = int(sy0 + 0.0001);
Chris@1267 150 int by1 = int(sy1 + 0.0001);
Chris@1283 151
Chris@1283 152 if (by0 < 0 || by0 >= bins || by1 > bins) {
Chris@1283 153 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 154 continue;
Chris@1283 155 }
Chris@1267 156
Chris@1267 157 for (int bin = by0; bin == by0 || bin < by1; ++bin) {
Chris@1267 158
Chris@1267 159 float value = in[bin];
Chris@1267 160
Chris@1267 161 if (bin == by0 || value > out[y]) {
Chris@1267 162 out[y] = value;
Chris@1267 163 }
Chris@1267 164 }
Chris@1267 165 }
Chris@1267 166 }
Chris@1267 167
Chris@1267 168 return out;
Chris@1267 169 }