-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
LevelsProcessor.h
121 lines (101 loc) · 4.03 KB
/
LevelsProcessor.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/** The list of possible modes for audio level analysis.
@see LevelsProcessor, Meter
*/
enum class MeteringMode
{
peak = 0,
rms,
midSide
};
/** Use an instance of this within an audio callback of some kind,
and call getChannelLevels (on the main thread) to get the
last known audio levels.
@see MeteringMode, Meter
*/
class LevelsProcessor final : public InternalProcessor
{
public:
/** Constructor. */
LevelsProcessor();
//==============================================================================
/** */
void getChannelLevels (Array<float>& destData);
/** */
void getChannelLevels (Array<double>& destData);
//==============================================================================
/** Changes the mode of analysis for the audio levels. */
void setMeteringMode (MeteringMode);
/** @returns the current mode for audio levels analysis. */
[[nodiscard]] MeteringMode getMeteringMode() const;
//==============================================================================
/** @internal */
const String getName() const override { return NEEDS_TRANS ("Levels Meter"); }
/** @internal */
Identifier getIdentifier() const override { return "levelsMeter"; }
/** @internal */
bool supportsDoublePrecisionProcessing() const override { return true; }
/** @internal */
void prepareToPlay (double, int) override;
/** @internal */
void processBlock (juce::AudioBuffer<float>&, MidiBuffer&) override;
/** @internal */
void processBlock (juce::AudioBuffer<double>&, MidiBuffer&) override;
private:
//==============================================================================
/** Stores the resulting measured levels depending on the MeteringMode. */
template<typename FloatType>
struct ChannelDetails final
{
void prepare (int numChannels)
{
for (auto& a : { &channels, &tempBuffer })
{
a->resize (numChannels);
a->clearQuick();
}
}
template<typename OtherFloatType>
void process (juce::AudioBuffer<OtherFloatType>& buffer,
MeteringMode meteringMode,
bool possiblyBypassed)
{
tempBuffer.clearQuick();
if (! possiblyBypassed)
{
const auto numChannels = std::min (buffer.getNumChannels(), tempBuffer.size());
switch (meteringMode)
{
case MeteringMode::peak:
for (int i = 0; i < numChannels; ++i)
tempBuffer.add ((FloatType) buffer.getMagnitude (i, 0, buffer.getNumSamples()));
break;
case MeteringMode::rms:
for (int i = 0; i < numChannels; ++i)
tempBuffer.add ((FloatType) buffer.getRMSLevel (i, 0, buffer.getNumSamples()));
break;
case MeteringMode::midSide:
for (int i = 0; i < numChannels; ++i)
{
const auto v = buffer.getMagnitude (i, 0, buffer.getNumSamples());
tempBuffer.add ((FloatType) square (v));
}
break;
default:
jassertfalse;
break;
};
}
channels.swapWith (tempBuffer);
}
Array<FloatType> channels, tempBuffer;
};
class MeteringModeParameter;
MeteringModeParameter* meteringModeParam = nullptr;
ChannelDetails<float> floatChannelDetails;
ChannelDetails<double> doubleChannelDetails;
//==============================================================================
template<typename FloatType>
void process (juce::AudioBuffer<FloatType>&);
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LevelsProcessor)
};