annotate data/fft/FFTMemoryCache.cpp @ 264:260032c26c4f

* don't store fft values scaled by fftsize/2; that's a special requirement for the spectrogram, and other applications will not expect it -- make the spectrogram do that scaling itself * add a higher-resolution memory cache (still polar, though) as an alternative to the 16-bit compact cache * don't use the memory cache if we want rectangular coords (unless the disc cache is totally infeasible) as conversion slows it down anyway * avoid redundant rectangular -> polar -> rectangular conversion when storing values in a rectangular-mode disc cache
author Chris Cannam
date Fri, 01 Jun 2007 13:56:35 +0000
parents ff46f251139e
children aa8dbac62024
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@264 28 m_factor(0),
Chris@264 29 m_storageType(storageType)
Chris@159 30 {
Chris@264 31 std::cerr << "FFTMemoryCache[" << this << "]::FFTMemoryCache (type "
Chris@264 32 << m_storageType << ")" << std::endl;
Chris@159 33 }
Chris@159 34
Chris@159 35 FFTMemoryCache::~FFTMemoryCache()
Chris@159 36 {
Chris@264 37 // std::cerr << "FFTMemoryCache[" << this << "]::~FFTMemoryCache" << std::endl;
Chris@159 38
Chris@159 39 for (size_t i = 0; i < m_width; ++i) {
Chris@159 40 if (m_magnitude && m_magnitude[i]) free(m_magnitude[i]);
Chris@159 41 if (m_phase && m_phase[i]) free(m_phase[i]);
Chris@264 42 if (m_fmagnitude && m_fmagnitude[i]) free(m_fmagnitude[i]);
Chris@264 43 if (m_fphase && m_fphase[i]) free(m_fphase[i]);
Chris@159 44 }
Chris@159 45
Chris@159 46 if (m_magnitude) free(m_magnitude);
Chris@159 47 if (m_phase) free(m_phase);
Chris@264 48 if (m_fmagnitude) free(m_fmagnitude);
Chris@264 49 if (m_fphase) free(m_fphase);
Chris@159 50 if (m_factor) free(m_factor);
Chris@159 51 }
Chris@159 52
Chris@159 53 void
Chris@159 54 FFTMemoryCache::resize(size_t width, size_t height)
Chris@159 55 {
Chris@243 56 // std::cerr << "FFTMemoryCache[" << this << "]::resize(" << width << "x" << height << " = " << width*height << ")" << std::endl;
Chris@159 57
Chris@159 58 if (m_width == width && m_height == height) return;
Chris@159 59
Chris@264 60 if (m_storageType == Compact) {
Chris@264 61 resize(m_magnitude, width, height);
Chris@264 62 resize(m_phase, width, height);
Chris@264 63 } else {
Chris@264 64 resize(m_fmagnitude, width, height);
Chris@264 65 resize(m_fphase, width, height);
Chris@264 66 }
Chris@264 67
Chris@159 68 m_colset.resize(width);
Chris@159 69
Chris@159 70 m_factor = (float *)realloc(m_factor, width * sizeof(float));
Chris@159 71
Chris@159 72 m_width = width;
Chris@159 73 m_height = height;
Chris@159 74
Chris@243 75 // std::cerr << "done, width = " << m_width << " height = " << m_height << std::endl;
Chris@159 76 }
Chris@159 77
Chris@159 78 void
Chris@159 79 FFTMemoryCache::resize(uint16_t **&array, size_t width, size_t height)
Chris@159 80 {
Chris@159 81 for (size_t i = width; i < m_width; ++i) {
Chris@159 82 free(array[i]);
Chris@159 83 }
Chris@159 84
Chris@159 85 if (width != m_width) {
Chris@159 86 array = (uint16_t **)realloc(array, width * sizeof(uint16_t *));
Chris@159 87 if (!array) throw std::bad_alloc();
Chris@159 88 MUNLOCK(array, width * sizeof(uint16_t *));
Chris@159 89 }
Chris@159 90
Chris@159 91 for (size_t i = m_width; i < width; ++i) {
Chris@159 92 array[i] = 0;
Chris@159 93 }
Chris@159 94
Chris@159 95 for (size_t i = 0; i < width; ++i) {
Chris@159 96 array[i] = (uint16_t *)realloc(array[i], height * sizeof(uint16_t));
Chris@159 97 if (!array[i]) throw std::bad_alloc();
Chris@159 98 MUNLOCK(array[i], height * sizeof(uint16_t));
Chris@159 99 }
Chris@159 100 }
Chris@159 101
Chris@159 102 void
Chris@264 103 FFTMemoryCache::resize(float **&array, size_t width, size_t height)
Chris@264 104 {
Chris@264 105 for (size_t i = width; i < m_width; ++i) {
Chris@264 106 free(array[i]);
Chris@264 107 }
Chris@264 108
Chris@264 109 if (width != m_width) {
Chris@264 110 array = (float **)realloc(array, width * sizeof(float *));
Chris@264 111 if (!array) throw std::bad_alloc();
Chris@264 112 MUNLOCK(array, width * sizeof(float *));
Chris@264 113 }
Chris@264 114
Chris@264 115 for (size_t i = m_width; i < width; ++i) {
Chris@264 116 array[i] = 0;
Chris@264 117 }
Chris@264 118
Chris@264 119 for (size_t i = 0; i < width; ++i) {
Chris@264 120 array[i] = (float *)realloc(array[i], height * sizeof(float));
Chris@264 121 if (!array[i]) throw std::bad_alloc();
Chris@264 122 MUNLOCK(array[i], height * sizeof(float));
Chris@264 123 }
Chris@264 124 }
Chris@264 125
Chris@264 126 void
Chris@159 127 FFTMemoryCache::reset()
Chris@159 128 {
Chris@264 129 switch (m_storageType) {
Chris@264 130
Chris@264 131 case Compact:
Chris@264 132 for (size_t x = 0; x < m_width; ++x) {
Chris@264 133 for (size_t y = 0; y < m_height; ++y) {
Chris@264 134 m_magnitude[x][y] = 0;
Chris@264 135 m_phase[x][y] = 0;
Chris@264 136 }
Chris@264 137 m_factor[x] = 1.0;
Chris@264 138 }
Chris@264 139 break;
Chris@264 140
Chris@264 141 case Polar:
Chris@264 142 for (size_t x = 0; x < m_width; ++x) {
Chris@264 143 for (size_t y = 0; y < m_height; ++y) {
Chris@264 144 m_fmagnitude[x][y] = 0;
Chris@264 145 m_fphase[x][y] = 0;
Chris@264 146 }
Chris@264 147 m_factor[x] = 1.0;
Chris@264 148 }
Chris@264 149 break;
Chris@159 150 }
Chris@159 151 }
Chris@159 152
Chris@159 153 void
Chris@159 154 FFTMemoryCache::setColumnAt(size_t x, float *reals, float *imags)
Chris@159 155 {
Chris@159 156 float max = 0.0;
Chris@159 157
Chris@264 158 switch (m_storageType) {
Chris@264 159
Chris@264 160 case Compact:
Chris@264 161 case Polar:
Chris@264 162 for (size_t y = 0; y < m_height; ++y) {
Chris@264 163 float mag = sqrtf(reals[y] * reals[y] + imags[y] * imags[y]);
Chris@264 164 float phase = atan2f(imags[y], reals[y]);
Chris@264 165 phase = princargf(phase);
Chris@264 166 reals[y] = mag;
Chris@264 167 imags[y] = phase;
Chris@264 168 if (mag > max) max = mag;
Chris@264 169 }
Chris@264 170 break;
Chris@264 171 };
Chris@159 172
Chris@159 173 setColumnAt(x, reals, imags, max);
Chris@159 174 }
Chris@159 175
Chris@170 176 size_t
Chris@264 177 FFTMemoryCache::getCacheSize(size_t width, size_t height, StorageType type)
Chris@170 178 {
Chris@264 179 size_t sz = 0;
Chris@264 180
Chris@264 181 switch (type) {
Chris@264 182
Chris@264 183 case Compact:
Chris@264 184 sz = (height * 2 + 1) * width * sizeof(uint16_t);
Chris@264 185
Chris@264 186 case Polar:
Chris@264 187 sz = (height * 2 + 1) * width * sizeof(float);
Chris@264 188 }
Chris@264 189
Chris@264 190 return sz;
Chris@170 191 }
Chris@170 192