svcore
1.9
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Sonic Visualiser 00005 An audio file viewer and annotation editor. 00006 Centre for Digital Music, Queen Mary, University of London. 00007 This file copyright 2006 Chris Cannam. 00008 00009 This program is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU General Public License as 00011 published by the Free Software Foundation; either version 2 of the 00012 License, or (at your option) any later version. See the file 00013 COPYING included with this distribution for more information. 00014 */ 00015 00016 #include "FFTMemoryCache.h" 00017 #include "system/System.h" 00018 00019 #include <iostream> 00020 #include <cstdlib> 00021 00022 //#define DEBUG_FFT_MEMORY_CACHE 1 00023 00024 FFTMemoryCache::FFTMemoryCache(FFTCache::StorageType storageType, 00025 int width, int height) : 00026 m_width(width), 00027 m_height(height), 00028 m_magnitude(0), 00029 m_phase(0), 00030 m_fmagnitude(0), 00031 m_fphase(0), 00032 m_freal(0), 00033 m_fimag(0), 00034 m_factor(0), 00035 m_storageType(storageType) 00036 { 00037 #ifdef DEBUG_FFT_MEMORY_CACHE 00038 cerr << "FFTMemoryCache[" << this << "]::FFTMemoryCache (type " 00039 << m_storageType << "), size " << m_width << "x" << m_height << endl; 00040 #endif 00041 00042 initialise(); 00043 } 00044 00045 FFTMemoryCache::~FFTMemoryCache() 00046 { 00047 #ifdef DEBUG_FFT_MEMORY_CACHE 00048 cerr << "FFTMemoryCache[" << this << "]::~FFTMemoryCache" << endl; 00049 #endif 00050 00051 for (int i = 0; i < m_width; ++i) { 00052 if (m_magnitude && m_magnitude[i]) free(m_magnitude[i]); 00053 if (m_phase && m_phase[i]) free(m_phase[i]); 00054 if (m_fmagnitude && m_fmagnitude[i]) free(m_fmagnitude[i]); 00055 if (m_fphase && m_fphase[i]) free(m_fphase[i]); 00056 if (m_freal && m_freal[i]) free(m_freal[i]); 00057 if (m_fimag && m_fimag[i]) free(m_fimag[i]); 00058 } 00059 00060 if (m_magnitude) free(m_magnitude); 00061 if (m_phase) free(m_phase); 00062 if (m_fmagnitude) free(m_fmagnitude); 00063 if (m_fphase) free(m_fphase); 00064 if (m_freal) free(m_freal); 00065 if (m_fimag) free(m_fimag); 00066 if (m_factor) free(m_factor); 00067 } 00068 00069 void 00070 FFTMemoryCache::initialise() 00071 { 00072 Profiler profiler("FFTMemoryCache::initialise"); 00073 00074 int width = m_width, height = m_height; 00075 00076 #ifdef DEBUG_FFT_MEMORY_CACHE 00077 cerr << "FFTMemoryCache[" << this << "]::initialise(" << width << "x" << height << " = " << width*height << ")" << endl; 00078 #endif 00079 00080 if (m_storageType == FFTCache::Compact) { 00081 initialise(m_magnitude); 00082 initialise(m_phase); 00083 } else if (m_storageType == FFTCache::Polar) { 00084 initialise(m_fmagnitude); 00085 initialise(m_fphase); 00086 } else { 00087 initialise(m_freal); 00088 initialise(m_fimag); 00089 } 00090 00091 m_colset.resize(width); 00092 00093 m_factor = (float *)realloc(m_factor, width * sizeof(float)); 00094 00095 m_width = width; 00096 m_height = height; 00097 00098 #ifdef DEBUG_FFT_MEMORY_CACHE 00099 cerr << "done, width = " << m_width << " height = " << m_height << endl; 00100 #endif 00101 } 00102 00103 void 00104 FFTMemoryCache::initialise(uint16_t **&array) 00105 { 00106 array = (uint16_t **)malloc(m_width * sizeof(uint16_t *)); 00107 if (!array) throw std::bad_alloc(); 00108 MUNLOCK(array, m_width * sizeof(uint16_t *)); 00109 00110 for (int i = 0; i < m_width; ++i) { 00111 array[i] = (uint16_t *)malloc(m_height * sizeof(uint16_t)); 00112 if (!array[i]) throw std::bad_alloc(); 00113 MUNLOCK(array[i], m_height * sizeof(uint16_t)); 00114 } 00115 } 00116 00117 void 00118 FFTMemoryCache::initialise(float **&array) 00119 { 00120 array = (float **)malloc(m_width * sizeof(float *)); 00121 if (!array) throw std::bad_alloc(); 00122 MUNLOCK(array, m_width * sizeof(float *)); 00123 00124 for (int i = 0; i < m_width; ++i) { 00125 array[i] = (float *)malloc(m_height * sizeof(float)); 00126 if (!array[i]) throw std::bad_alloc(); 00127 MUNLOCK(array[i], m_height * sizeof(float)); 00128 } 00129 } 00130 00131 void 00132 FFTMemoryCache::setColumnAt(int x, float *mags, float *phases, float factor) 00133 { 00134 Profiler profiler("FFTMemoryCache::setColumnAt: from polar"); 00135 00136 setNormalizationFactor(x, factor); 00137 00138 if (m_storageType == FFTCache::Rectangular) { 00139 Profiler subprof("FFTMemoryCache::setColumnAt: polar to cart"); 00140 for (int y = 0; y < m_height; ++y) { 00141 m_freal[x][y] = mags[y] * cosf(phases[y]); 00142 m_fimag[x][y] = mags[y] * sinf(phases[y]); 00143 } 00144 } else { 00145 for (int y = 0; y < m_height; ++y) { 00146 setMagnitudeAt(x, y, mags[y]); 00147 setPhaseAt(x, y, phases[y]); 00148 } 00149 } 00150 00151 m_colsetLock.lockForWrite(); 00152 m_colset.set(x); 00153 m_colsetLock.unlock(); 00154 } 00155 00156 void 00157 FFTMemoryCache::setColumnAt(int x, float *reals, float *imags) 00158 { 00159 Profiler profiler("FFTMemoryCache::setColumnAt: from cart"); 00160 00161 float max = 0.0; 00162 00163 switch (m_storageType) { 00164 00165 case FFTCache::Rectangular: 00166 for (int y = 0; y < m_height; ++y) { 00167 m_freal[x][y] = reals[y]; 00168 m_fimag[x][y] = imags[y]; 00169 float mag = sqrtf(reals[y] * reals[y] + imags[y] * imags[y]); 00170 if (mag > max) max = mag; 00171 } 00172 break; 00173 00174 case FFTCache::Compact: 00175 case FFTCache::Polar: 00176 { 00177 Profiler subprof("FFTMemoryCache::setColumnAt: cart to polar"); 00178 for (int y = 0; y < m_height; ++y) { 00179 float mag = sqrtf(reals[y] * reals[y] + imags[y] * imags[y]); 00180 float phase = atan2f(imags[y], reals[y]); 00181 reals[y] = mag; 00182 imags[y] = phase; 00183 if (mag > max) max = mag; 00184 } 00185 break; 00186 } 00187 }; 00188 00189 if (m_storageType == FFTCache::Rectangular) { 00190 m_factor[x] = max; 00191 m_colsetLock.lockForWrite(); 00192 m_colset.set(x); 00193 m_colsetLock.unlock(); 00194 } else { 00195 setColumnAt(x, reals, imags, max); 00196 } 00197 } 00198 00199 int 00200 FFTMemoryCache::getCacheSize(int width, int height, FFTCache::StorageType type) 00201 { 00202 int sz = 0; 00203 00204 switch (type) { 00205 00206 case FFTCache::Compact: 00207 sz = (height * 2 + 1) * width * sizeof(uint16_t); 00208 break; 00209 00210 case FFTCache::Polar: 00211 case FFTCache::Rectangular: 00212 sz = (height * 2 + 1) * width * sizeof(float); 00213 break; 00214 } 00215 00216 return sz; 00217 } 00218