From 567e8636cdcc5407b8b9c15ed2a34b52850b560b Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Wed, 6 Jul 2022 10:40:10 +0100 Subject: [PATCH] Enable PROCESS_SAMPLE_TYPE for R3 as well, switching from double to process_t throughout --- src/finer/BinClassifier.h | 36 +++++++++++------------ src/finer/Guide.h | 18 ++++++------ src/finer/PhaseAdvance.h | 52 +++++++++++++++++----------------- src/finer/R3Stretcher.cpp | 24 ++++++++-------- src/finer/R3Stretcher.h | 52 +++++++++++++++++----------------- src/test/TestBinClassifier.cpp | 4 ++- 6 files changed, 94 insertions(+), 92 deletions(-) diff --git a/src/finer/BinClassifier.h b/src/finer/BinClassifier.h index 80069a9..2c58d29 100644 --- a/src/finer/BinClassifier.h +++ b/src/finer/BinClassifier.h @@ -62,18 +62,18 @@ public: BinClassifier(Parameters parameters) : m_parameters(parameters), - m_hFilters(new MovingMedianStack(m_parameters.binCount, - m_parameters.horizontalFilterLength)), - m_vFilter(new MovingMedian(m_parameters.verticalFilterLength)), + m_hFilters(new MovingMedianStack(m_parameters.binCount, + m_parameters.horizontalFilterLength)), + m_vFilter(new MovingMedian(m_parameters.verticalFilterLength)), m_vfQueue(parameters.horizontalFilterLag) { int n = m_parameters.binCount; - m_hf = allocate_and_zero(n); - m_vf = allocate_and_zero(n); + m_hf = allocate_and_zero(n); + m_vf = allocate_and_zero(n); for (int i = 0; i < m_parameters.horizontalFilterLag; ++i) { - double *entry = allocate_and_zero(n); + process_t *entry = allocate_and_zero(n); m_vfQueue.write(&entry, 1); } } @@ -81,7 +81,7 @@ public: ~BinClassifier() { while (m_vfQueue.getReadSpace() > 0) { - double *entry = m_vfQueue.readOne(); + process_t *entry = m_vfQueue.readOne(); deallocate(entry); } @@ -94,7 +94,7 @@ public: m_hFilters->reset(); } - void classify(const double *const mag, // input, of at least binCount bins + void classify(const process_t *const mag, // input, of at least binCount bins Classification *classification) // output, of binCount bins { const int n = m_parameters.binCount; @@ -105,22 +105,22 @@ public: } v_copy(m_vf, mag, n); - MovingMedian::filter(*m_vFilter, m_vf, n); + MovingMedian::filter(*m_vFilter, m_vf, n); if (m_parameters.horizontalFilterLag > 0) { - double *lagged = m_vfQueue.readOne(); + process_t *lagged = m_vfQueue.readOne(); m_vfQueue.write(&m_vf, 1); m_vf = lagged; } - double eps = 1.0e-7; + process_t eps = 1.0e-7; for (int i = 0; i < n; ++i) { Classification c; - if (double(m_hf[i]) / (double(m_vf[i]) + eps) > + if (process_t(m_hf[i]) / (process_t(m_vf[i]) + eps) > m_parameters.harmonicThreshold) { c = Classification::Harmonic; - } else if (double(m_vf[i]) / (double(m_hf[i]) + eps) > + } else if (process_t(m_vf[i]) / (process_t(m_hf[i]) + eps) > m_parameters.percussiveThreshold) { c = Classification::Percussive; } else { @@ -132,13 +132,13 @@ public: protected: Parameters m_parameters; - std::unique_ptr> m_hFilters; - std::unique_ptr> m_vFilter; + std::unique_ptr> m_hFilters; + std::unique_ptr> m_vFilter; // We manage the queued frames through pointer swapping, hence // bare pointers here - double *m_hf; - double *m_vf; - RingBuffer m_vfQueue; + process_t *m_hf; + process_t *m_vf; + RingBuffer m_vfQueue; BinClassifier(const BinClassifier &) =delete; BinClassifier &operator=(const BinClassifier &) =delete; diff --git a/src/finer/Guide.h b/src/finer/Guide.h index 50b3cf8..108fd27 100644 --- a/src/finer/Guide.h +++ b/src/finer/Guide.h @@ -147,13 +147,13 @@ public: void updateGuidance(double ratio, int outhop, - const double *const magnitudes, - const double *const prevMagnitudes, - const double *const nextMagnitudes, + const process_t *const magnitudes, + const process_t *const prevMagnitudes, + const process_t *const nextMagnitudes, const BinSegmenter::Segmentation &segmentation, const BinSegmenter::Segmentation &prevSegmentation, const BinSegmenter::Segmentation &nextSegmentation, - double meanMagnitude, + process_t meanMagnitude, int unityCount, bool realtime, bool tighterChannelLock, @@ -388,7 +388,7 @@ protected: void updateForUnity(Guidance &guidance, bool hadPhaseReset, uint32_t /* unityCount */, - const double *const /* magnitudes */, + const process_t *const /* magnitudes */, const BinSegmenter::Segmentation &segmentation, bool realtime) const { @@ -449,11 +449,11 @@ protected: // } } - bool checkPotentialKick(const double *const magnitudes, - const double *const prevMagnitudes) const { + bool checkPotentialKick(const process_t *const magnitudes, + const process_t *const prevMagnitudes) const { int b = binForFrequency(200.0, m_configuration.classificationFftSize, m_parameters.sampleRate); - double here = 0.0, there = 0.0; + process_t here = 0.0, there = 0.0; for (int i = 1; i <= b; ++i) { here += magnitudes[i]; } @@ -463,7 +463,7 @@ protected: return (here > 10.e-3 && here > there * 1.4); } - double descendToValley(double f, const double *const magnitudes) const { + double descendToValley(double f, const process_t *const magnitudes) const { if (f == 0.0 || f == m_parameters.sampleRate/2.0) { // These are special cases return f; diff --git a/src/finer/PhaseAdvance.h b/src/finer/PhaseAdvance.h index b2dd33c..aec35b9 100644 --- a/src/finer/PhaseAdvance.h +++ b/src/finer/PhaseAdvance.h @@ -56,9 +56,9 @@ public: m_currentPeaks = allocate_and_zero_channels(ch, m_binCount); m_prevPeaks = allocate_and_zero_channels(ch, m_binCount); m_greatestChannel = allocate_and_zero(m_binCount); - m_prevInPhase = allocate_and_zero_channels(ch, m_binCount); - m_prevOutPhase = allocate_and_zero_channels(ch, m_binCount); - m_unlocked = allocate_and_zero_channels(ch, m_binCount); + m_prevInPhase = allocate_and_zero_channels(ch, m_binCount); + m_prevOutPhase = allocate_and_zero_channels(ch, m_binCount); + m_unlocked = allocate_and_zero_channels(ch, m_binCount); for (int c = 0; c < ch; ++c) { for (int i = 0; i < m_binCount; ++i) { @@ -84,10 +84,10 @@ public: v_zero_channels(m_prevOutPhase, ch, m_binCount); } - void advance(double *const *outPhase, - const double *const *mag, - const double *const *phase, - const double *const *prevMag, + void advance(process_t *const *outPhase, + const process_t *const *mag, + const process_t *const *phase, + const process_t *const *prevMag, const Guide::Configuration &configuration, const Guide::Guidance *const *guidance, int inhop, @@ -163,14 +163,14 @@ public: v_zero(m_greatestChannel, bs); } - double omegaFactor = 2.0 * M_PI * double(inhop) / - double(m_parameters.fftSize); + process_t omegaFactor = 2.0 * M_PI * process_t(inhop) / + process_t(m_parameters.fftSize); for (int c = 0; c < channels; ++c) { for (int i = lowest; i <= highest; ++i) { - double omega = omegaFactor * double(i); - double expected = m_prevInPhase[c][i] + omega; - double error = princarg(phase[c][i] - expected); - double advance = ratio * (omega + error); + process_t omega = omegaFactor * process_t(i); + process_t expected = m_prevInPhase[c][i] + omega; + process_t error = princarg(phase[c][i] - expected); + process_t advance = ratio * (omega + error); m_unlocked[c][i] = m_prevOutPhase[c][i] + advance; } } @@ -179,12 +179,12 @@ public: const Guide::Guidance *g = guidance[c]; int phaseLockBand = 0; for (int i = lowest; i <= highest; ++i) { - double f = frequencyForBin + process_t f = frequencyForBin (i, m_parameters.fftSize, m_parameters.sampleRate); while (f > g->phaseLockBands[phaseLockBand].f1) { ++phaseLockBand; } - double ph = 0.0; + process_t ph = 0.0; if (inRange(f, g->phaseReset) || inRange(f, g->kick)) { ph = phase[c][i]; } else if (inhop == outhop) { @@ -206,14 +206,14 @@ public: } } } - double peakAdvance = + process_t peakAdvance = m_unlocked[peakCh][peak] - m_prevOutPhase[peakCh][peak]; - double peakNew = + process_t peakNew = m_prevOutPhase[peakCh][prevPeak] + peakAdvance; - double diff = - double(phase[c][i]) - double(phase[peakCh][peak]); - double beta = - double(g->phaseLockBands[phaseLockBand].beta); + process_t diff = + process_t(phase[c][i]) - process_t(phase[peakCh][peak]); + process_t beta = + process_t(g->phaseLockBands[phaseLockBand].beta); ph = peakNew + beta * diff; } outPhase[c][i] = princarg(ph); @@ -238,16 +238,16 @@ protected: Parameters m_parameters; Log m_log; int m_binCount; - Peak m_peakPicker; + Peak m_peakPicker; int **m_currentPeaks; int **m_prevPeaks; int *m_greatestChannel; - double **m_prevInPhase; - double **m_prevOutPhase; - double **m_unlocked; + process_t **m_prevInPhase; + process_t **m_prevOutPhase; + process_t **m_unlocked; bool m_reported; - bool inRange(double f, const Guide::Range &r) { + bool inRange(process_t f, const Guide::Range &r) { return r.present && f >= r.f0 && f < r.f1; } diff --git a/src/finer/R3Stretcher.cpp b/src/finer/R3Stretcher.cpp index 17a3b36..b22cf08 100644 --- a/src/finer/R3Stretcher.cpp +++ b/src/finer/R3Stretcher.cpp @@ -796,7 +796,7 @@ R3Stretcher::analyseChannel(int c, int inhop, int prevInhop, int prevOuthop) int classify = m_guideConfiguration.classificationFftSize; auto &cd = m_channelData.at(c); - double *buf = cd->scales.at(longest)->timeDomain.data(); + process_t *buf = cd->scales.at(longest)->timeDomain.data(); int readSpace = cd->inbuf->getReadSpace(); if (readSpace < longest) { @@ -1074,20 +1074,20 @@ R3Stretcher::adjustFormant(int c) auto &scale = it.second; int highBin = int(floor(fftSize * 10000.0 / m_parameters.sampleRate)); - double targetFactor = double(cd->formant->fftSize) / double(fftSize); - double formantScale = m_formantScale; + process_t targetFactor = process_t(cd->formant->fftSize) / process_t(fftSize); + process_t formantScale = m_formantScale; if (formantScale == 0.0) formantScale = 1.0 / m_pitchScale; - double sourceFactor = targetFactor / formantScale; - double maxRatio = 60.0; - double minRatio = 1.0 / maxRatio; + process_t sourceFactor = targetFactor / formantScale; + process_t maxRatio = 60.0; + process_t minRatio = 1.0 / maxRatio; for (const auto &b : m_guideConfiguration.fftBandLimits) { if (b.fftSize != fftSize) continue; for (int i = b.b0min; i < b.b1max && i < highBin; ++i) { - double source = cd->formant->envelopeAt(i * sourceFactor); - double target = cd->formant->envelopeAt(i * targetFactor); + process_t source = cd->formant->envelopeAt(i * sourceFactor); + process_t target = cd->formant->envelopeAt(i * targetFactor); if (target > 0.0) { - double ratio = source / target; + process_t ratio = source / target; if (ratio < minRatio) ratio = minRatio; if (ratio > maxRatio) ratio = maxRatio; scale->mag[i] *= ratio; @@ -1109,7 +1109,7 @@ R3Stretcher::adjustPreKick(int c) int to = binForFrequency(cd->guidance.preKick.f1, fftSize, m_parameters.sampleRate); for (int i = from; i <= to; ++i) { - double diff = scale->mag[i] - scale->prevMag[i]; + process_t diff = scale->mag[i] - scale->prevMag[i]; if (diff > 0.0) { scale->pendingKick[i] = diff; scale->mag[i] -= diff; @@ -1145,7 +1145,7 @@ R3Stretcher::synthesiseChannel(int c, int outhop) scale->mag.data(), scale->bufSize); - double winscale = double(outhop) / scaleData->windowScaleFactor; + process_t winscale = process_t(outhop) / scaleData->windowScaleFactor; // The frequency filter is applied naively in the frequency // domain. Aliasing is reduced by the shorter resynthesis @@ -1204,7 +1204,7 @@ R3Stretcher::synthesiseChannel(int c, int outhop) for (auto &it : cd->scales) { auto &scale = it.second; - double *accptr = scale->accumulator.data(); + process_t *accptr = scale->accumulator.data(); for (int i = 0; i < outhop; ++i) { mixptr[i] += float(accptr[i]); } diff --git a/src/finer/R3Stretcher.h b/src/finer/R3Stretcher.h index 0f6bc0a..f7bcc0b 100644 --- a/src/finer/R3Stretcher.h +++ b/src/finer/R3Stretcher.h @@ -103,9 +103,9 @@ public: protected: struct ClassificationReadaheadData { - FixedVector timeDomain; - FixedVector mag; - FixedVector phase; + FixedVector timeDomain; + FixedVector mag; + FixedVector phase; ClassificationReadaheadData(int _fftSize) : timeDomain(_fftSize, 0.f), mag(_fftSize/2 + 1, 0.f), @@ -120,15 +120,15 @@ protected: struct ChannelScaleData { int fftSize; int bufSize; // size of every freq-domain array here: fftSize/2 + 1 - FixedVector timeDomain; - FixedVector real; - FixedVector imag; - FixedVector mag; - FixedVector phase; - FixedVector advancedPhase; - FixedVector prevMag; - FixedVector pendingKick; - FixedVector accumulator; + FixedVector timeDomain; + FixedVector real; + FixedVector imag; + FixedVector mag; + FixedVector phase; + FixedVector advancedPhase; + FixedVector prevMag; + FixedVector pendingKick; + FixedVector accumulator; ChannelScaleData(int _fftSize, int _longestFftSize) : fftSize(_fftSize), @@ -156,9 +156,9 @@ protected: struct FormantData { int fftSize; - FixedVector cepstra; - FixedVector envelope; - FixedVector spare; + FixedVector cepstra; + FixedVector envelope; + FixedVector spare; FormantData(int _fftSize) : fftSize(_fftSize), @@ -166,14 +166,14 @@ protected: envelope(_fftSize/2 + 1, 0.0), spare(_fftSize/2 + 1, 0.0) { } - double envelopeAt(double bin) const { + process_t envelopeAt(process_t bin) const { int b0 = int(floor(bin)), b1 = int(ceil(bin)); if (b0 < 0 || b0 > fftSize/2) { return 0.0; } else if (b1 == b0 || b1 > fftSize/2) { return envelope.at(b0); } else { - double diff = bin - double(b0); + process_t diff = bin - process_t(b0); return envelope.at(b0) * (1.0 - diff) + envelope.at(b1) * diff; } } @@ -233,11 +233,11 @@ protected: struct ChannelAssembly { // Vectors of bare pointers, used to package container data // from different channels into arguments for PhaseAdvance - FixedVector mag; - FixedVector phase; - FixedVector prevMag; + FixedVector mag; + FixedVector phase; + FixedVector prevMag; FixedVector guidance; - FixedVector outPhase; + FixedVector outPhase; FixedVector mixdown; FixedVector resampled; ChannelAssembly(int channels) : @@ -250,9 +250,9 @@ protected: struct ScaleData { int fftSize; FFT fft; - Window analysisWindow; - Window synthesisWindow; - double windowScaleFactor; + Window analysisWindow; + Window synthesisWindow; + process_t windowScaleFactor; GuidedPhaseAdvance guided; ScaleData(GuidedPhaseAdvance::Parameters guidedParameters, Log log) : @@ -331,8 +331,8 @@ protected: int polarBinCount; }; - void convertToPolar(double *mag, double *phase, - const double *real, const double *imag, + void convertToPolar(process_t *mag, process_t *phase, + const process_t *real, const process_t *imag, const ToPolarSpec &s) const { v_cartesian_to_polar(mag + s.polarFromBin, phase + s.polarFromBin, diff --git a/src/test/TestBinClassifier.cpp b/src/test/TestBinClassifier.cpp index 303ffe7..c233cc9 100644 --- a/src/test/TestBinClassifier.cpp +++ b/src/test/TestBinClassifier.cpp @@ -30,6 +30,8 @@ #include "../finer/BinClassifier.h" #include "../finer/BinSegmenter.h" +#include "../common/sysutils.h" + using namespace RubberBand; using namespace std; namespace tt = boost::test_tools; @@ -59,7 +61,7 @@ BOOST_AUTO_TEST_SUITE(TestBinClassifier) BOOST_AUTO_TEST_CASE(classify_bins) { - vector> magColumns { + vector> magColumns { { 0, 8, 1, 1, 0, 1 }, { 0, 8, 0, 0, 0, 0 }, { 8, 8, 8, 8, 8, 0 },