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
|