65 lines
No EOL
2.3 KiB
C++
65 lines
No EOL
2.3 KiB
C++
|
|
|
|
#include "fl/time_alpha.h"
|
|
#include "fl/math_macros.h"
|
|
|
|
/// Tracks a smoothed peak with attack, decay, and output-inertia time-constants.
|
|
class MaxFadeTracker {
|
|
public:
|
|
/// @param attackTimeSec τ₁: how quickly to rise toward a new peak.
|
|
/// @param decayTimeSec τ₂: how quickly to decay to 1/e of value.
|
|
/// @param outputTimeSec τ₃: how quickly the returned value follows currentLevel_.
|
|
/// @param sampleRate audio sample rate (e.g. 44100 or 48000).
|
|
MaxFadeTracker(float attackTimeSec,
|
|
float decayTimeSec,
|
|
float outputTimeSec,
|
|
float sampleRate)
|
|
: attackRate_(1.0f / attackTimeSec)
|
|
, decayRate_(1.0f / decayTimeSec)
|
|
, outputRate_(1.0f / outputTimeSec)
|
|
, sampleRate_(sampleRate)
|
|
, currentLevel_(0.0f)
|
|
, smoothedOutput_(0.0f)
|
|
{}
|
|
|
|
void setAttackTime(float t){ attackRate_ = 1.0f/t; }
|
|
void setDecayTime (float t){ decayRate_ = 1.0f/t; }
|
|
void setOutputTime(float t){ outputRate_ = 1.0f/t; }
|
|
|
|
/// Process one 512-sample block; returns [0…1] with inertia.
|
|
float operator()(const int16_t* samples, size_t length) {
|
|
assert(length == 512);
|
|
// 1) block peak
|
|
float peak = 0.0f;
|
|
for (size_t i = 0; i < length; ++i) {
|
|
float v = ABS(samples[i]) * (1.0f/32768.0f);
|
|
peak = MAX(peak, v);
|
|
}
|
|
|
|
// 2) time delta
|
|
float dt = static_cast<float>(length) / sampleRate_;
|
|
|
|
// 3) update currentLevel_ with attack/decay
|
|
if (peak > currentLevel_) {
|
|
float riseFactor = 1.0f - exp(-attackRate_ * dt);
|
|
currentLevel_ += (peak - currentLevel_) * riseFactor;
|
|
} else {
|
|
float decayFactor = exp(-decayRate_ * dt);
|
|
currentLevel_ *= decayFactor;
|
|
}
|
|
|
|
// 4) output inertia: smooth smoothedOutput_ → currentLevel_
|
|
float outFactor = 1.0f - exp(-outputRate_ * dt);
|
|
smoothedOutput_ += (currentLevel_ - smoothedOutput_) * outFactor;
|
|
|
|
return smoothedOutput_;
|
|
}
|
|
|
|
private:
|
|
float attackRate_; // = 1/τ₁
|
|
float decayRate_; // = 1/τ₂
|
|
float outputRate_; // = 1/τ₃
|
|
float sampleRate_;
|
|
float currentLevel_; // instantaneous peak with attack/decay
|
|
float smoothedOutput_; // returned value with inertia
|
|
}; |