11namespace tracktion {
inline namespace engine
15template <
typename FloatType>
17 FloatType& sum, FloatType& diff,
18 int startIndex,
int numSamples)
28 FloatType lo = (FloatType) 1;
33 auto mag = buffer.
getMagnitude (i, startIndex, numSamples);
45LevelMeasurer::LevelMeasurer()
50LevelMeasurer::~LevelMeasurer()
52 TRACKTION_ASSERT_MESSAGE_THREAD
56int LevelMeasurer::Client::getNumChannelsUsed() const noexcept
58 return numChannelsUsed;
61void LevelMeasurer::Client::reset() noexcept
64 for (
auto& l : audioLevels)
67 for (
auto& o : overload)
74bool LevelMeasurer::Client::getAndClearOverload() noexcept
77 auto result = clearOverload;
78 clearOverload =
false;
82bool LevelMeasurer::Client::getAndClearPeak() noexcept
85 auto result = clearPeak;
90DbTimePair LevelMeasurer::Client::getAndClearMidiLevel() noexcept
93 auto result = midiLevels;
94 midiLevels.dB = -100.0f;
98DbTimePair LevelMeasurer::Client::getAndClearAudioLevel (
int chan)
noexcept
101 jassert (chan >= 0 && chan < maxNumChannels);
102 auto result = audioLevels[chan];
103 audioLevels[chan].dB = -100.0f;
107void LevelMeasurer::Client::setNumChannelsUsed (
int numChannels)
noexcept
110 numChannelsUsed = numChannels;
113void LevelMeasurer::Client::setOverload (
int channel,
bool hasOverloaded)
noexcept
116 overload[channel] = hasOverloaded;
119void LevelMeasurer::Client::setClearOverload (
bool clear)
noexcept
122 clearOverload = clear;
125void LevelMeasurer::Client::setClearPeak (
bool clear)
noexcept
131void LevelMeasurer::Client::updateAudioLevel (
int channel, DbTimePair newAudioLevel)
noexcept
135 if (newAudioLevel.dB >= audioLevels[channel].dB)
136 audioLevels[channel] = newAudioLevel;
139void LevelMeasurer::Client::updateMidiLevel (DbTimePair newMidiLevel)
noexcept
143 if (newMidiLevel.dB >= midiLevels.dB)
144 midiLevels = newMidiLevel;
153 if (clients.isEmpty())
157 numActiveChannels = numChans;
160 if (mode == LevelMeasurer::peakMode)
163 for (
int i = numChans; --i >= 0;)
166 bool overloaded = gain > 0.999f;
167 auto newDB = gainToDb (gain);
169 for (
auto c : clients)
171 c->updateAudioLevel (i, { now, newDB });
174 c->setOverload (i,
true);
176 c->setNumChannelsUsed (numChans);
180 else if (mode == LevelMeasurer::RMSMode)
183 for (
int i = numChans; --i >= 0;)
185 auto gain = buffer.
getRMSLevel (i, start, numSamples);
186 bool overloaded = gain > 0.999f;
187 auto newDB = gainToDb (gain);
189 for (
auto c : clients)
191 c->updateAudioLevel (i, { now, newDB });
194 c->setOverload (i,
true);
196 c->setNumChannelsUsed (numChans);
204 getSumAndDiff (buffer, sum, diff, start, numSamples);
206 auto sumDB = gainToDb (sum);
207 auto diffDB = gainToDb (diff);
209 for (
auto c : clients)
211 c->updateAudioLevel (0, { now, sumDB });
212 c->updateAudioLevel (1, { now, diffDB });
214 if (sum > 0.999f) c->setOverload (0,
true);
215 if (diff > 0.999f) c->setOverload (1,
true);
217 c->setNumChannelsUsed (2);
220 numActiveChannels = 2;
224void LevelMeasurer::processMidi (MidiMessageArray& midiBuffer,
const float*)
228 if (clients.isEmpty() || ! showMidi)
233 for (
auto& m : midiBuffer)
239 for (
auto c : clients)
240 c->updateMidiLevel ({ now, gainToDb (max) });
243void LevelMeasurer::processMidiLevel (
float level)
247 if (clients.isEmpty() || ! showMidi)
252 for (
auto c : clients)
253 c->updateMidiLevel ({ now, gainToDb (level) });
256void LevelMeasurer::clearOverload()
260 for (
auto c : clients)
261 c->setClearOverload (true);
264void LevelMeasurer::clearPeak()
268 for (
auto c : clients)
269 c->setClearPeak (true);
272void LevelMeasurer::clear()
276 for (
auto c : clients)
279 levelCacheL = -100.0f;
280 levelCacheR = -100.0f;
281 numActiveChannels = 1;
284void LevelMeasurer::setMode (LevelMeasurer::Mode m)
290void LevelMeasurer::addClient (Client& c)
293 jassert (! clients.contains (&c));
297void LevelMeasurer::removeClient (Client& c)
300 clients.removeFirstMatchingValue (&c);
303void LevelMeasurer::setShowMidi (
bool show)
309void SharedLevelMeasurer::startNextBlock (
double streamTime)
313 if (streamTime != lastStreamTime)
315 lastStreamTime = streamTime;
317 processBuffer (sumBuffer, 0, sumBuffer.getNumSamples());
322void SharedLevelMeasurer::setSize (
int channels,
int numSamples)
326 if (channels > sumBuffer.getNumChannels() || numSamples > sumBuffer.getNumSamples())
327 sumBuffer.setSize (channels, numSamples);
332 setSize (2, numSamples);
337 sumBuffer.addFrom (i, 0, inBuffer, i, startSample, numSamples);
Type getMagnitude(int channel, int startSample, int numSamples) const noexcept
Type getRMSLevel(int channel, int startSample, int numSamples) const noexcept
int getNumChannels() const noexcept
static uint32 getApproximateMillisecondCounter() noexcept
constexpr Type jmin(Type a, Type b)
constexpr Type jmax(Type a, Type b)