annotate data/fft/FFTMemoryCache.cpp @ 415:e37e44681720

* Fix failure to take into account near-OOM situations!
author Chris Cannam
date Mon, 09 Jun 2008 16:01:22 +0000
parents 115f60df1e4d
children 3cc4b7cd2aa5
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@408 68 Profiler profiler("FFTMemoryCache::resize");
Chris@408 69
Chris@374 70 #ifdef DEBUG_FFT_MEMORY_CACHE
Chris@359 71 std::cerr << "FFTMemoryCache[" << this << "]::resize(" << width << "x" << height << " = " << width*height << ")" << std::endl;
Chris@374 72 #endif
Chris@159 73
Chris@159 74 if (m_width == width && m_height == height) return;
Chris@159 75
Chris@264 76 if (m_storageType == Compact) {
Chris@264 77 resize(m_magnitude, width, height);
Chris@264 78 resize(m_phase, width, height);
Chris@334 79 } else if (m_storageType == Polar) {
Chris@264 80 resize(m_fmagnitude, width, height);
Chris@264 81 resize(m_fphase, width, height);
Chris@334 82 } else {
Chris@334 83 resize(m_freal, width, height);
Chris@334 84 resize(m_fimag, width, height);
Chris@264 85 }
Chris@264 86
Chris@159 87 m_colset.resize(width);
Chris@159 88
Chris@159 89 m_factor = (float *)realloc(m_factor, width * sizeof(float));
Chris@159 90
Chris@159 91 m_width = width;
Chris@159 92 m_height = height;
Chris@159 93
Chris@374 94 #ifdef DEBUG_FFT_MEMORY_CACHE
Chris@374 95 std::cerr << "done, width = " << m_width << " height = " << m_height << std::endl;
Chris@374 96 #endif
Chris@159 97 }
Chris@159 98
Chris@159 99 void
Chris@159 100 FFTMemoryCache::resize(uint16_t **&array, size_t width, size_t height)
Chris@159 101 {
Chris@159 102 for (size_t i = width; i < m_width; ++i) {
Chris@159 103 free(array[i]);
Chris@159 104 }
Chris@159 105
Chris@159 106 if (width != m_width) {
Chris@159 107 array = (uint16_t **)realloc(array, width * sizeof(uint16_t *));
Chris@159 108 if (!array) throw std::bad_alloc();
Chris@159 109 MUNLOCK(array, width * sizeof(uint16_t *));
Chris@159 110 }
Chris@159 111
Chris@159 112 for (size_t i = m_width; i < width; ++i) {
Chris@159 113 array[i] = 0;
Chris@159 114 }
Chris@159 115
Chris@159 116 for (size_t i = 0; i < width; ++i) {
Chris@159 117 array[i] = (uint16_t *)realloc(array[i], height * sizeof(uint16_t));
Chris@159 118 if (!array[i]) throw std::bad_alloc();
Chris@159 119 MUNLOCK(array[i], height * sizeof(uint16_t));
Chris@159 120 }
Chris@159 121 }
Chris@159 122
Chris@159 123 void
Chris@264 124 FFTMemoryCache::resize(float **&array, size_t width, size_t height)
Chris@264 125 {
Chris@264 126 for (size_t i = width; i < m_width; ++i) {
Chris@264 127 free(array[i]);
Chris@264 128 }
Chris@264 129
Chris@264 130 if (width != m_width) {
Chris@264 131 array = (float **)realloc(array, width * sizeof(float *));
Chris@264 132 if (!array) throw std::bad_alloc();
Chris@264 133 MUNLOCK(array, width * sizeof(float *));
Chris@264 134 }
Chris@264 135
Chris@264 136 for (size_t i = m_width; i < width; ++i) {
Chris@264 137 array[i] = 0;
Chris@264 138 }
Chris@264 139
Chris@264 140 for (size_t i = 0; i < width; ++i) {
Chris@264 141 array[i] = (float *)realloc(array[i], height * sizeof(float));
Chris@264 142 if (!array[i]) throw std::bad_alloc();
Chris@264 143 MUNLOCK(array[i], height * sizeof(float));
Chris@264 144 }
Chris@264 145 }
Chris@264 146
Chris@264 147 void
Chris@159 148 FFTMemoryCache::reset()
Chris@159 149 {
Chris@264 150 switch (m_storageType) {
Chris@264 151
Chris@264 152 case Compact:
Chris@264 153 for (size_t x = 0; x < m_width; ++x) {
Chris@264 154 for (size_t y = 0; y < m_height; ++y) {
Chris@264 155 m_magnitude[x][y] = 0;
Chris@264 156 m_phase[x][y] = 0;
Chris@264 157 }
Chris@264 158 m_factor[x] = 1.0;
Chris@264 159 }
Chris@264 160 break;
Chris@264 161
Chris@264 162 case Polar:
Chris@264 163 for (size_t x = 0; x < m_width; ++x) {
Chris@264 164 for (size_t y = 0; y < m_height; ++y) {
Chris@264 165 m_fmagnitude[x][y] = 0;
Chris@264 166 m_fphase[x][y] = 0;
Chris@264 167 }
Chris@264 168 m_factor[x] = 1.0;
Chris@264 169 }
Chris@264 170 break;
Chris@334 171
Chris@334 172 case Rectangular:
Chris@334 173 for (size_t x = 0; x < m_width; ++x) {
Chris@334 174 for (size_t y = 0; y < m_height; ++y) {
Chris@334 175 m_freal[x][y] = 0;
Chris@334 176 m_fimag[x][y] = 0;
Chris@334 177 }
Chris@334 178 m_factor[x] = 1.0;
Chris@334 179 }
Chris@334 180 break;
Chris@159 181 }
Chris@159 182 }
Chris@159 183
Chris@159 184 void
Chris@334 185 FFTMemoryCache::setColumnAt(size_t x, float *mags, float *phases, float factor)
Chris@334 186 {
Chris@408 187 Profiler profiler("FFTMemoryCache::setColumnAt: from polar");
Chris@408 188
Chris@334 189 setNormalizationFactor(x, factor);
Chris@334 190
Chris@334 191 if (m_storageType == Rectangular) {
Chris@408 192 Profiler subprof("FFTMemoryCache::setColumnAt: polar to cart");
Chris@334 193 for (size_t y = 0; y < m_height; ++y) {
Chris@334 194 m_freal[x][y] = mags[y] * cosf(phases[y]);
Chris@334 195 m_fimag[x][y] = mags[y] * sinf(phases[y]);
Chris@334 196 }
Chris@334 197 } else {
Chris@334 198 for (size_t y = 0; y < m_height; ++y) {
Chris@334 199 setMagnitudeAt(x, y, mags[y]);
Chris@334 200 setPhaseAt(x, y, phases[y]);
Chris@334 201 }
Chris@334 202 }
Chris@334 203
Chris@334 204 m_colset.set(x);
Chris@334 205 }
Chris@334 206
Chris@334 207 void
Chris@159 208 FFTMemoryCache::setColumnAt(size_t x, float *reals, float *imags)
Chris@159 209 {
Chris@408 210 Profiler profiler("FFTMemoryCache::setColumnAt: from cart");
Chris@408 211
Chris@159 212 float max = 0.0;
Chris@159 213
Chris@264 214 switch (m_storageType) {
Chris@264 215
Chris@334 216 case Rectangular:
Chris@334 217 for (size_t y = 0; y < m_height; ++y) {
Chris@334 218 m_freal[x][y] = reals[y];
Chris@334 219 m_fimag[x][y] = imags[y];
Chris@334 220 float mag = sqrtf(reals[y] * reals[y] + imags[y] * imags[y]);
Chris@334 221 if (mag > max) max = mag;
Chris@334 222 }
Chris@334 223 break;
Chris@334 224
Chris@264 225 case Compact:
Chris@264 226 case Polar:
Chris@408 227 {
Chris@408 228 Profiler subprof("FFTMemoryCache::setColumnAt: cart to polar");
Chris@264 229 for (size_t y = 0; y < m_height; ++y) {
Chris@264 230 float mag = sqrtf(reals[y] * reals[y] + imags[y] * imags[y]);
Chris@264 231 float phase = atan2f(imags[y], reals[y]);
Chris@264 232 reals[y] = mag;
Chris@264 233 imags[y] = phase;
Chris@264 234 if (mag > max) max = mag;
Chris@264 235 }
Chris@264 236 break;
Chris@408 237 }
Chris@264 238 };
Chris@159 239
Chris@334 240 if (m_storageType == Rectangular) {
Chris@334 241 m_factor[x] = max;
Chris@334 242 m_colset.set(x);
Chris@334 243 } else {
Chris@334 244 setColumnAt(x, reals, imags, max);
Chris@334 245 }
Chris@159 246 }
Chris@159 247
Chris@170 248 size_t
Chris@264 249 FFTMemoryCache::getCacheSize(size_t width, size_t height, StorageType type)
Chris@170 250 {
Chris@264 251 size_t sz = 0;
Chris@264 252
Chris@264 253 switch (type) {
Chris@264 254
Chris@264 255 case Compact:
Chris@264 256 sz = (height * 2 + 1) * width * sizeof(uint16_t);
Chris@264 257
Chris@264 258 case Polar:
Chris@334 259 case Rectangular:
Chris@264 260 sz = (height * 2 + 1) * width * sizeof(float);
Chris@264 261 }
Chris@264 262
Chris@264 263 return sz;
Chris@170 264 }
Chris@170 265