1 #include "SpectralAnalyzer.h"
2 #include <algorithm>
3 #include <cmath>
4
configureBasic(uint32_t numBins)5 void BasicAnalyzer::configureBasic(uint32_t numBins)
6 {
7 _numBins = numBins;
8 _freqs.resize(numBins);
9 _mags.resize(numBins);
10 }
11
clear()12 void BasicAnalyzer::clear()
13 {
14 std::fill_n(_mags.begin(), _numBins, 20.0 * std::log10(kStftFloorMagnitude));
15 }
16
17 ///
SteppingAnalyzer()18 SteppingAnalyzer::SteppingAnalyzer()
19 {
20 }
21
configureStepping(uint32_t numBins,const Configuration & config)22 void SteppingAnalyzer::configureStepping(uint32_t numBins, const Configuration &config)
23 {
24 configureBasic(numBins);
25
26 const uint32_t windowSize = _windowSize = config.windowSize;
27 _stepSize = config.stepSize;
28 _ring.resize(2 * windowSize);
29 _window.resize(windowSize);
30 _input.resize(windowSize);
31
32 float *window = _window.data();
33 for (uint32_t i = 0; i < windowSize; ++i)
34 window[i] = 0.5 * (1.0 - std::cos(2.0 * M_PI * i / (windowSize - 1)));
35
36 _smoother.configure(numBins, config.stepSize, config.attackTime, config.releaseTime, config.sampleRate);
37 }
38
configureBinRange(uint32_t start,uint32_t end)39 void SteppingAnalyzer::configureBinRange(uint32_t start, uint32_t end)
40 {
41 _binRange[0] = start;
42 _binRange[1] = end;
43 _smoother.configureBinRange(start, end);
44 }
45
setAttackAndRelease(float attack,float release)46 void SteppingAnalyzer::setAttackAndRelease(float attack, float release)
47 {
48 _smoother.setAttackAndRelease(attack, release);
49 }
50
clear()51 void SteppingAnalyzer::clear()
52 {
53 BasicAnalyzer::clear();
54
55 _stepCounter = 0;
56 _ringIndex = 0;
57 std::fill(_ring.begin(), _ring.end(), 0.0f);
58
59 _smoother.clear();
60 }
61
process(const float * input,uint32_t numFrames)62 void SteppingAnalyzer::process(const float *input, uint32_t numFrames)
63 {
64 const float* window = _window.data();
65 const uint32_t windowSize = _windowSize;
66
67 uint32_t stepCounter = _stepCounter;
68 const uint32_t stepSize = _stepSize;
69
70 float *ring = _ring.data();
71 uint32_t ringIndex = _ringIndex;
72
73 for (uint32_t i = 0; i < numFrames; ++i) {
74 ring[ringIndex] = ring[ringIndex + windowSize] = input[i];
75 ringIndex = (ringIndex + 1 != windowSize) ? (ringIndex + 1) : 0;
76 if (++stepCounter == stepSize) {
77 stepCounter = 0;
78
79 float* windowedBlock = _input.data();
80 for (uint32_t i = 0; i < windowSize; ++i)
81 windowedBlock[i] = ring[ringIndex + i] * window[i];
82
83 processNewBlock(windowedBlock);
84
85 _smoother.process(getMagnitudes());
86 }
87 }
88
89 _stepCounter = stepCounter;
90 _ringIndex = ringIndex;
91 }
92
configure(uint32_t numBins,uint32_t stepSize,double attackTime,double releaseTime,double sampleRate)93 void SteppingAnalyzer::Smoother::configure(uint32_t numBins, uint32_t stepSize, double attackTime, double releaseTime, double sampleRate)
94 {
95 _ar.resize(numBins);
96 _stepSize = stepSize;
97 ARFollower *ar = _ar.data();
98 ar[0].init(sampleRate);
99 setAttackAndRelease(attackTime, releaseTime);
100 }
101
configureBinRange(uint32_t start,uint32_t end)102 void SteppingAnalyzer::Smoother::configureBinRange(uint32_t start, uint32_t end)
103 {
104 _binRange[0] = start;
105 _binRange[1] = end;
106 }
107
setAttackAndRelease(float attack,float release)108 void SteppingAnalyzer::Smoother::setAttackAndRelease(float attack, float release)
109 {
110 ARFollower *ar = _ar.data();
111 uint32_t numBins = (uint32_t)_ar.size();
112 uint32_t stepSize = (uint32_t)_stepSize;
113 ar[0].setAttackTime(attack / stepSize);
114 ar[0].setReleaseTime(release / stepSize);
115 for (uint32_t i = 1; i < numBins; ++i)
116 ar[i].configureLike(ar[0]);
117 }
118
clear()119 void SteppingAnalyzer::Smoother::clear()
120 {
121 ARFollower *ar = _ar.data();
122 uint32_t numBins = (uint32_t)_ar.size();
123 for (uint32_t i = 0; i < numBins; ++i)
124 ar[i].clear();
125 }
126
process(float * stepData)127 void SteppingAnalyzer::Smoother::process(float *stepData)
128 {
129 ARFollower *ar = _ar.data();
130 uint32_t numBins = (uint32_t)_ar.size();
131
132 uint32_t start = _binRange[0];
133 uint32_t end = std::min(_binRange[1], numBins);
134
135 for (uint32_t i = start; i < end; ++i)
136 stepData[i] = ar[i].compute(stepData[i]);
137 }
138