diff options
-rw-r--r-- | Alc/alc.cpp | 11 | ||||
-rw-r--r-- | Alc/alu.cpp | 4 | ||||
-rw-r--r-- | Alc/mastering.cpp | 238 | ||||
-rw-r--r-- | Alc/mastering.h | 62 |
4 files changed, 162 insertions, 153 deletions
diff --git a/Alc/alc.cpp b/Alc/alc.cpp index ad47e43c..c225eaf2 100644 --- a/Alc/alc.cpp +++ b/Alc/alc.cpp @@ -1550,7 +1550,7 @@ static void alcSetError(ALCdevice *device, ALCenum errorCode) } -static Compressor *CreateDeviceLimiter(const ALCdevice *device, const ALfloat threshold) +static std::unique_ptr<Compressor> CreateDeviceLimiter(const ALCdevice *device, const ALfloat threshold) { return CompressorInit(device->RealOut.NumChannels, device->Frequency, AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, 0.001f, 0.002f, @@ -1816,6 +1816,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) device->Uhj_Encoder = nullptr; device->Bs2b = nullptr; + device->Limiter = nullptr; device->ChannelDelay.clear(); device->ChannelDelay.shrink_to_fit(); @@ -2044,14 +2045,12 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) if(device->DitherDepth > 0.0f) thrshld -= 1.0f / device->DitherDepth; - device->Limiter.reset(CreateDeviceLimiter(device, std::log10(thrshld) * 20.0f)); + auto limiter = CreateDeviceLimiter(device, std::log10(thrshld) * 20.0f); /* Convert the lookahead from samples to nanosamples to nanoseconds. */ device->FixedLatency += std::chrono::duration_cast<std::chrono::nanoseconds>( - std::chrono::seconds(GetCompressorLookAhead(device->Limiter.get())) - ) / device->Frequency; + std::chrono::seconds(limiter->getLookAhead())) / device->Frequency; + device->Limiter = std::move(limiter); } - else - device->Limiter = nullptr; TRACE("Output limiter %s\n", device->Limiter ? "enabled" : "disabled"); aluSelectPostProcess(device); diff --git a/Alc/alu.cpp b/Alc/alu.cpp index fbdbc4b2..1917dd9d 100644 --- a/Alc/alu.cpp +++ b/Alc/alu.cpp @@ -1745,8 +1745,8 @@ void aluMixData(ALCdevice *device, ALvoid *OutBuffer, ALsizei NumSamples) } /* Apply compression, limiting sample amplitude if needed or desired. */ - if(device->Limiter) - ApplyCompression(device->Limiter.get(), SamplesToDo, device->RealOut.Buffer); + if(Compressor *comp{device->Limiter.get()}) + comp->process(SamplesToDo, device->RealOut.Buffer); /* Apply delays and attenuation for mismatched speaker distances. */ ApplyDistanceComp(device->RealOut.Buffer, device->ChannelDelay, device->TempBuffer[0], diff --git a/Alc/mastering.cpp b/Alc/mastering.cpp index bdd67aa4..e886b127 100644 --- a/Alc/mastering.cpp +++ b/Alc/mastering.cpp @@ -15,11 +15,11 @@ static_assert((BUFFERSIZE & (BUFFERSIZE-1)) == 0, "BUFFERSIZE is not a power of 2"); struct SlidingHold { - ALfloat Values[BUFFERSIZE]; - ALsizei Expiries[BUFFERSIZE]; - ALsizei LowerIndex; - ALsizei UpperIndex; - ALsizei Length; + ALfloat mValues[BUFFERSIZE]; + ALsizei mExpiries[BUFFERSIZE]; + ALsizei mLowerIndex; + ALsizei mUpperIndex; + ALsizei mLength; }; @@ -34,14 +34,17 @@ using namespace std::placeholders; * * http://www.richardhartersworld.com/cri/2001/slidingmin.html */ -static ALfloat UpdateSlidingHold(SlidingHold *Hold, const ALsizei i, const ALfloat in) +ALfloat UpdateSlidingHold(SlidingHold *Hold, const ALsizei i, const ALfloat in) { static constexpr ALsizei mask{BUFFERSIZE - 1}; - const ALsizei length{Hold->Length}; - ALfloat (&values)[BUFFERSIZE] = Hold->Values; - ALsizei (&expiries)[BUFFERSIZE] = Hold->Expiries; - ALsizei lowerIndex{Hold->LowerIndex}; - ALsizei upperIndex{Hold->UpperIndex}; + const ALsizei length{Hold->mLength}; + ALfloat (&values)[BUFFERSIZE] = Hold->mValues; + ALsizei (&expiries)[BUFFERSIZE] = Hold->mExpiries; + ALsizei lowerIndex{Hold->mLowerIndex}; + ALsizei upperIndex{Hold->mUpperIndex}; + + ASSUME(upperIndex >= 0); + ASSUME(lowerIndex >= 0); if(i >= expiries[upperIndex]) upperIndex = (upperIndex + 1) & mask; @@ -68,41 +71,42 @@ static ALfloat UpdateSlidingHold(SlidingHold *Hold, const ALsizei i, const ALflo expiries[lowerIndex] = i + length; } - Hold->LowerIndex = lowerIndex; - Hold->UpperIndex = upperIndex; + Hold->mLowerIndex = lowerIndex; + Hold->mUpperIndex = upperIndex; return values[upperIndex]; } -static void ShiftSlidingHold(SlidingHold *Hold, const ALsizei n) +void ShiftSlidingHold(SlidingHold *Hold, const ALsizei n) { - ASSUME(Hold->UpperIndex >= 0); - ASSUME(Hold->LowerIndex >= 0); + ASSUME(Hold->mUpperIndex >= 0); + ASSUME(Hold->mLowerIndex >= 0); - auto exp_begin = std::begin(Hold->Expiries) + Hold->UpperIndex; - auto exp_last = std::begin(Hold->Expiries) + Hold->LowerIndex; + auto exp_begin = std::begin(Hold->mExpiries) + Hold->mUpperIndex; + auto exp_last = std::begin(Hold->mExpiries) + Hold->mLowerIndex; if(exp_last < exp_begin) { - std::transform(exp_begin, std::end(Hold->Expiries), exp_begin, + std::transform(exp_begin, std::end(Hold->mExpiries), exp_begin, std::bind(std::minus<ALsizei>{}, _1, n)); - exp_begin = std::begin(Hold->Expiries); + exp_begin = std::begin(Hold->mExpiries); } std::transform(exp_begin, exp_last+1, exp_begin, std::bind(std::minus<ALsizei>{}, _1, n)); } + /* Multichannel compression is linked via the absolute maximum of all * channels. */ void LinkChannels(Compressor *Comp, const ALsizei SamplesToDo, const ALfloat (*RESTRICT OutBuffer)[BUFFERSIZE]) { - const ALsizei index{Comp->LookAhead}; - const ALsizei numChans{Comp->NumChans}; + const ALsizei index{Comp->mLookAhead}; + const ALsizei numChans{Comp->mNumChans}; ASSUME(SamplesToDo > 0); ASSUME(numChans > 0); ASSUME(index >= 0); - auto side_begin = std::begin(Comp->SideChain) + index; + auto side_begin = std::begin(Comp->mSideChain) + index; std::fill(side_begin, side_begin+SamplesToDo, 0.0f); auto fill_max = [SamplesToDo,side_begin](const ALfloat *input) -> void @@ -121,10 +125,10 @@ void LinkChannels(Compressor *Comp, const ALsizei SamplesToDo, const ALfloat (*R */ static void CrestDetector(Compressor *Comp, const ALsizei SamplesToDo) { - const ALfloat a_crest{Comp->CrestCoeff}; - const ALsizei index{Comp->LookAhead}; - ALfloat y2_peak{Comp->LastPeakSq}; - ALfloat y2_rms{Comp->LastRmsSq}; + const ALfloat a_crest{Comp->mCrestCoeff}; + const ALsizei index{Comp->mLookAhead}; + ALfloat y2_peak{Comp->mLastPeakSq}; + ALfloat y2_rms{Comp->mLastRmsSq}; ASSUME(SamplesToDo > 0); ASSUME(index >= 0); @@ -137,11 +141,11 @@ static void CrestDetector(Compressor *Comp, const ALsizei SamplesToDo) y2_rms = lerp(x2, y2_rms, a_crest); return y2_peak / y2_rms; }; - auto side_begin = std::begin(Comp->SideChain) + index; - std::transform(side_begin, side_begin+SamplesToDo, std::begin(Comp->CrestFactor), calc_crest); + auto side_begin = std::begin(Comp->mSideChain) + index; + std::transform(side_begin, side_begin+SamplesToDo, std::begin(Comp->mCrestFactor), calc_crest); - Comp->LastPeakSq = y2_peak; - Comp->LastRmsSq = y2_rms; + Comp->mLastPeakSq = y2_peak; + Comp->mLastRmsSq = y2_rms; } /* The side-chain starts with a simple peak detector (based on the absolute @@ -150,13 +154,13 @@ static void CrestDetector(Compressor *Comp, const ALsizei SamplesToDo) */ void PeakDetector(Compressor *Comp, const ALsizei SamplesToDo) { - const ALsizei index{Comp->LookAhead}; + const ALsizei index{Comp->mLookAhead}; ASSUME(SamplesToDo > 0); ASSUME(index >= 0); /* Clamp the minimum amplitude to near-zero and convert to logarithm. */ - auto side_begin = std::begin(Comp->SideChain) + index; + auto side_begin = std::begin(Comp->mSideChain) + index; std::transform(side_begin, side_begin+SamplesToDo, side_begin, std::bind(static_cast<float(&)(float)>(std::log), std::bind(maxf, 0.000001f, _1))); } @@ -167,19 +171,19 @@ void PeakDetector(Compressor *Comp, const ALsizei SamplesToDo) */ void PeakHoldDetector(Compressor *Comp, const ALsizei SamplesToDo) { - const ALsizei index{Comp->LookAhead}; + const ALsizei index{Comp->mLookAhead}; ASSUME(SamplesToDo > 0); ASSUME(index >= 0); - SlidingHold *hold{Comp->Hold}; + SlidingHold *hold{Comp->mHold}; ALsizei i{0}; auto detect_peak = [&i,hold](const ALfloat x_abs) -> ALfloat { const ALfloat x_G{std::log(maxf(0.000001f, x_abs))}; return UpdateSlidingHold(hold, i++, x_G); }; - auto side_begin = std::begin(Comp->SideChain) + index; + auto side_begin = std::begin(Comp->mSideChain) + index; std::transform(side_begin, side_begin+SamplesToDo, side_begin, detect_peak); ShiftSlidingHold(hold, SamplesToDo); @@ -192,29 +196,29 @@ void PeakHoldDetector(Compressor *Comp, const ALsizei SamplesToDo) */ void GainCompressor(Compressor *Comp, const ALsizei SamplesToDo) { - const bool autoKnee{Comp->Auto.Knee}; - const bool autoAttack{Comp->Auto.Attack}; - const bool autoRelease{Comp->Auto.Release}; - const bool autoPostGain{Comp->Auto.PostGain}; - const bool autoDeclip{Comp->Auto.Declip}; - const ALsizei lookAhead{Comp->LookAhead}; - const ALfloat threshold{Comp->Threshold}; - const ALfloat slope{Comp->Slope}; - const ALfloat attack{Comp->Attack}; - const ALfloat release{Comp->Release}; - const ALfloat c_est{Comp->GainEstimate}; - const ALfloat a_adp{Comp->AdaptCoeff}; - const ALfloat (&crestFactor)[BUFFERSIZE] = Comp->CrestFactor; - ALfloat (&sideChain)[BUFFERSIZE*2] = Comp->SideChain; - ALfloat postGain{Comp->PostGain}; - ALfloat knee{Comp->Knee}; + const bool autoKnee{Comp->mAuto.Knee}; + const bool autoAttack{Comp->mAuto.Attack}; + const bool autoRelease{Comp->mAuto.Release}; + const bool autoPostGain{Comp->mAuto.PostGain}; + const bool autoDeclip{Comp->mAuto.Declip}; + const ALsizei lookAhead{Comp->mLookAhead}; + const ALfloat threshold{Comp->mThreshold}; + const ALfloat slope{Comp->mSlope}; + const ALfloat attack{Comp->mAttack}; + const ALfloat release{Comp->mRelease}; + const ALfloat c_est{Comp->mGainEstimate}; + const ALfloat a_adp{Comp->mAdaptCoeff}; + const ALfloat (&crestFactor)[BUFFERSIZE] = Comp->mCrestFactor; + ALfloat (&sideChain)[BUFFERSIZE*2] = Comp->mSideChain; + ALfloat postGain{Comp->mPostGain}; + ALfloat knee{Comp->mKnee}; ALfloat t_att{attack}; ALfloat t_rel{release - attack}; ALfloat a_att{std::exp(-1.0f / t_att)}; ALfloat a_rel{std::exp(-1.0f / t_rel)}; - ALfloat y_1{Comp->LastRelease}; - ALfloat y_L{Comp->LastAttack}; - ALfloat c_dev{Comp->LastGainDev}; + ALfloat y_1{Comp->mLastRelease}; + ALfloat y_L{Comp->mLastAttack}; + ALfloat c_dev{Comp->mLastGainDev}; ASSUME(SamplesToDo > 0); ASSUME(lookAhead >= 0); @@ -279,9 +283,9 @@ void GainCompressor(Compressor *Comp, const ALsizei SamplesToDo) sideChain[i] = std::exp(postGain - y_L); } - Comp->LastRelease = y_1; - Comp->LastAttack = y_L; - Comp->LastGainDev = c_dev; + Comp->mLastRelease = y_1; + Comp->mLastAttack = y_L; + Comp->mLastGainDev = c_dev; } /* Combined with the hold time, a look-ahead delay can improve handling of @@ -292,9 +296,9 @@ void GainCompressor(Compressor *Comp, const ALsizei SamplesToDo) void SignalDelay(Compressor *Comp, const ALsizei SamplesToDo, ALfloat (*RESTRICT OutBuffer)[BUFFERSIZE]) { static constexpr ALsizei mask{BUFFERSIZE - 1}; - const ALsizei numChans{Comp->NumChans}; - const ALsizei indexIn{Comp->DelayIndex}; - const ALsizei indexOut{Comp->DelayIndex - Comp->LookAhead}; + const ALsizei numChans{Comp->mNumChans}; + const ALsizei indexIn{Comp->mDelayIndex}; + const ALsizei indexOut{Comp->mDelayIndex - Comp->mLookAhead}; ASSUME(SamplesToDo > 0); ASSUME(numChans > 0); @@ -302,7 +306,7 @@ void SignalDelay(Compressor *Comp, const ALsizei SamplesToDo, ALfloat (*RESTRICT for(ALsizei c{0};c < numChans;c++) { ALfloat *RESTRICT inout{al::assume_aligned<16>(OutBuffer[c])}; - ALfloat *RESTRICT delay{al::assume_aligned<16>(Comp->Delay[c])}; + ALfloat *RESTRICT delay{al::assume_aligned<16>(Comp->mDelay[c])}; for(ALsizei i{0};i < SamplesToDo;i++) { const ALfloat sig{inout[i]}; @@ -312,7 +316,7 @@ void SignalDelay(Compressor *Comp, const ALsizei SamplesToDo, ALfloat (*RESTRICT } } - Comp->DelayIndex = (indexIn + SamplesToDo) & mask; + Comp->mDelayIndex = (indexIn + SamplesToDo) & mask; } } // namespace @@ -341,7 +345,7 @@ void SignalDelay(Compressor *Comp, const ALsizei SamplesToDo, ALfloat (*RESTRICT * ReleaseTimeMin - Release time (in seconds). Acts as a maximum when * automating release time. */ -Compressor* CompressorInit(const ALsizei NumChans, const ALuint SampleRate, +std::unique_ptr<Compressor> CompressorInit(const ALsizei NumChans, const ALuint SampleRate, const ALboolean AutoKnee, const ALboolean AutoAttack, const ALboolean AutoRelease, const ALboolean AutoPostGain, const ALboolean AutoDeclip, const ALfloat LookAheadTime, @@ -354,74 +358,82 @@ Compressor* CompressorInit(const ALsizei NumChans, const ALuint SampleRate, clampf(std::round(LookAheadTime*SampleRate), 0.0f, BUFFERSIZE-1)); auto hold = static_cast<ALsizei>(clampf(std::round(HoldTime*SampleRate), 0.0f, BUFFERSIZE-1)); - Compressor *Comp; - size_t size{sizeof(*Comp)}; + std::unique_ptr<Compressor> Comp; + size_t size{sizeof(Compressor)}; if(lookAhead > 0) { - size += sizeof(*Comp->Delay) * NumChans; + size += sizeof(*Comp->mDelay) * NumChans; /* The sliding hold implementation doesn't handle a length of 1. A 1- * sample hold is useless anyway, it would only ever give back what was * just given to it. */ if(hold > 1) - size += sizeof(*Comp->Hold); + size += sizeof(*Comp->mHold); } - Comp = new (al_calloc(16, size)) Compressor{}; - Comp->NumChans = NumChans; - Comp->SampleRate = SampleRate; - Comp->Auto.Knee = AutoKnee != AL_FALSE; - Comp->Auto.Attack = AutoAttack != AL_FALSE; - Comp->Auto.Release = AutoRelease != AL_FALSE; - Comp->Auto.PostGain = AutoPostGain != AL_FALSE; - Comp->Auto.Declip = AutoPostGain && AutoDeclip; - Comp->LookAhead = lookAhead; - Comp->PreGain = std::pow(10.0f, PreGainDb / 20.0f); - Comp->PostGain = PostGainDb * std::log(10.0f) / 20.0f; - Comp->Threshold = ThresholdDb * std::log(10.0f) / 20.0f; - Comp->Slope = 1.0f / maxf(1.0f, Ratio) - 1.0f; - Comp->Knee = maxf(0.0f, KneeDb * std::log(10.0f) / 20.0f); - Comp->Attack = maxf(1.0f, AttackTime * SampleRate); - Comp->Release = maxf(1.0f, ReleaseTime * SampleRate); + Comp = std::unique_ptr<Compressor>{new (al_calloc(16, size)) Compressor{}}; + Comp->mNumChans = NumChans; + Comp->mSampleRate = SampleRate; + Comp->mAuto.Knee = AutoKnee != AL_FALSE; + Comp->mAuto.Attack = AutoAttack != AL_FALSE; + Comp->mAuto.Release = AutoRelease != AL_FALSE; + Comp->mAuto.PostGain = AutoPostGain != AL_FALSE; + Comp->mAuto.Declip = AutoPostGain && AutoDeclip; + Comp->mLookAhead = lookAhead; + Comp->mPreGain = std::pow(10.0f, PreGainDb / 20.0f); + Comp->mPostGain = PostGainDb * std::log(10.0f) / 20.0f; + Comp->mThreshold = ThresholdDb * std::log(10.0f) / 20.0f; + Comp->mSlope = 1.0f / maxf(1.0f, Ratio) - 1.0f; + Comp->mKnee = maxf(0.0f, KneeDb * std::log(10.0f) / 20.0f); + Comp->mAttack = maxf(1.0f, AttackTime * SampleRate); + Comp->mRelease = maxf(1.0f, ReleaseTime * SampleRate); /* Knee width automation actually treats the compressor as a limiter. By * varying the knee width, it can effectively be seen as applying * compression over a wide range of ratios. */ if(AutoKnee) - Comp->Slope = -1.0f; + Comp->mSlope = -1.0f; if(lookAhead > 0) { if(hold > 1) { - Comp->Hold = new ((void*)(Comp + 1)) SlidingHold{}; - Comp->Hold->Values[0] = -std::numeric_limits<float>::infinity(); - Comp->Hold->Expiries[0] = hold; - Comp->Hold->Length = hold; - Comp->Delay = (ALfloat(*)[BUFFERSIZE])(Comp->Hold + 1); + Comp->mHold = new ((void*)(Comp.get() + 1)) SlidingHold{}; + Comp->mHold->mValues[0] = -std::numeric_limits<float>::infinity(); + Comp->mHold->mExpiries[0] = hold; + Comp->mHold->mLength = hold; + Comp->mDelay = (ALfloat(*)[BUFFERSIZE])(Comp->mHold + 1); } else { - Comp->Delay = (ALfloat(*)[BUFFERSIZE])(Comp + 1); + Comp->mDelay = (ALfloat(*)[BUFFERSIZE])(Comp.get() + 1); } } - Comp->CrestCoeff = std::exp(-1.0f / (0.200f * SampleRate)); // 200ms - Comp->GainEstimate = Comp->Threshold * -0.5f * Comp->Slope; - Comp->AdaptCoeff = std::exp(-1.0f / (2.0f * SampleRate)); // 2s + Comp->mCrestCoeff = std::exp(-1.0f / (0.200f * SampleRate)); // 200ms + Comp->mGainEstimate = Comp->mThreshold * -0.5f * Comp->mSlope; + Comp->mAdaptCoeff = std::exp(-1.0f / (2.0f * SampleRate)); // 2s return Comp; } -void ApplyCompression(Compressor *Comp, const ALsizei SamplesToDo, ALfloat (*OutBuffer)[BUFFERSIZE]) +Compressor::~Compressor() +{ + if(mHold) + mHold->~SlidingHold(); + mHold = nullptr; +} + + +void Compressor::process(const ALsizei SamplesToDo, ALfloat (*OutBuffer)[BUFFERSIZE]) { - const ALsizei numChans{Comp->NumChans}; + const ALsizei numChans{mNumChans}; ASSUME(SamplesToDo > 0); ASSUME(numChans > 0); - const ALfloat preGain{Comp->PreGain}; + const ALfloat preGain{mPreGain}; if(preGain != 1.0f) { auto apply_gain = [SamplesToDo,preGain](ALfloat *input) noexcept -> void @@ -433,26 +445,26 @@ void ApplyCompression(Compressor *Comp, const ALsizei SamplesToDo, ALfloat (*Out std::for_each(OutBuffer, OutBuffer+numChans, apply_gain); } - LinkChannels(Comp, SamplesToDo, OutBuffer); + LinkChannels(this, SamplesToDo, OutBuffer); - if(Comp->Auto.Attack || Comp->Auto.Release) - CrestDetector(Comp, SamplesToDo); + if(mAuto.Attack || mAuto.Release) + CrestDetector(this, SamplesToDo); - if(Comp->Hold) - PeakHoldDetector(Comp, SamplesToDo); + if(mHold) + PeakHoldDetector(this, SamplesToDo); else - PeakDetector(Comp, SamplesToDo); + PeakDetector(this, SamplesToDo); - GainCompressor(Comp, SamplesToDo); + GainCompressor(this, SamplesToDo); - if(Comp->Delay) - SignalDelay(Comp, SamplesToDo, OutBuffer); + if(mDelay) + SignalDelay(this, SamplesToDo, OutBuffer); - const ALfloat (&sideChain)[BUFFERSIZE*2] = Comp->SideChain; + const ALfloat (&sideChain)[BUFFERSIZE*2] = mSideChain; auto apply_comp = [SamplesToDo,&sideChain](ALfloat *input) noexcept -> void { ALfloat *buffer{al::assume_aligned<16>(input)}; - const ALfloat *gains{al::assume_aligned<16>(sideChain)}; + const ALfloat *gains{al::assume_aligned<16>(&sideChain[0])}; /* Mark the gains "input-1 type" as restrict, so the compiler can * vectorize this loop (otherwise it assumes a write to buffer[n] can * change gains[n+1]). @@ -462,11 +474,7 @@ void ApplyCompression(Compressor *Comp, const ALsizei SamplesToDo, ALfloat (*Out }; std::for_each(OutBuffer, OutBuffer+numChans, apply_comp); - ASSUME(Comp->LookAhead >= 0); - auto side_begin = std::begin(Comp->SideChain) + SamplesToDo; - std::copy(side_begin, side_begin+Comp->LookAhead, std::begin(Comp->SideChain)); + ASSUME(mLookAhead >= 0); + auto side_begin = std::begin(mSideChain) + SamplesToDo; + std::copy(side_begin, side_begin+mLookAhead, std::begin(mSideChain)); } - - -ALsizei GetCompressorLookAhead(const Compressor *Comp) -{ return Comp->LookAhead; } diff --git a/Alc/mastering.h b/Alc/mastering.h index 55b7c258..a9411bd0 100644 --- a/Alc/mastering.h +++ b/Alc/mastering.h @@ -1,6 +1,8 @@ #ifndef MASTERING_H #define MASTERING_H +#include <memory> + #include "AL/al.h" #include "almalloc.h" @@ -21,8 +23,8 @@ struct SlidingHold; * http://c4dm.eecs.qmul.ac.uk/audioengineering/compressors/ */ struct Compressor { - ALsizei NumChans; - ALuint SampleRate; + ALsizei mNumChans{0}; + ALuint mSampleRate{0u}; struct { bool Knee : 1; @@ -30,36 +32,41 @@ struct Compressor { bool Release : 1; bool PostGain : 1; bool Declip : 1; - } Auto; + } mAuto{}; + + ALsizei mLookAhead{0}; + + ALfloat mPreGain{0.0f}; + ALfloat mPostGain{0.0f}; - ALsizei LookAhead; + ALfloat mThreshold{0.0f}; + ALfloat mSlope{0.0f}; + ALfloat mKnee{0.0f}; - ALfloat PreGain; - ALfloat PostGain; + ALfloat mAttack{0.0f}; + ALfloat mRelease{0.0f}; - ALfloat Threshold; - ALfloat Slope; - ALfloat Knee; + alignas(16) ALfloat mSideChain[2*BUFFERSIZE]{}; + alignas(16) ALfloat mCrestFactor[BUFFERSIZE]{}; - ALfloat Attack; - ALfloat Release; + SlidingHold *mHold{nullptr}; + ALfloat (*mDelay)[BUFFERSIZE]{nullptr}; + ALsizei mDelayIndex{0}; - alignas(16) ALfloat SideChain[2*BUFFERSIZE]; - alignas(16) ALfloat CrestFactor[BUFFERSIZE]; + ALfloat mCrestCoeff{0.0f}; + ALfloat mGainEstimate{0.0f}; + ALfloat mAdaptCoeff{0.0f}; - SlidingHold *Hold; - ALfloat (*Delay)[BUFFERSIZE]; - ALsizei DelayIndex; + ALfloat mLastPeakSq{0.0f}; + ALfloat mLastRmsSq{0.0f}; + ALfloat mLastRelease{0.0f}; + ALfloat mLastAttack{0.0f}; + ALfloat mLastGainDev{0.0f}; - ALfloat CrestCoeff; - ALfloat GainEstimate; - ALfloat AdaptCoeff; - ALfloat LastPeakSq; - ALfloat LastRmsSq; - ALfloat LastRelease; - ALfloat LastAttack; - ALfloat LastGainDev; + ~Compressor(); + void process(const ALsizei SamplesToDo, ALfloat (*OutBuffer)[BUFFERSIZE]); + ALsizei getLookAhead() const noexcept { return mLookAhead; } DEF_PLACE_NEWDEL() }; @@ -88,7 +95,7 @@ struct Compressor { * ReleaseTimeMin - Release time (in seconds). Acts as a maximum when * automating release time. */ -Compressor* CompressorInit(const ALsizei NumChans, const ALuint SampleRate, +std::unique_ptr<Compressor> CompressorInit(const ALsizei NumChans, const ALuint SampleRate, const ALboolean AutoKnee, const ALboolean AutoAttack, const ALboolean AutoRelease, const ALboolean AutoPostGain, const ALboolean AutoDeclip, const ALfloat LookAheadTime, @@ -97,9 +104,4 @@ Compressor* CompressorInit(const ALsizei NumChans, const ALuint SampleRate, const ALfloat Ratio, const ALfloat KneeDb, const ALfloat AttackTime, const ALfloat ReleaseTime); -void ApplyCompression(Compressor *Comp, const ALsizei SamplesToDo, - ALfloat (*OutBuffer)[BUFFERSIZE]); - -ALsizei GetCompressorLookAhead(const Compressor *Comp); - #endif /* MASTERING_H */ |