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@537
|
36 size_t width, size_t 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@537
|
46 std::cerr << "FFTFileCacheWriter: storage type is " << (storageType == FFTCache::Compact ? "Compact" : storageType == FFTCache::Polar ? "Polar" : "Rectangular") << ", size " << width << "x" << height << std::endl;
|
Chris@537
|
47 m_writebuf = new char[(height * 2 + m_factorSize) * m_mfc->getCellSize()];
|
Chris@537
|
48 }
|
Chris@537
|
49
|
Chris@537
|
50 FFTFileCacheWriter::~FFTFileCacheWriter()
|
Chris@537
|
51 {
|
Chris@537
|
52 if (m_writebuf) delete[] m_writebuf;
|
Chris@537
|
53 delete m_mfc;
|
Chris@537
|
54 }
|
Chris@537
|
55
|
Chris@537
|
56 QString
|
Chris@537
|
57 FFTFileCacheWriter::getFileBase() const
|
Chris@537
|
58 {
|
Chris@537
|
59 return m_fileBase;
|
Chris@537
|
60 }
|
Chris@537
|
61
|
Chris@537
|
62 size_t
|
Chris@537
|
63 FFTFileCacheWriter::getWidth() const
|
Chris@537
|
64 {
|
Chris@537
|
65 return m_mfc->getWidth();
|
Chris@537
|
66 }
|
Chris@537
|
67
|
Chris@537
|
68 size_t
|
Chris@537
|
69 FFTFileCacheWriter::getHeight() const
|
Chris@537
|
70 {
|
Chris@537
|
71 size_t mh = m_mfc->getHeight();
|
Chris@537
|
72 if (mh > m_factorSize) return (mh - m_factorSize) / 2;
|
Chris@537
|
73 else return 0;
|
Chris@537
|
74 }
|
Chris@537
|
75
|
Chris@537
|
76 void
|
Chris@537
|
77 FFTFileCacheWriter::setColumnAt(size_t x, float *mags, float *phases, float factor)
|
Chris@537
|
78 {
|
Chris@537
|
79 size_t h = getHeight();
|
Chris@537
|
80
|
Chris@537
|
81 switch (m_storageType) {
|
Chris@537
|
82
|
Chris@537
|
83 case FFTCache::Compact:
|
Chris@537
|
84 for (size_t y = 0; y < h; ++y) {
|
Chris@537
|
85 ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mags[y] / factor) * 65535.0);
|
Chris@537
|
86 ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phases[y] * 32767) / M_PI));
|
Chris@537
|
87 }
|
Chris@537
|
88 break;
|
Chris@537
|
89
|
Chris@537
|
90 case FFTCache::Rectangular:
|
Chris@537
|
91 for (size_t y = 0; y < h; ++y) {
|
Chris@537
|
92 ((float *)m_writebuf)[y * 2] = mags[y] * cosf(phases[y]);
|
Chris@537
|
93 ((float *)m_writebuf)[y * 2 + 1] = mags[y] * sinf(phases[y]);
|
Chris@537
|
94 }
|
Chris@537
|
95 break;
|
Chris@537
|
96
|
Chris@537
|
97 case FFTCache::Polar:
|
Chris@537
|
98 for (size_t y = 0; y < h; ++y) {
|
Chris@537
|
99 ((float *)m_writebuf)[y * 2] = mags[y];
|
Chris@537
|
100 ((float *)m_writebuf)[y * 2 + 1] = phases[y];
|
Chris@537
|
101 }
|
Chris@537
|
102 break;
|
Chris@537
|
103 }
|
Chris@537
|
104
|
Chris@537
|
105 static float maxFactor = 0;
|
Chris@537
|
106 if (factor > maxFactor) maxFactor = factor;
|
Chris@537
|
107 #ifdef DEBUG_FFT_FILE_CACHE_WRITER
|
Chris@537
|
108 std::cerr << "Column " << x << ": normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << std::endl;
|
Chris@537
|
109 #endif
|
Chris@537
|
110
|
Chris@537
|
111 setNormalizationFactorToWritebuf(factor);
|
Chris@537
|
112
|
Chris@537
|
113 m_mfc->setColumnAt(x, m_writebuf);
|
Chris@537
|
114 }
|
Chris@537
|
115
|
Chris@537
|
116 void
|
Chris@537
|
117 FFTFileCacheWriter::setColumnAt(size_t x, float *real, float *imag)
|
Chris@537
|
118 {
|
Chris@537
|
119 size_t h = getHeight();
|
Chris@537
|
120
|
Chris@537
|
121 float factor = 0.0f;
|
Chris@537
|
122
|
Chris@537
|
123 switch (m_storageType) {
|
Chris@537
|
124
|
Chris@537
|
125 case FFTCache::Compact:
|
Chris@537
|
126 for (size_t y = 0; y < h; ++y) {
|
Chris@537
|
127 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
|
Chris@537
|
128 if (mag > factor) factor = mag;
|
Chris@537
|
129 }
|
Chris@537
|
130 for (size_t y = 0; y < h; ++y) {
|
Chris@537
|
131 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
|
Chris@537
|
132 float phase = atan2f(imag[y], real[y]);
|
Chris@537
|
133 ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mag / factor) * 65535.0);
|
Chris@537
|
134 ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phase * 32767) / M_PI));
|
Chris@537
|
135 }
|
Chris@537
|
136 break;
|
Chris@537
|
137
|
Chris@537
|
138 case FFTCache::Rectangular:
|
Chris@537
|
139 for (size_t y = 0; y < h; ++y) {
|
Chris@537
|
140 ((float *)m_writebuf)[y * 2] = real[y];
|
Chris@537
|
141 ((float *)m_writebuf)[y * 2 + 1] = imag[y];
|
Chris@537
|
142 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
|
Chris@537
|
143 if (mag > factor) factor = mag;
|
Chris@537
|
144 }
|
Chris@537
|
145 break;
|
Chris@537
|
146
|
Chris@537
|
147 case FFTCache::Polar:
|
Chris@537
|
148 for (size_t y = 0; y < h; ++y) {
|
Chris@537
|
149 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
|
Chris@537
|
150 if (mag > factor) factor = mag;
|
Chris@537
|
151 ((float *)m_writebuf)[y * 2] = mag;
|
Chris@537
|
152 float phase = atan2f(imag[y], real[y]);
|
Chris@537
|
153 ((float *)m_writebuf)[y * 2 + 1] = phase;
|
Chris@537
|
154 }
|
Chris@537
|
155 break;
|
Chris@537
|
156 }
|
Chris@537
|
157
|
Chris@537
|
158 static float maxFactor = 0;
|
Chris@537
|
159 if (factor > maxFactor) maxFactor = factor;
|
Chris@537
|
160 #ifdef DEBUG_FFT_FILE_CACHE_WRITER
|
Chris@537
|
161 std::cerr << "[RI] Column " << x << ": normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << std::endl;
|
Chris@537
|
162 #endif
|
Chris@537
|
163
|
Chris@537
|
164 setNormalizationFactorToWritebuf(factor);
|
Chris@537
|
165
|
Chris@537
|
166 m_mfc->setColumnAt(x, m_writebuf);
|
Chris@537
|
167 }
|
Chris@537
|
168
|
Chris@537
|
169 size_t
|
Chris@537
|
170 FFTFileCacheWriter::getCacheSize(size_t width, size_t height,
|
Chris@537
|
171 FFTCache::StorageType type)
|
Chris@537
|
172 {
|
Chris@537
|
173 return (height * 2 + (type == FFTCache::Compact ? 2 : 1)) * width *
|
Chris@537
|
174 (type == FFTCache::Compact ? sizeof(uint16_t) : sizeof(float)) +
|
Chris@537
|
175 2 * sizeof(size_t); // matrix file header size
|
Chris@537
|
176 }
|
Chris@537
|
177
|
Chris@537
|
178 void
|
Chris@537
|
179 FFTFileCacheWriter::allColumnsWritten()
|
Chris@537
|
180 {
|
Chris@537
|
181 #ifdef DEBUG_FFT_FILE_CACHE_WRITER
|
Chris@537
|
182 std::cerr << "FFTFileCacheWriter::allColumnsWritten" << std::endl;
|
Chris@537
|
183 #endif
|
Chris@537
|
184 m_mfc->close();
|
Chris@537
|
185 }
|
Chris@537
|
186
|