1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-04-29 15:19:44 +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"
//#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
{
kExpFit,
@ -225,6 +234,19 @@ size_t EnvelopeDetector::GetBlockSize() const
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(
float rate, float attackTime, float releaseTime, size_t bufferSize)
: EnvelopeDetector(bufferSize)
@ -927,10 +949,58 @@ void EffectCompressor2::FreePipeline()
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;
for(size_t i = 0; i < PIPELINE_DEPTH-1; ++i)
mPipeline[i].swap(mPipeline[i+1]);
#ifdef DEBUG_COMPRESSOR2_TRACE
std::cerr << "\n";
#endif
}
/// 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.
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;
#ifdef DEBUG_COMPRESSOR2_DUMP_BUFFERS
buf_num = 0;
#endif
while(pos < end)
{
#ifdef DEBUG_COMPRESSOR2_TRACE
std::cerr << "ProcessBlock at: " << pos.as_size_t() << "\n" << std::flush;
#endif
StorePipeline(range);
SwapPipeline();
@ -985,6 +1068,15 @@ bool EffectCompressor2::ProcessOne(TrackIterRange<WaveTrack> range)
// Handle short selections
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();
FillPipeline();
}
@ -995,6 +1087,9 @@ bool EffectCompressor2::ProcessOne(TrackIterRange<WaveTrack> range)
SwapPipeline();
DrainPipeline();
}
#ifdef DEBUG_COMPRESSOR2_TRACE
std::cerr << "StoreLastBlock\n" << std::flush;
#endif
StorePipeline(range);
// Return true because the effect processing succeeded ... unless cancelled
@ -1006,6 +1101,11 @@ bool EffectCompressor2::LoadPipeline(
{
sampleCount 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
int idx = 0;
for(auto channel : range)
@ -1034,6 +1134,16 @@ bool EffectCompressor2::LoadPipeline(
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
mPipeline[PIPELINE_DEPTH-1].pad_to(mEnvelope->GetBlockSize(), 0, mProcStereo);
@ -1050,12 +1160,26 @@ void EffectCompressor2::FillPipeline()
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;
size_t length = mPipeline[0].size;
for(size_t i = 0; i < PIPELINE_DEPTH-2; ++i)
{ 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)
{
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)
{
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;
#endif
if(mProcStereo)
mPipeline[0][1][wp] = mPipeline[0][1][wp] * gain;
}
@ -1099,13 +1230,37 @@ bool EffectCompressor2::PipelineHasData()
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;
size_t length = mPipeline[0].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)
{
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);
}
else
@ -1117,6 +1272,11 @@ void EffectCompressor2::DrainPipeline()
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;
for(auto channel : range)
{

View File

@ -74,6 +74,7 @@ class EnvelopeDetector
float ProcessSample(float value);
size_t GetBlockSize() const;
const float* GetBuffer(int idx) const;
protected:
size_t mPos;
std::vector<float> mLookaheadBuffer;