Enable PROCESS_SAMPLE_TYPE for R3 as well, switching from double to process_t throughout

This commit is contained in:
Chris Cannam
2022-07-06 10:40:10 +01:00
parent 6e941fa2d3
commit 567e8636cd
6 changed files with 94 additions and 92 deletions

View File

@@ -62,18 +62,18 @@ public:
BinClassifier(Parameters parameters) :
m_parameters(parameters),
m_hFilters(new MovingMedianStack<double>(m_parameters.binCount,
m_hFilters(new MovingMedianStack<process_t>(m_parameters.binCount,
m_parameters.horizontalFilterLength)),
m_vFilter(new MovingMedian<double>(m_parameters.verticalFilterLength)),
m_vFilter(new MovingMedian<process_t>(m_parameters.verticalFilterLength)),
m_vfQueue(parameters.horizontalFilterLag)
{
int n = m_parameters.binCount;
m_hf = allocate_and_zero<double>(n);
m_vf = allocate_and_zero<double>(n);
m_hf = allocate_and_zero<process_t>(n);
m_vf = allocate_and_zero<process_t>(n);
for (int i = 0; i < m_parameters.horizontalFilterLag; ++i) {
double *entry = allocate_and_zero<double>(n);
process_t *entry = allocate_and_zero<process_t>(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<double>::filter(*m_vFilter, m_vf, n);
MovingMedian<process_t>::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<MovingMedianStack<double>> m_hFilters;
std::unique_ptr<MovingMedian<double>> m_vFilter;
std::unique_ptr<MovingMedianStack<process_t>> m_hFilters;
std::unique_ptr<MovingMedian<process_t>> m_vFilter;
// We manage the queued frames through pointer swapping, hence
// bare pointers here
double *m_hf;
double *m_vf;
RingBuffer<double *> m_vfQueue;
process_t *m_hf;
process_t *m_vf;
RingBuffer<process_t *> m_vfQueue;
BinClassifier(const BinClassifier &) =delete;
BinClassifier &operator=(const BinClassifier &) =delete;

View File

@@ -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;

View File

@@ -56,9 +56,9 @@ public:
m_currentPeaks = allocate_and_zero_channels<int>(ch, m_binCount);
m_prevPeaks = allocate_and_zero_channels<int>(ch, m_binCount);
m_greatestChannel = allocate_and_zero<int>(m_binCount);
m_prevInPhase = allocate_and_zero_channels<double>(ch, m_binCount);
m_prevOutPhase = allocate_and_zero_channels<double>(ch, m_binCount);
m_unlocked = allocate_and_zero_channels<double>(ch, m_binCount);
m_prevInPhase = allocate_and_zero_channels<process_t>(ch, m_binCount);
m_prevOutPhase = allocate_and_zero_channels<process_t>(ch, m_binCount);
m_unlocked = allocate_and_zero_channels<process_t>(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<double> m_peakPicker;
Peak<process_t> 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;
}

View File

@@ -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]);
}

View File

@@ -103,9 +103,9 @@ public:
protected:
struct ClassificationReadaheadData {
FixedVector<double> timeDomain;
FixedVector<double> mag;
FixedVector<double> phase;
FixedVector<process_t> timeDomain;
FixedVector<process_t> mag;
FixedVector<process_t> 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<double> timeDomain;
FixedVector<double> real;
FixedVector<double> imag;
FixedVector<double> mag;
FixedVector<double> phase;
FixedVector<double> advancedPhase;
FixedVector<double> prevMag;
FixedVector<double> pendingKick;
FixedVector<double> accumulator;
FixedVector<process_t> timeDomain;
FixedVector<process_t> real;
FixedVector<process_t> imag;
FixedVector<process_t> mag;
FixedVector<process_t> phase;
FixedVector<process_t> advancedPhase;
FixedVector<process_t> prevMag;
FixedVector<process_t> pendingKick;
FixedVector<process_t> accumulator;
ChannelScaleData(int _fftSize, int _longestFftSize) :
fftSize(_fftSize),
@@ -156,9 +156,9 @@ protected:
struct FormantData {
int fftSize;
FixedVector<double> cepstra;
FixedVector<double> envelope;
FixedVector<double> spare;
FixedVector<process_t> cepstra;
FixedVector<process_t> envelope;
FixedVector<process_t> 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<double *> mag;
FixedVector<double *> phase;
FixedVector<double *> prevMag;
FixedVector<process_t *> mag;
FixedVector<process_t *> phase;
FixedVector<process_t *> prevMag;
FixedVector<Guide::Guidance *> guidance;
FixedVector<double *> outPhase;
FixedVector<process_t *> outPhase;
FixedVector<float *> mixdown;
FixedVector<float *> resampled;
ChannelAssembly(int channels) :
@@ -250,9 +250,9 @@ protected:
struct ScaleData {
int fftSize;
FFT fft;
Window<double> analysisWindow;
Window<double> synthesisWindow;
double windowScaleFactor;
Window<process_t> analysisWindow;
Window<process_t> 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,

View File

@@ -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<vector<double>> magColumns {
vector<vector<process_t>> magColumns {
{ 0, 8, 1, 1, 0, 1 },
{ 0, 8, 0, 0, 0, 0 },
{ 8, 8, 8, 8, 8, 0 },