Merge from branch resetcheck
This commit is contained in:
@@ -223,6 +223,8 @@ R2Stretcher::reset()
|
|||||||
m_mode = JustCreated;
|
m_mode = JustCreated;
|
||||||
if (m_phaseResetAudioCurve) m_phaseResetAudioCurve->reset();
|
if (m_phaseResetAudioCurve) m_phaseResetAudioCurve->reset();
|
||||||
if (m_silentAudioCurve) m_silentAudioCurve->reset();
|
if (m_silentAudioCurve) m_silentAudioCurve->reset();
|
||||||
|
m_expectedInputDuration = 0;
|
||||||
|
m_maxProcessSize = 0;
|
||||||
m_inputDuration = 0;
|
m_inputDuration = 0;
|
||||||
m_silentHistory = 0;
|
m_silentHistory = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,17 @@ public:
|
|||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
|
while (m_vfQueue.getReadSpace() > 0) {
|
||||||
|
process_t *entry = m_vfQueue.readOne();
|
||||||
|
deallocate(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < m_parameters.horizontalFilterLag; ++i) {
|
||||||
|
process_t *entry =
|
||||||
|
allocate_and_zero<process_t>(m_parameters.binCount);
|
||||||
|
m_vfQueue.write(&entry, 1);
|
||||||
|
}
|
||||||
|
|
||||||
m_hFilters->reset();
|
m_hFilters->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,12 @@ R3Stretcher::R3Stretcher(Parameters parameters,
|
|||||||
{
|
{
|
||||||
Profiler profiler("R3Stretcher::R3Stretcher");
|
Profiler profiler("R3Stretcher::R3Stretcher");
|
||||||
|
|
||||||
|
initialise();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
R3Stretcher::initialise()
|
||||||
|
{
|
||||||
m_log.log(1, "R3Stretcher::R3Stretcher: rate, options",
|
m_log.log(1, "R3Stretcher::R3Stretcher: rate, options",
|
||||||
m_parameters.sampleRate, m_parameters.options);
|
m_parameters.sampleRate, m_parameters.options);
|
||||||
m_log.log(1, "R3Stretcher::R3Stretcher: initial time ratio and pitch scale",
|
m_log.log(1, "R3Stretcher::R3Stretcher: initial time ratio and pitch scale",
|
||||||
@@ -99,6 +105,8 @@ R3Stretcher::R3Stretcher(Parameters parameters,
|
|||||||
int inRingBufferSize = getWindowSourceSize() * 16;
|
int inRingBufferSize = getWindowSourceSize() * 16;
|
||||||
int outRingBufferSize = getWindowSourceSize() * 16;
|
int outRingBufferSize = getWindowSourceSize() * 16;
|
||||||
|
|
||||||
|
m_channelData.clear();
|
||||||
|
|
||||||
for (int c = 0; c < m_parameters.channels; ++c) {
|
for (int c = 0; c < m_parameters.channels; ++c) {
|
||||||
m_channelData.push_back(std::make_shared<ChannelData>
|
m_channelData.push_back(std::make_shared<ChannelData>
|
||||||
(segmenterParameters,
|
(segmenterParameters,
|
||||||
@@ -116,6 +124,8 @@ R3Stretcher::R3Stretcher(Parameters parameters,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_scaleData.clear();
|
||||||
|
|
||||||
for (int b = 0; b < m_guideConfiguration.fftBandLimitCount; ++b) {
|
for (int b = 0; b < m_guideConfiguration.fftBandLimitCount; ++b) {
|
||||||
const auto &band = m_guideConfiguration.fftBandLimits[b];
|
const auto &band = m_guideConfiguration.fftBandLimits[b];
|
||||||
int fftSize = band.fftSize;
|
int fftSize = band.fftSize;
|
||||||
@@ -141,9 +151,6 @@ R3Stretcher::R3Stretcher(Parameters parameters,
|
|||||||
|
|
||||||
calculateHop();
|
calculateHop();
|
||||||
|
|
||||||
m_prevInhop = m_inhop;
|
|
||||||
m_prevOuthop = int(round(m_inhop * getEffectiveRatio()));
|
|
||||||
|
|
||||||
if (!m_inhop.is_lock_free()) {
|
if (!m_inhop.is_lock_free()) {
|
||||||
m_log.log(0, "R3Stretcher: WARNING: std::atomic<int> is not lock-free");
|
m_log.log(0, "R3Stretcher: WARNING: std::atomic<int> is not lock-free");
|
||||||
}
|
}
|
||||||
@@ -382,12 +389,17 @@ R3Stretcher::calculateHop()
|
|||||||
m_log.log(1, "calculateHop: inhop and mean outhop", m_inhop, m_inhop * ratio);
|
m_log.log(1, "calculateHop: inhop and mean outhop", m_inhop, m_inhop * ratio);
|
||||||
|
|
||||||
if (m_inhop < m_limits.maxInhopWithReadahead) {
|
if (m_inhop < m_limits.maxInhopWithReadahead) {
|
||||||
m_log.log(1, "calculateHop: using readahead");
|
m_log.log(1, "calculateHop: using readahead; maxInhopWithReadahead", m_limits.maxInhopWithReadahead);
|
||||||
m_useReadahead = true;
|
m_useReadahead = true;
|
||||||
} else {
|
} else {
|
||||||
m_log.log(1, "calculateHop: not using readahead, inhop too long for buffer in current configuration");
|
m_log.log(1, "calculateHop: not using readahead; maxInhopWithReadahead", m_limits.maxInhopWithReadahead);
|
||||||
m_useReadahead = false;
|
m_useReadahead = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_mode == ProcessMode::JustCreated) {
|
||||||
|
m_prevInhop = m_inhop;
|
||||||
|
m_prevOuthop = int(round(m_inhop * getEffectiveRatio()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -532,7 +544,23 @@ R3Stretcher::getChannelCount() const
|
|||||||
void
|
void
|
||||||
R3Stretcher::reset()
|
R3Stretcher::reset()
|
||||||
{
|
{
|
||||||
|
m_inhop = 1;
|
||||||
|
m_prevInhop = 1;
|
||||||
|
m_prevOuthop = 1;
|
||||||
|
m_unityCount = 0;
|
||||||
|
m_startSkip = 0;
|
||||||
|
m_studyInputDuration = 0;
|
||||||
|
m_suppliedInputDuration = 0;
|
||||||
|
m_totalTargetDuration = 0;
|
||||||
|
m_consumedInputDuration = 0;
|
||||||
|
m_lastKeyFrameSurpassed = 0;
|
||||||
|
m_totalOutputDuration = 0;
|
||||||
|
m_keyFrameMap.clear();
|
||||||
|
|
||||||
|
m_mode = ProcessMode::JustCreated;
|
||||||
|
|
||||||
m_calculator->reset();
|
m_calculator->reset();
|
||||||
|
|
||||||
if (m_resampler) {
|
if (m_resampler) {
|
||||||
m_resampler->reset();
|
m_resampler->reset();
|
||||||
}
|
}
|
||||||
@@ -545,18 +573,7 @@ R3Stretcher::reset()
|
|||||||
cd->reset();
|
cd->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_prevInhop = m_inhop;
|
calculateHop();
|
||||||
m_prevOuthop = int(round(m_inhop * getEffectiveRatio()));
|
|
||||||
|
|
||||||
m_studyInputDuration = 0;
|
|
||||||
m_suppliedInputDuration = 0;
|
|
||||||
m_totalTargetDuration = 0;
|
|
||||||
m_consumedInputDuration = 0;
|
|
||||||
m_lastKeyFrameSurpassed = 0;
|
|
||||||
m_totalOutputDuration = 0;
|
|
||||||
m_keyFrameMap.clear();
|
|
||||||
|
|
||||||
m_mode = ProcessMode::JustCreated;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -114,8 +114,8 @@ protected:
|
|||||||
minPreferredOuthop(roundUpDiv(rate, 512)), // 128
|
minPreferredOuthop(roundUpDiv(rate, 512)), // 128
|
||||||
maxPreferredOuthop(roundUpDiv(rate, 128)), // 512
|
maxPreferredOuthop(roundUpDiv(rate, 128)), // 512
|
||||||
minInhop(1),
|
minInhop(1),
|
||||||
maxInhopWithReadahead(roundUpDiv(rate, 32)), // 1024
|
maxInhopWithReadahead(roundUpDiv(rate, 64)), // 1024
|
||||||
maxInhop(roundUpDiv(rate, 32)) { // 1024
|
maxInhop(roundUpDiv(rate, 32)) { // 2048
|
||||||
if (options & RubberBandStretcher::OptionWindowShort) {
|
if (options & RubberBandStretcher::OptionWindowShort) {
|
||||||
// See note in calculateHop
|
// See note in calculateHop
|
||||||
minPreferredOuthop = roundUpDiv(rate, 256); // 256
|
minPreferredOuthop = roundUpDiv(rate, 256); // 256
|
||||||
@@ -172,6 +172,7 @@ protected:
|
|||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
v_zero(prevMag.data(), prevMag.size());
|
v_zero(prevMag.data(), prevMag.size());
|
||||||
|
v_zero(pendingKick.data(), pendingKick.size());
|
||||||
v_zero(accumulator.data(), accumulator.size());
|
v_zero(accumulator.data(), accumulator.size());
|
||||||
accumulatorFill = 0;
|
accumulatorFill = 0;
|
||||||
}
|
}
|
||||||
@@ -226,7 +227,7 @@ protected:
|
|||||||
std::unique_ptr<FormantData> formant;
|
std::unique_ptr<FormantData> formant;
|
||||||
ChannelData(BinSegmenter::Parameters segmenterParameters,
|
ChannelData(BinSegmenter::Parameters segmenterParameters,
|
||||||
BinClassifier::Parameters classifierParameters,
|
BinClassifier::Parameters classifierParameters,
|
||||||
int longestFftSize,
|
int /*!!! longestFftSize */,
|
||||||
int windowSourceSize,
|
int windowSourceSize,
|
||||||
int inRingBufferSize,
|
int inRingBufferSize,
|
||||||
int outRingBufferSize) :
|
int outRingBufferSize) :
|
||||||
@@ -252,6 +253,9 @@ protected:
|
|||||||
segmentation = BinSegmenter::Segmentation();
|
segmentation = BinSegmenter::Segmentation();
|
||||||
prevSegmentation = BinSegmenter::Segmentation();
|
prevSegmentation = BinSegmenter::Segmentation();
|
||||||
nextSegmentation = BinSegmenter::Segmentation();
|
nextSegmentation = BinSegmenter::Segmentation();
|
||||||
|
for (size_t i = 0; i < nextClassification.size(); ++i) {
|
||||||
|
nextClassification[i] = BinClassifier::Classification::Residual;
|
||||||
|
}
|
||||||
inbuf->reset();
|
inbuf->reset();
|
||||||
outbuf->reset();
|
outbuf->reset();
|
||||||
for (auto &s : scales) {
|
for (auto &s : scales) {
|
||||||
@@ -352,6 +356,7 @@ protected:
|
|||||||
};
|
};
|
||||||
ProcessMode m_mode;
|
ProcessMode m_mode;
|
||||||
|
|
||||||
|
void initialise();
|
||||||
void prepareInput(const float *const *input, int ix, int n);
|
void prepareInput(const float *const *input, int ix, int n);
|
||||||
void consume();
|
void consume();
|
||||||
void createResampler();
|
void createResampler();
|
||||||
|
|||||||
@@ -881,7 +881,7 @@ BOOST_AUTO_TEST_CASE(impulses_2x_5up_offline_finer)
|
|||||||
if (out[i] > max) { max = out[i]; peak2 = i; }
|
if (out[i] > max) { max = out[i]; peak2 = i; }
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_TEST(peak0 < 100);
|
BOOST_TEST(peak0 < 250);
|
||||||
BOOST_TEST(peak1 > n - 400);
|
BOOST_TEST(peak1 > n - 400);
|
||||||
BOOST_TEST(peak1 < n + 50);
|
BOOST_TEST(peak1 < n + 50);
|
||||||
BOOST_TEST(peak2 > n*2 - 600);
|
BOOST_TEST(peak2 > n*2 - 600);
|
||||||
@@ -1251,5 +1251,212 @@ BOOST_AUTO_TEST_CASE(final_fast_lower_realtime_finer_after)
|
|||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void with_resets(RubberBandStretcher::Options options,
|
||||||
|
double timeRatio,
|
||||||
|
double pitchScale)
|
||||||
|
{
|
||||||
|
const int n = 10000;
|
||||||
|
const int nOut = int(round(n * timeRatio));
|
||||||
|
const int rate = 44100;
|
||||||
|
const bool realtime =
|
||||||
|
(options & RubberBandStretcher::OptionProcessRealTime);
|
||||||
|
|
||||||
|
vector<float> in(n, 0.f), outRef(nOut, 0.f), out(nOut, 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;
|
||||||
|
|
||||||
|
int nExpected = 0;
|
||||||
|
|
||||||
|
RubberBandStretcher *stretcher = nullptr;
|
||||||
|
|
||||||
|
// Combinations we need to ensure produce identical outputs:
|
||||||
|
// 1. With timeRatio and pitchScale passed to constructor
|
||||||
|
// 2. Then reset called and run again
|
||||||
|
// 3. New instance, no ratios passed to ctor, timeRatio and
|
||||||
|
// pitchScale set after construction
|
||||||
|
// 4. Then reset called and run again
|
||||||
|
// 5. Reset called again, timeRatio and pitchScale set again (to
|
||||||
|
// the same things, just in case the act of setting them
|
||||||
|
// changes anything) and run again
|
||||||
|
// 6. More input supplied and left in stretcher (output not
|
||||||
|
// retrieved) - then reset called and run again
|
||||||
|
|
||||||
|
for (int run = 1; run <= 6; ++run) { // run being index into list above
|
||||||
|
|
||||||
|
float *inp = in.data(), *outp = out.data();
|
||||||
|
|
||||||
|
if (run == 1 || run == 3) {
|
||||||
|
delete stretcher;
|
||||||
|
if (run == 1) {
|
||||||
|
stretcher = new RubberBandStretcher(rate, 1, options,
|
||||||
|
timeRatio, pitchScale);
|
||||||
|
} else {
|
||||||
|
stretcher = new RubberBandStretcher(rate, 1, options);
|
||||||
|
stretcher->setTimeRatio(timeRatio);
|
||||||
|
stretcher->setPitchScale(pitchScale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (run == 2 || run > 3) {
|
||||||
|
stretcher->reset();
|
||||||
|
if (run == 5) {
|
||||||
|
stretcher->setTimeRatio(timeRatio);
|
||||||
|
stretcher->setPitchScale(pitchScale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (run == 6) {
|
||||||
|
if (realtime) {
|
||||||
|
stretcher->process(&inp, n / 2, false);
|
||||||
|
} else {
|
||||||
|
stretcher->study(&inp, n / 2, true);
|
||||||
|
stretcher->process(&inp, n / 2, false);
|
||||||
|
}
|
||||||
|
stretcher->reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// In every case we request nOut samples into out, and nActual
|
||||||
|
// records how many we actually get
|
||||||
|
int nActual = 0;
|
||||||
|
|
||||||
|
if (realtime) {
|
||||||
|
|
||||||
|
int blocksize = 1024;
|
||||||
|
int nIn = 0;
|
||||||
|
|
||||||
|
while (nActual < nOut) {
|
||||||
|
int bsHere = blocksize;
|
||||||
|
bool final = false;
|
||||||
|
if (nIn + blocksize > n) {
|
||||||
|
bsHere = n - nIn;
|
||||||
|
final = true;
|
||||||
|
}
|
||||||
|
stretcher->process(&inp, bsHere, final);
|
||||||
|
nIn += bsHere;
|
||||||
|
inp += bsHere;
|
||||||
|
int avail = stretcher->available();
|
||||||
|
if (avail < 0) break;
|
||||||
|
int toGet = avail;
|
||||||
|
if (nActual + toGet > nOut) {
|
||||||
|
toGet = nOut - nActual;
|
||||||
|
}
|
||||||
|
int got = (int)stretcher->retrieve(&outp, toGet);
|
||||||
|
nActual += got;
|
||||||
|
outp += got;
|
||||||
|
if (final) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST(nActual <= nOut);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
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() == nOut);
|
||||||
|
|
||||||
|
BOOST_TEST(stretcher->getStartDelay() == 0); // offline mode
|
||||||
|
|
||||||
|
nActual = (int)stretcher->retrieve(&outp, nOut);
|
||||||
|
BOOST_TEST(nActual == nOut);
|
||||||
|
BOOST_TEST(stretcher->available() == -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (run == 1) { // set up expectations for subsequent runs
|
||||||
|
|
||||||
|
for (int i = 0; i < nActual; ++i) {
|
||||||
|
outRef[i] = out[i];
|
||||||
|
}
|
||||||
|
nExpected = nActual;
|
||||||
|
|
||||||
|
} else { // check expectations
|
||||||
|
|
||||||
|
BOOST_TEST(nActual == nExpected);
|
||||||
|
|
||||||
|
for (int i = 0; i < nActual; ++i) {
|
||||||
|
BOOST_TEST(out[i] == outRef[i]);
|
||||||
|
if (out[i] != outRef[i]) {
|
||||||
|
std::cerr << "Failure at index " << i << " in run "
|
||||||
|
<< run << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete stretcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(with_resets_1x_0up_offline_finer)
|
||||||
|
{
|
||||||
|
with_resets(RubberBandStretcher::OptionEngineFiner, 1.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(with_resets_2x_0up_offline_finer)
|
||||||
|
{
|
||||||
|
with_resets(RubberBandStretcher::OptionEngineFiner, 2.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(with_resets_2x_5up_offline_finer)
|
||||||
|
{
|
||||||
|
with_resets(RubberBandStretcher::OptionEngineFiner, 2.0, 1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(with_resets_1x_0up_offline_faster)
|
||||||
|
{
|
||||||
|
with_resets(RubberBandStretcher::OptionEngineFaster, 1.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(with_resets_2x_0up_offline_faster)
|
||||||
|
{
|
||||||
|
with_resets(RubberBandStretcher::OptionEngineFaster, 2.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(with_resets_2x_5up_offline_faster)
|
||||||
|
{
|
||||||
|
with_resets(RubberBandStretcher::OptionEngineFaster, 2.0, 1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(with_resets_1x_0up_realtime_finer)
|
||||||
|
{
|
||||||
|
with_resets(RubberBandStretcher::OptionProcessRealTime | RubberBandStretcher::OptionEngineFiner, 1.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(with_resets_2x_0up_realtime_finer)
|
||||||
|
{
|
||||||
|
with_resets(RubberBandStretcher::OptionProcessRealTime | RubberBandStretcher::OptionEngineFiner, 2.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(with_resets_2x_5up_realtime_finer)
|
||||||
|
{
|
||||||
|
with_resets(RubberBandStretcher::OptionProcessRealTime | RubberBandStretcher::OptionEngineFiner, 2.0, 1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(with_resets_1x_0up_realtime_faster)
|
||||||
|
{
|
||||||
|
with_resets(RubberBandStretcher::OptionProcessRealTime | RubberBandStretcher::OptionEngineFaster, 1.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(with_resets_2x_0up_realtime_faster)
|
||||||
|
{
|
||||||
|
with_resets(RubberBandStretcher::OptionProcessRealTime | RubberBandStretcher::OptionEngineFaster, 2.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(with_resets_2x_5up_realtime_faster)
|
||||||
|
{
|
||||||
|
with_resets(RubberBandStretcher::OptionProcessRealTime | RubberBandStretcher::OptionEngineFaster, 2.0, 1.5);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|||||||
Reference in New Issue
Block a user