svcore  1.9
FFTFileCacheReader.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7  This file copyright 2006-2009 Chris Cannam and QMUL.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #include "FFTFileCacheReader.h"
17 #include "FFTFileCacheWriter.h"
18 
19 #include "fileio/MatrixFile.h"
20 
21 #include "base/Profiler.h"
22 #include "base/Thread.h"
23 #include "base/Exceptions.h"
24 
25 #include <iostream>
26 
27 
28 // The underlying matrix has height (m_height * 2 + 1). In each
29 // column we store magnitude at [0], [2] etc and phase at [1], [3]
30 // etc, and then store the normalization factor (maximum magnitude) at
31 // [m_height * 2]. In compact mode, the factor takes two cells.
32 
34  m_readbuf(0),
35  m_readbufCol(0),
36  m_readbufWidth(0),
37  m_readbufGood(false),
38  m_storageType(writer->getStorageType()),
39  m_factorSize(m_storageType == FFTCache::Compact ? 2 : 1),
40  m_mfc(new MatrixFile
41  (writer->getFileBase(),
42  MatrixFile::ReadOnly,
43  m_storageType == FFTCache::Compact ? sizeof(uint16_t) : sizeof(float),
44  writer->getWidth(),
45  writer->getHeight() * 2 + m_factorSize))
46 {
47 // cerr << "FFTFileCacheReader: storage type is " << (storageType == FFTCache::Compact ? "Compact" : storageType == Polar ? "Polar" : "Rectangular") << endl;
48 }
49 
51 {
52  if (m_readbuf) delete[] m_readbuf;
53  delete m_mfc;
54 }
55 
56 int
58 {
59  return m_mfc->getWidth();
60 }
61 
62 int
64 {
65  int mh = m_mfc->getHeight();
66  if (mh > m_factorSize) return (mh - m_factorSize) / 2;
67  else return 0;
68 }
69 
70 float
72 {
73  Profiler profiler("FFTFileCacheReader::getMagnitudeAt", false);
74 
75  float value = 0.f;
76 
77  switch (m_storageType) {
78 
79  case FFTCache::Compact:
80  value = (getFromReadBufCompactUnsigned(x, y * 2) / 65535.0)
82  break;
83 
85  {
86  float real, imag;
87  getValuesAt(x, y, real, imag);
88  value = sqrtf(real * real + imag * imag);
89  break;
90  }
91 
92  case FFTCache::Polar:
93  value = getFromReadBufStandard(x, y * 2);
94  break;
95  }
96 
97  return value;
98 }
99 
100 float
102 {
103  float value = 0.f;
104 
105  switch (m_storageType) {
106 
107  case FFTCache::Compact:
108  value = getFromReadBufCompactUnsigned(x, y * 2) / 65535.0;
109  break;
110 
112  case FFTCache::Polar:
113  {
114  float mag = getMagnitudeAt(x, y);
115  float factor = getNormalizationFactor(x);
116  if (factor != 0) value = mag / factor;
117  else value = 0.f;
118  break;
119  }
120  }
121 
122  return value;
123 }
124 
125 float
127 {
128  return getNormalizationFactor(x);
129 }
130 
131 float
133 {
134  float value = 0.f;
135 
136  switch (m_storageType) {
137 
138  case FFTCache::Compact:
139  value = (getFromReadBufCompactSigned(x, y * 2 + 1) / 32767.0) * M_PI;
140  break;
141 
143  {
144  float real, imag;
145  getValuesAt(x, y, real, imag);
146  value = atan2f(imag, real);
147  break;
148  }
149 
150  case FFTCache::Polar:
151  value = getFromReadBufStandard(x, y * 2 + 1);
152  break;
153  }
154 
155  return value;
156 }
157 
158 void
159 FFTFileCacheReader::getValuesAt(int x, int y, float &real, float &imag) const
160 {
161 // SVDEBUG << "FFTFileCacheReader::getValuesAt(" << x << "," << y << ")" << endl;
162 
163  switch (m_storageType) {
164 
166  real = getFromReadBufStandard(x, y * 2);
167  imag = getFromReadBufStandard(x, y * 2 + 1);
168  return;
169 
170  case FFTCache::Compact:
171  case FFTCache::Polar:
172  float mag = getMagnitudeAt(x, y);
173  float phase = getPhaseAt(x, y);
174  real = mag * cosf(phase);
175  imag = mag * sinf(phase);
176  return;
177  }
178 }
179 
180 void
181 FFTFileCacheReader::getMagnitudesAt(int x, float *values, int minbin, int count, int step) const
182 {
183  Profiler profiler("FFTFileCacheReader::getMagnitudesAt");
184 
185  switch (m_storageType) {
186 
187  case FFTCache::Compact:
188  for (int i = 0; i < count; ++i) {
189  int y = minbin + i * step;
190  values[i] = (getFromReadBufCompactUnsigned(x, y * 2) / 65535.0)
192  }
193  break;
194 
196  {
197  float real, imag;
198  for (int i = 0; i < count; ++i) {
199  int y = minbin + i * step;
200  real = getFromReadBufStandard(x, y * 2);
201  imag = getFromReadBufStandard(x, y * 2 + 1);
202  values[i] = sqrtf(real * real + imag * imag);
203  }
204  break;
205  }
206 
207  case FFTCache::Polar:
208  for (int i = 0; i < count; ++i) {
209  int y = minbin + i * step;
210  values[i] = getFromReadBufStandard(x, y * 2);
211  }
212  break;
213  }
214 }
215 
216 bool
218 {
219  if (m_readbuf && m_readbufGood &&
220  (m_readbufCol == x || (m_readbufWidth > 1 && m_readbufCol+1 == x))) {
221 // SVDEBUG << "FFTFileCacheReader::haveSetColumnAt: short-circuiting; we know about this one" << endl;
222  return true;
223  }
224  return m_mfc->haveSetColumnAt(x);
225 }
226 
227 int
228 FFTFileCacheReader::getCacheSize(int width, int height,
230 {
231  return (height * 2 + (type == FFTCache::Compact ? 2 : 1)) * width *
232  (type == FFTCache::Compact ? sizeof(uint16_t) : sizeof(float)) +
233  2 * sizeof(int); // matrix file header size
234 }
235 
236 void
238 {
239  Profiler profiler("FFTFileCacheReader::populateReadBuf", false);
240 
241 // SVDEBUG << "FFTFileCacheReader::populateReadBuf(" << x << ")" << endl;
242 
243  if (!m_readbuf) {
244  m_readbuf = new char[m_mfc->getHeight() * 2 * m_mfc->getCellSize()];
245  }
246 
247  m_readbufGood = false;
248 
249  try {
250  bool good = false;
251  if (m_mfc->haveSetColumnAt(x)) {
252  // If the column is not available, we have no obligation
253  // to do anything with the readbuf -- we can cheerfully
254  // return garbage. It's the responsibility of the caller
255  // to check haveSetColumnAt before trusting any retrieved
256  // data. However, we do record whether the data in the
257  // readbuf is good or not, because we can use that to
258  // return an immediate result for haveSetColumnAt if the
259  // column is right.
260  good = true;
262  }
263  if (m_mfc->haveSetColumnAt(x + 1)) {
265  (x + 1, m_readbuf + m_mfc->getCellSize() * m_mfc->getHeight());
266  m_readbufWidth = 2;
267  } else {
268  m_readbufWidth = 1;
269  }
270  m_readbufGood = good;
271  } catch (FileReadFailed f) {
272  cerr << "ERROR: FFTFileCacheReader::populateReadBuf: File read failed: "
273  << f.what() << endl;
274  memset(m_readbuf, 0, m_mfc->getHeight() * 2 * m_mfc->getCellSize());
275  }
276  m_readbufCol = x;
277 }
278 
float getNormalizationFactor(int col) const
void getMagnitudesAt(int x, float *values, int minbin, int count, int step) const
float getNormalizedMagnitudeAt(int x, int y) const
float getPhaseAt(int x, int y) const
int getCellSize() const
Definition: MatrixFile.h:69
bool haveSetColumnAt(int x) const
Definition: MatrixFile.cpp:306
float getMagnitudeAt(int x, int y) const
void getValuesAt(int x, int y, float &real, float &imag) const
FFTFileCacheReader(FFTFileCacheWriter *)
virtual const char * what() const
Definition: Exceptions.cpp:72
float getMaximumMagnitudeAt(int x) const
float getFromReadBufCompactSigned(int x, int y) const
int getHeight() const
Definition: MatrixFile.h:68
int getWidth() const
Definition: MatrixFile.h:67
void populateReadBuf(int x) const
static int getCacheSize(int width, int height, FFTCache::StorageType type)
bool haveSetColumnAt(int x) const
FFTCache::StorageType m_storageType
void getColumnAt(int x, void *data)
Definition: MatrixFile.cpp:266
float getFromReadBufCompactUnsigned(int x, int y) const
float getFromReadBufStandard(int x, int y) const
Profile point instance class.
Definition: Profiler.h:86