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

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_TempoDetect.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
14#ifdef __clang__
15 #pragma clang diagnostic push
16 #pragma clang diagnostic ignored "-Wsign-conversion"
17 #pragma clang diagnostic ignored "-Wunused-parameter"
18 #pragma clang diagnostic ignored "-Wshadow"
19 #pragma clang diagnostic ignored "-Wmacro-redefined"
20 #pragma clang diagnostic ignored "-Wconversion"
21 #pragma clang diagnostic ignored "-Wunused"
22 #if __has_warning("-Wzero-as-null-pointer-constant")
23 #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
24 #endif
25 #pragma clang diagnostic ignored "-Wextra-semi"
26#endif
27
28#ifdef __GNUC__
29 #pragma GCC diagnostic push
30 #pragma GCC diagnostic ignored "-Wsign-conversion"
31 #pragma GCC diagnostic ignored "-Wshadow"
32 #if ! __clang__
33 #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
34 #endif
35 #pragma GCC diagnostic ignored "-Wunused-variable"
36 #pragma GCC diagnostic ignored "-Wpedantic"
37 #pragma GCC diagnostic ignored "-Wunknown-pragmas"
38#endif
39
40#include "soundtouch/include/BPMDetect.h"
41
42#ifdef __clang__
43 #pragma clang diagnostic pop
44#endif
45
46#ifdef __GNUC__
47 #pragma GCC diagnostic pop
48#endif
49
54{
55public:
56 TempoDetect (int numChannels_, double sampleRate)
57 : numChannels (numChannels_),
58 bpmDetect (numChannels, (int) sampleRate)
59 {
60 }
61
66 {
67 jassert ((int) reader.numChannels == numChannels);
68
69 const SampleCount blockSize = 65536;
70 const bool useRightChan = numChannels > 1;
71
72 // can't use an AudioScratchBuffer yet
73 juce::AudioBuffer<float> buffer (numChannels, blockSize);
74
75 SampleCount numLeft = reader.lengthInSamples;
76 int startSample = 0;
77
78 while (numLeft > 0)
79 {
80 auto numThisTime = (int) std::min (numLeft, blockSize);
81 reader.read (&buffer, 0, numThisTime, startSample, true, useRightChan);
82 processSection (buffer, numThisTime);
83
84 startSample += numThisTime;
85 numLeft -= numThisTime;
86 }
87
88 return finishAndDetect();
89 }
90
94 float processAndDetect (const float** const inputSamples, int numSamples)
95 {
96 processSection (inputSamples, numSamples);
97
98 return bpm = bpmDetect.getBpm();
99 }
100
102 float getBpm() const { return bpm; }
103
104 bool isBpmSensible() const { return getSensibleRange().contains (bpm); }
105 static juce::Range<float> getSensibleRange() { return { 29, 200 }; }
106
107 //==============================================================================
109 void processSection (juce::AudioBuffer<float>& buffer, int numSamplesToProcess)
110 {
111 processSection (buffer.getArrayOfReadPointers(), numSamplesToProcess);
112 }
113
116 {
117 return bpm = bpmDetect.getBpm();
118 }
119
120 void processSection (const float* const* inputSamples, int numSamples)
121 {
122 AudioScratchBuffer scratch (1, numChannels * numSamples);
123 float* interleaved = scratch.buffer.getWritePointer (0);
124
127 juce::AudioData::InterleavedDest<Format> { interleaved, numChannels },
128 numSamples);
129
130 bpmDetect.inputSamples (interleaved, numSamples);
131 }
132
133private:
134 //==============================================================================
135 int numChannels;
136 soundtouch::BPMDetect bpmDetect;
137 float bpm = -1.0f;
138
140};
141
142}} // namespace tracktion { inline namespace engine
const Type *const * getArrayOfReadPointers() const noexcept
static void interleaveSamples(NonInterleavedSource< SourceFormat... > source, InterleavedDest< DestFormat... > dest, int numSamples)
ChannelData< true, false, Format... > InterleavedDest
ChannelData< false, true, Format... > NonInterleavedSource
bool read(float *const *destChannels, int numDestChannels, int64 startSampleInSource, int numSamplesToRead)
unsigned int numChannels
constexpr bool contains(const ValueType position) const noexcept
An audio scratch buffer that has pooled storage.
Uses the SoundTouch BPMDetect class to guess the tempo of some audio.
float processReader(juce::AudioFormatReader &reader)
Processes an entire AudioFormatReader returning the tempo for it.
float getBpm() const
Returns the last BPM detected.
float finishAndDetect()
Completes the detection process and returns the BPM.
float processAndDetect(const float **const inputSamples, int numSamples)
Processes a block of audio returning the tempo for it.
void processSection(juce::AudioBuffer< float > &buffer, int numSamplesToProcess)
Processes a non-interleaved buffer section.
#define jassert(expression)
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
typedef int
T min(T... args)