tracktion-engine 3.0-10-g034fdde4aa5
Tracktion Engine — High level data model for audio applications

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_BeatDetect.h
Go to the documentation of this file.
1 /*
2 ,--. ,--. ,--. ,--.
3 ,-' '-.,--.--.,--,--.,---.| |,-.,-' '-.`--' ,---. ,--,--, Copyright 2024
4 '-. .-'| .--' ,-. | .--'| /'-. .-',--.| .-. || \ Tracktion Software
5 | | | | \ '-' \ `--.| \ \ | | | |' '-' '| || | Corporation
6 `---' `--' `--`--'`---'`--'`--' `---' `--' `---' `--''--' www.tracktion.com
7
8 Tracktion Engine uses a GPL/commercial licence - see LICENCE.md for details.
9*/
10
11namespace tracktion { inline namespace engine
12{
13
15{
16 BeatDetect() = default;
17
18 void setSampleRate (double sampleRate)
19 {
20 blockSize = juce::roundToInt (sampleRate / 43.06640625);
21 }
22
23 void setSensitivity (double newSensitivity)
24 {
25 const double C_MIN = 0.8f;
26 const double C_MAX = 4.0f;
27
28 sensitivity = C_MIN + newSensitivity * (C_MAX - C_MIN);
29 }
30
31 template <typename Buffer>
32 void audioProcess (const Buffer& buffer)
33 {
34 double blockEnergy = 0;
35 auto size = buffer.getSize();
36
37 for (decltype (size.numChannels) chan = 0; chan < size.numChannels; ++chan)
38 {
39 auto d = buffer.getIterator (chan);
40
41 for (decltype (size.numFrames) i = 0; i < size.numFrames; ++i)
42 {
43 auto sample = static_cast<double> (*d);
44 blockEnergy += sample * sample;
45 ++d;
46 }
47 }
48
49 pushEnergy (blockEnergy);
50 }
51
52 SampleCount getBlockSize() const { return blockSize; }
53 const juce::Array<SampleCount>& getBeats() const { return beatSamples; }
54
55private:
56 static constexpr int historyLength = 43;
57 double energy[historyLength] = {};
58 int curBlock = 0, lastBlock = -2;
59 SampleCount blockSize = 0;
60 juce::Array<SampleCount> beatSamples;
61 double sensitivity = 0;
62
63 void pushEnergy (double e)
64 {
65 if (curBlock < historyLength)
66 {
67 energy[curBlock++] = e;
68
69 if (curBlock == historyLength)
70 {
71 auto ave = getAverageEnergy();
72
73 for (int i = 0; i < historyLength; ++i)
74 if (energy[i] > sensitivity * ave)
75 addBlock(i);
76 }
77 }
78 else
79 {
80 energy[curBlock % historyLength] = e;
81
82 if (e > sensitivity * getAverageEnergy())
83 addBlock(curBlock);
84
85 curBlock++;
86 }
87 }
88
89 void addBlock (int i)
90 {
91 if (i - 1 != lastBlock)
92 beatSamples.add (i * blockSize);
93
94 lastBlock = i;
95 }
96
97 double getAverageEnergy() const noexcept
98 {
99 double total = 0;
100
101 for (auto e : energy)
102 total += e;
103
104 return total / historyLength;
105 }
106
108};
109
110}} // namespace tracktion { inline namespace engine
void add(const ElementType &newElement)
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
int roundToInt(const FloatType value) noexcept