mirror of
https://github.com/cookiengineer/audacity
synced 2025-04-29 15:19:44 +02:00
Add realtime support to Compressor2 effect.
Signed-off-by: Max Maisel <max.maisel@posteo.de>
This commit is contained in:
parent
2a6c2aaf80
commit
aa619de49c
@ -133,6 +133,12 @@ void SlidingRmsPreprocessor::Reset()
|
|||||||
std::fill(mWindow.begin(), mWindow.end(), 0);
|
std::fill(mWindow.begin(), mWindow.end(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SlidingRmsPreprocessor::SetWindowSize(size_t windowSize)
|
||||||
|
{
|
||||||
|
mWindow.resize(windowSize);
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
float SlidingRmsPreprocessor::DoProcessSample(float value)
|
float SlidingRmsPreprocessor::DoProcessSample(float value)
|
||||||
{
|
{
|
||||||
if(mInsertCount > REFRESH_WINDOW_EVERY)
|
if(mInsertCount > REFRESH_WINDOW_EVERY)
|
||||||
@ -198,6 +204,13 @@ void SlidingMaxPreprocessor::Reset()
|
|||||||
std::fill(mMaxes.begin(), mMaxes.end(), 0);
|
std::fill(mMaxes.begin(), mMaxes.end(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SlidingMaxPreprocessor::SetWindowSize(size_t windowSize)
|
||||||
|
{
|
||||||
|
mWindow.resize(windowSize);
|
||||||
|
mMaxes.resize(windowSize);
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
float SlidingMaxPreprocessor::DoProcessSample(float value)
|
float SlidingMaxPreprocessor::DoProcessSample(float value)
|
||||||
{
|
{
|
||||||
size_t oldHead = (mPos-1) % mWindow.size();
|
size_t oldHead = (mPos-1) % mWindow.size();
|
||||||
@ -272,8 +285,14 @@ ExpFitEnvelopeDetector::ExpFitEnvelopeDetector(
|
|||||||
float rate, float attackTime, float releaseTime, size_t bufferSize)
|
float rate, float attackTime, float releaseTime, size_t bufferSize)
|
||||||
: EnvelopeDetector(bufferSize)
|
: EnvelopeDetector(bufferSize)
|
||||||
{
|
{
|
||||||
mAttackFactor = exp(-1.0 / (rate * attackTime));
|
SetParams(rate, attackTime, releaseTime);
|
||||||
mReleaseFactor = exp(-1.0 / (rate * releaseTime));
|
}
|
||||||
|
|
||||||
|
void ExpFitEnvelopeDetector::SetParams(
|
||||||
|
float sampleRate, float attackTime, float releaseTime)
|
||||||
|
{
|
||||||
|
mAttackFactor = exp(-1.0 / (sampleRate * attackTime));
|
||||||
|
mReleaseFactor = exp(-1.0 / (sampleRate * releaseTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExpFitEnvelopeDetector::Follow()
|
void ExpFitEnvelopeDetector::Follow()
|
||||||
@ -361,17 +380,24 @@ void ExpFitEnvelopeDetector::Follow()
|
|||||||
Pt1EnvelopeDetector::Pt1EnvelopeDetector(
|
Pt1EnvelopeDetector::Pt1EnvelopeDetector(
|
||||||
float rate, float attackTime, float releaseTime, size_t bufferSize,
|
float rate, float attackTime, float releaseTime, size_t bufferSize,
|
||||||
bool correctGain)
|
bool correctGain)
|
||||||
: EnvelopeDetector(bufferSize)
|
: EnvelopeDetector(bufferSize),
|
||||||
|
mCorrectGain(correctGain)
|
||||||
|
{
|
||||||
|
SetParams(rate, attackTime, releaseTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pt1EnvelopeDetector::SetParams(
|
||||||
|
float sampleRate, float attackTime, float releaseTime)
|
||||||
{
|
{
|
||||||
// Approximate peak amplitude correction factor.
|
// Approximate peak amplitude correction factor.
|
||||||
if(correctGain)
|
if(mCorrectGain)
|
||||||
mGainCorrection = 1.0 + exp(attackTime / 30.0);
|
mGainCorrection = 1.0 + exp(attackTime / 30.0);
|
||||||
else
|
else
|
||||||
mGainCorrection = 1.0;
|
mGainCorrection = 1.0;
|
||||||
|
|
||||||
mAttackFactor = 1.0 / (attackTime * rate);
|
mAttackFactor = 1.0 / (attackTime * sampleRate);
|
||||||
mReleaseFactor = 1.0 / (releaseTime * rate);
|
mReleaseFactor = 1.0 / (releaseTime * sampleRate);
|
||||||
mInitialBlockSize = std::min(size_t(rate * sqrt(attackTime)), bufferSize);
|
mInitialBlockSize = std::min(size_t(sampleRate * sqrt(attackTime)), mLookaheadBuffer.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pt1EnvelopeDetector::CalcInitialCondition(float value)
|
void Pt1EnvelopeDetector::CalcInitialCondition(float value)
|
||||||
@ -461,7 +487,11 @@ void PipelineBuffer::free()
|
|||||||
}
|
}
|
||||||
|
|
||||||
EffectCompressor2::EffectCompressor2()
|
EffectCompressor2::EffectCompressor2()
|
||||||
: mIgnoreGuiEvents(false)
|
: mIgnoreGuiEvents(false),
|
||||||
|
mAlgorithmCtrl(0),
|
||||||
|
mPreprocCtrl(0),
|
||||||
|
mAttackTimeCtrl(0),
|
||||||
|
mLookaheadTimeCtrl(0)
|
||||||
{
|
{
|
||||||
mAlgorithm = DEF_Algorithm;
|
mAlgorithm = DEF_Algorithm;
|
||||||
mCompressBy = DEF_CompressBy;
|
mCompressBy = DEF_CompressBy;
|
||||||
@ -508,6 +538,84 @@ EffectType EffectCompressor2::GetType()
|
|||||||
return EffectTypeProcess;
|
return EffectTypeProcess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EffectCompressor2::SupportsRealtime()
|
||||||
|
{
|
||||||
|
#if defined(EXPERIMENTAL_REALTIME_AUDACITY_EFFECTS)
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned EffectCompressor2::GetAudioInCount()
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned EffectCompressor2::GetAudioOutCount()
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EffectCompressor2::RealtimeInitialize()
|
||||||
|
{
|
||||||
|
SetBlockSize(512);
|
||||||
|
AllocRealtimePipeline();
|
||||||
|
mAlgorithmCtrl->Enable(false);
|
||||||
|
mPreprocCtrl->Enable(false);
|
||||||
|
mLookaheadTimeCtrl->Enable(false);
|
||||||
|
if(mAlgorithm == kExpFit)
|
||||||
|
mAttackTimeCtrl->Enable(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EffectCompressor2::RealtimeAddProcessor(
|
||||||
|
unsigned WXUNUSED(numChannels), float sampleRate)
|
||||||
|
{
|
||||||
|
mSampleRate = sampleRate;
|
||||||
|
mProcStereo = true;
|
||||||
|
mPreproc = InitPreprocessor(mSampleRate);
|
||||||
|
mEnvelope = InitEnvelope(mSampleRate, mPipeline[0].size);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EffectCompressor2::RealtimeFinalize()
|
||||||
|
{
|
||||||
|
mPreproc.reset(nullptr);
|
||||||
|
mEnvelope.reset(nullptr);
|
||||||
|
FreePipeline();
|
||||||
|
mAlgorithmCtrl->Enable(true);
|
||||||
|
mPreprocCtrl->Enable(true);
|
||||||
|
mLookaheadTimeCtrl->Enable(true);
|
||||||
|
if(mAlgorithm == kExpFit)
|
||||||
|
mAttackTimeCtrl->Enable(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t EffectCompressor2::RealtimeProcess(
|
||||||
|
int group, float **inbuf, float **outbuf, size_t numSamples)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(mRealtimeMutex);
|
||||||
|
const size_t j = PIPELINE_DEPTH-1;
|
||||||
|
for(size_t i = 0; i < numSamples; ++i)
|
||||||
|
{
|
||||||
|
if(mPipeline[j].trackSize == mPipeline[j].size)
|
||||||
|
{
|
||||||
|
ProcessPipeline();
|
||||||
|
mPipeline[j].trackSize = 0;
|
||||||
|
SwapPipeline();
|
||||||
|
}
|
||||||
|
|
||||||
|
outbuf[0][i] = mPipeline[j][0][mPipeline[j].trackSize];
|
||||||
|
outbuf[1][i] = mPipeline[j][1][mPipeline[j].trackSize];
|
||||||
|
mPipeline[j][0][mPipeline[j].trackSize] = inbuf[0][i];
|
||||||
|
mPipeline[j][1][mPipeline[j].trackSize] = inbuf[1][i];
|
||||||
|
++mPipeline[j].trackSize;
|
||||||
|
}
|
||||||
|
return numSamples;
|
||||||
|
}
|
||||||
|
|
||||||
// EffectClientInterface implementation
|
// EffectClientInterface implementation
|
||||||
bool EffectCompressor2::DefineParams( ShuttleParams & S )
|
bool EffectCompressor2::DefineParams( ShuttleParams & S )
|
||||||
{
|
{
|
||||||
@ -714,24 +822,22 @@ void EffectCompressor2::PopulateOrExchange(ShuttleGui & S)
|
|||||||
{
|
{
|
||||||
S.SetStretchyCol(1);
|
S.SetStretchyCol(1);
|
||||||
|
|
||||||
wxChoice* ctrl = nullptr;
|
mAlgorithmCtrl = S.Validator<wxGenericValidator>(&mAlgorithm)
|
||||||
|
|
||||||
ctrl = S.Validator<wxGenericValidator>(&mAlgorithm)
|
|
||||||
.AddChoice(XO("Envelope Algorithm:"),
|
.AddChoice(XO("Envelope Algorithm:"),
|
||||||
Msgids(kAlgorithmStrings, nAlgos),
|
Msgids(kAlgorithmStrings, nAlgos),
|
||||||
mAlgorithm);
|
mAlgorithm);
|
||||||
|
|
||||||
wxSize box_size = ctrl->GetMinSize();
|
wxSize box_size = mAlgorithmCtrl->GetMinSize();
|
||||||
int width = S.GetParent()->GetTextExtent(wxString::Format(
|
int width = S.GetParent()->GetTextExtent(wxString::Format(
|
||||||
"%sxxxx", kAlgorithmStrings[nAlgos-1].Translation())).GetWidth();
|
"%sxxxx", kAlgorithmStrings[nAlgos-1].Translation())).GetWidth();
|
||||||
box_size.SetWidth(width);
|
box_size.SetWidth(width);
|
||||||
ctrl->SetMinSize(box_size);
|
mAlgorithmCtrl->SetMinSize(box_size);
|
||||||
|
|
||||||
ctrl = S.Validator<wxGenericValidator>(&mCompressBy)
|
mPreprocCtrl = S.Validator<wxGenericValidator>(&mCompressBy)
|
||||||
.AddChoice(XO("Compress based on:"),
|
.AddChoice(XO("Compress based on:"),
|
||||||
Msgids(kCompressByStrings, nBy),
|
Msgids(kCompressByStrings, nBy),
|
||||||
mCompressBy);
|
mCompressBy);
|
||||||
ctrl->SetMinSize(box_size);
|
mPreprocCtrl->SetMinSize(box_size);
|
||||||
|
|
||||||
S.Validator<wxGenericValidator>(&mStereoInd)
|
S.Validator<wxGenericValidator>(&mStereoInd)
|
||||||
.AddCheckBox(XO("Compress stereo channels independently"),
|
.AddCheckBox(XO("Compress stereo channels independently"),
|
||||||
@ -784,12 +890,12 @@ void EffectCompressor2::PopulateOrExchange(ShuttleGui & S)
|
|||||||
|
|
||||||
S.AddVariableText(XO("Attack Time:"), true,
|
S.AddVariableText(XO("Attack Time:"), true,
|
||||||
wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
|
wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
|
||||||
ctrl = S.Name(XO("Attack Time"))
|
mAttackTimeCtrl = S.Name(XO("Attack Time"))
|
||||||
.Style(SliderTextCtrl::HORIZONTAL | SliderTextCtrl::LOG)
|
.Style(SliderTextCtrl::HORIZONTAL | SliderTextCtrl::LOG)
|
||||||
.AddSliderTextCtrl({}, DEF_AttackTime, MAX_AttackTime,
|
.AddSliderTextCtrl({}, DEF_AttackTime, MAX_AttackTime,
|
||||||
MIN_AttackTime, ScaleToPrecision(SCL_AttackTime),
|
MIN_AttackTime, ScaleToPrecision(SCL_AttackTime),
|
||||||
&mAttackTime, SCL_AttackTime / 1000);
|
&mAttackTime, SCL_AttackTime / 1000);
|
||||||
ctrl->SetMinTextboxWidth(textbox_width);
|
mAttackTimeCtrl->SetMinTextboxWidth(textbox_width);
|
||||||
S.AddVariableText(XO("s"), true,
|
S.AddVariableText(XO("s"), true,
|
||||||
wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
|
wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
|
||||||
|
|
||||||
@ -806,12 +912,12 @@ void EffectCompressor2::PopulateOrExchange(ShuttleGui & S)
|
|||||||
|
|
||||||
S.AddVariableText(XO("Lookahead Time:"), true,
|
S.AddVariableText(XO("Lookahead Time:"), true,
|
||||||
wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
|
wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
|
||||||
ctrl = S.Name(XO("Lookahead Time"))
|
mLookaheadTimeCtrl = S.Name(XO("Lookahead Time"))
|
||||||
.Style(SliderTextCtrl::HORIZONTAL | SliderTextCtrl::LOG)
|
.Style(SliderTextCtrl::HORIZONTAL | SliderTextCtrl::LOG)
|
||||||
.AddSliderTextCtrl({}, DEF_LookaheadTime, MAX_LookaheadTime,
|
.AddSliderTextCtrl({}, DEF_LookaheadTime, MAX_LookaheadTime,
|
||||||
MIN_LookaheadTime, ScaleToPrecision(SCL_LookaheadTime),
|
MIN_LookaheadTime, ScaleToPrecision(SCL_LookaheadTime),
|
||||||
&mLookaheadTime);
|
&mLookaheadTime);
|
||||||
ctrl->SetMinTextboxWidth(textbox_width);
|
mLookaheadTimeCtrl->SetMinTextboxWidth(textbox_width);
|
||||||
S.AddVariableText(XO("s"), true,
|
S.AddVariableText(XO("s"), true,
|
||||||
wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
|
wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
|
||||||
|
|
||||||
@ -988,6 +1094,24 @@ void EffectCompressor2::AllocPipeline()
|
|||||||
mPipeline[i].init(capacity, stereoTrackFound);
|
mPipeline[i].init(capacity, stereoTrackFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EffectCompressor2::AllocRealtimePipeline()
|
||||||
|
{
|
||||||
|
mLookaheadLength =
|
||||||
|
std::max(0, int(round(mLookaheadTime * mSampleRate)));
|
||||||
|
|
||||||
|
size_t blockSize = std::max(mLookaheadLength, size_t(512));
|
||||||
|
if(mAlgorithm == kExpFit)
|
||||||
|
{
|
||||||
|
size_t riseTime = round(5.0 * (0.1 + mAttackTime)) * mSampleRate;
|
||||||
|
blockSize = std::max(blockSize, riseTime);
|
||||||
|
}
|
||||||
|
for(size_t i = 0; i < PIPELINE_DEPTH; ++i)
|
||||||
|
{
|
||||||
|
mPipeline[i].init(blockSize, true);
|
||||||
|
mPipeline[i].size = blockSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EffectCompressor2::FreePipeline()
|
void EffectCompressor2::FreePipeline()
|
||||||
{
|
{
|
||||||
for(size_t i = 0; i < PIPELINE_DEPTH; ++i)
|
for(size_t i = 0; i < PIPELINE_DEPTH; ++i)
|
||||||
@ -1379,6 +1503,8 @@ void EffectCompressor2::UpdateUI()
|
|||||||
{
|
{
|
||||||
UpdateCompressorPlot();
|
UpdateCompressorPlot();
|
||||||
UpdateResponsePlot();
|
UpdateResponsePlot();
|
||||||
|
if(mEnvelope.get() != nullptr)
|
||||||
|
UpdateRealtimeParams();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectCompressor2::UpdateCompressorPlot()
|
void EffectCompressor2::UpdateCompressorPlot()
|
||||||
@ -1432,3 +1558,15 @@ void EffectCompressor2::UpdateResponsePlot()
|
|||||||
|
|
||||||
mResponsePlot->Refresh(false);
|
mResponsePlot->Refresh(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EffectCompressor2::UpdateRealtimeParams()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(mRealtimeMutex);
|
||||||
|
// TODO: extract it
|
||||||
|
size_t window_size =
|
||||||
|
std::max(1, int(round((mLookaheadTime + mLookbehindTime) * mSampleRate)));
|
||||||
|
mLookaheadLength = // TODO: depup this everywhere
|
||||||
|
std::max(0, int(round(mLookaheadTime * mSampleRate)));
|
||||||
|
mPreproc->SetWindowSize(window_size);
|
||||||
|
mEnvelope->SetParams(mSampleRate, mAttackTime, mReleaseTime);
|
||||||
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
class Plot;
|
class Plot;
|
||||||
class ShuttleGui;
|
class ShuttleGui;
|
||||||
|
class SliderTextCtrl;
|
||||||
|
|
||||||
class SamplePreprocessor
|
class SamplePreprocessor
|
||||||
{
|
{
|
||||||
@ -29,6 +30,7 @@ class SamplePreprocessor
|
|||||||
virtual float ProcessSample(float value) = 0;
|
virtual float ProcessSample(float value) = 0;
|
||||||
virtual float ProcessSample(float valueL, float valueR) = 0;
|
virtual float ProcessSample(float valueL, float valueR) = 0;
|
||||||
virtual void Reset() = 0;
|
virtual void Reset() = 0;
|
||||||
|
virtual void SetWindowSize(size_t windowSize) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SlidingRmsPreprocessor : public SamplePreprocessor
|
class SlidingRmsPreprocessor : public SamplePreprocessor
|
||||||
@ -39,6 +41,7 @@ class SlidingRmsPreprocessor : public SamplePreprocessor
|
|||||||
virtual float ProcessSample(float value);
|
virtual float ProcessSample(float value);
|
||||||
virtual float ProcessSample(float valueL, float valueR);
|
virtual float ProcessSample(float valueL, float valueR);
|
||||||
virtual void Reset();
|
virtual void Reset();
|
||||||
|
virtual void SetWindowSize(size_t windowSize);
|
||||||
|
|
||||||
static const size_t REFRESH_WINDOW_EVERY = 1048576; // 1 MB
|
static const size_t REFRESH_WINDOW_EVERY = 1048576; // 1 MB
|
||||||
|
|
||||||
@ -61,6 +64,7 @@ class SlidingMaxPreprocessor : public SamplePreprocessor
|
|||||||
virtual float ProcessSample(float value);
|
virtual float ProcessSample(float value);
|
||||||
virtual float ProcessSample(float valueL, float valueR);
|
virtual float ProcessSample(float valueL, float valueR);
|
||||||
virtual void Reset();
|
virtual void Reset();
|
||||||
|
virtual void SetWindowSize(size_t windowSize);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<float> mWindow;
|
std::vector<float> mWindow;
|
||||||
@ -82,6 +86,10 @@ class EnvelopeDetector
|
|||||||
virtual void CalcInitialCondition(float value);
|
virtual void CalcInitialCondition(float value);
|
||||||
inline float InitialCondition() const { return mInitialCondition; }
|
inline float InitialCondition() const { return mInitialCondition; }
|
||||||
inline size_t InitialConditionSize() const { return mInitialBlockSize; }
|
inline size_t InitialConditionSize() const { return mInitialBlockSize; }
|
||||||
|
|
||||||
|
virtual void SetParams(float sampleRate, float attackTime,
|
||||||
|
float releaseTime) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
size_t mPos;
|
size_t mPos;
|
||||||
float mInitialCondition;
|
float mInitialCondition;
|
||||||
@ -97,7 +105,10 @@ class ExpFitEnvelopeDetector : public EnvelopeDetector
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ExpFitEnvelopeDetector(float rate, float attackTime, float releaseTime,
|
ExpFitEnvelopeDetector(float rate, float attackTime, float releaseTime,
|
||||||
size_t buffer_size = 0);
|
size_t buffer_size);
|
||||||
|
|
||||||
|
virtual void SetParams(float sampleRate, float attackTime,
|
||||||
|
float releaseTime);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double mAttackFactor;
|
double mAttackFactor;
|
||||||
@ -110,10 +121,14 @@ class Pt1EnvelopeDetector : public EnvelopeDetector
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Pt1EnvelopeDetector(float rate, float attackTime, float releaseTime,
|
Pt1EnvelopeDetector(float rate, float attackTime, float releaseTime,
|
||||||
size_t buffer_size = 0, bool correctGain = true);
|
size_t buffer_size, bool correctGain = true);
|
||||||
virtual void CalcInitialCondition(float value);
|
virtual void CalcInitialCondition(float value);
|
||||||
|
|
||||||
|
virtual void SetParams(float sampleRate, float attackTime,
|
||||||
|
float releaseTime);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool mCorrectGain;
|
||||||
double mGainCorrection;
|
double mGainCorrection;
|
||||||
double mAttackFactor;
|
double mAttackFactor;
|
||||||
double mReleaseFactor;
|
double mReleaseFactor;
|
||||||
@ -160,9 +175,17 @@ public:
|
|||||||
// EffectDefinitionInterface implementation
|
// EffectDefinitionInterface implementation
|
||||||
|
|
||||||
EffectType GetType() override;
|
EffectType GetType() override;
|
||||||
|
bool SupportsRealtime() override;
|
||||||
|
|
||||||
// EffectClientInterface implementation
|
// EffectClientInterface implementation
|
||||||
|
|
||||||
|
unsigned GetAudioInCount() override;
|
||||||
|
unsigned GetAudioOutCount() override;
|
||||||
|
bool RealtimeInitialize() override;
|
||||||
|
bool RealtimeAddProcessor(unsigned numChannels, float sampleRate) override;
|
||||||
|
bool RealtimeFinalize() override;
|
||||||
|
size_t RealtimeProcess(int group, float **inbuf, float **outbuf,
|
||||||
|
size_t numSamples) override;
|
||||||
bool DefineParams( ShuttleParams & S ) override;
|
bool DefineParams( ShuttleParams & S ) override;
|
||||||
bool GetAutomationParameters(CommandParameters & parms) override;
|
bool GetAutomationParameters(CommandParameters & parms) override;
|
||||||
bool SetAutomationParameters(CommandParameters & parms) override;
|
bool SetAutomationParameters(CommandParameters & parms) override;
|
||||||
@ -187,6 +210,7 @@ private:
|
|||||||
size_t CalcBufferSize(size_t sampleRate);
|
size_t CalcBufferSize(size_t sampleRate);
|
||||||
|
|
||||||
void AllocPipeline();
|
void AllocPipeline();
|
||||||
|
void AllocRealtimePipeline();
|
||||||
void FreePipeline();
|
void FreePipeline();
|
||||||
void SwapPipeline();
|
void SwapPipeline();
|
||||||
bool ProcessOne(TrackIterRange<WaveTrack> range);
|
bool ProcessOne(TrackIterRange<WaveTrack> range);
|
||||||
@ -205,6 +229,7 @@ private:
|
|||||||
void UpdateUI();
|
void UpdateUI();
|
||||||
void UpdateCompressorPlot();
|
void UpdateCompressorPlot();
|
||||||
void UpdateResponsePlot();
|
void UpdateResponsePlot();
|
||||||
|
void UpdateRealtimeParams();
|
||||||
|
|
||||||
static const int TAU_FACTOR = 5;
|
static const int TAU_FACTOR = 5;
|
||||||
static const size_t MIN_BUFFER_CAPACITY = 1048576; // 1MB
|
static const size_t MIN_BUFFER_CAPACITY = 1048576; // 1MB
|
||||||
@ -218,6 +243,7 @@ private:
|
|||||||
double mTrackLen;
|
double mTrackLen;
|
||||||
bool mProcStereo;
|
bool mProcStereo;
|
||||||
|
|
||||||
|
std::mutex mRealtimeMutex;
|
||||||
std::unique_ptr<SamplePreprocessor> mPreproc;
|
std::unique_ptr<SamplePreprocessor> mPreproc;
|
||||||
std::unique_ptr<EnvelopeDetector> mEnvelope;
|
std::unique_ptr<EnvelopeDetector> mEnvelope;
|
||||||
|
|
||||||
@ -246,9 +272,13 @@ private:
|
|||||||
static const size_t RESPONSE_PLOT_STEP_START = 2;
|
static const size_t RESPONSE_PLOT_STEP_START = 2;
|
||||||
static const size_t RESPONSE_PLOT_STEP_STOP = 3;
|
static const size_t RESPONSE_PLOT_STEP_STOP = 3;
|
||||||
|
|
||||||
|
bool mIgnoreGuiEvents;
|
||||||
Plot* mGainPlot;
|
Plot* mGainPlot;
|
||||||
Plot* mResponsePlot;
|
Plot* mResponsePlot;
|
||||||
bool mIgnoreGuiEvents;
|
wxChoice* mAlgorithmCtrl;
|
||||||
|
wxChoice* mPreprocCtrl;
|
||||||
|
SliderTextCtrl* mAttackTimeCtrl;
|
||||||
|
SliderTextCtrl* mLookaheadTimeCtrl;
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user