Further timing tests

This commit is contained in:
Chris Cannam
2023-02-20 17:46:10 +00:00
parent 1368ba87ee
commit d5dd0e573a

View File

@@ -229,40 +229,13 @@ BOOST_AUTO_TEST_CASE(sinusoid_2x_offline_finer)
BOOST_TEST(rms < 0.1); BOOST_TEST(rms < 0.1);
} }
static void sinusoid_realtime(RubberBandStretcher::Options options, static vector<float> process_realtime(RubberBandStretcher &stretcher,
double timeRatio, const vector<float> &in,
double pitchScale, int nOut,
bool printDebug) int bs,
bool printDebug)
{ {
int n = (timeRatio < 1.0 ? 80000 : 40000); int n = in.size();
int nOut = int(ceil(n * timeRatio));
float freq = 441.f;
int rate = 44100;
int bs = 512;
// This test simulates block-by-block realtime processing with
// latency compensation, and checks that the output is all in the
// expected place
RubberBandStretcher stretcher(rate, 1, options, timeRatio, pitchScale);
stretcher.setMaxProcessSize(bs);
if (printDebug) {
stretcher.setDebugLevel(2);
}
// The input signal is a fixed frequency sinusoid that steps up in
// amplitude every 1/10 of the total duration - from 0.1 at the
// start, via increments of 0.1, to 1.0 at the end
vector<float> in(n);
for (int i = 0; i < n; ++i) {
float amplitude = float((i / (n/10)) + 1) / 10.f;
float sample = amplitude *
sinf(float(i) * freq * M_PI * 2.f / float(rate));
in[i] = sample;
}
vector<float> out(nOut, 0.f); vector<float> out(nOut, 0.f);
// Prime the start // Prime the start
@@ -298,7 +271,7 @@ static void sinusoid_realtime(RubberBandStretcher::Options options,
int required = stretcher.getSamplesRequired(); int required = stretcher.getSamplesRequired();
BOOST_TEST(required > 0); // because available == 0 BOOST_TEST(required > 0); // because available == 0
int toProcess = std::min(required, n - inOffset); int toProcess = std::min(required, n - inOffset);
float *source = in.data() + inOffset; const float *const source = in.data() + inOffset;
bool final = (toProcess < required); bool final = (toProcess < required);
stretcher.process(&source, toProcess, final); stretcher.process(&source, toProcess, final);
inOffset += toProcess; inOffset += toProcess;
@@ -330,6 +303,45 @@ static void sinusoid_realtime(RubberBandStretcher::Options options,
std::cout << "#" << i << "\t" << out[i] << std::endl; std::cout << "#" << i << "\t" << out[i] << std::endl;
} }
} }
return out;
}
static void sinusoid_realtime(RubberBandStretcher::Options options,
double timeRatio,
double pitchScale,
bool printDebug)
{
int n = (timeRatio < 1.0 ? 80000 : 40000);
int nOut = int(ceil(n * timeRatio));
float freq = 441.f;
int rate = 44100;
int bs = 512;
// This test simulates block-by-block realtime processing with
// latency compensation, and checks that the output is all in the
// expected place
RubberBandStretcher stretcher(rate, 1, options, timeRatio, pitchScale);
stretcher.setMaxProcessSize(bs);
if (printDebug) {
stretcher.setDebugLevel(2);
}
// The input signal is a fixed frequency sinusoid that steps up in
// amplitude every 1/10 of the total duration - from 0.1 at the
// start, via increments of 0.1, to 1.0 at the end
vector<float> in(n);
for (int i = 0; i < n; ++i) {
float amplitude = float((i / (n/10)) + 1) / 10.f;
float sample = amplitude *
sinf(float(i) * freq * M_PI * 2.f / float(rate));
in[i] = sample;
}
vector<float> out = process_realtime(stretcher, in, nOut, bs, printDebug);
// Step through the output signal in chunk of 1/20 of its duration // Step through the output signal in chunk of 1/20 of its duration
// (i.e. a rather arbitrary two per expected 0.1 increment in // (i.e. a rather arbitrary two per expected 0.1 increment in
@@ -368,7 +380,9 @@ static void sinusoid_realtime(RubberBandStretcher::Options options,
int slack = 0; int slack = 0;
if (options & RubberBandStretcher::OptionEngineFiner) { if (options & RubberBandStretcher::OptionEngineFiner) {
if (chunk == 0 || chunk == 19 || highSpeedPitch) { if (options & RubberBandStretcher::OptionWindowShort) {
slack = 2;
} else if (chunk == 0 || chunk == 19 || highSpeedPitch) {
slack = 1; slack = 1;
} }
} else { } else {
@@ -399,7 +413,8 @@ static void sinusoid_realtime(RubberBandStretcher::Options options,
double maxOver = 0.01; double maxOver = 0.01;
double maxUnder = 0.1; double maxUnder = 0.1;
if (!(options & RubberBandStretcher::OptionEngineFiner)) { if (!(options & RubberBandStretcher::OptionEngineFiner) ||
(options & RubberBandStretcher::OptionWindowShort)) {
maxUnder = 0.2; maxUnder = 0.2;
} }
@@ -416,14 +431,6 @@ BOOST_AUTO_TEST_CASE(sinusoid_slow_samepitch_realtime_finer)
false); false);
} }
BOOST_AUTO_TEST_CASE(sinusoid_slow_samepitch_realtime_faster)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFaster |
RubberBandStretcher::OptionProcessRealTime,
8.0, 1.0,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_fast_samepitch_realtime_finer) BOOST_AUTO_TEST_CASE(sinusoid_fast_samepitch_realtime_finer)
{ {
sinusoid_realtime(RubberBandStretcher::OptionEngineFiner | sinusoid_realtime(RubberBandStretcher::OptionEngineFiner |
@@ -432,14 +439,6 @@ BOOST_AUTO_TEST_CASE(sinusoid_fast_samepitch_realtime_finer)
false); false);
} }
BOOST_AUTO_TEST_CASE(sinusoid_fast_samepitch_realtime_faster)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFaster |
RubberBandStretcher::OptionProcessRealTime,
0.5, 1.0,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_slow_higher_realtime_finer) BOOST_AUTO_TEST_CASE(sinusoid_slow_higher_realtime_finer)
{ {
sinusoid_realtime(RubberBandStretcher::OptionEngineFiner | sinusoid_realtime(RubberBandStretcher::OptionEngineFiner |
@@ -466,32 +465,6 @@ BOOST_AUTO_TEST_CASE(sinusoid_slow_higher_realtime_finer_hcpitch)
false); false);
} }
BOOST_AUTO_TEST_CASE(sinusoid_slow_higher_realtime_faster)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFaster |
RubberBandStretcher::OptionProcessRealTime,
4.0, 1.5,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_slow_higher_realtime_faster_hqpitch)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFaster |
RubberBandStretcher::OptionProcessRealTime |
RubberBandStretcher::OptionPitchHighQuality,
4.0, 1.5,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_slow_higher_realtime_faster_hcpitch)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFaster |
RubberBandStretcher::OptionProcessRealTime |
RubberBandStretcher::OptionPitchHighConsistency,
4.0, 1.5,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_fast_higher_realtime_finer) BOOST_AUTO_TEST_CASE(sinusoid_fast_higher_realtime_finer)
{ {
sinusoid_realtime(RubberBandStretcher::OptionEngineFiner | sinusoid_realtime(RubberBandStretcher::OptionEngineFiner |
@@ -518,32 +491,6 @@ BOOST_AUTO_TEST_CASE(sinusoid_fast_higher_realtime_finer_hcpitch)
false); false);
} }
BOOST_AUTO_TEST_CASE(sinusoid_fast_higher_realtime_faster)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFaster |
RubberBandStretcher::OptionProcessRealTime,
0.5, 1.5,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_fast_higher_realtime_faster_hqpitch)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFaster |
RubberBandStretcher::OptionProcessRealTime |
RubberBandStretcher::OptionPitchHighQuality,
0.5, 1.5,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_fast_higher_realtime_faster_hcpitch)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFaster |
RubberBandStretcher::OptionProcessRealTime |
RubberBandStretcher::OptionPitchHighConsistency,
0.5, 1.5,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_slow_lower_realtime_finer) BOOST_AUTO_TEST_CASE(sinusoid_slow_lower_realtime_finer)
{ {
sinusoid_realtime(RubberBandStretcher::OptionEngineFiner | sinusoid_realtime(RubberBandStretcher::OptionEngineFiner |
@@ -570,6 +517,149 @@ BOOST_AUTO_TEST_CASE(sinusoid_slow_lower_realtime_finer_hcpitch)
false); false);
} }
BOOST_AUTO_TEST_CASE(sinusoid_slow_samepitch_realtime_finer_short)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFiner |
RubberBandStretcher::OptionProcessRealTime |
RubberBandStretcher::OptionWindowShort,
8.0, 1.0,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_fast_samepitch_realtime_finer_short)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFiner |
RubberBandStretcher::OptionProcessRealTime |
RubberBandStretcher::OptionWindowShort,
0.5, 1.0,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_slow_higher_realtime_finer_short)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFiner |
RubberBandStretcher::OptionProcessRealTime |
RubberBandStretcher::OptionWindowShort,
4.0, 1.5,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_slow_higher_realtime_finer_short_hcpitch)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFiner |
RubberBandStretcher::OptionProcessRealTime |
RubberBandStretcher::OptionWindowShort |
RubberBandStretcher::OptionPitchHighConsistency,
4.0, 1.5,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_fast_higher_realtime_finer_short)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFiner |
RubberBandStretcher::OptionProcessRealTime |
RubberBandStretcher::OptionWindowShort,
0.5, 1.5,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_fast_higher_realtime_finer_hcpitch_short)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFiner |
RubberBandStretcher::OptionProcessRealTime |
RubberBandStretcher::OptionWindowShort |
RubberBandStretcher::OptionPitchHighConsistency,
0.5, 1.5,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_slow_lower_realtime_finer_short)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFiner |
RubberBandStretcher::OptionProcessRealTime |
RubberBandStretcher::OptionWindowShort,
8.0, 0.5,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_slow_lower_realtime_finer_short_hcpitch)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFiner |
RubberBandStretcher::OptionProcessRealTime |
RubberBandStretcher::OptionWindowShort |
RubberBandStretcher::OptionPitchHighConsistency,
8.0, 0.5,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_slow_samepitch_realtime_faster)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFaster |
RubberBandStretcher::OptionProcessRealTime,
8.0, 1.0,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_fast_samepitch_realtime_faster)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFaster |
RubberBandStretcher::OptionProcessRealTime,
0.5, 1.0,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_slow_higher_realtime_faster)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFaster |
RubberBandStretcher::OptionProcessRealTime,
4.0, 1.5,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_slow_higher_realtime_faster_hqpitch)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFaster |
RubberBandStretcher::OptionProcessRealTime |
RubberBandStretcher::OptionPitchHighQuality,
4.0, 1.5,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_slow_higher_realtime_faster_hcpitch)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFaster |
RubberBandStretcher::OptionProcessRealTime |
RubberBandStretcher::OptionPitchHighConsistency,
4.0, 1.5,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_fast_higher_realtime_faster)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFaster |
RubberBandStretcher::OptionProcessRealTime,
0.5, 1.5,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_fast_higher_realtime_faster_hqpitch)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFaster |
RubberBandStretcher::OptionProcessRealTime |
RubberBandStretcher::OptionPitchHighQuality,
0.5, 1.5,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_fast_higher_realtime_faster_hcpitch)
{
sinusoid_realtime(RubberBandStretcher::OptionEngineFaster |
RubberBandStretcher::OptionProcessRealTime |
RubberBandStretcher::OptionPitchHighConsistency,
0.5, 1.5,
false);
}
BOOST_AUTO_TEST_CASE(sinusoid_slow_lower_realtime_faster) BOOST_AUTO_TEST_CASE(sinusoid_slow_lower_realtime_faster)
{ {
sinusoid_realtime(RubberBandStretcher::OptionEngineFaster | sinusoid_realtime(RubberBandStretcher::OptionEngineFaster |
@@ -803,7 +893,142 @@ BOOST_AUTO_TEST_CASE(impulses_2x_5up_offline_finer)
} }
*/ */
} }
static void impulses_realtime(RubberBandStretcher::Options options,
double timeRatio,
double pitchScale,
bool printDebug)
{
int n = 10000;
int nOut = int(ceil(n * timeRatio));
int rate = 48000;
int bs = 1024;
RubberBandStretcher stretcher(rate, 1, options, timeRatio, pitchScale);
if (printDebug) {
stretcher.setDebugLevel(2);
}
vector<float> in(n, 0.f);
in[100] = 1.f;
in[101] = -1.f;
in[5000] = 1.f;
in[5001] = -1.f;
in[9900] = 1.f;
in[9901] = -1.f;
vector<float> out = process_realtime(stretcher, in, nOut, bs, printDebug);
int peak0 = -1, peak1 = -1, peak2 = -1;
float max;
max = -2.f;
for (int i = 0; i < nOut/4; ++i) {
if (out[i] > max) { max = out[i]; peak0 = i; }
}
max = -2.f;
for (int i = nOut/4; i < (nOut*3)/4; ++i) {
if (out[i] > max) { max = out[i]; peak1 = i; }
}
max = -2.f;
for (int i = (nOut*3)/4; i < nOut; ++i) {
if (out[i] > max) { max = out[i]; peak2 = i; }
}
// These limits aren't alarming, but it be worth tightening them
// and and taking a look at the waveforms
BOOST_TEST(peak0 < int(ceil(200 * timeRatio)));
BOOST_TEST(peak0 > int(ceil(50 * timeRatio)));
BOOST_TEST(peak1 < int(ceil(5070 * timeRatio)));
BOOST_TEST(peak1 > int(ceil(4840 * timeRatio)));
BOOST_TEST(peak2 < int(ceil(9970 * timeRatio)));
BOOST_TEST(peak2 > int(ceil(9770 * timeRatio)));
/* /*
std::cout << "ms\tV" << std::endl;
for (int i = 0; i < n*2; ++i) {
std::cout << i << "\t" << out[i] << std::endl;
}
*/
}
BOOST_AUTO_TEST_CASE(impulses_slow_samepitch_realtime_finer)
{
impulses_realtime(RubberBandStretcher::OptionEngineFiner |
RubberBandStretcher::OptionProcessRealTime,
8.0, 1.0,
false);
}
BOOST_AUTO_TEST_CASE(impulses_fast_samepitch_realtime_finer)
{
impulses_realtime(RubberBandStretcher::OptionEngineFiner |
RubberBandStretcher::OptionProcessRealTime,
0.5, 1.0,
false);
}
BOOST_AUTO_TEST_CASE(impulses_slow_higher_realtime_finer)
{
impulses_realtime(RubberBandStretcher::OptionEngineFiner |
RubberBandStretcher::OptionProcessRealTime,
4.0, 1.5,
false);
}
BOOST_AUTO_TEST_CASE(impulses_slow_higher_realtime_finer_hqpitch)
{
impulses_realtime(RubberBandStretcher::OptionEngineFiner |
RubberBandStretcher::OptionProcessRealTime |
RubberBandStretcher::OptionPitchHighQuality,
4.0, 1.5,
false);
}
BOOST_AUTO_TEST_CASE(impulses_slow_higher_realtime_finer_hcpitch)
{
impulses_realtime(RubberBandStretcher::OptionEngineFiner |
RubberBandStretcher::OptionProcessRealTime |
RubberBandStretcher::OptionPitchHighConsistency,
4.0, 1.5,
false);
}
BOOST_AUTO_TEST_CASE(impulses_slow_lower_realtime_finer)
{
impulses_realtime(RubberBandStretcher::OptionEngineFiner |
RubberBandStretcher::OptionProcessRealTime,
8.0, 0.5,
false);
}
BOOST_AUTO_TEST_CASE(impulses_slow_lower_realtime_finer_hqpitch)
{
impulses_realtime(RubberBandStretcher::OptionEngineFiner |
RubberBandStretcher::OptionProcessRealTime |
RubberBandStretcher::OptionPitchHighQuality,
8.0, 0.5,
false);
}
BOOST_AUTO_TEST_CASE(impulses_slow_lower_realtime_finer_hcpitch)
{
impulses_realtime(RubberBandStretcher::OptionEngineFiner |
RubberBandStretcher::OptionProcessRealTime |
RubberBandStretcher::OptionPitchHighConsistency,
8.0, 0.5,
false);
}
BOOST_AUTO_TEST_CASE(final_realtime_faster) BOOST_AUTO_TEST_CASE(final_realtime_faster)
{ {
int n = 10000; int n = 10000;
@@ -845,11 +1070,18 @@ BOOST_AUTO_TEST_CASE(final_realtime_faster)
float *out = outp + outcount; float *out = outp + outcount;
size_t got = stretcher.retrieve(&out, avail); size_t got = stretcher.retrieve(&out, avail);
BOOST_TEST(got == size_t(avail)); BOOST_TEST(got == size_t(avail));
BOOST_TEST(stretcher.available() == 0);
incount += inbs; incount += inbs;
outcount += got; outcount += got;
cerr << "outcount = " << outcount << ", n = " << n << endl;
if (outcount >= n * 2) {
BOOST_TEST(stretcher.available() == -1);
} else {
BOOST_TEST(stretcher.available() == 0);
}
} }
} }
*/
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()