mirror of
https://github.com/cookiengineer/audacity
synced 2025-07-17 09:07:41 +02:00
Debugging helper code for Compressor2 effect.
Signed-off-by: Max Maisel <max.maisel@posteo.de>
This commit is contained in:
parent
6941c66de8
commit
1d7b143c91
25
scripts/debug/compressor2_buffers.m
Normal file
25
scripts/debug/compressor2_buffers.m
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
%% Debug Compressor v2 pipeline buffers
|
||||||
|
buffer_ids = [1,2,3,4,5];
|
||||||
|
prefix = '/tmp';
|
||||||
|
|
||||||
|
figure(1);
|
||||||
|
for k = 1:length(buffer_ids)
|
||||||
|
subplot(length(buffer_ids), 1, k)
|
||||||
|
bfile = fopen(sprintf('%s/envbuf.%d.bin', prefix, buffer_ids(k)));
|
||||||
|
env = fread(bfile, 'float').';
|
||||||
|
bfile = fopen(sprintf('%s/blockbuf.%d.bin', prefix, buffer_ids(k)));
|
||||||
|
block_raw = fread(bfile, 'float').';
|
||||||
|
|
||||||
|
sizes = reshape(block_raw(1:12), 3, 4);
|
||||||
|
capacity = (1:4).*sizes(3,:);
|
||||||
|
track_size = horzcat(0, capacity(1:3)) + sizes(1,:);
|
||||||
|
block = block_raw(13:end);
|
||||||
|
|
||||||
|
plot(block, 'b', 'linewidth', 3);
|
||||||
|
hold on;
|
||||||
|
plot(circshift(env, length(env)/3), 'r');
|
||||||
|
stem(capacity, ones(1, length(capacity)), 'g');
|
||||||
|
stem(track_size, 1.5.*ones(1, length(capacity)), 'b');
|
||||||
|
ylim([-2 2]);
|
||||||
|
hold off;
|
||||||
|
end
|
@ -38,6 +38,15 @@
|
|||||||
|
|
||||||
#include "LoadEffects.h"
|
#include "LoadEffects.h"
|
||||||
|
|
||||||
|
//#define DEBUG_COMPRESSOR2_DUMP_BUFFERS
|
||||||
|
//#define DEBUG_COMPRESSOR2_ENV
|
||||||
|
//#define DEBUG_COMPRESSOR2_TRACE
|
||||||
|
|
||||||
|
#ifdef DEBUG_COMPRESSOR2_DUMP_BUFFERS
|
||||||
|
#include <fstream>
|
||||||
|
int buf_num;
|
||||||
|
#endif
|
||||||
|
|
||||||
enum kAlgorithms
|
enum kAlgorithms
|
||||||
{
|
{
|
||||||
kExpFit,
|
kExpFit,
|
||||||
@ -225,6 +234,19 @@ size_t EnvelopeDetector::GetBlockSize() const
|
|||||||
return mLookaheadBuffer.size();
|
return mLookaheadBuffer.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const float* EnvelopeDetector::GetBuffer(int idx) const
|
||||||
|
{
|
||||||
|
if(idx == 0)
|
||||||
|
return mProcessedBuffer.data();
|
||||||
|
else if(idx == 1)
|
||||||
|
return mProcessingBuffer.data();
|
||||||
|
else if(idx == 2)
|
||||||
|
return mLookaheadBuffer.data();
|
||||||
|
else
|
||||||
|
wxASSERT(false);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
ExpFitEnvelopeDetector::ExpFitEnvelopeDetector(
|
ExpFitEnvelopeDetector::ExpFitEnvelopeDetector(
|
||||||
float rate, float attackTime, float releaseTime, size_t bufferSize)
|
float rate, float attackTime, float releaseTime, size_t bufferSize)
|
||||||
: EnvelopeDetector(bufferSize)
|
: EnvelopeDetector(bufferSize)
|
||||||
@ -927,10 +949,58 @@ void EffectCompressor2::FreePipeline()
|
|||||||
|
|
||||||
void EffectCompressor2::SwapPipeline()
|
void EffectCompressor2::SwapPipeline()
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG_COMPRESSOR2_DUMP_BUFFERS
|
||||||
|
wxString blockname = wxString::Format("/tmp/blockbuf.%d.bin", buf_num);
|
||||||
|
std::cerr << "Writing to " << blockname << "\n" << std::flush;
|
||||||
|
std::fstream blockbuffer = std::fstream();
|
||||||
|
blockbuffer.open(blockname, std::ios::binary | std::ios::out);
|
||||||
|
for(size_t i = 0; i < PIPELINE_DEPTH; ++i) {
|
||||||
|
float val = mPipeline[i].trackSize;
|
||||||
|
blockbuffer.write((char*)&val, sizeof(float));
|
||||||
|
val = mPipeline[i].size;
|
||||||
|
blockbuffer.write((char*)&val, sizeof(float));
|
||||||
|
val = mPipeline[i].capacity();
|
||||||
|
blockbuffer.write((char*)&val, sizeof(float));
|
||||||
|
}
|
||||||
|
for(size_t i = 0; i < PIPELINE_DEPTH; ++i)
|
||||||
|
blockbuffer.write((char*)mPipeline[i][0], mPipeline[i].capacity() * sizeof(float));
|
||||||
|
|
||||||
|
wxString envname = wxString::Format("/tmp/envbuf.%d.bin", buf_num++);
|
||||||
|
std::cerr << "Writing to " << envname << "\n" << std::flush;
|
||||||
|
std::fstream envbuffer = std::fstream();
|
||||||
|
envbuffer.open(envname, std::ios::binary | std::ios::out);
|
||||||
|
envbuffer.write((char*)mEnvelope->GetBuffer(0),
|
||||||
|
mEnvelope->GetBlockSize() * sizeof(float));
|
||||||
|
envbuffer.write((char*)mEnvelope->GetBuffer(1),
|
||||||
|
mEnvelope->GetBlockSize() * sizeof(float));
|
||||||
|
envbuffer.write((char*)mEnvelope->GetBuffer(2),
|
||||||
|
mEnvelope->GetBlockSize() * sizeof(float));
|
||||||
|
|
||||||
|
std::cerr << "PipelineState: ";
|
||||||
|
for(size_t i = 0; i < PIPELINE_DEPTH; ++i)
|
||||||
|
std::cerr << !!mPipeline[i].size;
|
||||||
|
std::cerr << " ";
|
||||||
|
for(size_t i = 0; i < PIPELINE_DEPTH; ++i)
|
||||||
|
std::cerr << !!mPipeline[i].trackSize;
|
||||||
|
|
||||||
|
std::cerr << "\ntrackSize: ";
|
||||||
|
for(size_t i = 0; i < PIPELINE_DEPTH; ++i)
|
||||||
|
std::cerr << mPipeline[i].trackSize << " ";
|
||||||
|
std::cerr << "\ntrackPos: ";
|
||||||
|
for(size_t i = 0; i < PIPELINE_DEPTH; ++i)
|
||||||
|
std::cerr << mPipeline[i].trackPos.as_size_t() << " ";
|
||||||
|
std::cerr << "\nsize: ";
|
||||||
|
for(size_t i = 0; i < PIPELINE_DEPTH; ++i)
|
||||||
|
std::cerr << mPipeline[i].size << " ";
|
||||||
|
std::cerr << "\n" << std::flush;
|
||||||
|
#endif
|
||||||
|
|
||||||
++mProgressVal;
|
++mProgressVal;
|
||||||
for(size_t i = 0; i < PIPELINE_DEPTH-1; ++i)
|
for(size_t i = 0; i < PIPELINE_DEPTH-1; ++i)
|
||||||
mPipeline[i].swap(mPipeline[i+1]);
|
mPipeline[i].swap(mPipeline[i+1]);
|
||||||
|
#ifdef DEBUG_COMPRESSOR2_TRACE
|
||||||
std::cerr << "\n";
|
std::cerr << "\n";
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ProcessOne() takes a track, transforms it to bunch of buffer-blocks,
|
/// ProcessOne() takes a track, transforms it to bunch of buffer-blocks,
|
||||||
@ -956,9 +1026,22 @@ bool EffectCompressor2::ProcessOne(TrackIterRange<WaveTrack> range)
|
|||||||
// sample the current buffer starts at.
|
// sample the current buffer starts at.
|
||||||
auto pos = start;
|
auto pos = start;
|
||||||
|
|
||||||
|
#ifdef DEBUG_COMPRESSOR2_TRACE
|
||||||
|
std::cerr << "ProcLen: " << (end - start).as_size_t() << "\n" << std::flush;
|
||||||
|
std::cerr << "EnvBlockLen: " << mEnvelope->GetBlockSize() << "\n" << std::flush;
|
||||||
|
std::cerr << "PipeBlockLen: " << mPipeline[0].capacity() << "\n" << std::flush;
|
||||||
|
std::cerr << "LookaheadLen: " << mLookaheadLength << "\n" << std::flush;
|
||||||
|
#endif
|
||||||
|
|
||||||
mProgressVal = 0;
|
mProgressVal = 0;
|
||||||
|
#ifdef DEBUG_COMPRESSOR2_DUMP_BUFFERS
|
||||||
|
buf_num = 0;
|
||||||
|
#endif
|
||||||
while(pos < end)
|
while(pos < end)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG_COMPRESSOR2_TRACE
|
||||||
|
std::cerr << "ProcessBlock at: " << pos.as_size_t() << "\n" << std::flush;
|
||||||
|
#endif
|
||||||
StorePipeline(range);
|
StorePipeline(range);
|
||||||
SwapPipeline();
|
SwapPipeline();
|
||||||
|
|
||||||
@ -985,6 +1068,15 @@ bool EffectCompressor2::ProcessOne(TrackIterRange<WaveTrack> range)
|
|||||||
// Handle short selections
|
// Handle short selections
|
||||||
while(mPipeline[1].size == 0)
|
while(mPipeline[1].size == 0)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG_COMPRESSOR2_TRACE
|
||||||
|
std::cerr << "PaddingLoop: ";
|
||||||
|
for(size_t i = 0; i < PIPELINE_DEPTH; ++i)
|
||||||
|
std::cerr << !!mPipeline[i].size;
|
||||||
|
std::cerr << " ";
|
||||||
|
for(size_t i = 0; i < PIPELINE_DEPTH; ++i)
|
||||||
|
std::cerr << !!mPipeline[i].trackSize;
|
||||||
|
std::cerr << "\n" << std::flush;
|
||||||
|
#endif
|
||||||
SwapPipeline();
|
SwapPipeline();
|
||||||
FillPipeline();
|
FillPipeline();
|
||||||
}
|
}
|
||||||
@ -995,6 +1087,9 @@ bool EffectCompressor2::ProcessOne(TrackIterRange<WaveTrack> range)
|
|||||||
SwapPipeline();
|
SwapPipeline();
|
||||||
DrainPipeline();
|
DrainPipeline();
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG_COMPRESSOR2_TRACE
|
||||||
|
std::cerr << "StoreLastBlock\n" << std::flush;
|
||||||
|
#endif
|
||||||
StorePipeline(range);
|
StorePipeline(range);
|
||||||
|
|
||||||
// Return true because the effect processing succeeded ... unless cancelled
|
// Return true because the effect processing succeeded ... unless cancelled
|
||||||
@ -1006,6 +1101,11 @@ bool EffectCompressor2::LoadPipeline(
|
|||||||
{
|
{
|
||||||
sampleCount read_size = -1;
|
sampleCount read_size = -1;
|
||||||
sampleCount last_read_size = -1;
|
sampleCount last_read_size = -1;
|
||||||
|
#ifdef DEBUG_COMPRESSOR2_TRACE
|
||||||
|
std::cerr << "LoadBlock at: " <<
|
||||||
|
mPipeline[PIPELINE_DEPTH-1].trackPos.as_size_t() <<
|
||||||
|
" with len: " << len << "\n" << std::flush;
|
||||||
|
#endif
|
||||||
// Get the samples from the track and put them in the buffer
|
// Get the samples from the track and put them in the buffer
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
for(auto channel : range)
|
for(auto channel : range)
|
||||||
@ -1034,6 +1134,16 @@ bool EffectCompressor2::LoadPipeline(
|
|||||||
|
|
||||||
void EffectCompressor2::FillPipeline()
|
void EffectCompressor2::FillPipeline()
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG_COMPRESSOR2_TRACE
|
||||||
|
std::cerr << "FillBlock: " <<
|
||||||
|
!!mPipeline[0].size << !!mPipeline[1].size <<
|
||||||
|
!!mPipeline[2].size << !!mPipeline[3].size <<
|
||||||
|
"\n" << std::flush;
|
||||||
|
std::cerr << " from " << -int(mLookaheadLength)
|
||||||
|
<< " to " << mPipeline[PIPELINE_DEPTH-1].size - mLookaheadLength << "\n" << std::flush;
|
||||||
|
std::cerr << "Padding from " << mPipeline[PIPELINE_DEPTH-1].trackSize
|
||||||
|
<< " to " << mEnvelope->GetBlockSize() << "\n" << std::flush;
|
||||||
|
#endif
|
||||||
// TODO: correct end conditions
|
// TODO: correct end conditions
|
||||||
mPipeline[PIPELINE_DEPTH-1].pad_to(mEnvelope->GetBlockSize(), 0, mProcStereo);
|
mPipeline[PIPELINE_DEPTH-1].pad_to(mEnvelope->GetBlockSize(), 0, mProcStereo);
|
||||||
|
|
||||||
@ -1050,12 +1160,26 @@ void EffectCompressor2::FillPipeline()
|
|||||||
|
|
||||||
void EffectCompressor2::ProcessPipeline()
|
void EffectCompressor2::ProcessPipeline()
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG_COMPRESSOR2_TRACE
|
||||||
|
std::cerr << "ProcessBlock: " <<
|
||||||
|
!!mPipeline[0].size << !!mPipeline[1].size <<
|
||||||
|
!!mPipeline[2].size << !!mPipeline[3].size <<
|
||||||
|
"\n" << std::flush;
|
||||||
|
#endif
|
||||||
float env;
|
float env;
|
||||||
size_t length = mPipeline[0].size;
|
size_t length = mPipeline[0].size;
|
||||||
|
|
||||||
for(size_t i = 0; i < PIPELINE_DEPTH-2; ++i)
|
for(size_t i = 0; i < PIPELINE_DEPTH-2; ++i)
|
||||||
{ wxASSERT(mPipeline[0].size == mPipeline[i+1].size); }
|
{ wxASSERT(mPipeline[0].size == mPipeline[i+1].size); }
|
||||||
|
|
||||||
|
#ifdef DEBUG_COMPRESSOR2_TRACE
|
||||||
|
std::cerr << "LookaheadLen: " << mLookaheadLength << "\n" << std::flush;
|
||||||
|
std::cerr << "PipeLength: " <<
|
||||||
|
mPipeline[0].size << " " << mPipeline[1].size << " " <<
|
||||||
|
mPipeline[2].size << " " << mPipeline[3].size <<
|
||||||
|
"\n" << std::flush;
|
||||||
|
#endif
|
||||||
|
|
||||||
for(size_t rp = mLookaheadLength, wp = 0; wp < length; ++rp, ++wp)
|
for(size_t rp = mLookaheadLength, wp = 0; wp < length; ++rp, ++wp)
|
||||||
{
|
{
|
||||||
if(rp < length)
|
if(rp < length)
|
||||||
@ -1082,7 +1206,14 @@ inline float EffectCompressor2::EnvelopeSample(PipelineBuffer& pbuf, size_t rp)
|
|||||||
inline void EffectCompressor2::CompressSample(float env, size_t wp)
|
inline void EffectCompressor2::CompressSample(float env, size_t wp)
|
||||||
{
|
{
|
||||||
float gain = (1.0 - mDryWet) + CompressorGain(env) * mDryWet;
|
float gain = (1.0 - mDryWet) + CompressorGain(env) * mDryWet;
|
||||||
|
#ifdef DEBUG_COMPRESSOR2_ENV
|
||||||
|
if(wp < 100)
|
||||||
|
mPipeline[0][0][wp] = 0;
|
||||||
|
else
|
||||||
|
mPipeline[0][0][wp] = env;
|
||||||
|
#else
|
||||||
mPipeline[0][0][wp] = mPipeline[0][0][wp] * gain;
|
mPipeline[0][0][wp] = mPipeline[0][0][wp] * gain;
|
||||||
|
#endif
|
||||||
if(mProcStereo)
|
if(mProcStereo)
|
||||||
mPipeline[0][1][wp] = mPipeline[0][1][wp] * gain;
|
mPipeline[0][1][wp] = mPipeline[0][1][wp] * gain;
|
||||||
}
|
}
|
||||||
@ -1099,13 +1230,37 @@ bool EffectCompressor2::PipelineHasData()
|
|||||||
|
|
||||||
void EffectCompressor2::DrainPipeline()
|
void EffectCompressor2::DrainPipeline()
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG_COMPRESSOR2_TRACE
|
||||||
|
std::cerr << "DrainBlock: " <<
|
||||||
|
!!mPipeline[0].size << !!mPipeline[1].size <<
|
||||||
|
!!mPipeline[2].size << !!mPipeline[3].size <<
|
||||||
|
"\n" << std::flush;
|
||||||
|
bool once = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
float env;
|
float env;
|
||||||
size_t length = mPipeline[0].size;
|
size_t length = mPipeline[0].size;
|
||||||
size_t length2 = mPipeline[PIPELINE_DEPTH-2].size;
|
size_t length2 = mPipeline[PIPELINE_DEPTH-2].size;
|
||||||
|
|
||||||
|
#ifdef DEBUG_COMPRESSOR2_TRACE
|
||||||
|
std::cerr << "LookaheadLen: " << mLookaheadLength << "\n" << std::flush;
|
||||||
|
std::cerr << "PipeLength: " <<
|
||||||
|
mPipeline[0].size << " " << mPipeline[1].size << " " <<
|
||||||
|
mPipeline[2].size << " " << mPipeline[3].size <<
|
||||||
|
"\n" << std::flush;
|
||||||
|
#endif
|
||||||
|
|
||||||
for(size_t rp = mLookaheadLength, wp = 0; wp < length; ++rp, ++wp)
|
for(size_t rp = mLookaheadLength, wp = 0; wp < length; ++rp, ++wp)
|
||||||
{
|
{
|
||||||
if(rp < length2 && mPipeline[PIPELINE_DEPTH-2].size != 0)
|
if(rp < length2 && mPipeline[PIPELINE_DEPTH-2].size != 0)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG_COMPRESSOR2_TRACE
|
||||||
|
if(!once)
|
||||||
|
{
|
||||||
|
once = true;
|
||||||
|
std::cerr << "Draining overlapping buffer\n" << std::flush;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
env = EnvelopeSample(mPipeline[PIPELINE_DEPTH-2], rp);
|
env = EnvelopeSample(mPipeline[PIPELINE_DEPTH-2], rp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1117,6 +1272,11 @@ void EffectCompressor2::DrainPipeline()
|
|||||||
|
|
||||||
void EffectCompressor2::StorePipeline(TrackIterRange<WaveTrack> range)
|
void EffectCompressor2::StorePipeline(TrackIterRange<WaveTrack> range)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG_COMPRESSOR2_TRACE
|
||||||
|
std::cerr << "StoreBlock at: " << mPipeline[0].trackPos.as_size_t() <<
|
||||||
|
" with len: " << mPipeline[0].trackSize << "\n" << std::flush;
|
||||||
|
#endif
|
||||||
|
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
for(auto channel : range)
|
for(auto channel : range)
|
||||||
{
|
{
|
||||||
|
@ -74,6 +74,7 @@ class EnvelopeDetector
|
|||||||
|
|
||||||
float ProcessSample(float value);
|
float ProcessSample(float value);
|
||||||
size_t GetBlockSize() const;
|
size_t GetBlockSize() const;
|
||||||
|
const float* GetBuffer(int idx) const;
|
||||||
protected:
|
protected:
|
||||||
size_t mPos;
|
size_t mPos;
|
||||||
std::vector<float> mLookaheadBuffer;
|
std::vector<float> mLookaheadBuffer;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user