From 3b168ca55eeafe8be5029381c7c0b7029935fe75 Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Thu, 23 Jun 2022 15:13:48 +0100 Subject: [PATCH] Initial simple test --- meson.build | 1 + src/test/TestStretcher.cpp | 88 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 src/test/TestStretcher.cpp diff --git a/meson.build b/meson.build index 8345d48..28786fc 100644 --- a/meson.build +++ b/meson.build @@ -93,6 +93,7 @@ unit_test_sources = [ 'src/test/TestVectorOps.cpp', 'src/test/TestSignalBits.cpp', 'src/test/TestStretchCalculator.cpp', + 'src/test/TestStretcher.cpp', 'src/test/TestBinClassifier.cpp', 'src/test/test.cpp', ] diff --git a/src/test/TestStretcher.cpp b/src/test/TestStretcher.cpp new file mode 100644 index 0000000..db29c66 --- /dev/null +++ b/src/test/TestStretcher.cpp @@ -0,0 +1,88 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rubber Band Library + An audio time-stretching and pitch-shifting library. + Copyright 2007-2022 Particular Programs Ltd. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. + + Alternatively, if you have a valid commercial licence for the + Rubber Band Library obtained by agreement with the copyright + holders, you may redistribute and/or modify it under the terms + described in that licence. + + If you wish to distribute code using the Rubber Band Library + under terms other than those of the GNU General Public License, + you must obtain a valid commercial licence before doing so. +*/ + +#define BOOST_TEST_DYN_LINK +#include + +#include "../../rubberband/RubberBandStretcher.h" + +#include + +#include + +using namespace RubberBand; +using namespace std; +namespace tt = boost::test_tools; + +BOOST_AUTO_TEST_SUITE(TestStretcher) + +BOOST_AUTO_TEST_CASE(sinusoid_unchanged_single_offline) +{ + int n = 10000; + float freq = 440.f; + int rate = 44100; + RubberBandStretcher stretcher(rate, 1); + vector in(n), out(n); + for (int i = 0; i < n; ++i) { + in[i] = sinf(float(i) * freq * M_PI * 2.f / float(rate)); + } + float *inp = in.data(), *outp = out.data(); + + stretcher.setMaxProcessSize(n); + stretcher.setExpectedInputDuration(n); + BOOST_TEST(stretcher.available() == 0); + + stretcher.study(&inp, n, true); + BOOST_TEST(stretcher.available() == 0); + + stretcher.process(&inp, n, true); + BOOST_TEST(stretcher.available() == n); + + size_t got = stretcher.retrieve(&outp, n); + BOOST_TEST(got == n); + BOOST_TEST(stretcher.available() == -1); + + // We now have n samples of a simple sinusoid with stretch factor + // 1.0; obviously we expect the output to be essentially the same + // thing. It will have lower precision for a while at the start + // and end because of windowing factors, so we check those with a + // threshold of 0.1; in the middle we expect better precision. + + // This syntax for comparing containers with a certain tolerance + // using BOOST_TEST is just bonkers. I can't find the << syntax to + // combine manipulators documented anywhere other than in a + // release note, but it does work. Well, sort of - it works this + // way around but not as per_element << tolerance. And + // tolerance(0.1) doesn't do what you'd expect if the things + // you're comparing are floats (it sets the tolerance for doubles, + // leaving float comparison unchanged). Clever... too clever. + + BOOST_TEST(in == out, + tt::tolerance(0.1f) << tt::per_element()); + + BOOST_TEST(vector(in.begin() + 1000, in.begin() + n - 1000) == + vector(out.begin() + 1000, out.begin() + n - 1000), + tt::tolerance(0.0001f) << tt::per_element()); +} + +BOOST_AUTO_TEST_SUITE_END()