mirror of
https://github.com/cookiengineer/audacity
synced 2025-04-29 15:19:44 +02:00
Implement initial condition optimization.
Signed-off-by: Max Maisel <max.maisel@posteo.de>
This commit is contained in:
parent
277f64c4ca
commit
ae4189a533
@ -125,6 +125,14 @@ float SlidingRmsPreprocessor::ProcessSample(float valueL, float valueR)
|
||||
return DoProcessSample((valueL * valueL + valueR * valueR) / 2.0);
|
||||
}
|
||||
|
||||
void SlidingRmsPreprocessor::Reset()
|
||||
{
|
||||
mSum = 0;
|
||||
mPos = 0;
|
||||
mInsertCount = 0;
|
||||
std::fill(mWindow.begin(), mWindow.end(), 0);
|
||||
}
|
||||
|
||||
float SlidingRmsPreprocessor::DoProcessSample(float value)
|
||||
{
|
||||
if(mInsertCount > REFRESH_WINDOW_EVERY)
|
||||
@ -183,6 +191,13 @@ float SlidingMaxPreprocessor::ProcessSample(float valueL, float valueR)
|
||||
return DoProcessSample((fabs(valueL) + fabs(valueR)) / 2.0);
|
||||
}
|
||||
|
||||
void SlidingMaxPreprocessor::Reset()
|
||||
{
|
||||
mPos = 0;
|
||||
std::fill(mWindow.begin(), mWindow.end(), 0);
|
||||
std::fill(mMaxes.begin(), mMaxes.end(), 0);
|
||||
}
|
||||
|
||||
float SlidingMaxPreprocessor::DoProcessSample(float value)
|
||||
{
|
||||
size_t oldHead = (mPos-1) % mWindow.size();
|
||||
@ -207,6 +222,8 @@ float SlidingMaxPreprocessor::DoProcessSample(float value)
|
||||
|
||||
EnvelopeDetector::EnvelopeDetector(size_t buffer_size)
|
||||
: mPos(0),
|
||||
mInitialCondition(0),
|
||||
mInitialBlockSize(0),
|
||||
mLookaheadBuffer(buffer_size, 0),
|
||||
mProcessingBuffer(buffer_size, 0),
|
||||
mProcessedBuffer(buffer_size, 0)
|
||||
@ -227,6 +244,10 @@ float EnvelopeDetector::ProcessSample(float value)
|
||||
return retval;
|
||||
}
|
||||
|
||||
void EnvelopeDetector::CalcInitialCondition(float value)
|
||||
{
|
||||
}
|
||||
|
||||
size_t EnvelopeDetector::GetBlockSize() const
|
||||
{
|
||||
wxASSERT(mProcessedBuffer.size() == mProcessingBuffer.size());
|
||||
@ -350,6 +371,28 @@ Pt1EnvelopeDetector::Pt1EnvelopeDetector(
|
||||
|
||||
mAttackFactor = 1.0 / (attackTime * rate);
|
||||
mReleaseFactor = 1.0 / (releaseTime * rate);
|
||||
mInitialBlockSize = std::min(size_t(rate * sqrt(attackTime)), bufferSize);
|
||||
}
|
||||
|
||||
void Pt1EnvelopeDetector::CalcInitialCondition(float value)
|
||||
{
|
||||
mLookaheadBuffer[mPos++] = value;
|
||||
if(mPos == mInitialBlockSize)
|
||||
{
|
||||
float level = 0;
|
||||
for(size_t i = 0; i < mPos; ++i)
|
||||
{
|
||||
if(mLookaheadBuffer[i] >= level)
|
||||
if(i < mInitialBlockSize / 5)
|
||||
level += 5 * mAttackFactor * (mLookaheadBuffer[i] - level);
|
||||
else
|
||||
level += mAttackFactor * (mLookaheadBuffer[i] - level);
|
||||
else
|
||||
level += mReleaseFactor * (mLookaheadBuffer[i] - level);
|
||||
}
|
||||
mInitialCondition = level;
|
||||
mPos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Pt1EnvelopeDetector::Follow()
|
||||
@ -399,12 +442,16 @@ void PipelineBuffer::init(size_t capacity, bool stereo)
|
||||
size = 0;
|
||||
mCapacity = capacity;
|
||||
mBlockBuffer[0].reinit(capacity);
|
||||
std::fill(mBlockBuffer[0].get(), mBlockBuffer[0].get() + capacity, 0);
|
||||
if(stereo)
|
||||
{
|
||||
mBlockBuffer[1].reinit(capacity);
|
||||
std::fill(mBlockBuffer[1].get(), mBlockBuffer[1].get() + capacity, 0);
|
||||
}
|
||||
fill(0, stereo);
|
||||
}
|
||||
|
||||
void PipelineBuffer::fill(float value, bool stereo)
|
||||
{
|
||||
std::fill(mBlockBuffer[0].get(), mBlockBuffer[0].get() + mCapacity, value);
|
||||
if(stereo)
|
||||
std::fill(mBlockBuffer[1].get(), mBlockBuffer[1].get() + mCapacity, value);
|
||||
}
|
||||
|
||||
void PipelineBuffer::free()
|
||||
@ -1032,6 +1079,7 @@ bool EffectCompressor2::ProcessOne(TrackIterRange<WaveTrack> range)
|
||||
std::cerr << "LookaheadLen: " << mLookaheadLength << "\n" << std::flush;
|
||||
#endif
|
||||
|
||||
bool first = true;
|
||||
mProgressVal = 0;
|
||||
#ifdef DEBUG_COMPRESSOR2_DUMP_BUFFERS
|
||||
buf_num = 0;
|
||||
@ -1055,6 +1103,21 @@ bool EffectCompressor2::ProcessOne(TrackIterRange<WaveTrack> range)
|
||||
if(!LoadPipeline(range, blockLen))
|
||||
return false;
|
||||
|
||||
if(first)
|
||||
{
|
||||
first = false;
|
||||
size_t sampleCount = mEnvelope->InitialConditionSize();
|
||||
for(size_t i = 0; i < sampleCount; ++i)
|
||||
{
|
||||
size_t rp = i % mPipeline[PIPELINE_DEPTH-1].trackSize;
|
||||
mEnvelope->CalcInitialCondition(
|
||||
PreprocSample(mPipeline[PIPELINE_DEPTH-1], rp));
|
||||
}
|
||||
mPipeline[PIPELINE_DEPTH-2].fill(
|
||||
mEnvelope->InitialCondition(), mProcStereo);
|
||||
mPreproc->Reset();
|
||||
}
|
||||
|
||||
if(mPipeline[0].size == 0)
|
||||
FillPipeline();
|
||||
else
|
||||
@ -1156,7 +1219,6 @@ void EffectCompressor2::FillPipeline()
|
||||
size_t length = mPipeline[PIPELINE_DEPTH-1].size;
|
||||
for(size_t rp = mLookaheadLength, wp = 0; wp < length; ++rp, ++wp)
|
||||
{
|
||||
// TODO: correct initial conditions
|
||||
if(rp < length)
|
||||
EnvelopeSample(mPipeline[PIPELINE_DEPTH-2], rp);
|
||||
else
|
||||
@ -1199,14 +1261,17 @@ void EffectCompressor2::ProcessPipeline()
|
||||
}
|
||||
}
|
||||
|
||||
inline float EffectCompressor2::PreprocSample(PipelineBuffer& pbuf, size_t rp)
|
||||
{
|
||||
if(mProcStereo)
|
||||
return mPreproc->ProcessSample(pbuf[0][rp], pbuf[1][rp]);
|
||||
else
|
||||
return mPreproc->ProcessSample(pbuf[0][rp]);
|
||||
}
|
||||
|
||||
inline float EffectCompressor2::EnvelopeSample(PipelineBuffer& pbuf, size_t rp)
|
||||
{
|
||||
float preprocessed;
|
||||
if(mProcStereo)
|
||||
preprocessed = mPreproc->ProcessSample(pbuf[0][rp], pbuf[1][rp]);
|
||||
else
|
||||
preprocessed = mPreproc->ProcessSample(pbuf[0][rp]);
|
||||
return mEnvelope->ProcessSample(preprocessed);
|
||||
return mEnvelope->ProcessSample(PreprocSample(pbuf, rp));
|
||||
}
|
||||
|
||||
inline void EffectCompressor2::CompressSample(float env, size_t wp)
|
||||
|
@ -28,6 +28,7 @@ class SamplePreprocessor
|
||||
public:
|
||||
virtual float ProcessSample(float value) = 0;
|
||||
virtual float ProcessSample(float valueL, float valueR) = 0;
|
||||
virtual void Reset() = 0;
|
||||
};
|
||||
|
||||
class SlidingRmsPreprocessor : public SamplePreprocessor
|
||||
@ -37,6 +38,7 @@ class SlidingRmsPreprocessor : public SamplePreprocessor
|
||||
|
||||
virtual float ProcessSample(float value);
|
||||
virtual float ProcessSample(float valueL, float valueR);
|
||||
virtual void Reset();
|
||||
|
||||
static const size_t REFRESH_WINDOW_EVERY = 1048576; // 1 MB
|
||||
|
||||
@ -58,6 +60,7 @@ class SlidingMaxPreprocessor : public SamplePreprocessor
|
||||
|
||||
virtual float ProcessSample(float value);
|
||||
virtual float ProcessSample(float valueL, float valueR);
|
||||
virtual void Reset();
|
||||
|
||||
private:
|
||||
std::vector<float> mWindow;
|
||||
@ -75,8 +78,14 @@ class EnvelopeDetector
|
||||
float ProcessSample(float value);
|
||||
size_t GetBlockSize() const;
|
||||
const float* GetBuffer(int idx) const;
|
||||
|
||||
virtual void CalcInitialCondition(float value);
|
||||
inline float InitialCondition() const { return mInitialCondition; }
|
||||
inline size_t InitialConditionSize() const { return mInitialBlockSize; }
|
||||
protected:
|
||||
size_t mPos;
|
||||
float mInitialCondition;
|
||||
size_t mInitialBlockSize;
|
||||
std::vector<float> mLookaheadBuffer;
|
||||
std::vector<float> mProcessingBuffer;
|
||||
std::vector<float> mProcessedBuffer;
|
||||
@ -102,6 +111,7 @@ class Pt1EnvelopeDetector : public EnvelopeDetector
|
||||
public:
|
||||
Pt1EnvelopeDetector(float rate, float attackTime, float releaseTime,
|
||||
size_t buffer_size = 0, bool correctGain = true);
|
||||
virtual void CalcInitialCondition(float value);
|
||||
|
||||
private:
|
||||
double mGainCorrection;
|
||||
@ -124,6 +134,7 @@ struct PipelineBuffer
|
||||
void pad_to(size_t len, float value, bool stereo);
|
||||
void swap(PipelineBuffer& other);
|
||||
void init(size_t size, bool stereo);
|
||||
void fill(float value, bool stereo);
|
||||
inline size_t capacity() const { return mCapacity; }
|
||||
void free();
|
||||
|
||||
@ -182,6 +193,7 @@ private:
|
||||
bool LoadPipeline(TrackIterRange<WaveTrack> range, size_t len);
|
||||
void FillPipeline();
|
||||
void ProcessPipeline();
|
||||
inline float PreprocSample(PipelineBuffer& pbuf, size_t rp);
|
||||
inline float EnvelopeSample(PipelineBuffer& pbuf, size_t rp);
|
||||
inline void CompressSample(float env, size_t wp);
|
||||
bool PipelineHasData();
|
||||
|
Loading…
x
Reference in New Issue
Block a user