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:
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"
|
||||
|
||||
//#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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user