Audacity 3.2.0
Classes | Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes | List of all members
CompressorProcessor Class Reference

#include <CompressorProcessor.h>

Collaboration diagram for CompressorProcessor:
[legend]

Classes

struct  FrameStats
 

Public Member Functions

 CompressorProcessor (const DynamicRangeProcessorSettings &settings={ CompressorSettings {} })
 
 CompressorProcessor (const CompressorProcessor &other)=delete
 
 ~CompressorProcessor ()
 
void ApplySettingsIfNeeded (const DynamicRangeProcessorSettings &settings)
 
void Init (int sampleRate, int numChannels, int blockSize)
 
void Reinit ()
 
const DynamicRangeProcessorSettingsGetSettings () const
 
void Process (const float *const *inBlock, float *const *outBlock, int blockLen)
 
const std::vector< std::vector< float > > & GetDelayedInput () const
 
const FrameStatsGetLastFrameStats () const
 
float EvaluateTransferFunction (float inputDb) const
 

Static Public Member Functions

static float GetMaxCompressionDb (const DynamicRangeProcessorSettings &settings)
 
static float GetMakeupGainDb (const DynamicRangeProcessorSettings &settings)
 
static float EvaluateTransferFunction (const DynamicRangeProcessorSettings &settings, float inputDb)
 

Private Member Functions

void UpdateEnvelope (const float *const *inBlock, int blockLen)
 
void CopyWithDelay (const float *const *inBlock, int blockLen)
 
void ApplyEnvelope (float *const *outBlock, int blockLen, float &delayedInputMax, int &delayedInputMaxIndex)
 
bool Initialized () const
 

Private Attributes

const std::unique_ptr< DanielRudrich::GainReductionComputermGainReductionComputer
 
const std::unique_ptr< DanielRudrich::LookAheadGainReductionmLookAheadGainReduction
 
DynamicRangeProcessorSettings mSettings
 
int mSampleRate = 0
 
int mNumChannels = 0
 
int mBlockSize = 0
 
std::array< float, maxBlockSizemEnvelope
 
std::vector< std::vector< float > > mDelayedInput
 
FrameStats mLastFrameStats
 

Static Private Attributes

static constexpr auto maxBlockSize = 512
 

Detailed Description

Definition at line 25 of file CompressorProcessor.h.

Constructor & Destructor Documentation

◆ CompressorProcessor() [1/2]

CompressorProcessor::CompressorProcessor ( const DynamicRangeProcessorSettings settings = {   CompressorSettings {} })

Definition at line 42 of file CompressorProcessor.cpp.

44 : mGainReductionComputer { std::make_unique<
46 , mLookAheadGainReduction { std::make_unique<
49{
50}
static Settings & settings()
Definition: TrackInfo.cpp:51
DynamicRangeProcessorSettings mSettings
const std::unique_ptr< DanielRudrich::GainReductionComputer > mGainReductionComputer
const std::unique_ptr< DanielRudrich::LookAheadGainReduction > mLookAheadGainReduction

◆ CompressorProcessor() [2/2]

CompressorProcessor::CompressorProcessor ( const CompressorProcessor other)
delete

◆ ~CompressorProcessor()

CompressorProcessor::~CompressorProcessor ( )
default

Member Function Documentation

◆ ApplyEnvelope()

void CompressorProcessor::ApplyEnvelope ( float *const *  outBlock,
int  blockLen,
float &  delayedInputMax,
int &  delayedInputMaxIndex 
)
private

Definition at line 181 of file CompressorProcessor.cpp.

184{
185 const auto makeupGainDb = mGainReductionComputer->getMakeUpGain();
186 const auto d = mLookAheadGainReduction->getDelayInSamples();
187 std::array<float, 2> chanAbsMax { 0.f, 0.f };
188 std::array<int, 2> chanAbsMaxIndex { 0, 0 };
189 for (auto i = 0; i < mNumChannels; ++i)
190 {
191 const auto in = mDelayedInput[i].data();
192 for (auto j = 0; j < blockLen; ++j)
193 {
194 if (std::abs(in[j]) > chanAbsMax[i])
195 {
196 chanAbsMax[i] = std::abs(in[j]);
197 chanAbsMaxIndex[i] = j;
198 }
199 out[i][j] =
200 in[j] * std::pow(10.f, 0.05f * (mEnvelope[j] + makeupGainDb));
201 }
202 std::move(in + blockLen, in + blockLen + d, in);
203 }
204 const auto i = chanAbsMax[0] > chanAbsMax[1] ? 0 : 1;
205 delayedInputAbsMax = chanAbsMax[i];
206 delayedInputAbsMaxIndex = chanAbsMaxIndex[i];
207}
std::array< float, maxBlockSize > mEnvelope
std::vector< std::vector< float > > mDelayedInput

References mDelayedInput, mEnvelope, mGainReductionComputer, mLookAheadGainReduction, and mNumChannels.

Referenced by Process().

Here is the caller graph for this function:

◆ ApplySettingsIfNeeded()

void CompressorProcessor::ApplySettingsIfNeeded ( const DynamicRangeProcessorSettings settings)

Definition at line 54 of file CompressorProcessor.cpp.

56{
57 if (settings == mSettings)
58 return;
59
60 const auto lookaheadNeedsReinit =
61 settings.lookaheadMs != mSettings.lookaheadMs;
63
64 mGainReductionComputer->setThreshold(settings.inCompressionThreshDb);
65 mGainReductionComputer->setKnee(settings.kneeWidthDb);
66 mGainReductionComputer->setAttackTime(settings.attackMs / 1000);
67 mGainReductionComputer->setReleaseTime(settings.releaseMs / 1000);
68 mGainReductionComputer->setRatio(settings.compressionRatio);
70
71 if (lookaheadNeedsReinit)
72 {
73 mLookAheadGainReduction->setDelayTime(settings.lookaheadMs / 1000);
74 Reinit();
75 }
76}
static float GetMakeupGainDb(const DynamicRangeProcessorSettings &settings)

References GetMakeupGainDb(), DynamicRangeProcessorSettings::lookaheadMs, mGainReductionComputer, mLookAheadGainReduction, mSettings, Reinit(), and settings().

Referenced by CompressorInstance::InstanceProcess().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ CopyWithDelay()

void CompressorProcessor::CopyWithDelay ( const float *const *  inBlock,
int  blockLen 
)
private

Definition at line 174 of file CompressorProcessor.cpp.

175{
176 const auto d = mLookAheadGainReduction->getDelayInSamples();
177 for (auto i = 0; i < mNumChannels; ++i)
178 std::copy(in[i], in[i] + blockLen, mDelayedInput[i].data() + d);
179}
void copy(const T *src, T *dst, int32_t n)
Definition: VectorOps.h:40

References staffpad::vo::copy(), mDelayedInput, mLookAheadGainReduction, and mNumChannels.

Referenced by Process().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ EvaluateTransferFunction() [1/2]

float CompressorProcessor::EvaluateTransferFunction ( const DynamicRangeProcessorSettings settings,
float  inputDb 
)
static

Definition at line 34 of file CompressorProcessor.cpp.

36{
38 inputDb, settings.kneeWidthDb, settings.inCompressionThreshDb,
39 settings.compressionRatio, GetMakeupGainDb(settings));
40}
static float getCharacteristicSample(float inputLevelInDecibels, float kneeInDecibels, float thresholdInDecibels, float ratio, float makeUpGainInDecibels)

References DanielRudrich::GainReductionComputer::getCharacteristicSample(), GetMakeupGainDb(), and settings().

Referenced by anonymous_namespace{DynamicRangeProcessorTransferFunctionPanel.cpp}::DrawTransferFunction(), and GetMaxCompressionDb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ EvaluateTransferFunction() [2/2]

float CompressorProcessor::EvaluateTransferFunction ( float  inputDb) const

Definition at line 142 of file CompressorProcessor.cpp.

143{
144 return mGainReductionComputer->getCharacteristicSample(inputDb);
145}

References mGainReductionComputer.

◆ GetDelayedInput()

const std::vector< std::vector< float > > & CompressorProcessor::GetDelayedInput ( ) const

Definition at line 131 of file CompressorProcessor.cpp.

132{
133 return mDelayedInput;
134}

References mDelayedInput.

◆ GetLastFrameStats()

const CompressorProcessor::FrameStats & CompressorProcessor::GetLastFrameStats ( ) const

Definition at line 137 of file CompressorProcessor.cpp.

138{
139 return mLastFrameStats;
140}

References mLastFrameStats.

◆ GetMakeupGainDb()

float CompressorProcessor::GetMakeupGainDb ( const DynamicRangeProcessorSettings settings)
static

Audacity: A Digital Audio Editor

CompressorProcessor.cpp

Matthieu Hodgkinson

Definition at line 19 of file CompressorProcessor.cpp.

21{
22 return settings.outCompressionThreshDb - settings.inCompressionThreshDb;
23}

References settings().

Referenced by ApplySettingsIfNeeded(), EvaluateTransferFunction(), and anonymous_namespace{CompressorInstance.cpp}::GetOutputDb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetMaxCompressionDb()

float CompressorProcessor::GetMaxCompressionDb ( const DynamicRangeProcessorSettings settings)
static

Definition at line 25 of file CompressorProcessor.cpp.

27{
28 const auto tfEval = EvaluateTransferFunction(settings, 0);
29 const auto netGain =
30 settings.outCompressionThreshDb - settings.inCompressionThreshDb;
31 return netGain - tfEval;
32}
static float EvaluateTransferFunction(const DynamicRangeProcessorSettings &settings, float inputDb)

References EvaluateTransferFunction(), and settings().

Referenced by DynamicRangeProcessorEditor::PopulateOrExchange(), and TEST_CASE().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetSettings()

const DynamicRangeProcessorSettings & CompressorProcessor::GetSettings ( ) const

Definition at line 86 of file CompressorProcessor.cpp.

87{
88 return mSettings;
89}

References mSettings.

◆ Init()

void CompressorProcessor::Init ( int  sampleRate,
int  numChannels,
int  blockSize 
)

Definition at line 78 of file CompressorProcessor.cpp.

79{
81 mNumChannels = numChannels;
82 mBlockSize = std::min(blockSize, maxBlockSize);
83 Reinit();
84}
int min(int a, int b)
static constexpr auto maxBlockSize

References maxBlockSize, mBlockSize, min(), mNumChannels, mSampleRate, Reinit(), and anonymous_namespace{ClipSegmentTest.cpp}::sampleRate.

Here is the call graph for this function:

◆ Initialized()

bool CompressorProcessor::Initialized ( ) const
private

Definition at line 232 of file CompressorProcessor.cpp.

233{
234 return mSampleRate != 0 && mNumChannels != 0 && mBlockSize != 0;
235}

References mBlockSize, mNumChannels, and mSampleRate.

Referenced by Process(), and Reinit().

Here is the caller graph for this function:

◆ Process()

void CompressorProcessor::Process ( const float *const *  inBlock,
float *const *  outBlock,
int  blockLen 
)

Definition at line 91 of file CompressorProcessor.cpp.

93{
94 assert(Initialized());
95 if (!Initialized())
96 return;
97
98 auto processed = 0;
99 mLastFrameStats = {};
100 std::vector<const float*> in(mNumChannels);
101 std::vector<float*> out(mNumChannels);
102 while (processed < blockLen)
103 {
104 for (auto i = 0; i < mNumChannels; ++i)
105 {
106 in[i] = inBlock[i] + processed;
107 out[i] = outBlock[i] + processed;
108 }
109 const auto toProcess = std::min(blockLen - processed, mBlockSize);
110 UpdateEnvelope(in.data(), toProcess);
111 CopyWithDelay(in.data(), toProcess);
112
113 float delayedInputAbsMax = 0;
114 int delayedInputAbsMaxIndex = 0;
116 out.data(), toProcess, delayedInputAbsMax, delayedInputAbsMaxIndex);
117
118 const auto blockMaxDb = log2ToDb * FastLog2(delayedInputAbsMax);
119 if (mLastFrameStats.maxInputSampleDb < blockMaxDb)
120 {
123 mEnvelope[delayedInputAbsMaxIndex];
124 }
125
126 processed += toProcess;
127 }
128}
constexpr float FastLog2(float x)
Approximates the base-2 logarithm of a float to two decimal places, adapted from https://stackoverflo...
Definition: MathApprox.h:32
static constexpr float log2ToDb
Definition: MathApprox.h:46
void ApplyEnvelope(float *const *outBlock, int blockLen, float &delayedInputMax, int &delayedInputMaxIndex)
void CopyWithDelay(const float *const *inBlock, int blockLen)
void UpdateEnvelope(const float *const *inBlock, int blockLen)

References ApplyEnvelope(), CopyWithDelay(), CompressorProcessor::FrameStats::dbGainOfMaxInputSample, FastLog2(), Initialized(), log2ToDb, CompressorProcessor::FrameStats::maxInputSampleDb, mBlockSize, mEnvelope, min(), mLastFrameStats, mNumChannels, and UpdateEnvelope().

Referenced by CompressorInstance::InstanceProcess().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Reinit()

void CompressorProcessor::Reinit ( )

Definition at line 209 of file CompressorProcessor.cpp.

210{
211 if (!Initialized())
212 // Not there yet.
213 return;
215 // In this order: setDelayTime, then prepare:
216 mLookAheadGainReduction->setDelayTime(mSettings.lookaheadMs / 1000);
218 const auto maxDelay =
220 1000;
221 const auto d = mLookAheadGainReduction->getDelayInSamples();
222 assert(d <= maxDelay);
224 std::for_each(mDelayedInput.begin(), mDelayedInput.end(), [&](auto& v) {
225 v.reserve(maxDelay + mBlockSize);
226 v.resize(d + mBlockSize);
227 std::fill(v.begin(), v.end(), 0.f);
228 });
229 std::fill(mEnvelope.begin(), mEnvelope.end(), 0.f);
230}
constexpr double compressorMaxLookaheadMs
constexpr double limiterMaxLookaheadMs

References compressorMaxLookaheadMs, Initialized(), limiterMaxLookaheadMs, DynamicRangeProcessorSettings::lookaheadMs, mBlockSize, mDelayedInput, mEnvelope, mGainReductionComputer, mLookAheadGainReduction, mNumChannels, mSampleRate, and mSettings.

Referenced by ApplySettingsIfNeeded(), and Init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ UpdateEnvelope()

void CompressorProcessor::UpdateEnvelope ( const float *const *  inBlock,
int  blockLen 
)
private

Definition at line 147 of file CompressorProcessor.cpp.

148{
149 // Fill mEnvelope with max of all in channels;
150 for (auto i = 0; i < blockLen; ++i)
151 {
152 auto max = 0.f;
153 for (auto j = 0; j < mNumChannels; ++j)
154 {
155 const auto x = std::abs(in[j][i]);
156 if (x > max)
157 max = x;
158 }
159 mEnvelope[i] = max;
160 }
161
162 // TODO: uses std::log10 ; use log2 optimization instead.
163 mGainReductionComputer->computeGainInDecibelsFromSidechainSignal(
164 mEnvelope.data(), mEnvelope.data(), blockLen);
165
166 if (mSettings.lookaheadMs <= 0)
167 return;
168
169 mLookAheadGainReduction->pushSamples(mEnvelope.data(), blockLen);
170 mLookAheadGainReduction->process();
171 mLookAheadGainReduction->readSamples(mEnvelope.data(), blockLen);
172}

References DynamicRangeProcessorSettings::lookaheadMs, mEnvelope, mGainReductionComputer, mLookAheadGainReduction, mNumChannels, and mSettings.

Referenced by Process().

Here is the caller graph for this function:

Member Data Documentation

◆ maxBlockSize

constexpr auto CompressorProcessor::maxBlockSize = 512
staticconstexprprivate

Definition at line 66 of file CompressorProcessor.h.

Referenced by Init().

◆ mBlockSize

int CompressorProcessor::mBlockSize = 0
private

Definition at line 75 of file CompressorProcessor.h.

Referenced by Init(), Initialized(), Process(), and Reinit().

◆ mDelayedInput

std::vector<std::vector<float> > CompressorProcessor::mDelayedInput
private

Definition at line 78 of file CompressorProcessor.h.

Referenced by ApplyEnvelope(), CopyWithDelay(), GetDelayedInput(), and Reinit().

◆ mEnvelope

std::array<float, maxBlockSize> CompressorProcessor::mEnvelope
private

Definition at line 76 of file CompressorProcessor.h.

Referenced by ApplyEnvelope(), Process(), Reinit(), and UpdateEnvelope().

◆ mGainReductionComputer

const std::unique_ptr<DanielRudrich::GainReductionComputer> CompressorProcessor::mGainReductionComputer
private

◆ mLastFrameStats

FrameStats CompressorProcessor::mLastFrameStats
private

Definition at line 83 of file CompressorProcessor.h.

Referenced by GetLastFrameStats(), and Process().

◆ mLookAheadGainReduction

const std::unique_ptr<DanielRudrich::LookAheadGainReduction> CompressorProcessor::mLookAheadGainReduction
private

◆ mNumChannels

int CompressorProcessor::mNumChannels = 0
private

◆ mSampleRate

int CompressorProcessor::mSampleRate = 0
private

Definition at line 73 of file CompressorProcessor.h.

Referenced by Init(), Initialized(), and Reinit().

◆ mSettings

DynamicRangeProcessorSettings CompressorProcessor::mSettings
private

Definition at line 72 of file CompressorProcessor.h.

Referenced by ApplySettingsIfNeeded(), GetSettings(), Reinit(), and UpdateEnvelope().


The documentation for this class was generated from the following files: