annotate plugins/DWT.cpp @ 130:c655fa61884f

* Solaris build fixes
author Chris Cannam <c.cannam@qmul.ac.uk>
date Mon, 14 Sep 2009 13:01:57 +0000
parents 1a24b134cd79
children dcf5800f0f00
rev   line source
c@97 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
c@97 2
c@97 3 /*
c@97 4 QM Vamp Plugin Set
c@97 5
c@97 6 Centre for Digital Music, Queen Mary, University of London.
c@97 7 This file copyright 2009 Thomas Wilmering.
c@97 8 All rights reserved.
c@97 9 */
c@97 10
c@97 11 #include "DWT.h"
c@97 12
c@97 13 #include <cmath>
c@97 14
c@97 15 using std::string;
c@97 16 using std::vector;
c@97 17 using std::cerr;
c@97 18 using std::endl;
c@97 19
c@97 20 DWT::DWT(float inputSampleRate) :
c@97 21 Plugin(inputSampleRate),
c@97 22 m_stepSize(0),
c@97 23 m_blockSize(0)
c@97 24 {
c@97 25 m_scales = 10;
c@97 26 m_flength = 0;
c@97 27 m_wavelet = Wavelet::Haar;
c@97 28 m_threshold = 0;
c@97 29 m_absolute = 0;
c@97 30 }
c@97 31
c@97 32 DWT::~DWT()
c@97 33 {
c@97 34 }
c@97 35
c@97 36 string
c@97 37 DWT::getIdentifier() const
c@97 38 {
c@98 39 return "qm-dwt";
c@97 40 }
c@97 41
c@97 42 string
c@97 43 DWT::getName() const
c@97 44 {
c@97 45 return "Discrete Wavelet Transform";
c@97 46 }
c@97 47
c@97 48 string
c@97 49 DWT::getDescription() const
c@97 50 {
c@97 51 return "Visualisation by scalogram";
c@97 52 }
c@97 53
c@97 54 string
c@97 55 DWT::getMaker() const
c@97 56 {
c@97 57 return "Queen Mary, University of London";
c@97 58 }
c@97 59
c@97 60 int
c@97 61 DWT::getPluginVersion() const
c@97 62 {
c@97 63 return 1;
c@97 64 }
c@97 65
c@97 66 string
c@97 67 DWT::getCopyright() const
c@97 68 {
c@97 69 return "Plugin by Thomas Wilmering. Copyright (c) 2009 Thomas Wilmering and QMUL - All Rights Reserved";
c@97 70 }
c@97 71
c@97 72 size_t
c@129 73 DWT::getPreferredBlockSize() const
c@129 74 {
c@129 75 size_t s = (1 << m_scales);
c@129 76 while (s < 1024) s *= 2;
c@129 77 return s;
c@129 78 }
c@129 79
c@129 80 size_t
c@97 81 DWT::getPreferredStepSize() const
c@97 82 {
c@97 83 return 0;
c@97 84 }
c@97 85
c@97 86 bool
c@97 87 DWT::initialise(size_t channels, size_t stepSize, size_t blockSize)
c@97 88 {
c@97 89 if (channels < getMinChannelCount() ||
c@97 90 channels > getMaxChannelCount()) return false;
c@97 91
c@129 92 if ((1 << m_scales) > blockSize) {
c@129 93 std::cerr << "DWT::initialise: ERROR: Block size must be at least 2^scales (specified block size " << blockSize << " < " << (1 << m_scales) << ")" << std::endl;
c@129 94 return false;
c@129 95 }
c@129 96
c@97 97 m_stepSize = stepSize;
c@97 98 m_blockSize = blockSize;
c@97 99
c@97 100 Wavelet::createDecompositionFilters(m_wavelet, m_lpd, m_hpd);
c@97 101
c@97 102 m_flength = m_lpd.size(); // or m_hpd.size()
c@97 103
c@97 104 m_samplePass.resize(m_scales); // resize buffer for samples to pass to next block
c@97 105
c@97 106 for (int i=0; i<m_scales; ++i) {
c@97 107 m_samplePass[i].resize(m_flength-2, 0.0);
c@97 108 }
c@97 109
c@97 110 return true;
c@97 111 }
c@97 112
c@97 113 void
c@97 114 DWT::reset()
c@97 115 {
c@97 116 m_samplePass.clear();
c@97 117
c@97 118 m_samplePass.resize(m_scales);
c@97 119
c@97 120 for (int i=0; i<m_scales; ++i) {
c@97 121 m_samplePass[i].resize(m_flength-2, 0.0);
c@97 122 }
c@97 123 }
c@97 124
c@97 125 DWT::OutputList
c@97 126 DWT::getOutputDescriptors() const
c@97 127 {
c@97 128 OutputList list;
c@97 129
c@97 130 OutputDescriptor sg;
c@97 131 sg.identifier = "wcoeff";
c@97 132 sg.name = "Wavelet Coefficients";
c@97 133 sg.description = "Wavelet coefficients";
c@97 134 sg.unit = "";
c@97 135 sg.hasFixedBinCount = true; // depends on block size
c@97 136 sg.binCount = m_scales; // number of scales
c@97 137 sg.hasKnownExtents = false;
c@97 138 sg.isQuantized = false;
c@97 139 sg.sampleType = OutputDescriptor::FixedSampleRate;
c@97 140 sg.sampleRate = .5 * m_inputSampleRate;
c@97 141
c@97 142 list.push_back(sg);
c@97 143
c@97 144 return list;
c@97 145 }
c@97 146
c@97 147
c@97 148 DWT::ParameterList
c@97 149 DWT::getParameterDescriptors() const
c@97 150 {
c@97 151 ParameterList list;
c@97 152
c@97 153 ParameterDescriptor d;
c@97 154 d.identifier = "scales";
c@97 155 d.name = "Scales";
c@97 156 d.description = "Scale depth";
c@97 157 d.unit = "";
c@97 158 d.minValue = 1.0f;
c@97 159 d.maxValue = 16.0f;
c@97 160 d.defaultValue = 10.0f;
c@97 161 d.isQuantized = true;
c@97 162 d.quantizeStep = 1.0f;
c@97 163 list.push_back(d);
c@97 164
c@97 165 d.identifier = "wavelet";
c@97 166 d.name = "Wavelet";
c@119 167 d.description = "Wavelet type to use";
c@97 168 d.unit = "";
c@97 169 d.minValue = 0.f;
c@97 170 d.maxValue = int(Wavelet::LastType);
c@97 171 d.defaultValue = int(Wavelet::Haar);
c@97 172 d.isQuantized = true;
c@97 173 d.quantizeStep = 1.0f;
c@97 174
c@97 175 for (int i = 0; i <= int(Wavelet::LastType); ++i) {
c@97 176 d.valueNames.push_back(Wavelet::getWaveletName(Wavelet::Type(i)));
c@97 177 }
c@97 178 list.push_back(d);
c@97 179 d.valueNames.clear();
c@97 180
c@97 181 d.identifier = "threshold";
c@97 182 d.name = "Threshold";
c@97 183 d.description = "Wavelet coefficient threshold";
c@97 184 d.unit = "";
c@97 185 d.minValue = 0.0f;
c@97 186 d.maxValue = 0.01f;
c@97 187 d.defaultValue = 0.0f;
c@97 188 d.isQuantized = false;
c@97 189 list.push_back(d);
c@97 190
c@97 191 d.identifier = "absolute";
c@97 192 d.name = "Absolute values";
c@97 193 d.description = "Return absolute values";
c@97 194 d.unit = "";
c@97 195 d.minValue = 0.0f;
c@97 196 d.maxValue = 1.00f;
c@97 197 d.defaultValue = 0.0f;
c@97 198 d.isQuantized = true;
c@97 199 d.quantizeStep = 1.0f;
c@97 200 list.push_back(d);
c@97 201
c@97 202 return list;
c@97 203 }
c@97 204
c@97 205 void DWT::setParameter(std::string paramid, float newval)
c@97 206 {
c@97 207 if (paramid == "scales") {
c@97 208 m_scales = newval;
c@97 209 }
c@97 210 else if (paramid == "wavelet") {
c@97 211 m_wavelet = (Wavelet::Type)(int(newval + 0.1));
c@97 212 }
c@97 213 else if (paramid == "threshold") {
c@97 214 m_threshold = newval;
c@97 215 }
c@97 216 else if (paramid == "absolute") {
c@97 217 m_absolute = newval;
c@97 218 }
c@97 219 }
c@97 220
c@97 221 float DWT::getParameter(std::string paramid) const
c@97 222 {
c@97 223 if (paramid == "scales") {
c@97 224 return m_scales;
c@97 225 }
c@97 226 else if (paramid == "wavelet") {
c@97 227 return int(m_wavelet);
c@97 228 }
c@97 229 else if (paramid == "threshold") {
c@97 230 return m_threshold;
c@97 231 }
c@97 232 else if (paramid == "absolute") {
c@97 233 return m_absolute;
c@97 234 }
c@97 235
c@97 236 return 0.0f;
c@97 237 }
c@97 238
c@97 239
c@97 240 DWT::FeatureSet
c@97 241 DWT::process(const float *const *inputBuffers,
c@97 242 Vamp::RealTime)
c@97 243 {
c@97 244 FeatureSet fs;
c@97 245
c@97 246 if (m_blockSize == 0) {
c@97 247 cerr << "ERROR: DWT::process: Not initialised" << endl;
c@97 248 return fs;
c@97 249 }
c@97 250
c@97 251 int s = m_scales;
c@97 252 int b = m_blockSize;
c@97 253 int b_init = b;
c@97 254
c@97 255 if ((1 << s) > b) b = 1 << s; // correct blocksize if smaller than 2^(max scale)
c@97 256
c@97 257 //--------------------------------------------------------------------------------------------------
c@97 258
c@97 259 float tempDet;
c@127 260 float aTempDet;
c@97 261 int outloc;
c@97 262 int halfblocksize = int(.5 * b);
c@97 263 int fbufloc;
c@97 264 int fbufloc2;
c@97 265
c@97 266 vector< vector<float> > wCoefficients(m_scales); // result
c@97 267 vector<float> tempAprx(halfblocksize,0.0); // approximation
c@97 268 vector<float> fbuf(b+m_flength-2,0.0); // input buffer
c@97 269
c@97 270 for (int n=m_flength-2; n<b+m_flength-2; n++) // copy input buffer to dwt input
c@97 271 fbuf[n] = inputBuffers[0][n-m_flength+2];
c@97 272
c@97 273 for (int scale=0; scale<m_scales; ++scale) // do for each scale
c@97 274 {
c@97 275 for (int n=0; n<m_flength-2; ++n) // get samples from previous block
c@97 276 fbuf[n] = m_samplePass[scale][n];
c@97 277
c@97 278
c@97 279 if ((m_flength-2)<b) // pass samples to next block
c@97 280 for (int n=0; n<m_flength-2; ++n)
c@97 281 m_samplePass[scale][n] = fbuf[b+n];
c@97 282 else {
c@97 283 for (int n=0; n<b; ++n) // if number of samples to pass > blocksize
c@97 284 m_samplePass[scale].push_back(fbuf[m_flength-2+n]);
c@97 285 m_samplePass[scale].erase (m_samplePass[scale].begin(),m_samplePass[scale].begin()+b);
c@97 286 }
c@97 287
c@97 288 for (int n=0; n<halfblocksize; ++n) { // do for every other sample of the input buffer
c@97 289 tempDet = 0;
c@97 290 fbufloc = 2*n+m_flength-1;
c@97 291 for (int m=0; m<m_flength; ++m) { // Convolve the sample with filter coefficients
c@97 292 fbufloc2 = fbufloc - m;
c@97 293 tempAprx[n] += fbuf[fbufloc2] * m_lpd[m]; // approximation
c@97 294 tempDet += fbuf[fbufloc2] * m_hpd[m]; // detail
c@97 295 }
c@97 296
c@127 297 aTempDet = fabs(tempDet);
c@127 298 if (m_absolute == 1) tempDet = aTempDet;
c@97 299
c@97 300
c@127 301 if (aTempDet < m_threshold) tempDet = 0; // simple hard thresholding, same for each scale
c@97 302 wCoefficients[scale].push_back(tempDet);
c@97 303 }
c@97 304
c@97 305 if (scale+1<m_scales) { // prepare variables for next scale
c@97 306 b = b >> 1; // the approximation in tmpfwd is stored as
c@97 307 halfblocksize = halfblocksize >> 1; // input for next level
c@97 308
c@97 309 for (int n=m_flength-2; n<b+m_flength-2; n++) // copy approximation to dwt input
c@97 310 fbuf[n] = tempAprx[n-m_flength+2];
c@97 311
c@97 312 //vector<float>(b+m_flength-2).swap(fbuf);
c@97 313 vector<float>(halfblocksize).swap(tempAprx); // set new size with zeros
c@97 314 }
c@97 315 }
c@97 316
c@97 317
c@97 318 //-----------------------------------------------------------------------------------------
c@97 319
c@97 320 halfblocksize = int(.5 * b_init);
c@97 321
c@97 322 for (int m = 0; m<halfblocksize; m++) {
c@97 323
c@97 324 Feature feature;
c@97 325 feature.hasTimestamp = false;
c@97 326
c@97 327 for (int j = 0; j < s; j++) {
c@130 328 outloc = m / (1 << j); // This one pushes a single result bin
c@97 329 // onto the top of a feature column
c@97 330 feature.values.push_back(wCoefficients[j][outloc]); // each coefficient on higher scales need
c@97 331 } // to be copied multiple times to feature columns
c@97 332 fs[0].push_back(feature);
c@97 333 }
c@97 334 return fs;
c@97 335 }
c@97 336
c@97 337
c@97 338
c@97 339 DWT::FeatureSet
c@97 340 DWT::getRemainingFeatures()
c@97 341 {
c@97 342 int s = m_scales;
c@97 343
c@97 344 FeatureSet fs;
c@97 345
c@97 346 /*
c@97 347 int b = 1;
c@97 348 while (b<((m_flength-1) * (1 << s))) { //set blocksize to tail length
c@97 349 b= (b << 1);
c@97 350 }
c@97 351 int b_init = b;
c@97 352
c@97 353 */
c@97 354 int b = m_blockSize;
c@97 355 int b_init = b;
c@97 356 int tailIterations = int(((m_flength-1) * (1 << s)) / b) + 1; // number of iterations for tail
c@97 357
c@97 358
c@97 359 for(int m=0; m<tailIterations; ++m)
c@97 360 {
c@97 361
c@97 362 b = b_init;
c@97 363
c@97 364 //-------------------------------------------------------------------------------------------
c@97 365 float tempDet;
c@127 366 float aTempDet;
c@97 367 int outloc;
c@97 368 int halfblocksize = int(.5 * b);
c@97 369 int fbufloc;
c@97 370 int fbufloc2;
c@97 371 int len = m_flength;
c@97 372
c@97 373 vector< vector<float> > wCoefficients(m_scales); // result
c@97 374 vector<float> tempAprx(halfblocksize,0.0); // approximation
c@97 375 vector<float> fbuf(b+len-2,0.0); // input buffer
c@97 376
c@97 377 //for (int n=len-2; n<b+len-2; n++) // copy input buffer to dwt input
c@97 378 // fbuf[n] = 0; //inputBuffers[0][n-len+2];
c@97 379
c@97 380 for (int scale=0; scale<m_scales; ++scale) // do for each scale
c@97 381 {
c@97 382 for (int n=0; n<len-2; ++n) // get samples from previous block
c@97 383 fbuf[n] = m_samplePass[scale][n];
c@97 384
c@97 385
c@97 386 if ((len-2)<b) // pass samples to next block
c@97 387 for (int n=0; n<len-2; ++n)
c@97 388 m_samplePass[scale][n] = fbuf[b+n];
c@97 389 else {
c@97 390 for (int n=0; n<b; ++n) // if number of samples to pass > blocksize
c@97 391 m_samplePass[scale].push_back(fbuf[len-2+n]);
c@97 392 m_samplePass[scale].erase (m_samplePass[scale].begin(),m_samplePass[scale].begin()+b);
c@97 393 }
c@97 394
c@97 395 for (int n=0; n<halfblocksize; ++n) { // do for every other sample of the input buffer
c@97 396 tempDet = 0;
c@97 397 fbufloc = 2*n+len-1;
c@97 398 for (int m=0; m<len; ++m) { // Convolve the sample with filter coefficients
c@97 399 fbufloc2 = fbufloc - m;
c@97 400 tempAprx[n] += fbuf[fbufloc2] * m_lpd[m]; // approximation
c@97 401 tempDet += fbuf[fbufloc2] * m_hpd[m]; // detail
c@97 402 }
c@127 403
c@127 404 aTempDet = fabs(tempDet);
c@127 405 if (m_absolute == 1) tempDet = aTempDet;
c@127 406 if (aTempDet < m_threshold) tempDet = 0; // simple hard thresholding, same for each scale
c@97 407 wCoefficients[scale].push_back(tempDet);
c@97 408 }
c@97 409
c@97 410 if (scale+1<m_scales) { // prepare variables for next scale
c@97 411 b = b >> 1; // the approximation in tmpfwd is stored as
c@97 412 halfblocksize = halfblocksize >> 1; // input for next level
c@97 413
c@97 414 for (int n=len-2; n<b+len-2; n++) // copy approximation to dwt input
c@97 415 fbuf[n] = tempAprx[n-len+2];
c@97 416
c@97 417 //vector<float>(b+len-2).swap(fbuf);
c@97 418 vector<float>(halfblocksize).swap(tempAprx); // set new size with zeros
c@97 419 }
c@97 420
c@97 421 }
c@97 422
c@97 423 //-----------------------------------------------------------------------------------------
c@97 424
c@97 425 halfblocksize = int(.5 * b_init + 0.1);
c@97 426
c@97 427 for (int m = 0; m<halfblocksize; m++) {
c@97 428
c@97 429 Feature feature;
c@97 430 feature.hasTimestamp = false;
c@97 431
c@97 432 for (int j = 0; j < s; j++) {
c@130 433 outloc = m / (1 << j); // This one pushes a single result bin
c@97 434 // onto the top of a feature column
c@97 435 feature.values.push_back(wCoefficients[j][outloc]); // each coefficient on higher scales need
c@97 436 } // to be copied multiple times to feature columns
c@97 437 fs[0].push_back(feature);
c@97 438 }
c@97 439 }
c@97 440 return fs;
c@97 441
c@97 442 }
c@97 443