annotate data/fft/FFTMemoryCache.cpp @ 388:370aa9714ef5

* Move plugin/transform to plain transform. This way transform can depend on model and GUI classes, but plugin doesn't have to.
author Chris Cannam
date Wed, 12 Mar 2008 18:02:17 +0000
parents 7cc6b7b0d819
children 115f60df1e4d
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@159 20
Chris@374 21 //#define DEBUG_FFT_MEMORY_CACHE 1
Chris@374 22
Chris@264 23 FFTMemoryCache::FFTMemoryCache(StorageType storageType) :
Chris@159 24 m_width(0),
Chris@159 25 m_height(0),
Chris@159 26 m_magnitude(0),
Chris@159 27 m_phase(0),
Chris@264 28 m_fmagnitude(0),
Chris@264 29 m_fphase(0),
Chris@334 30 m_freal(0),
Chris@334 31 m_fimag(0),
Chris@264 32 m_factor(0),
Chris@264 33 m_storageType(storageType)
Chris@159 34 {
Chris@374 35 #ifdef DEBUG_FFT_MEMORY_CACHE
Chris@264 36 std::cerr << "FFTMemoryCache[" << this << "]::FFTMemoryCache (type "
Chris@264 37 << m_storageType << ")" << std::endl;
Chris@374 38 #endif
Chris@159 39 }
Chris@159 40
Chris@159 41 FFTMemoryCache::~FFTMemoryCache()
Chris@159 42 {
Chris@374 43 #ifdef DEBUG_FFT_MEMORY_CACHE
Chris@374 44 std::cerr << "FFTMemoryCache[" << this << "]::~FFTMemoryCache" << std::endl;
Chris@374 45 #endif
Chris@159 46
Chris@159 47 for (size_t i = 0; i < m_width; ++i) {
Chris@159 48 if (m_magnitude && m_magnitude[i]) free(m_magnitude[i]);
Chris@159 49 if (m_phase && m_phase[i]) free(m_phase[i]);
Chris@264 50 if (m_fmagnitude && m_fmagnitude[i]) free(m_fmagnitude[i]);
Chris@264 51 if (m_fphase && m_fphase[i]) free(m_fphase[i]);
Chris@334 52 if (m_freal && m_freal[i]) free(m_freal[i]);
Chris@334 53 if (m_fimag && m_fimag[i]) free(m_fimag[i]);
Chris@159 54 }
Chris@159 55
Chris@159 56 if (m_magnitude) free(m_magnitude);
Chris@159 57 if (m_phase) free(m_phase);
Chris@264 58 if (m_fmagnitude) free(m_fmagnitude);
Chris@264 59 if (m_fphase) free(m_fphase);
Chris@334 60 if (m_freal) free(m_freal);
Chris@334 61 if (m_fimag) free(m_fimag);
Chris@159 62 if (m_factor) free(m_factor);
Chris@159 63 }
Chris@159 64
Chris@159 65 void
Chris@159 66 FFTMemoryCache::resize(size_t width, size_t height)
Chris@159 67 {
Chris@374 68 #ifdef DEBUG_FFT_MEMORY_CACHE
Chris@359 69 std::cerr << "FFTMemoryCache[" << this << "]::resize(" << width << "x" << height << " = " << width*height << ")" << std::endl;
Chris@374 70 #endif
Chris@159 71
Chris@159 72 if (m_width == width && m_height == height) return;
Chris@159 73
Chris@264 74 if (m_storageType == Compact) {
Chris@264 75 resize(m_magnitude, width, height);
Chris@264 76 resize(m_phase, width, height);
Chris@334 77 } else if (m_storageType == Polar) {
Chris@264 78 resize(m_fmagnitude, width, height);
Chris@264 79 resize(m_fphase, width, height);
Chris@334 80 } else {
Chris@334 81 resize(m_freal, width, height);
Chris@334 82 resize(m_fimag, width, height);
Chris@264 83 }
Chris@264 84
Chris@159 85 m_colset.resize(width);
Chris@159 86
Chris@159 87 m_factor = (float *)realloc(m_factor, width * sizeof(float));
Chris@159 88
Chris@159 89 m_width = width;
Chris@159 90 m_height = height;
Chris@159 91
Chris@374 92 #ifdef DEBUG_FFT_MEMORY_CACHE
Chris@374 93 std::cerr << "done, width = " << m_width << " height = " << m_height << std::endl;
Chris@374 94 #endif
Chris@159 95 }
Chris@159 96
Chris@159 97 void
Chris@159 98 FFTMemoryCache::resize(uint16_t **&array, size_t width, size_t height)
Chris@159 99 {
Chris@159 100 for (size_t i = width; i < m_width; ++i) {
Chris@159 101 free(array[i]);
Chris@159 102 }
Chris@159 103
Chris@159 104 if (width != m_width) {
Chris@159 105 array = (uint16_t **)realloc(array, width * sizeof(uint16_t *));
Chris@159 106 if (!array) throw std::bad_alloc();
Chris@159 107 MUNLOCK(array, width * sizeof(uint16_t *));
Chris@159 108 }
Chris@159 109
Chris@159 110 for (size_t i = m_width; i < width; ++i) {
Chris@159 111 array[i] = 0;
Chris@159 112 }
Chris@159 113
Chris@159 114 for (size_t i = 0; i < width; ++i) {
Chris@159 115 array[i] = (uint16_t *)realloc(array[i], height * sizeof(uint16_t));
Chris@159 116 if (!array[i]) throw std::bad_alloc();
Chris@159 117 MUNLOCK(array[i], height * sizeof(uint16_t));
Chris@159 118 }
Chris@159 119 }
Chris@159 120
Chris@159 121 void
Chris@264 122 FFTMemoryCache::resize(float **&array, size_t width, size_t height)
Chris@264 123 {
Chris@264 124 for (size_t i = width; i < m_width; ++i) {
Chris@264 125 free(array[i]);
Chris@264 126 }
Chris@264 127
Chris@264 128 if (width != m_width) {
Chris@264 129 array = (float **)realloc(array, width * sizeof(float *));
Chris@264 130 if (!array) throw std::bad_alloc();
Chris@264 131 MUNLOCK(array, width * sizeof(float *));
Chris@264 132 }
Chris@264 133
Chris@264 134 for (size_t i = m_width; i < width; ++i) {
Chris@264 135 array[i] = 0;
Chris@264 136 }
Chris@264 137
Chris@264 138 for (size_t i = 0; i < width; ++i) {
Chris@264 139 array[i] = (float *)realloc(array[i], height * sizeof(float));
Chris@264 140 if (!array[i]) throw std::bad_alloc();
Chris@264 141 MUNLOCK(array[i], height * sizeof(float));
Chris@264 142 }
Chris@264 143 }
Chris@264 144
Chris@264 145 void
Chris@159 146 FFTMemoryCache::reset()
Chris@159 147 {
Chris@264 148 switch (m_storageType) {
Chris@264 149
Chris@264 150 case Compact:
Chris@264 151 for (size_t x = 0; x < m_width; ++x) {
Chris@264 152 for (size_t y = 0; y < m_height; ++y) {
Chris@264 153 m_magnitude[x][y] = 0;
Chris@264 154 m_phase[x][y] = 0;
Chris@264 155 }
Chris@264 156 m_factor[x] = 1.0;
Chris@264 157 }
Chris@264 158 break;
Chris@264 159
Chris@264 160 case Polar:
Chris@264 161 for (size_t x = 0; x < m_width; ++x) {
Chris@264 162 for (size_t y = 0; y < m_height; ++y) {
Chris@264 163 m_fmagnitude[x][y] = 0;
Chris@264 164 m_fphase[x][y] = 0;
Chris@264 165 }
Chris@264 166 m_factor[x] = 1.0;
Chris@264 167 }
Chris@264 168 break;
Chris@334 169
Chris@334 170 case Rectangular:
Chris@334 171 for (size_t x = 0; x < m_width; ++x) {
Chris@334 172 for (size_t y = 0; y < m_height; ++y) {
Chris@334 173 m_freal[x][y] = 0;
Chris@334 174 m_fimag[x][y] = 0;
Chris@334 175 }
Chris@334 176 m_factor[x] = 1.0;
Chris@334 177 }
Chris@334 178 break;
Chris@159 179 }
Chris@159 180 }
Chris@159 181
Chris@159 182 void
Chris@334 183 FFTMemoryCache::setColumnAt(size_t x, float *mags, float *phases, float factor)
Chris@334 184 {
Chris@334 185 setNormalizationFactor(x, factor);
Chris@334 186
Chris@334 187 if (m_storageType == Rectangular) {
Chris@334 188 for (size_t y = 0; y < m_height; ++y) {
Chris@334 189 m_freal[x][y] = mags[y] * cosf(phases[y]);
Chris@334 190 m_fimag[x][y] = mags[y] * sinf(phases[y]);
Chris@334 191 }
Chris@334 192 } else {
Chris@334 193 for (size_t y = 0; y < m_height; ++y) {
Chris@334 194 setMagnitudeAt(x, y, mags[y]);
Chris@334 195 setPhaseAt(x, y, phases[y]);
Chris@334 196 }
Chris@334 197 }
Chris@334 198
Chris@334 199 m_colset.set(x);
Chris@334 200 }
Chris@334 201
Chris@334 202 void
Chris@159 203 FFTMemoryCache::setColumnAt(size_t x, float *reals, float *imags)
Chris@159 204 {
Chris@159 205 float max = 0.0;
Chris@159 206
Chris@264 207 switch (m_storageType) {
Chris@264 208
Chris@334 209 case Rectangular:
Chris@334 210 for (size_t y = 0; y < m_height; ++y) {
Chris@334 211 m_freal[x][y] = reals[y];
Chris@334 212 m_fimag[x][y] = imags[y];
Chris@334 213 float mag = sqrtf(reals[y] * reals[y] + imags[y] * imags[y]);
Chris@334 214 if (mag > max) max = mag;
Chris@334 215 }
Chris@334 216 break;
Chris@334 217
Chris@264 218 case Compact:
Chris@264 219 case Polar:
Chris@264 220 for (size_t y = 0; y < m_height; ++y) {
Chris@264 221 float mag = sqrtf(reals[y] * reals[y] + imags[y] * imags[y]);
Chris@264 222 float phase = atan2f(imags[y], reals[y]);
Chris@264 223 phase = princargf(phase);
Chris@264 224 reals[y] = mag;
Chris@264 225 imags[y] = phase;
Chris@264 226 if (mag > max) max = mag;
Chris@264 227 }
Chris@264 228 break;
Chris@264 229 };
Chris@159 230
Chris@334 231 if (m_storageType == Rectangular) {
Chris@334 232 m_factor[x] = max;
Chris@334 233 m_colset.set(x);
Chris@334 234 } else {
Chris@334 235 setColumnAt(x, reals, imags, max);
Chris@334 236 }
Chris@159 237 }
Chris@159 238
Chris@170 239 size_t
Chris@264 240 FFTMemoryCache::getCacheSize(size_t width, size_t height, StorageType type)
Chris@170 241 {
Chris@264 242 size_t sz = 0;
Chris@264 243
Chris@264 244 switch (type) {
Chris@264 245
Chris@264 246 case Compact:
Chris@264 247 sz = (height * 2 + 1) * width * sizeof(uint16_t);
Chris@264 248
Chris@264 249 case Polar:
Chris@334 250 case Rectangular:
Chris@264 251 sz = (height * 2 + 1) * width * sizeof(float);
Chris@264 252 }
Chris@264 253
Chris@264 254 return sz;
Chris@170 255 }
Chris@170 256