annotate data/fft/FFTMemoryCache.cpp @ 537:3cc4b7cd2aa5

* Merge from one-fftdataserver-per-fftmodel branch. This bit of reworking (which is not described very accurately by the title of the branch) turns the MatrixFile object into something that either reads or writes, but not both, and separates the FFT file cache reader and writer implementations separately. This allows the FFT data server to have a single thread owning writers and one reader per "customer" thread, and for all locking to be vastly simplified and concentrated in the data server alone (because none of the classes it makes use of is used in more than one thread at a time). The result is faster and more trustworthy code.
author Chris Cannam
date Tue, 27 Jan 2009 13:25:10 +0000
parents 115f60df1e4d
children 1469caaa8e67
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@537 25 size_t width, size_t 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@264 38 std::cerr << "FFTMemoryCache[" << this << "]::FFTMemoryCache (type "
Chris@537 39 << m_storageType << "), size " << m_width << "x" << m_height << std::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@374 48 std::cerr << "FFTMemoryCache[" << this << "]::~FFTMemoryCache" << std::endl;
Chris@374 49 #endif
Chris@159 50
Chris@159 51 for (size_t 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@537 74 size_t width = m_width, height = m_height;
Chris@408 75
Chris@374 76 #ifdef DEBUG_FFT_MEMORY_CACHE
Chris@537 77 std::cerr << "FFTMemoryCache[" << this << "]::initialise(" << width << "x" << height << " = " << width*height << ")" << std::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@374 99 std::cerr << "done, width = " << m_width << " height = " << m_height << std::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@537 110 for (size_t 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@537 124 for (size_t 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@334 132 FFTMemoryCache::setColumnAt(size_t 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@334 140 for (size_t 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@334 145 for (size_t 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@537 151 m_colsetMutex.lock();
Chris@334 152 m_colset.set(x);
Chris@537 153 m_colsetMutex.unlock();
Chris@334 154 }
Chris@334 155
Chris@334 156 void
Chris@159 157 FFTMemoryCache::setColumnAt(size_t 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@334 166 for (size_t 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@264 178 for (size_t 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@537 191 m_colsetMutex.lock();
Chris@334 192 m_colset.set(x);
Chris@537 193 m_colsetMutex.unlock();
Chris@334 194 } else {
Chris@334 195 setColumnAt(x, reals, imags, max);
Chris@334 196 }
Chris@159 197 }
Chris@159 198
Chris@170 199 size_t
Chris@537 200 FFTMemoryCache::getCacheSize(size_t width, size_t height, FFTCache::StorageType type)
Chris@170 201 {
Chris@264 202 size_t 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@264 208
Chris@537 209 case FFTCache::Polar:
Chris@537 210 case FFTCache::Rectangular:
Chris@264 211 sz = (height * 2 + 1) * width * sizeof(float);
Chris@264 212 }
Chris@264 213
Chris@264 214 return sz;
Chris@170 215 }
Chris@170 216