Skip to content

Commit c2fbd6f

Browse files
committed
Some work on resampler delay
1 parent 3bb287b commit c2fbd6f

File tree

3 files changed

+57
-21
lines changed

3 files changed

+57
-21
lines changed

src/finer/R3LiveShifter.cpp

+33-7
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,10 @@ R3LiveShifter::createResamplers()
212212
resamplerParameters.maxBufferSize = m_guideConfiguration.longestFftSize;
213213
resamplerParameters.dynamism = Resampler::RatioOftenChanging;
214214
resamplerParameters.ratioChange = Resampler::SmoothRatioChange;
215+
216+
int debug = m_log.getDebugLevel();
217+
if (debug > 0) --debug;
218+
resamplerParameters.debugLevel = debug;
215219

216220
m_inResampler = std::unique_ptr<Resampler>
217221
(new Resampler(resamplerParameters, m_parameters.channels));
@@ -235,15 +239,18 @@ R3LiveShifter::getFormantScale() const
235239
size_t
236240
R3LiveShifter::getPreferredStartPad() const
237241
{
238-
//!!!???
239242
return 0;
240243
}
241244

242245
size_t
243246
R3LiveShifter::getStartDelay() const
244247
{
248+
//!!! need a principled way - measure it in ctor perhaps
245249
int resamplerDelay = 32;
246-
int fixed = getWindowSourceSize() / 2 + resamplerDelay;
250+
#ifdef HAVE_LIBSAMPLERATE
251+
resamplerDelay = 47;
252+
#endif
253+
int fixed = getWindowSourceSize() / 2 + resamplerDelay * 2;
247254
int variable = getWindowSourceSize() / 2;
248255
if (m_contractThenExpand) {
249256
if (m_pitchScale < 1.0) {
@@ -305,7 +312,6 @@ R3LiveShifter::shift(const float *const *input, float *const *output)
305312
m_log.log(2, "R3LiveShifter::shift: initially in outbuf", m_channelData[0]->outbuf->getReadSpace());
306313

307314
int pad = 0;
308-
int resamplerDelay = 32;
309315
if (m_firstProcess) {
310316
if (m_contractThenExpand) {
311317
pad = getWindowSourceSize();
@@ -315,7 +321,6 @@ R3LiveShifter::shift(const float *const *input, float *const *output)
315321
} else {
316322
pad = getWindowSourceSize() / 2;
317323
}
318-
pad += resamplerDelay;
319324
m_log.log(2, "R3LiveShifter::shift: extending input with pre-pad", incount, pad);
320325
for (int c = 0; c < m_parameters.channels; ++c) {
321326
m_channelData[c]->inbuf->zero(pad);
@@ -336,7 +341,7 @@ R3LiveShifter::shift(const float *const *input, float *const *output)
336341
}
337342
}
338343

339-
int requiredInOutbuf = int(ceil(incount / outRatio)) + resamplerDelay;
344+
int requiredInOutbuf = int(ceil(incount / outRatio));
340345
generate(requiredInOutbuf);
341346

342347
int got = readOut(output, incount, 0);
@@ -417,8 +422,18 @@ R3LiveShifter::readIn(const float *const *input)
417422
incount,
418423
inRatio,
419424
false);
420-
425+
421426
m_log.log(2, "R3LiveShifter::readIn: writing to inbuf from resampled data, former read space and samples being added", m_channelData[0]->inbuf->getReadSpace(), resampleOutput);
427+
428+
if (m_firstProcess) {
429+
int expected = floor(incount * inRatio);
430+
if (resampleOutput < expected) {
431+
m_log.log(2, "R3LiveShifter::readIn: resampler left us short on first process, pre-padding output: expected and obtained", expected, resampleOutput);
432+
for (int c = 0; c < m_parameters.channels; ++c) {
433+
m_channelData[c]->inbuf->zero(expected - resampleOutput);
434+
}
435+
}
436+
}
422437

423438
for (int c = 0; c < m_parameters.channels; ++c) {
424439
m_channelData[c]->inbuf->write
@@ -646,7 +661,18 @@ R3LiveShifter::readOut(float *const *output, int outcount, int origin)
646661
}
647662

648663
if (resampledCount < outcount) {
649-
m_log.log(0, "R3LiveShifter::readOut: WARNING: Failed to obtain enough samples from resampler", resampledCount, outcount);
664+
if (m_firstProcess) {
665+
m_log.log(2, "R3LiveShifter::readOut: resampler left us short on first process, pre-padding output: expected and obtained", outcount, resampledCount);
666+
int prepad = outcount - resampledCount;
667+
for (int c = 0; c < m_parameters.channels; ++c) {
668+
v_move(m_channelAssembly.mixdown.data()[c] + prepad,
669+
m_channelAssembly.mixdown.data()[c], resampledCount);
670+
v_zero(m_channelAssembly.mixdown.data()[c], prepad);
671+
}
672+
resampledCount = outcount;
673+
} else {
674+
m_log.log(0, "R3LiveShifter::readOut: WARNING: Failed to obtain enough samples from resampler", resampledCount, outcount);
675+
}
650676
}
651677

652678
if (useMidSide()) {

src/finer/R3Stretcher.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,10 @@ R3Stretcher::createResampler()
299299
resamplerParameters.dynamism = Resampler::RatioMostlyFixed;
300300
resamplerParameters.ratioChange = Resampler::SuddenRatioChange;
301301
}
302+
303+
int debug = m_log.getDebugLevel();
304+
if (debug > 0) --debug;
305+
resamplerParameters.debugLevel = debug;
302306

303307
m_resampler = std::unique_ptr<Resampler>
304308
(new Resampler(resamplerParameters, m_parameters.channels));

src/test/TestLiveShifter.cpp

+20-14
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,19 @@ BOOST_AUTO_TEST_CASE(sinusoid_unchanged)
5252
int n = 100000;
5353
float freq = 440.f;
5454
int rate = 44100;
55+
56+
if (printDebug) {
57+
RubberBandLiveShifter::setDefaultDebugLevel(2);
58+
}
59+
5560
RubberBandLiveShifter shifter
5661
(rate, 1, RubberBandLiveShifter::OptionPitchModeB);
5762

5863
//!!!
59-
shifter.setPitchScale(2.0);
60-
61-
if (printDebug) {
62-
shifter.setDebugLevel(2);
63-
}
64+
// shifter.setPitchScale(2.0);
6465

6566
int blocksize = shifter.getBlockSize();
66-
BOOST_TEST(blocksize == 2560);
67+
BOOST_TEST(blocksize == 512);
6768

6869
n = (n / blocksize + 1) * blocksize;
6970

@@ -79,6 +80,8 @@ BOOST_AUTO_TEST_CASE(sinusoid_unchanged)
7980
}
8081

8182
int delay = shifter.getStartDelay();
83+
84+
std::cerr << "delay reported as " << delay << std::endl;
8285

8386
// We now have n samples of a simple sinusoid with stretch factor
8487
// 1.0; obviously we expect the output to be essentially the same
@@ -106,18 +109,21 @@ BOOST_AUTO_TEST_CASE(sinusoid_unchanged)
106109
tt::tolerance(0.001f) << tt::per_element());
107110

108111
if (printDebug) {
109-
// The initial # is to allow grep on the test output
110-
std::cout << "#sample\tV" << std::endl;
112+
// The prefix is to allow grep on the test output
113+
114+
std::cout << "IN,sample,V" << std::endl;
115+
for (int i = 0; i < int(in.size()); ++i) {
116+
std::cout << "IN," << i << "," << in[i] << std::endl;
117+
}
118+
119+
std::cout << "OUT,sample,V" << std::endl;
111120
for (int i = 0; i < int(out.size()); ++i) {
112-
std::cout << "#" << i << "\t" << out[i] << std::endl;
121+
std::cout << "OUT," << i << "," << out[i] << std::endl;
113122
}
114-
}
115123

116-
if (printDebug) {
117-
// The initial @ is to allow grep on the test output
118-
std::cout << "@sample\tV" << std::endl;
124+
std::cout << "DIFF,V" << std::endl;
119125
for (int i = 0; i + delay < int(in.size()); ++i) {
120-
std::cout << "@" << i << "\t" << out[i + delay] - in[i] << std::endl;
126+
std::cout << "DIFF," << i << "," << out[i + delay] - in[i] << std::endl;
121127
}
122128
}
123129
#endif

0 commit comments

Comments
 (0)