Use size_t for the compressor channel count

And general cleanup of the compressor
This commit is contained in:
Chris Robinson
2019-12-21 03:21:13 -08:00
parent 54e7f48df9
commit c2ca617ed6
3 changed files with 101 additions and 124 deletions
+4 -4
View File
@@ -1633,11 +1633,11 @@ static void alcSetError(ALCdevice *device, ALCenum errorCode)
}
static std::unique_ptr<Compressor> CreateDeviceLimiter(const ALCdevice *device, const ALfloat threshold)
static std::unique_ptr<Compressor> CreateDeviceLimiter(const ALCdevice *device, const float threshold)
{
return CompressorInit(static_cast<ALuint>(device->RealOut.Buffer.size()),
static_cast<float>(device->Frequency), AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, 0.001f,
0.002f, 0.0f, 0.0f, threshold, INFINITY, 0.0f, 0.020f, 0.200f);
return Compressor::Create(device->RealOut.Buffer.size(), static_cast<float>(device->Frequency),
AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, AL_TRUE, 0.001f, 0.002f, 0.0f, 0.0f, threshold,
std::numeric_limits<float>::infinity(), 0.0f, 0.020f, 0.200f);
}
/* UpdateClockBase
+46 -71
View File
@@ -23,7 +23,7 @@
static_assert((BUFFERSIZE & (BUFFERSIZE-1)) == 0, "BUFFERSIZE is not a power of 2");
struct SlidingHold {
alignas(16) ALfloat mValues[BUFFERSIZE];
alignas(16) float mValues[BUFFERSIZE];
ALuint mExpiries[BUFFERSIZE];
ALuint mLowerIndex;
ALuint mUpperIndex;
@@ -42,11 +42,11 @@ using namespace std::placeholders;
*
* http://www.richardhartersworld.com/cri/2001/slidingmin.html
*/
ALfloat UpdateSlidingHold(SlidingHold *Hold, const ALuint i, const ALfloat in)
ALfloat UpdateSlidingHold(SlidingHold *Hold, const ALuint i, const float in)
{
static constexpr ALuint mask{BUFFERSIZE - 1};
const ALuint length{Hold->mLength};
ALfloat (&values)[BUFFERSIZE] = Hold->mValues;
float (&values)[BUFFERSIZE] = Hold->mValues;
ALuint (&expiries)[BUFFERSIZE] = Hold->mExpiries;
ALuint lowerIndex{Hold->mLowerIndex};
ALuint upperIndex{Hold->mUpperIndex};
@@ -101,7 +101,7 @@ void ShiftSlidingHold(SlidingHold *Hold, const ALuint n)
*/
void LinkChannels(Compressor *Comp, const ALuint SamplesToDo, const FloatBufferLine *OutBuffer)
{
const ALuint numChans{Comp->mNumChans};
const size_t numChans{Comp->mNumChans};
ASSUME(SamplesToDo > 0);
ASSUME(numChans > 0);
@@ -111,7 +111,7 @@ void LinkChannels(Compressor *Comp, const ALuint SamplesToDo, const FloatBufferL
auto fill_max = [SamplesToDo,side_begin](const FloatBufferLine &input) -> void
{
const ALfloat *RESTRICT buffer{al::assume_aligned<16>(input.data())};
const float *RESTRICT buffer{al::assume_aligned<16>(input.data())};
auto max_abs = std::bind(maxf, _1, std::bind(static_cast<float(&)(float)>(std::fabs), _2));
std::transform(side_begin, side_begin+SamplesToDo, buffer, side_begin, max_abs);
};
@@ -125,15 +125,15 @@ void LinkChannels(Compressor *Comp, const ALuint SamplesToDo, const FloatBufferL
*/
static void CrestDetector(Compressor *Comp, const ALuint SamplesToDo)
{
const ALfloat a_crest{Comp->mCrestCoeff};
ALfloat y2_peak{Comp->mLastPeakSq};
ALfloat y2_rms{Comp->mLastRmsSq};
const float a_crest{Comp->mCrestCoeff};
float y2_peak{Comp->mLastPeakSq};
float y2_rms{Comp->mLastRmsSq};
ASSUME(SamplesToDo > 0);
auto calc_crest = [&y2_rms,&y2_peak,a_crest](const ALfloat x_abs) noexcept -> ALfloat
auto calc_crest = [&y2_rms,&y2_peak,a_crest](const float x_abs) noexcept -> float
{
const ALfloat x2{clampf(x_abs * x_abs, 0.000001f, 1000000.0f)};
const float x2{clampf(x_abs * x_abs, 0.000001f, 1000000.0f)};
y2_peak = maxf(x2, lerp(x2, y2_peak, a_crest));
y2_rms = lerp(x2, y2_rms, a_crest);
@@ -157,7 +157,7 @@ void PeakDetector(Compressor *Comp, const ALuint SamplesToDo)
/* Clamp the minimum amplitude to near-zero and convert to logarithm. */
auto side_begin = std::begin(Comp->mSideChain) + Comp->mLookAhead;
std::transform(side_begin, side_begin+SamplesToDo, side_begin,
std::bind(static_cast<float(&)(float)>(std::log), std::bind(maxf, 0.000001f, _1)));
[](const float s) -> float { return std::log(maxf(0.000001f, s)); });
}
/* An optional hold can be used to extend the peak detector so it can more
@@ -172,7 +172,7 @@ void PeakHoldDetector(Compressor *Comp, const ALuint SamplesToDo)
ALuint i{0};
auto detect_peak = [&i,hold](const ALfloat x_abs) -> ALfloat
{
const ALfloat x_G{std::log(maxf(0.000001f, x_abs))};
const float x_G{std::log(maxf(0.000001f, x_abs))};
return UpdateSlidingHold(hold, i++, x_G);
};
auto side_begin = std::begin(Comp->mSideChain) + Comp->mLookAhead;
@@ -194,42 +194,41 @@ void GainCompressor(Compressor *Comp, const ALuint SamplesToDo)
const bool autoPostGain{Comp->mAuto.PostGain};
const bool autoDeclip{Comp->mAuto.Declip};
const ALuint 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{Comp->mCrestFactor};
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->mLastRelease};
ALfloat y_L{Comp->mLastAttack};
ALfloat c_dev{Comp->mLastGainDev};
const float threshold{Comp->mThreshold};
const float slope{Comp->mSlope};
const float attack{Comp->mAttack};
const float release{Comp->mRelease};
const float c_est{Comp->mGainEstimate};
const float a_adp{Comp->mAdaptCoeff};
const float *crestFactor{Comp->mCrestFactor};
float postGain{Comp->mPostGain};
float knee{Comp->mKnee};
float t_att{attack};
float t_rel{release - attack};
float a_att{std::exp(-1.0f / t_att)};
float a_rel{std::exp(-1.0f / t_rel)};
float y_1{Comp->mLastRelease};
float y_L{Comp->mLastAttack};
float c_dev{Comp->mLastGainDev};
ASSUME(SamplesToDo > 0);
for(ALfloat &sideChain : al::span<float>{Comp->mSideChain, SamplesToDo})
for(float &sideChain : al::span<float>{Comp->mSideChain, SamplesToDo})
{
if(autoKnee)
knee = maxf(0.0f, 2.5f * (c_dev + c_est));
const ALfloat knee_h{0.5f * knee};
const float knee_h{0.5f * knee};
/* This is the gain computer. It applies a static compression curve
* to the control signal.
*/
const ALfloat x_over{std::addressof(sideChain)[lookAhead] - threshold};
const ALfloat y_G{
const float x_over{std::addressof(sideChain)[lookAhead] - threshold};
const float y_G{
(x_over <= -knee_h) ? 0.0f :
(std::fabs(x_over) < knee_h) ? (x_over + knee_h) * (x_over + knee_h) / (2.0f * knee) :
x_over
};
x_over};
const ALfloat y2_crest{*(crestFactor++)};
const float y2_crest{*(crestFactor++)};
if(autoAttack)
{
t_att = 2.0f*attack/y2_crest;
@@ -245,7 +244,7 @@ void GainCompressor(Compressor *Comp, const ALuint SamplesToDo)
* detector. The attack time is subtracted from the release time
* above to compensate for the chained operating mode.
*/
const ALfloat x_L{-slope * y_G};
const float x_L{-slope * y_G};
y_1 = maxf(x_L, lerp(x_L, y_1, a_rel));
y_L = lerp(y_1, y_L, a_att);
@@ -285,14 +284,14 @@ void GainCompressor(Compressor *Comp, const ALuint SamplesToDo)
*/
void SignalDelay(Compressor *Comp, const ALuint SamplesToDo, FloatBufferLine *OutBuffer)
{
const ALuint numChans{Comp->mNumChans};
const size_t numChans{Comp->mNumChans};
const ALuint lookAhead{Comp->mLookAhead};
ASSUME(SamplesToDo > 0);
ASSUME(numChans > 0);
ASSUME(lookAhead > 0);
for(ALuint c{0};c < numChans;c++)
for(size_t c{0};c < numChans;c++)
{
ALfloat *inout{al::assume_aligned<16>(OutBuffer[c].data())};
ALfloat *delaybuf{al::assume_aligned<16>(Comp->mDelay[c].data())};
@@ -313,36 +312,12 @@ void SignalDelay(Compressor *Comp, const ALuint SamplesToDo, FloatBufferLine *Ou
} // namespace
/* The compressor is initialized with the following settings:
*
* NumChans - Number of channels to process.
* SampleRate - Sample rate to process.
* AutoKnee - Whether to automate the knee width parameter.
* AutoAttack - Whether to automate the attack time parameter.
* AutoRelease - Whether to automate the release time parameter.
* AutoPostGain - Whether to automate the make-up (post) gain parameter.
* AutoDeclip - Whether to automate clipping reduction. Ignored when
* not automating make-up gain.
* LookAheadTime - Look-ahead time (in seconds).
* HoldTime - Peak hold-time (in seconds).
* PreGainDb - Gain applied before detection (in dB).
* PostGainDb - Make-up gain applied after compression (in dB).
* ThresholdDb - Triggering threshold (in dB).
* Ratio - Compression ratio (x:1). Set to INFINITY for true
* limiting. Ignored when automating knee width.
* KneeDb - Knee width (in dB). Ignored when automating knee
* width.
* AttackTimeMin - Attack time (in seconds). Acts as a maximum when
* automating attack time.
* ReleaseTimeMin - Release time (in seconds). Acts as a maximum when
* automating release time.
*/
std::unique_ptr<Compressor> CompressorInit(const ALuint NumChans, const ALfloat SampleRate,
const ALboolean AutoKnee, const ALboolean AutoAttack, const ALboolean AutoRelease,
const ALboolean AutoPostGain, const ALboolean AutoDeclip, const ALfloat LookAheadTime,
const ALfloat HoldTime, const ALfloat PreGainDb, const ALfloat PostGainDb,
const ALfloat ThresholdDb, const ALfloat Ratio, const ALfloat KneeDb, const ALfloat AttackTime,
const ALfloat ReleaseTime)
std::unique_ptr<Compressor> Compressor::Create(const size_t NumChans, const float SampleRate,
const bool AutoKnee, const bool AutoAttack, const bool AutoRelease, const bool AutoPostGain,
const bool AutoDeclip, const float LookAheadTime, const float HoldTime, const float PreGainDb,
const float PostGainDb, const float ThresholdDb, const float Ratio, const float KneeDb,
const float AttackTime, const float ReleaseTime)
{
const auto lookAhead = static_cast<ALuint>(
clampf(std::round(LookAheadTime*SampleRate), 0.0f, BUFFERSIZE-1));
@@ -421,17 +396,17 @@ Compressor::~Compressor()
void Compressor::process(const ALuint SamplesToDo, FloatBufferLine *OutBuffer)
{
const ALuint numChans{mNumChans};
const size_t numChans{mNumChans};
ASSUME(SamplesToDo > 0);
ASSUME(numChans > 0);
const ALfloat preGain{mPreGain};
const float preGain{mPreGain};
if(preGain != 1.0f)
{
auto apply_gain = [SamplesToDo,preGain](FloatBufferLine &input) noexcept -> void
{
ALfloat *buffer{al::assume_aligned<16>(input.data())};
float *buffer{al::assume_aligned<16>(input.data())};
std::transform(buffer, buffer+SamplesToDo, buffer,
std::bind(std::multiplies<float>{}, _1, preGain));
};
+51 -49
View File
@@ -23,7 +23,7 @@ struct SlidingHold;
* http://c4dm.eecs.qmul.ac.uk/audioengineering/compressors/
*/
struct Compressor {
ALuint mNumChans{0u};
size_t mNumChans{0u};
struct {
bool Knee : 1;
@@ -35,31 +35,31 @@ struct Compressor {
ALuint mLookAhead{0};
ALfloat mPreGain{0.0f};
ALfloat mPostGain{0.0f};
float mPreGain{0.0f};
float mPostGain{0.0f};
ALfloat mThreshold{0.0f};
ALfloat mSlope{0.0f};
ALfloat mKnee{0.0f};
float mThreshold{0.0f};
float mSlope{0.0f};
float mKnee{0.0f};
ALfloat mAttack{0.0f};
ALfloat mRelease{0.0f};
float mAttack{0.0f};
float mRelease{0.0f};
alignas(16) ALfloat mSideChain[2*BUFFERSIZE]{};
alignas(16) ALfloat mCrestFactor[BUFFERSIZE]{};
alignas(16) float mSideChain[2*BUFFERSIZE]{};
alignas(16) float mCrestFactor[BUFFERSIZE]{};
SlidingHold *mHold{nullptr};
FloatBufferLine *mDelay{nullptr};
ALfloat mCrestCoeff{0.0f};
ALfloat mGainEstimate{0.0f};
ALfloat mAdaptCoeff{0.0f};
float mCrestCoeff{0.0f};
float mGainEstimate{0.0f};
float mAdaptCoeff{0.0f};
ALfloat mLastPeakSq{0.0f};
ALfloat mLastRmsSq{0.0f};
ALfloat mLastRelease{0.0f};
ALfloat mLastAttack{0.0f};
ALfloat mLastGainDev{0.0f};
float mLastPeakSq{0.0f};
float mLastRmsSq{0.0f};
float mLastRelease{0.0f};
float mLastAttack{0.0f};
float mLastGainDev{0.0f};
~Compressor();
@@ -67,37 +67,39 @@ struct Compressor {
ALsizei getLookAhead() const noexcept { return static_cast<ALsizei>(mLookAhead); }
DEF_PLACE_NEWDEL()
/**
* The compressor is initialized with the following settings:
*
* \param NumChans Number of channels to process.
* \param SampleRate Sample rate to process.
* \param AutoKnee Whether to automate the knee width parameter.
* \param AutoAttack Whether to automate the attack time parameter.
* \param AutoRelease Whether to automate the release time parameter.
* \param AutoPostGain Whether to automate the make-up (post) gain
* parameter.
* \param AutoDeclip Whether to automate clipping reduction. Ignored
* when not automating make-up gain.
* \param LookAheadTime Look-ahead time (in seconds).
* \param HoldTime Peak hold-time (in seconds).
* \param PreGainDb Gain applied before detection (in dB).
* \param PostGainDb Make-up gain applied after compression (in dB).
* \param ThresholdDb Triggering threshold (in dB).
* \param Ratio Compression ratio (x:1). Set to INFINIFTY for true
* limiting. Ignored when automating knee width.
* \param KneeDb Knee width (in dB). Ignored when automating knee
* width.
* \param AttackTime Attack time (in seconds). Acts as a maximum when
* automating attack time.
* \param ReleaseTime Release time (in seconds). Acts as a maximum when
* automating release time.
*/
static std::unique_ptr<Compressor> Create(const size_t NumChans, const float SampleRate,
const bool AutoKnee, const bool AutoAttack, const bool AutoRelease,
const bool AutoPostGain, const bool AutoDeclip, const float LookAheadTime,
const float HoldTime, const float PreGainDb, const float PostGainDb,
const float ThresholdDb, const float Ratio, const float KneeDb, const float AttackTime,
const float ReleaseTime);
};
/* The compressor is initialized with the following settings:
*
* NumChans - Number of channels to process.
* SampleRate - Sample rate to process.
* AutoKnee - Whether to automate the knee width parameter.
* AutoAttack - Whether to automate the attack time parameter.
* AutoRelease - Whether to automate the release time parameter.
* AutoPostGain - Whether to automate the make-up (post) gain parameter.
* AutoDeclip - Whether to automate clipping reduction. Ignored when
* not automating make-up gain.
* LookAheadTime - Look-ahead time (in seconds).
* HoldTime - Peak hold-time (in seconds).
* PreGainDb - Gain applied before detection (in dB).
* PostGainDb - Make-up gain applied after compression (in dB).
* ThresholdDb - Triggering threshold (in dB).
* Ratio - Compression ratio (x:1). Set to INFINIFTY for true
* limiting. Ignored when automating knee width.
* KneeDb - Knee width (in dB). Ignored when automating knee
* width.
* AttackTimeMin - Attack time (in seconds). Acts as a maximum when
* automating attack time.
* ReleaseTimeMin - Release time (in seconds). Acts as a maximum when
* automating release time.
*/
std::unique_ptr<Compressor> CompressorInit(const ALuint NumChans, const ALfloat SampleRate,
const ALboolean AutoKnee, const ALboolean AutoAttack, const ALboolean AutoRelease,
const ALboolean AutoPostGain, const ALboolean AutoDeclip, const ALfloat LookAheadTime,
const ALfloat HoldTime, const ALfloat PreGainDb, const ALfloat PostGainDb,
const ALfloat ThresholdDb, const ALfloat Ratio, const ALfloat KneeDb, const ALfloat AttackTime,
const ALfloat ReleaseTime);
#endif /* MASTERING_H */