Chris@537
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@537
|
2
|
Chris@537
|
3 /*
|
Chris@537
|
4 Sonic Visualiser
|
Chris@537
|
5 An audio file viewer and annotation editor.
|
Chris@537
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@537
|
7 This file copyright 2006-2009 Chris Cannam and QMUL.
|
Chris@537
|
8
|
Chris@537
|
9 This program is free software; you can redistribute it and/or
|
Chris@537
|
10 modify it under the terms of the GNU General Public License as
|
Chris@537
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@537
|
12 License, or (at your option) any later version. See the file
|
Chris@537
|
13 COPYING included with this distribution for more information.
|
Chris@537
|
14 */
|
Chris@537
|
15
|
Chris@537
|
16 #include "FFTFileCacheWriter.h"
|
Chris@537
|
17
|
Chris@537
|
18 #include "fileio/MatrixFile.h"
|
Chris@537
|
19
|
Chris@537
|
20 #include "base/Profiler.h"
|
Chris@537
|
21 #include "base/Thread.h"
|
Chris@537
|
22 #include "base/Exceptions.h"
|
Chris@537
|
23
|
Chris@537
|
24 #include <iostream>
|
Chris@537
|
25
|
Chris@537
|
26 //#define DEBUG_FFT_FILE_CACHE_WRITER 1
|
Chris@537
|
27
|
Chris@537
|
28
|
Chris@537
|
29 // The underlying matrix has height (m_height * 2 + 1). In each
|
Chris@537
|
30 // column we store magnitude at [0], [2] etc and phase at [1], [3]
|
Chris@537
|
31 // etc, and then store the normalization factor (maximum magnitude) at
|
Chris@537
|
32 // [m_height * 2]. In compact mode, the factor takes two cells.
|
Chris@537
|
33
|
Chris@537
|
34 FFTFileCacheWriter::FFTFileCacheWriter(QString fileBase,
|
Chris@537
|
35 FFTCache::StorageType storageType,
|
Chris@929
|
36 int width, int height) :
|
Chris@537
|
37 m_writebuf(0),
|
Chris@537
|
38 m_fileBase(fileBase),
|
Chris@537
|
39 m_storageType(storageType),
|
Chris@537
|
40 m_factorSize(storageType == FFTCache::Compact ? 2 : 1),
|
Chris@537
|
41 m_mfc(new MatrixFile
|
Chris@537
|
42 (fileBase, MatrixFile::WriteOnly,
|
Chris@537
|
43 storageType == FFTCache::Compact ? sizeof(uint16_t) : sizeof(float),
|
Chris@537
|
44 width, height * 2 + m_factorSize))
|
Chris@537
|
45 {
|
Chris@577
|
46 #ifdef DEBUG_FFT_FILE_CACHE_WRITER
|
Chris@843
|
47 cerr << "FFTFileCacheWriter: storage type is " << (storageType == FFTCache::Compact ? "Compact" : storageType == FFTCache::Polar ? "Polar" : "Rectangular") << ", size " << width << "x" << height << endl;
|
Chris@577
|
48 #endif
|
Chris@550
|
49 m_mfc->setAutoClose(true);
|
Chris@537
|
50 m_writebuf = new char[(height * 2 + m_factorSize) * m_mfc->getCellSize()];
|
Chris@537
|
51 }
|
Chris@537
|
52
|
Chris@537
|
53 FFTFileCacheWriter::~FFTFileCacheWriter()
|
Chris@537
|
54 {
|
Chris@537
|
55 if (m_writebuf) delete[] m_writebuf;
|
Chris@537
|
56 delete m_mfc;
|
Chris@537
|
57 }
|
Chris@537
|
58
|
Chris@537
|
59 QString
|
Chris@537
|
60 FFTFileCacheWriter::getFileBase() const
|
Chris@537
|
61 {
|
Chris@537
|
62 return m_fileBase;
|
Chris@537
|
63 }
|
Chris@537
|
64
|
Chris@929
|
65 int
|
Chris@537
|
66 FFTFileCacheWriter::getWidth() const
|
Chris@537
|
67 {
|
Chris@537
|
68 return m_mfc->getWidth();
|
Chris@537
|
69 }
|
Chris@537
|
70
|
Chris@929
|
71 int
|
Chris@537
|
72 FFTFileCacheWriter::getHeight() const
|
Chris@537
|
73 {
|
Chris@929
|
74 int mh = m_mfc->getHeight();
|
Chris@537
|
75 if (mh > m_factorSize) return (mh - m_factorSize) / 2;
|
Chris@537
|
76 else return 0;
|
Chris@537
|
77 }
|
Chris@537
|
78
|
Chris@550
|
79 bool
|
Chris@929
|
80 FFTFileCacheWriter::haveSetColumnAt(int x) const
|
Chris@550
|
81 {
|
Chris@550
|
82 return m_mfc->haveSetColumnAt(x);
|
Chris@550
|
83 }
|
Chris@550
|
84
|
Chris@537
|
85 void
|
Chris@929
|
86 FFTFileCacheWriter::setColumnAt(int x, float *mags, float *phases, float factor)
|
Chris@537
|
87 {
|
Chris@929
|
88 int h = getHeight();
|
Chris@537
|
89
|
Chris@537
|
90 switch (m_storageType) {
|
Chris@537
|
91
|
Chris@537
|
92 case FFTCache::Compact:
|
Chris@929
|
93 for (int y = 0; y < h; ++y) {
|
Chris@537
|
94 ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mags[y] / factor) * 65535.0);
|
Chris@537
|
95 ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phases[y] * 32767) / M_PI));
|
Chris@537
|
96 }
|
Chris@537
|
97 break;
|
Chris@537
|
98
|
Chris@537
|
99 case FFTCache::Rectangular:
|
Chris@929
|
100 for (int y = 0; y < h; ++y) {
|
Chris@537
|
101 ((float *)m_writebuf)[y * 2] = mags[y] * cosf(phases[y]);
|
Chris@537
|
102 ((float *)m_writebuf)[y * 2 + 1] = mags[y] * sinf(phases[y]);
|
Chris@537
|
103 }
|
Chris@537
|
104 break;
|
Chris@537
|
105
|
Chris@537
|
106 case FFTCache::Polar:
|
Chris@929
|
107 for (int y = 0; y < h; ++y) {
|
Chris@537
|
108 ((float *)m_writebuf)[y * 2] = mags[y];
|
Chris@537
|
109 ((float *)m_writebuf)[y * 2 + 1] = phases[y];
|
Chris@537
|
110 }
|
Chris@537
|
111 break;
|
Chris@537
|
112 }
|
Chris@537
|
113
|
Chris@537
|
114 static float maxFactor = 0;
|
Chris@537
|
115 if (factor > maxFactor) maxFactor = factor;
|
Chris@537
|
116 #ifdef DEBUG_FFT_FILE_CACHE_WRITER
|
Chris@843
|
117 cerr << "Column " << x << ": normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << endl;
|
Chris@537
|
118 #endif
|
Chris@537
|
119
|
Chris@537
|
120 setNormalizationFactorToWritebuf(factor);
|
Chris@537
|
121
|
Chris@537
|
122 m_mfc->setColumnAt(x, m_writebuf);
|
Chris@537
|
123 }
|
Chris@537
|
124
|
Chris@537
|
125 void
|
Chris@929
|
126 FFTFileCacheWriter::setColumnAt(int x, float *real, float *imag)
|
Chris@537
|
127 {
|
Chris@929
|
128 int h = getHeight();
|
Chris@537
|
129
|
Chris@537
|
130 float factor = 0.0f;
|
Chris@537
|
131
|
Chris@537
|
132 switch (m_storageType) {
|
Chris@537
|
133
|
Chris@537
|
134 case FFTCache::Compact:
|
Chris@929
|
135 for (int y = 0; y < h; ++y) {
|
Chris@537
|
136 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
|
Chris@537
|
137 if (mag > factor) factor = mag;
|
Chris@537
|
138 }
|
Chris@929
|
139 for (int y = 0; y < h; ++y) {
|
Chris@537
|
140 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
|
Chris@537
|
141 float phase = atan2f(imag[y], real[y]);
|
Chris@537
|
142 ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mag / factor) * 65535.0);
|
Chris@537
|
143 ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phase * 32767) / M_PI));
|
Chris@537
|
144 }
|
Chris@537
|
145 break;
|
Chris@537
|
146
|
Chris@537
|
147 case FFTCache::Rectangular:
|
Chris@929
|
148 for (int y = 0; y < h; ++y) {
|
Chris@537
|
149 ((float *)m_writebuf)[y * 2] = real[y];
|
Chris@537
|
150 ((float *)m_writebuf)[y * 2 + 1] = imag[y];
|
Chris@537
|
151 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
|
Chris@537
|
152 if (mag > factor) factor = mag;
|
Chris@537
|
153 }
|
Chris@537
|
154 break;
|
Chris@537
|
155
|
Chris@537
|
156 case FFTCache::Polar:
|
Chris@929
|
157 for (int y = 0; y < h; ++y) {
|
Chris@537
|
158 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
|
Chris@537
|
159 if (mag > factor) factor = mag;
|
Chris@537
|
160 ((float *)m_writebuf)[y * 2] = mag;
|
Chris@537
|
161 float phase = atan2f(imag[y], real[y]);
|
Chris@537
|
162 ((float *)m_writebuf)[y * 2 + 1] = phase;
|
Chris@537
|
163 }
|
Chris@537
|
164 break;
|
Chris@537
|
165 }
|
Chris@537
|
166
|
Chris@537
|
167 static float maxFactor = 0;
|
Chris@537
|
168 if (factor > maxFactor) maxFactor = factor;
|
Chris@537
|
169 #ifdef DEBUG_FFT_FILE_CACHE_WRITER
|
Chris@843
|
170 cerr << "[RI] Column " << x << ": normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << endl;
|
Chris@537
|
171 #endif
|
Chris@537
|
172
|
Chris@537
|
173 setNormalizationFactorToWritebuf(factor);
|
Chris@537
|
174
|
Chris@537
|
175 m_mfc->setColumnAt(x, m_writebuf);
|
Chris@537
|
176 }
|
Chris@537
|
177
|
Chris@929
|
178 int
|
Chris@929
|
179 FFTFileCacheWriter::getCacheSize(int width, int height,
|
Chris@537
|
180 FFTCache::StorageType type)
|
Chris@537
|
181 {
|
Chris@537
|
182 return (height * 2 + (type == FFTCache::Compact ? 2 : 1)) * width *
|
Chris@537
|
183 (type == FFTCache::Compact ? sizeof(uint16_t) : sizeof(float)) +
|
Chris@929
|
184 2 * sizeof(int); // matrix file header size
|
Chris@537
|
185 }
|
Chris@537
|
186
|
Chris@537
|
187 void
|
Chris@537
|
188 FFTFileCacheWriter::allColumnsWritten()
|
Chris@537
|
189 {
|
Chris@537
|
190 #ifdef DEBUG_FFT_FILE_CACHE_WRITER
|
Chris@690
|
191 SVDEBUG << "FFTFileCacheWriter::allColumnsWritten" << endl;
|
Chris@537
|
192 #endif
|
Chris@537
|
193 m_mfc->close();
|
Chris@537
|
194 }
|
Chris@537
|
195
|