diff options
-rw-r--r-- | Alc/alc.cpp | 11 | ||||
-rw-r--r-- | Alc/alu.cpp | 2 | ||||
-rw-r--r-- | Alc/mastering.cpp | 104 | ||||
-rw-r--r-- | Alc/mastering.h | 68 | ||||
-rw-r--r-- | OpenAL32/Include/alMain.h | 2 |
5 files changed, 95 insertions, 92 deletions
diff --git a/Alc/alc.cpp b/Alc/alc.cpp index 2ad6c887..b942064f 100644 --- a/Alc/alc.cpp +++ b/Alc/alc.cpp @@ -2221,16 +2221,12 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) if(device->DitherDepth > 0.0f) thrshld -= 1.0f / device->DitherDepth; - al_free(device->Limiter); - device->Limiter = CreateDeviceLimiter(device, std::log10(thrshld) * 20.0f); - device->FixedLatency += (ALuint)(GetCompressorLookAhead(device->Limiter) * + device->Limiter.reset(CreateDeviceLimiter(device, std::log10(thrshld) * 20.0f)); + device->FixedLatency += (ALuint)(GetCompressorLookAhead(device->Limiter.get()) * DEVICE_CLOCK_RES / device->Frequency); } else - { - al_free(device->Limiter); device->Limiter = nullptr; - } TRACE("Output limiter %s\n", device->Limiter ? "enabled" : "disabled"); aluSelectPostProcess(device); @@ -2433,9 +2429,6 @@ ALCdevice_struct::~ALCdevice_struct() al_free(Stablizer); Stablizer = nullptr; - - al_free(Limiter); - Limiter = nullptr; } diff --git a/Alc/alu.cpp b/Alc/alu.cpp index a87be0b6..4d3ad9b2 100644 --- a/Alc/alu.cpp +++ b/Alc/alu.cpp @@ -1787,7 +1787,7 @@ void aluMixData(ALCdevice *device, ALvoid *OutBuffer, ALsizei NumSamples) SamplesToDo, device->RealOut.NumChannels); if(device->Limiter) - ApplyCompression(device->Limiter, SamplesToDo, device->RealOut.Buffer); + ApplyCompression(device->Limiter.get(), SamplesToDo, device->RealOut.Buffer); if(device->DitherDepth > 0.0f) ApplyDither(device->RealOut.Buffer, &device->DitherSeed, device->DitherDepth, diff --git a/Alc/mastering.cpp b/Alc/mastering.cpp index 131a0330..bf999709 100644 --- a/Alc/mastering.cpp +++ b/Alc/mastering.cpp @@ -2,6 +2,8 @@ #include <math.h> +#include <algorithm> + #include "mastering.h" #include "alu.h" #include "almalloc.h" @@ -23,65 +25,13 @@ static double round(double val) /* These structures assume BUFFERSIZE is a power of 2. */ static_assert((BUFFERSIZE & (BUFFERSIZE-1)) == 0, "BUFFERSIZE is not a power of 2"); -typedef struct SlidingHold { +struct SlidingHold { ALfloat Values[BUFFERSIZE]; ALsizei Expiries[BUFFERSIZE]; ALsizei LowerIndex; ALsizei UpperIndex; ALsizei Length; -} SlidingHold; - -/* General topology and basic automation was based on the following paper: - * - * D. Giannoulis, M. Massberg and J. D. Reiss, - * "Parameter Automation in a Dynamic Range Compressor," - * Journal of the Audio Engineering Society, v61 (10), Oct. 2013 - * - * Available (along with supplemental reading) at: - * - * http://c4dm.eecs.qmul.ac.uk/audioengineering/compressors/ - */ -typedef struct Compressor { - ALsizei NumChans; - ALuint SampleRate; - - struct { - ALuint Knee : 1; - ALuint Attack : 1; - ALuint Release : 1; - ALuint PostGain : 1; - ALuint Declip : 1; - } Auto; - - ALsizei LookAhead; - - ALfloat PreGain; - ALfloat PostGain; - - ALfloat Threshold; - ALfloat Slope; - ALfloat Knee; - - ALfloat Attack; - ALfloat Release; - - alignas(16) ALfloat SideChain[2*BUFFERSIZE]; - alignas(16) ALfloat CrestFactor[BUFFERSIZE]; - - SlidingHold *Hold; - ALfloat (*Delay)[BUFFERSIZE]; - ALsizei DelayIndex; - - ALfloat CrestCoeff; - ALfloat GainEstimate; - ALfloat AdaptCoeff; - - ALfloat LastPeakSq; - ALfloat LastRmsSq; - ALfloat LastRelease; - ALfloat LastAttack; - ALfloat LastGainDev; -} Compressor; +}; /* This sliding hold follows the input level with an instant attack and a @@ -446,7 +396,7 @@ Compressor* CompressorInit(const ALsizei NumChans, const ALuint SampleRate, size += sizeof(*Comp->Hold); } - Comp = static_cast<Compressor*>(al_calloc(16, size)); + Comp = new (al_calloc(16, size)) Compressor{}; Comp->NumChans = NumChans; Comp->SampleRate = SampleRate; Comp->Auto.Knee = AutoKnee; @@ -474,7 +424,7 @@ Compressor* CompressorInit(const ALsizei NumChans, const ALuint SampleRate, { if(hold > 0) { - Comp->Hold = (SlidingHold*)(Comp + 1); + Comp->Hold = new ((void*)(Comp + 1)) SlidingHold{}; Comp->Hold->Values[0] = -HUGE_VALF; Comp->Hold->Expiries[0] = hold; Comp->Hold->Length = hold; @@ -495,21 +445,23 @@ Compressor* CompressorInit(const ALsizei NumChans, const ALuint SampleRate, void ApplyCompression(Compressor *Comp, const ALsizei SamplesToDo, ALfloat (*RESTRICT OutBuffer)[BUFFERSIZE]) { - const ALsizei numChans = Comp->NumChans; - const ALfloat preGain = Comp->PreGain; - ALfloat *RESTRICT sideChain; - ALsizei c, i; + const ALsizei numChans{Comp->NumChans}; ASSUME(SamplesToDo > 0); ASSUME(numChans > 0); + const ALfloat preGain{Comp->PreGain}; if(preGain != 1.0f) { - for(c = 0;c < numChans;c++) - { - for(i = 0;i < SamplesToDo;i++) - OutBuffer[c][i] *= preGain; - } + std::for_each(OutBuffer, OutBuffer+numChans, + [SamplesToDo, preGain](ALfloat *buffer) noexcept -> void + { + std::for_each(buffer, buffer+SamplesToDo, + [preGain](ALfloat &samp) noexcept -> void + { samp *= preGain; } + ); + } + ); } LinkChannels(Comp, SamplesToDo, OutBuffer); @@ -527,14 +479,22 @@ void ApplyCompression(Compressor *Comp, const ALsizei SamplesToDo, ALfloat (*RES if(Comp->Delay) SignalDelay(Comp, SamplesToDo, OutBuffer); - sideChain = Comp->SideChain; - for(c = 0;c < numChans;c++) - { - for(i = 0;i < SamplesToDo;i++) - OutBuffer[c][i] *= sideChain[i]; - } + ALfloat *RESTRICT sideChain{Comp->SideChain}; + std::for_each(OutBuffer, OutBuffer+numChans, + [SamplesToDo, sideChain](ALfloat *buffer) noexcept -> void + { + /* Mark the sideChain "input-1 type" as restrict, so the compiler + * can vectorize this loop (otherwise it assumes a write to + * buffer[n] can change sideChain[n+1]). + */ + std::transform<ALfloat*RESTRICT>(sideChain, sideChain+SamplesToDo, buffer, buffer, + [](const ALfloat gain, const ALfloat samp) noexcept -> ALfloat + { return samp * gain; } + ); + } + ); - memmove(sideChain, sideChain+SamplesToDo, Comp->LookAhead*sizeof(ALfloat)); + std::copy(sideChain+SamplesToDo, sideChain+SamplesToDo+Comp->LookAhead, sideChain); } diff --git a/Alc/mastering.h b/Alc/mastering.h index 7738a4aa..a6cf58ed 100644 --- a/Alc/mastering.h +++ b/Alc/mastering.h @@ -3,14 +3,68 @@ #include "AL/al.h" +#include "almalloc.h" /* For BUFFERSIZE. */ #include "alMain.h" -#ifdef __cplusplus -extern "C" { -#endif -struct Compressor; +struct SlidingHold; + +/* General topology and basic automation was based on the following paper: + * + * D. Giannoulis, M. Massberg and J. D. Reiss, + * "Parameter Automation in a Dynamic Range Compressor," + * Journal of the Audio Engineering Society, v61 (10), Oct. 2013 + * + * Available (along with supplemental reading) at: + * + * http://c4dm.eecs.qmul.ac.uk/audioengineering/compressors/ + */ +struct Compressor { + ALsizei NumChans; + ALuint SampleRate; + + struct { + ALuint Knee : 1; + ALuint Attack : 1; + ALuint Release : 1; + ALuint PostGain : 1; + ALuint Declip : 1; + } Auto; + + ALsizei LookAhead; + + ALfloat PreGain; + ALfloat PostGain; + + ALfloat Threshold; + ALfloat Slope; + ALfloat Knee; + + ALfloat Attack; + ALfloat Release; + + alignas(16) ALfloat SideChain[2*BUFFERSIZE]; + alignas(16) ALfloat CrestFactor[BUFFERSIZE]; + + SlidingHold *Hold; + ALfloat (*Delay)[BUFFERSIZE]; + ALsizei DelayIndex; + + ALfloat CrestCoeff; + ALfloat GainEstimate; + ALfloat AdaptCoeff; + + ALfloat LastPeakSq; + ALfloat LastRmsSq; + ALfloat LastRelease; + ALfloat LastAttack; + ALfloat LastGainDev; + + void *operator new(size_t size) = delete; + void *operator new(size_t /*size*/, void *ptr) noexcept { return ptr; } + void operator delete(void *block) noexcept { al_free(block); } +}; /* The compressor is initialized with the following settings: * @@ -36,7 +90,7 @@ struct Compressor; * ReleaseTimeMin - Release time (in seconds). Acts as a maximum when * automating release time. */ -struct Compressor* CompressorInit(const ALsizei NumChans, const ALuint SampleRate, +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, @@ -50,8 +104,4 @@ void ApplyCompression(struct Compressor *Comp, const ALsizei SamplesToDo, ALsizei GetCompressorLookAhead(const struct Compressor *Comp); -#ifdef __cplusplus -} // extern "C" -#endif - #endif /* MASTERING_H */ diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 06ccd574..41465c1d 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -711,7 +711,7 @@ struct ALCdevice_struct { struct FrontStablizer *Stablizer{nullptr}; - struct Compressor *Limiter{nullptr}; + std::unique_ptr<Compressor> Limiter; /* The average speaker distance as determined by the ambdec configuration * (or alternatively, by the NFC-HOA reference delay). Only used for NFC. |