1
0
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:
Max Maisel 2020-05-27 16:39:54 +02:00
parent 6941c66de8
commit 1d7b143c91
3 changed files with 186 additions and 0 deletions

View 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

View File

@ -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)
{ {

View File

@ -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;