Krotos Modules 3
Loading...
Searching...
No Matches
MusicScaleFilterBank.cpp
Go to the documentation of this file.
1//=====================================================================================
7//=====================================================================================
9
10//=====================================================================================
12{
13 setSamplingRate(sampleRate);
14 setParameters(30.0f, 17000.0f, 24, 1025);
15}
16
17//=====================================================================================
18void krotos::MusicScaleFilterBank::setSamplingRate(float fs) { m_samplingRate = fs; }
19
20//=====================================================================================
21void krotos::MusicScaleFilterBank::setParameters(float fMin, float fMax, int numBandsPerOctave, int numFFTBins)
22{
23 m_minFreq = fMin;
24 m_maxFreq = fMax;
25 m_bandsPerOct = numBandsPerOctave;
26 m_numFFTBins = numFFTBins;
27
28 jassert(m_numFFTBins >= 128);
29 jassert(m_bandsPerOct >= 2);
30 jassert(m_minFreq >= 0 && m_minFreq < m_maxFreq);
31
32 // Reduce fmax if necessary
33 if (m_maxFreq > m_samplingRate / 2.0f)
34 m_maxFreq = m_samplingRate / 2.0f;
35
36 buildLogFreqAxis();
37 mapNotesToFFTBins();
38 buildFilterBank();
39}
40
41//=====================================================================================
43{
44 // Calculate distance in Hz between frequencies
45 float factor = std::pow(2.0f, 1.0f / m_bandsPerOct);
46
47 float newFreq = m_A4;
48 // initialise vector with A4
49 m_freqLogAxis.push_back(m_A4);
50
51 // increase frequencies until fMax
52 while (newFreq <= m_maxFreq)
53 {
54 newFreq *= factor;
55 m_freqLogAxis.push_back(newFreq);
56 }
57
58 // restart with A4 and decrease to fMin
59 newFreq = m_A4;
60 while (newFreq >= m_minFreq)
61 {
62 newFreq /= factor;
63 m_freqLogAxis.insert(std::begin(m_freqLogAxis), newFreq);
64 }
65}
66
67//=====================================================================================
69{
70 jassert(m_samplingRate != 1.0f && m_numFFTBins != -1);
71
72 // Factor for mapping log frequencies to DFT bins
73 float mapFactor = (m_samplingRate / 2.0f) / m_numFFTBins;
74 // Map musical notes to DFT bins
75 std::transform(std::begin(m_freqLogAxis), std::end(m_freqLogAxis), std::begin(m_freqLogAxis),
76 [mapFactor](float& c) { return std::round(c / mapFactor); });
77
78 // Keep only unique bins
79 std::vector<float>::iterator it = std::unique(std::begin(m_freqLogAxis), std::end(m_freqLogAxis));
80 m_freqLogAxis.resize(std::distance(std::begin(m_freqLogAxis), it));
81 // Filter out bins above the range
82 m_freqLogAxis.erase(std::remove_if(std::begin(m_freqLogAxis), std::end(m_freqLogAxis),
83 [=](float bin) { return bin >= m_numFFTBins; }),
84 std::end(m_freqLogAxis));
85 // Remove zeros
86 m_freqLogAxis.erase(std::remove(std::begin(m_freqLogAxis), std::end(m_freqLogAxis), 0.0f), std::end(m_freqLogAxis));
87
88 return m_freqLogAxis;
89}
90
91//=====================================================================================
92std::vector<std::vector<float>> krotos::MusicScaleFilterBank::buildFilterBank()
93{
94 // Number of Bands
95 auto numBands = m_freqLogAxis.size() - 2;
96 jassert(numBands >= 3); // Cannot create filterbank with less than 3 frequencies
97
98 // Create Filterbank matrix band by band
99 for (int i = 0; i < numBands; i++)
100 {
101 // Edge and center frequencies
102 float start = m_freqLogAxis.at(i);
103 float mid = m_freqLogAxis.at(i + 1);
104 float stop = m_freqLogAxis.at(i + 2);
105
106 // Create triangular Filter
107 std::vector<float> triangFilter = triangularFilterCoeff(start, mid, stop);
108 m_filterBank.push_back(triangFilter);
109 }
110
111 return m_filterBank;
112}
113
114//=====================================================================================
115std::vector<float> krotos::MusicScaleFilterBank::triangularFilterCoeff(float start, float mid, float stop)
116{
117 // Height of the filter
118 int height = 1;
119
120 // Rising edge
121 std::vector<float> rising;
122 float incr = 1.0f / (mid - start);
123 float riseVal{0.0f};
124
125 while (riseVal <= height)
126 {
127 rising.push_back(riseVal);
128 riseVal += incr;
129 }
130
131 // Falling edge
132 std::vector<float> falling;
133 float decr = -1.0f / (stop - mid);
134 float dropVal = height + decr;
135
136 while (dropVal >= 0.0f)
137 {
138 falling.push_back(dropVal);
139 dropVal += decr;
140 }
141 // Concatenate
142 std::vector<float> filterCoef(rising);
143 filterCoef.insert(std::end(filterCoef), std::begin(falling), std::end(falling));
144
145 std::vector<float> triangFilter(m_numFFTBins, 0.0f);
146 copy(std::cbegin(filterCoef), std::cend(filterCoef), std::begin(triangFilter) + static_cast<int>(start) - 1);
147
148 return triangFilter;
149}
150
151//=====================================================================================
152std::vector<std::vector<float>> krotos::MusicScaleFilterBank::filterSpectrum(
153 const std::vector<std::vector<float>>& spectrum)
154{
155 // Quick test to make sure we are multiplying spectrums with same number of
156 // FFT bins
157 jassert(m_filterBank[0].size() == spectrum[0].size() && spectrum[0].size() == m_numFFTBins);
158
159 // rows
160 auto numBands = m_filterBank.size();
161 // columns
162 auto numFrames = spectrum.size();
163 std::vector<std::vector<float>> filteredLogSpec(numBands, std::vector<float>(numFrames));
164
165 if (m_samplingRate == sr_96k)
166 {
167 for (int frame = 0; frame < numFrames; frame++)
168 {
169 musicScaleFilterUnrolled96000(filteredLogSpec, spectrum, frame);
170 }
171 }
172 else if (m_samplingRate == sr_48k)
173 {
174 for (int frame = 0; frame < numFrames; frame++)
175 {
176 musicScaleFilterUnrolled48000(filteredLogSpec, spectrum, frame);
177 }
178 }
179 else if (m_samplingRate == sr_441k)
180 {
181 for (int frame = 0; frame < numFrames; frame++)
182 {
183 musicScaleFilterUnrolled44100(filteredLogSpec, spectrum, frame);
184 }
185 }
186 else if (m_samplingRate == sr_225k)
187 {
188 for (int frame = 0; frame < numFrames; frame++)
189 {
190 musicScaleFilterUnrolled22050(filteredLogSpec, spectrum, frame);
191 }
192 }
193 else // Normal 3ple for loop, non major SR
194 {
195 for (int frame = 0; frame < numFrames; frame++)
196 {
197 auto spectralFrame = spectrum[frame];
198
199 for (int band = 0; band < numBands; band++)
200 {
201 float total = 0.f;
202
203 for (int bin = 0; bin < m_numFFTBins; bin++)
204 {
205 float filter = m_filterBank[band][bin];
206 if (filter != 0.f)
207 {
208 if (filter == 1.f)
209 {
210 total += std::log10f(spectralFrame[bin] + 1.0f);
211 }
212 else
213 {
214 total += std::log10f(filter * spectralFrame[bin] + 1.0f);
215 }
216 }
217 }
218 filteredLogSpec[band][frame] = total;
219 }
220 }
221 }
222
223 return filteredLogSpec;
224}
std::vector< std::vector< float > > filterSpectrum(const std::vector< std::vector< float > > &spectrum)
Definition MusicScaleFilterBank.cpp:152
void setParameters(float fMin, float fMax, int numBandsPerOctave, int numFFTBins)
Definition MusicScaleFilterBank.cpp:21
std::vector< float > mapNotesToFFTBins()
Definition MusicScaleFilterBank.cpp:68
std::vector< std::vector< float > > buildFilterBank()
Definition MusicScaleFilterBank.cpp:92
MusicScaleFilterBank(float sampleRate)
Definition MusicScaleFilterBank.cpp:11
void buildLogFreqAxis()
Definition MusicScaleFilterBank.cpp:42
std::vector< float > triangularFilterCoeff(float start, float mid, float stop)
Definition MusicScaleFilterBank.cpp:115
void setSamplingRate(float fs)
Definition MusicScaleFilterBank.cpp:18