annotate data/fft/FFTMemoryCache.cpp @ 1008:d9e0e59a1581

When using an aggregate model to pass data to a transform, zero-pad the shorter input to the duration of the longer rather than truncating the longer. (This is better behaviour for e.g. MATCH, and in any case the code was previously truncating incorrectly and ending up with garbage data at the end.)
author Chris Cannam
date Fri, 14 Nov 2014 13:51:33 +0000
parents 5173e56e17f7
children cc27f35aa75c
rev   line source
Chris@159 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@159 2
Chris@159 3 /*
Chris@159 4 Sonic Visualiser
Chris@159 5 An audio file viewer and annotation editor.
Chris@159 6 Centre for Digital Music, Queen Mary, University of London.
Chris@159 7 This file copyright 2006 Chris Cannam.
Chris@159 8
Chris@159 9 This program is free software; you can redistribute it and/or
Chris@159 10 modify it under the terms of the GNU General Public License as
Chris@159 11 published by the Free Software Foundation; either version 2 of the
Chris@159 12 License, or (at your option) any later version. See the file
Chris@159 13 COPYING included with this distribution for more information.
Chris@159 14 */
Chris@159 15
Chris@159 16 #include "FFTMemoryCache.h"
Chris@159 17 #include "system/System.h"
Chris@159 18
Chris@159 19 #include <iostream>
Chris@537 20 #include <cstdlib>
Chris@159 21
Chris@374 22 //#define DEBUG_FFT_MEMORY_CACHE 1
Chris@374 23
Chris@537 24 FFTMemoryCache::FFTMemoryCache(FFTCache::StorageType storageType,
Chris@929 25 int width, int height) :
Chris@537 26 m_width(width),
Chris@537 27 m_height(height),
Chris@159 28 m_magnitude(0),
Chris@159 29 m_phase(0),
Chris@264 30 m_fmagnitude(0),
Chris@264 31 m_fphase(0),
Chris@334 32 m_freal(0),
Chris@334 33 m_fimag(0),
Chris@264 34 m_factor(0),
Chris@264 35 m_storageType(storageType)
Chris@159 36 {
Chris@374 37 #ifdef DEBUG_FFT_MEMORY_CACHE
Chris@843 38 cerr << "FFTMemoryCache[" << this << "]::FFTMemoryCache (type "
Chris@843 39 << m_storageType << "), size " << m_width << "x" << m_height << endl;
Chris@374 40 #endif
Chris@537 41
Chris@537 42 initialise();
Chris@159 43 }
Chris@159 44
Chris@159 45 FFTMemoryCache::~FFTMemoryCache()
Chris@159 46 {
Chris@374 47 #ifdef DEBUG_FFT_MEMORY_CACHE
Chris@843 48 cerr << "FFTMemoryCache[" << this << "]::~FFTMemoryCache" << endl;
Chris@374 49 #endif
Chris@159 50
Chris@929 51 for (int i = 0; i < m_width; ++i) {
Chris@159 52 if (m_magnitude && m_magnitude[i]) free(m_magnitude[i]);
Chris@159 53 if (m_phase && m_phase[i]) free(m_phase[i]);
Chris@264 54 if (m_fmagnitude && m_fmagnitude[i]) free(m_fmagnitude[i]);
Chris@264 55 if (m_fphase && m_fphase[i]) free(m_fphase[i]);
Chris@334 56 if (m_freal && m_freal[i]) free(m_freal[i]);
Chris@334 57 if (m_fimag && m_fimag[i]) free(m_fimag[i]);
Chris@159 58 }
Chris@159 59
Chris@159 60 if (m_magnitude) free(m_magnitude);
Chris@159 61 if (m_phase) free(m_phase);
Chris@264 62 if (m_fmagnitude) free(m_fmagnitude);
Chris@264 63 if (m_fphase) free(m_fphase);
Chris@334 64 if (m_freal) free(m_freal);
Chris@334 65 if (m_fimag) free(m_fimag);
Chris@159 66 if (m_factor) free(m_factor);
Chris@159 67 }
Chris@159 68
Chris@159 69 void
Chris@537 70 FFTMemoryCache::initialise()
Chris@159 71 {
Chris@537 72 Profiler profiler("FFTMemoryCache::initialise");
Chris@537 73
Chris@929 74 int width = m_width, height = m_height;
Chris@408 75
Chris@374 76 #ifdef DEBUG_FFT_MEMORY_CACHE
Chris@843 77 cerr << "FFTMemoryCache[" << this << "]::initialise(" << width << "x" << height << " = " << width*height << ")" << endl;
Chris@374 78 #endif
Chris@159 79
Chris@537 80 if (m_storageType == FFTCache::Compact) {
Chris@537 81 initialise(m_magnitude);
Chris@537 82 initialise(m_phase);
Chris@537 83 } else if (m_storageType == FFTCache::Polar) {
Chris@537 84 initialise(m_fmagnitude);
Chris@537 85 initialise(m_fphase);
Chris@334 86 } else {
Chris@537 87 initialise(m_freal);
Chris@537 88 initialise(m_fimag);
Chris@264 89 }
Chris@264 90
Chris@159 91 m_colset.resize(width);
Chris@159 92
Chris@159 93 m_factor = (float *)realloc(m_factor, width * sizeof(float));
Chris@159 94
Chris@159 95 m_width = width;
Chris@159 96 m_height = height;
Chris@159 97
Chris@374 98 #ifdef DEBUG_FFT_MEMORY_CACHE
Chris@843 99 cerr << "done, width = " << m_width << " height = " << m_height << endl;
Chris@374 100 #endif
Chris@159 101 }
Chris@159 102
Chris@159 103 void
Chris@537 104 FFTMemoryCache::initialise(uint16_t **&array)
Chris@159 105 {
Chris@537 106 array = (uint16_t **)malloc(m_width * sizeof(uint16_t *));
Chris@537 107 if (!array) throw std::bad_alloc();
Chris@537 108 MUNLOCK(array, m_width * sizeof(uint16_t *));
Chris@159 109
Chris@929 110 for (int i = 0; i < m_width; ++i) {
Chris@537 111 array[i] = (uint16_t *)malloc(m_height * sizeof(uint16_t));
Chris@159 112 if (!array[i]) throw std::bad_alloc();
Chris@537 113 MUNLOCK(array[i], m_height * sizeof(uint16_t));
Chris@159 114 }
Chris@159 115 }
Chris@159 116
Chris@159 117 void
Chris@537 118 FFTMemoryCache::initialise(float **&array)
Chris@264 119 {
Chris@537 120 array = (float **)malloc(m_width * sizeof(float *));
Chris@537 121 if (!array) throw std::bad_alloc();
Chris@537 122 MUNLOCK(array, m_width * sizeof(float *));
Chris@264 123
Chris@929 124 for (int i = 0; i < m_width; ++i) {
Chris@537 125 array[i] = (float *)malloc(m_height * sizeof(float));
Chris@264 126 if (!array[i]) throw std::bad_alloc();
Chris@537 127 MUNLOCK(array[i], m_height * sizeof(float));
Chris@264 128 }
Chris@264 129 }
Chris@264 130
Chris@264 131 void
Chris@929 132 FFTMemoryCache::setColumnAt(int x, float *mags, float *phases, float factor)
Chris@334 133 {
Chris@408 134 Profiler profiler("FFTMemoryCache::setColumnAt: from polar");
Chris@408 135
Chris@334 136 setNormalizationFactor(x, factor);
Chris@334 137
Chris@537 138 if (m_storageType == FFTCache::Rectangular) {
Chris@408 139 Profiler subprof("FFTMemoryCache::setColumnAt: polar to cart");
Chris@929 140 for (int y = 0; y < m_height; ++y) {
Chris@334 141 m_freal[x][y] = mags[y] * cosf(phases[y]);
Chris@334 142 m_fimag[x][y] = mags[y] * sinf(phases[y]);
Chris@334 143 }
Chris@334 144 } else {
Chris@929 145 for (int y = 0; y < m_height; ++y) {
Chris@334 146 setMagnitudeAt(x, y, mags[y]);
Chris@334 147 setPhaseAt(x, y, phases[y]);
Chris@334 148 }
Chris@334 149 }
Chris@334 150
Chris@548 151 m_colsetLock.lockForWrite();
Chris@334 152 m_colset.set(x);
Chris@548 153 m_colsetLock.unlock();
Chris@334 154 }
Chris@334 155
Chris@334 156 void
Chris@929 157 FFTMemoryCache::setColumnAt(int x, float *reals, float *imags)
Chris@159 158 {
Chris@408 159 Profiler profiler("FFTMemoryCache::setColumnAt: from cart");
Chris@408 160
Chris@159 161 float max = 0.0;
Chris@159 162
Chris@264 163 switch (m_storageType) {
Chris@264 164
Chris@537 165 case FFTCache::Rectangular:
Chris@929 166 for (int y = 0; y < m_height; ++y) {
Chris@334 167 m_freal[x][y] = reals[y];
Chris@334 168 m_fimag[x][y] = imags[y];
Chris@334 169 float mag = sqrtf(reals[y] * reals[y] + imags[y] * imags[y]);
Chris@334 170 if (mag > max) max = mag;
Chris@334 171 }
Chris@334 172 break;
Chris@334 173
Chris@537 174 case FFTCache::Compact:
Chris@537 175 case FFTCache::Polar:
Chris@408 176 {
Chris@408 177 Profiler subprof("FFTMemoryCache::setColumnAt: cart to polar");
Chris@929 178 for (int y = 0; y < m_height; ++y) {
Chris@264 179 float mag = sqrtf(reals[y] * reals[y] + imags[y] * imags[y]);
Chris@264 180 float phase = atan2f(imags[y], reals[y]);
Chris@264 181 reals[y] = mag;
Chris@264 182 imags[y] = phase;
Chris@264 183 if (mag > max) max = mag;
Chris@264 184 }
Chris@264 185 break;
Chris@408 186 }
Chris@264 187 };
Chris@159 188
Chris@537 189 if (m_storageType == FFTCache::Rectangular) {
Chris@334 190 m_factor[x] = max;
Chris@548 191 m_colsetLock.lockForWrite();
Chris@334 192 m_colset.set(x);
Chris@548 193 m_colsetLock.unlock();
Chris@334 194 } else {
Chris@334 195 setColumnAt(x, reals, imags, max);
Chris@334 196 }
Chris@159 197 }
Chris@159 198
Chris@929 199 int
Chris@929 200 FFTMemoryCache::getCacheSize(int width, int height, FFTCache::StorageType type)
Chris@170 201 {
Chris@929 202 int sz = 0;
Chris@264 203
Chris@264 204 switch (type) {
Chris@264 205
Chris@537 206 case FFTCache::Compact:
Chris@264 207 sz = (height * 2 + 1) * width * sizeof(uint16_t);
Chris@960 208 break;
Chris@264 209
Chris@537 210 case FFTCache::Polar:
Chris@537 211 case FFTCache::Rectangular:
Chris@264 212 sz = (height * 2 + 1) * width * sizeof(float);
Chris@960 213 break;
Chris@264 214 }
Chris@264 215
Chris@264 216 return sz;
Chris@170 217 }
Chris@170 218