annotate data/fft/FFTMemoryCache.cpp @ 335:02d2ad95ea52 spectrogram-cache-rejig

* Get storage advice for each cache in an FFT data server. Allows us to be more confident about the actual memory situation and cut over from memory to disc part way through an FFT calculation if necessary. StorageAdviser is now a bit too optimistic though (it's too keen to allocate large numbers of small blocks in memory).
author Chris Cannam
date Tue, 13 Nov 2007 13:54:10 +0000
parents aa8dbac62024
children 7cc6b7b0d819
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@264 21 FFTMemoryCache::FFTMemoryCache(StorageType storageType) :
Chris@159 22 m_width(0),
Chris@159 23 m_height(0),
Chris@159 24 m_magnitude(0),
Chris@159 25 m_phase(0),
Chris@264 26 m_fmagnitude(0),
Chris@264 27 m_fphase(0),
Chris@334 28 m_freal(0),
Chris@334 29 m_fimag(0),
Chris@264 30 m_factor(0),
Chris@264 31 m_storageType(storageType)
Chris@159 32 {
Chris@264 33 std::cerr << "FFTMemoryCache[" << this << "]::FFTMemoryCache (type "
Chris@264 34 << m_storageType << ")" << std::endl;
Chris@159 35 }
Chris@159 36
Chris@159 37 FFTMemoryCache::~FFTMemoryCache()
Chris@159 38 {
Chris@264 39 // std::cerr << "FFTMemoryCache[" << this << "]::~FFTMemoryCache" << std::endl;
Chris@159 40
Chris@159 41 for (size_t i = 0; i < m_width; ++i) {
Chris@159 42 if (m_magnitude && m_magnitude[i]) free(m_magnitude[i]);
Chris@159 43 if (m_phase && m_phase[i]) free(m_phase[i]);
Chris@264 44 if (m_fmagnitude && m_fmagnitude[i]) free(m_fmagnitude[i]);
Chris@264 45 if (m_fphase && m_fphase[i]) free(m_fphase[i]);
Chris@334 46 if (m_freal && m_freal[i]) free(m_freal[i]);
Chris@334 47 if (m_fimag && m_fimag[i]) free(m_fimag[i]);
Chris@159 48 }
Chris@159 49
Chris@159 50 if (m_magnitude) free(m_magnitude);
Chris@159 51 if (m_phase) free(m_phase);
Chris@264 52 if (m_fmagnitude) free(m_fmagnitude);
Chris@264 53 if (m_fphase) free(m_fphase);
Chris@334 54 if (m_freal) free(m_freal);
Chris@334 55 if (m_fimag) free(m_fimag);
Chris@159 56 if (m_factor) free(m_factor);
Chris@159 57 }
Chris@159 58
Chris@159 59 void
Chris@159 60 FFTMemoryCache::resize(size_t width, size_t height)
Chris@159 61 {
Chris@335 62 std::cerr << "FFTMemoryCache[" << this << "]::resize(" << width << "x" << height << " = " << width*height << ")" << std::endl;
Chris@159 63
Chris@159 64 if (m_width == width && m_height == height) return;
Chris@159 65
Chris@264 66 if (m_storageType == Compact) {
Chris@264 67 resize(m_magnitude, width, height);
Chris@264 68 resize(m_phase, width, height);
Chris@334 69 } else if (m_storageType == Polar) {
Chris@264 70 resize(m_fmagnitude, width, height);
Chris@264 71 resize(m_fphase, width, height);
Chris@334 72 } else {
Chris@334 73 resize(m_freal, width, height);
Chris@334 74 resize(m_fimag, width, height);
Chris@264 75 }
Chris@264 76
Chris@159 77 m_colset.resize(width);
Chris@159 78
Chris@159 79 m_factor = (float *)realloc(m_factor, width * sizeof(float));
Chris@159 80
Chris@159 81 m_width = width;
Chris@159 82 m_height = height;
Chris@159 83
Chris@243 84 // std::cerr << "done, width = " << m_width << " height = " << m_height << std::endl;
Chris@159 85 }
Chris@159 86
Chris@159 87 void
Chris@159 88 FFTMemoryCache::resize(uint16_t **&array, size_t width, size_t height)
Chris@159 89 {
Chris@159 90 for (size_t i = width; i < m_width; ++i) {
Chris@159 91 free(array[i]);
Chris@159 92 }
Chris@159 93
Chris@159 94 if (width != m_width) {
Chris@159 95 array = (uint16_t **)realloc(array, width * sizeof(uint16_t *));
Chris@159 96 if (!array) throw std::bad_alloc();
Chris@159 97 MUNLOCK(array, width * sizeof(uint16_t *));
Chris@159 98 }
Chris@159 99
Chris@159 100 for (size_t i = m_width; i < width; ++i) {
Chris@159 101 array[i] = 0;
Chris@159 102 }
Chris@159 103
Chris@159 104 for (size_t i = 0; i < width; ++i) {
Chris@159 105 array[i] = (uint16_t *)realloc(array[i], height * sizeof(uint16_t));
Chris@159 106 if (!array[i]) throw std::bad_alloc();
Chris@159 107 MUNLOCK(array[i], height * sizeof(uint16_t));
Chris@159 108 }
Chris@159 109 }
Chris@159 110
Chris@159 111 void
Chris@264 112 FFTMemoryCache::resize(float **&array, size_t width, size_t height)
Chris@264 113 {
Chris@264 114 for (size_t i = width; i < m_width; ++i) {
Chris@264 115 free(array[i]);
Chris@264 116 }
Chris@264 117
Chris@264 118 if (width != m_width) {
Chris@264 119 array = (float **)realloc(array, width * sizeof(float *));
Chris@264 120 if (!array) throw std::bad_alloc();
Chris@264 121 MUNLOCK(array, width * sizeof(float *));
Chris@264 122 }
Chris@264 123
Chris@264 124 for (size_t i = m_width; i < width; ++i) {
Chris@264 125 array[i] = 0;
Chris@264 126 }
Chris@264 127
Chris@264 128 for (size_t i = 0; i < width; ++i) {
Chris@264 129 array[i] = (float *)realloc(array[i], height * sizeof(float));
Chris@264 130 if (!array[i]) throw std::bad_alloc();
Chris@264 131 MUNLOCK(array[i], height * sizeof(float));
Chris@264 132 }
Chris@264 133 }
Chris@264 134
Chris@264 135 void
Chris@159 136 FFTMemoryCache::reset()
Chris@159 137 {
Chris@264 138 switch (m_storageType) {
Chris@264 139
Chris@264 140 case Compact:
Chris@264 141 for (size_t x = 0; x < m_width; ++x) {
Chris@264 142 for (size_t y = 0; y < m_height; ++y) {
Chris@264 143 m_magnitude[x][y] = 0;
Chris@264 144 m_phase[x][y] = 0;
Chris@264 145 }
Chris@264 146 m_factor[x] = 1.0;
Chris@264 147 }
Chris@264 148 break;
Chris@264 149
Chris@264 150 case Polar:
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_fmagnitude[x][y] = 0;
Chris@264 154 m_fphase[x][y] = 0;
Chris@264 155 }
Chris@264 156 m_factor[x] = 1.0;
Chris@264 157 }
Chris@264 158 break;
Chris@334 159
Chris@334 160 case Rectangular:
Chris@334 161 for (size_t x = 0; x < m_width; ++x) {
Chris@334 162 for (size_t y = 0; y < m_height; ++y) {
Chris@334 163 m_freal[x][y] = 0;
Chris@334 164 m_fimag[x][y] = 0;
Chris@334 165 }
Chris@334 166 m_factor[x] = 1.0;
Chris@334 167 }
Chris@334 168 break;
Chris@159 169 }
Chris@159 170 }
Chris@159 171
Chris@159 172 void
Chris@334 173 FFTMemoryCache::setColumnAt(size_t x, float *mags, float *phases, float factor)
Chris@334 174 {
Chris@334 175 setNormalizationFactor(x, factor);
Chris@334 176
Chris@334 177 if (m_storageType == Rectangular) {
Chris@334 178 for (size_t y = 0; y < m_height; ++y) {
Chris@334 179 m_freal[x][y] = mags[y] * cosf(phases[y]);
Chris@334 180 m_fimag[x][y] = mags[y] * sinf(phases[y]);
Chris@334 181 }
Chris@334 182 } else {
Chris@334 183 for (size_t y = 0; y < m_height; ++y) {
Chris@334 184 setMagnitudeAt(x, y, mags[y]);
Chris@334 185 setPhaseAt(x, y, phases[y]);
Chris@334 186 }
Chris@334 187 }
Chris@334 188
Chris@334 189 m_colset.set(x);
Chris@334 190 }
Chris@334 191
Chris@334 192 void
Chris@159 193 FFTMemoryCache::setColumnAt(size_t x, float *reals, float *imags)
Chris@159 194 {
Chris@159 195 float max = 0.0;
Chris@159 196
Chris@264 197 switch (m_storageType) {
Chris@264 198
Chris@334 199 case Rectangular:
Chris@334 200 for (size_t y = 0; y < m_height; ++y) {
Chris@334 201 m_freal[x][y] = reals[y];
Chris@334 202 m_fimag[x][y] = imags[y];
Chris@334 203 float mag = sqrtf(reals[y] * reals[y] + imags[y] * imags[y]);
Chris@334 204 if (mag > max) max = mag;
Chris@334 205 }
Chris@334 206 break;
Chris@334 207
Chris@264 208 case Compact:
Chris@264 209 case Polar:
Chris@264 210 for (size_t y = 0; y < m_height; ++y) {
Chris@264 211 float mag = sqrtf(reals[y] * reals[y] + imags[y] * imags[y]);
Chris@264 212 float phase = atan2f(imags[y], reals[y]);
Chris@264 213 phase = princargf(phase);
Chris@264 214 reals[y] = mag;
Chris@264 215 imags[y] = phase;
Chris@264 216 if (mag > max) max = mag;
Chris@264 217 }
Chris@264 218 break;
Chris@264 219 };
Chris@159 220
Chris@334 221 if (m_storageType == Rectangular) {
Chris@334 222 m_factor[x] = max;
Chris@334 223 m_colset.set(x);
Chris@334 224 } else {
Chris@334 225 setColumnAt(x, reals, imags, max);
Chris@334 226 }
Chris@159 227 }
Chris@159 228
Chris@170 229 size_t
Chris@264 230 FFTMemoryCache::getCacheSize(size_t width, size_t height, StorageType type)
Chris@170 231 {
Chris@264 232 size_t sz = 0;
Chris@264 233
Chris@264 234 switch (type) {
Chris@264 235
Chris@264 236 case Compact:
Chris@264 237 sz = (height * 2 + 1) * width * sizeof(uint16_t);
Chris@264 238
Chris@264 239 case Polar:
Chris@334 240 case Rectangular:
Chris@264 241 sz = (height * 2 + 1) * width * sizeof(float);
Chris@264 242 }
Chris@264 243
Chris@264 244 return sz;
Chris@170 245 }
Chris@170 246