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