aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/alc.cpp11
-rw-r--r--Alc/alu.cpp4
-rw-r--r--Alc/mastering.cpp238
-rw-r--r--Alc/mastering.h62
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 */