Use doubles throughout (simpler, faster)
This commit is contained in:
@@ -138,8 +138,13 @@ public:
|
||||
* necessary to empty the buffer. If fewer than n are available,
|
||||
* the remainder will be zeroed out. Returns the number of
|
||||
* samples actually read.
|
||||
*
|
||||
* This is a template function, taking an argument S for the target
|
||||
* sample type, which is permitted to differ from T if the two
|
||||
* types are compatible for arithmetic operations.
|
||||
*/
|
||||
int peek(T *const R__ destination, int n) const;
|
||||
template <typename S>
|
||||
int peek(S *const R__ destination, int n) const;
|
||||
|
||||
/**
|
||||
* Read one sample from the buffer, if available, without
|
||||
@@ -384,8 +389,9 @@ RingBuffer<T>::readOne()
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename S>
|
||||
int
|
||||
RingBuffer<T>::peek(T *const R__ destination, int n) const
|
||||
RingBuffer<T>::peek(S *const R__ destination, int n) const
|
||||
{
|
||||
int w = m_writer;
|
||||
int r = m_reader;
|
||||
@@ -394,7 +400,6 @@ RingBuffer<T>::peek(T *const R__ destination, int n) const
|
||||
if (n > available) {
|
||||
std::cerr << "WARNING: RingBuffer::peek: " << n << " requested, only "
|
||||
<< available << " available" << std::endl;
|
||||
memset(destination + available, 0, (n - available) * sizeof(T));
|
||||
n = available;
|
||||
}
|
||||
if (n == 0) return n;
|
||||
@@ -403,10 +408,10 @@ RingBuffer<T>::peek(T *const R__ destination, int n) const
|
||||
const T *const R__ bufbase = m_buffer + r;
|
||||
|
||||
if (here >= n) {
|
||||
v_copy(destination, bufbase, n);
|
||||
v_convert(destination, bufbase, n);
|
||||
} else {
|
||||
v_copy(destination, bufbase, here);
|
||||
v_copy(destination + here, m_buffer, n - here);
|
||||
v_convert(destination, bufbase, here);
|
||||
v_convert(destination + here, m_buffer, n - here);
|
||||
}
|
||||
|
||||
return n;
|
||||
|
||||
@@ -50,11 +50,11 @@ public:
|
||||
int verticalFilterLength;
|
||||
double harmonicThreshold;
|
||||
double percussiveThreshold;
|
||||
float silenceThreshold;
|
||||
double silenceThreshold;
|
||||
Parameters(int _binCount, int _horizontalFilterLength,
|
||||
int _horizontalFilterLag, int _verticalFilterLength,
|
||||
double _harmonicThreshold, double _percussiveThreshold,
|
||||
float _silenceThreshold) :
|
||||
double _silenceThreshold) :
|
||||
binCount(_binCount),
|
||||
horizontalFilterLength(_horizontalFilterLength),
|
||||
horizontalFilterLag(_horizontalFilterLag),
|
||||
@@ -66,21 +66,21 @@ public:
|
||||
|
||||
BinClassifier(Parameters parameters) :
|
||||
m_parameters(parameters),
|
||||
m_vFilter(new MovingMedian<float>(m_parameters.verticalFilterLength)),
|
||||
m_vFilter(new MovingMedian<double>(m_parameters.verticalFilterLength)),
|
||||
m_vfQueue(parameters.horizontalFilterLag)
|
||||
{
|
||||
int n = m_parameters.binCount;
|
||||
|
||||
for (int i = 0; i < n; ++i) {
|
||||
m_hFilters.push_back(std::make_shared<MovingMedian<float>>
|
||||
m_hFilters.push_back(std::make_shared<MovingMedian<double>>
|
||||
(m_parameters.horizontalFilterLength));
|
||||
}
|
||||
|
||||
m_hf = allocate_and_zero<float>(n);
|
||||
m_vf = allocate_and_zero<float>(n);
|
||||
m_hf = allocate_and_zero<double>(n);
|
||||
m_vf = allocate_and_zero<double>(n);
|
||||
|
||||
for (int i = 0; i < m_parameters.horizontalFilterLag; ++i) {
|
||||
float *entry = allocate_and_zero<float>(n);
|
||||
double *entry = allocate_and_zero<double>(n);
|
||||
m_vfQueue.write(&entry, 1);
|
||||
}
|
||||
}
|
||||
@@ -88,7 +88,7 @@ public:
|
||||
~BinClassifier()
|
||||
{
|
||||
while (m_vfQueue.getReadSpace() > 0) {
|
||||
float *entry = m_vfQueue.readOne();
|
||||
double *entry = m_vfQueue.readOne();
|
||||
deallocate(entry);
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ public:
|
||||
deallocate(m_vf);
|
||||
}
|
||||
|
||||
void classify(const float *const mag, Classification *classification) {
|
||||
void classify(const double *const mag, Classification *classification) {
|
||||
const int n = m_parameters.binCount;
|
||||
|
||||
for (int i = 0; i < n; ++i) {
|
||||
@@ -105,10 +105,10 @@ public:
|
||||
}
|
||||
|
||||
v_copy(m_vf, mag, n);
|
||||
MovingMedian<float>::filter(*m_vFilter, m_vf);
|
||||
MovingMedian<double>::filter(*m_vFilter, m_vf);
|
||||
|
||||
if (m_parameters.horizontalFilterLag > 0) {
|
||||
float *lagged = m_vfQueue.readOne();
|
||||
double *lagged = m_vfQueue.readOne();
|
||||
m_vfQueue.write(&m_vf, 1);
|
||||
m_vf = lagged;
|
||||
}
|
||||
@@ -134,13 +134,13 @@ public:
|
||||
|
||||
protected:
|
||||
Parameters m_parameters;
|
||||
std::vector<std::shared_ptr<MovingMedian<float>>> m_hFilters;
|
||||
std::unique_ptr<MovingMedian<float>> m_vFilter;
|
||||
std::vector<std::shared_ptr<MovingMedian<double>>> m_hFilters;
|
||||
std::unique_ptr<MovingMedian<double>> m_vFilter;
|
||||
// We manage the queued frames through pointer swapping, hence
|
||||
// bare pointers here
|
||||
float *m_hf;
|
||||
float *m_vf;
|
||||
RingBuffer<float *> m_vfQueue;
|
||||
double *m_hf;
|
||||
double *m_vf;
|
||||
RingBuffer<double *> m_vfQueue;
|
||||
|
||||
BinClassifier(const BinClassifier &) =delete;
|
||||
BinClassifier &operator=(const BinClassifier &) =delete;
|
||||
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
Segmentation segment(const float *const mag) {
|
||||
Segmentation segment(const double *const mag) {
|
||||
int n = m_classifierParameters.binCount;
|
||||
m_classifier.classify(mag, m_classification.data());
|
||||
for (int i = 0; i < n; ++i) {
|
||||
|
||||
@@ -35,9 +35,9 @@ class Guide
|
||||
public:
|
||||
struct FftBand {
|
||||
int fftSize;
|
||||
float f0;
|
||||
float f1;
|
||||
FftBand(int _s, float _f0, float _f1) :
|
||||
double f0;
|
||||
double f1;
|
||||
FftBand(int _s, double _f0, double _f1) :
|
||||
fftSize(_s), f0(_f0), f1(_f1) { }
|
||||
FftBand() :
|
||||
fftSize(0), f0(0.f), f1(0.f) { }
|
||||
@@ -45,10 +45,10 @@ public:
|
||||
|
||||
struct PhaseLockBand {
|
||||
int p;
|
||||
float beta;
|
||||
float f0;
|
||||
float f1;
|
||||
PhaseLockBand(int _p, float _beta, float _f0, float _f1) :
|
||||
double beta;
|
||||
double f0;
|
||||
double f1;
|
||||
PhaseLockBand(int _p, double _beta, double _f0, double _f1) :
|
||||
p(_p), beta(_beta), f0(_f0), f1(_f1) { }
|
||||
PhaseLockBand() :
|
||||
p(0), beta(1.0), f0(0.f), f1(0.f) { }
|
||||
@@ -56,9 +56,9 @@ public:
|
||||
|
||||
struct Range {
|
||||
bool present;
|
||||
float f0;
|
||||
float f1;
|
||||
Range(bool _present, float _f0, float _f1) :
|
||||
double f0;
|
||||
double f1;
|
||||
Range(bool _present, double _f0, double _f1) :
|
||||
present(_present), f0(_f0), f1(_f1) { }
|
||||
Range() :
|
||||
present(false), f0(0.f), f1(0.f) { }
|
||||
@@ -76,9 +76,9 @@ public:
|
||||
|
||||
struct BandLimits {
|
||||
int fftSize;
|
||||
float f0min;
|
||||
float f1max;
|
||||
BandLimits(int _fftSize, float _f0min, float _f1max) :
|
||||
double f0min;
|
||||
double f1max;
|
||||
BandLimits(int _fftSize, double _f0min, double _f1max) :
|
||||
fftSize(_fftSize), f0min(_f0min), f1max(_f1max) { }
|
||||
BandLimits() :
|
||||
fftSize(0), f0min(0.f), f1max(0.f) { }
|
||||
@@ -132,9 +132,9 @@ public:
|
||||
}
|
||||
|
||||
void calculate(double ratio,
|
||||
const float *const magnitudes,
|
||||
const double *const magnitudes,
|
||||
const int *const troughs,
|
||||
const float *const prevMagnitudes,
|
||||
const double *const prevMagnitudes,
|
||||
const BinSegmenter::Segmentation &segmentation,
|
||||
const BinSegmenter::Segmentation &prevSegmentation,
|
||||
const BinSegmenter::Segmentation &nextSegmentation,
|
||||
@@ -272,17 +272,17 @@ protected:
|
||||
return value;
|
||||
}
|
||||
|
||||
bool checkPotentialKick(const float *const magnitudes,
|
||||
const float *const prevMagnitudes) const {
|
||||
bool checkPotentialKick(const double *const magnitudes,
|
||||
const double *const prevMagnitudes) const {
|
||||
int b = binForFrequency(200.0);
|
||||
float here = 0.0, there = 0.0;
|
||||
double here = 0.0, there = 0.0;
|
||||
for (int i = 1; i <= b; ++i) {
|
||||
here += magnitudes[i];
|
||||
}
|
||||
for (int i = 1; i <= b; ++i) {
|
||||
there += prevMagnitudes[i];
|
||||
}
|
||||
return (here > 10.e-3f && here > there * 1.4f);
|
||||
return (here > 10.e-3 && here > there * 1.4);
|
||||
}
|
||||
|
||||
double snapToTrough(double f, const int *const troughs) const {
|
||||
|
||||
@@ -55,8 +55,9 @@ public:
|
||||
m_currentPeaks = allocate_and_zero_channels<int>(ch, m_blockSize);
|
||||
m_prevPeaks = allocate_and_zero_channels<int>(ch, m_blockSize);
|
||||
m_greatestChannel = allocate_and_zero<int>(m_blockSize);
|
||||
m_prevInMag = allocate_and_zero_channels<float>(ch, m_blockSize);
|
||||
m_prevInPhase = allocate_and_zero_channels<float>(ch, m_blockSize);
|
||||
//!!! there is also a prevMag in R3StretcherImpl which could be passed in to here instead
|
||||
m_prevInMag = allocate_and_zero_channels<double>(ch, m_blockSize);
|
||||
m_prevInPhase = allocate_and_zero_channels<double>(ch, m_blockSize);
|
||||
m_prevOutPhase = allocate_and_zero_channels<double>(ch, m_blockSize);
|
||||
m_unlocked = allocate_and_zero_channels<double>(ch, m_blockSize);
|
||||
}
|
||||
@@ -73,8 +74,8 @@ public:
|
||||
}
|
||||
|
||||
void advance(double *const *outPhase,
|
||||
const float *const *mag,
|
||||
const float *const *phase,
|
||||
const double *const *mag,
|
||||
const double *const *phase,
|
||||
const Guide::Configuration &configuration,
|
||||
const Guide::Guidance *const *guidance,
|
||||
int inhop,
|
||||
@@ -245,12 +246,12 @@ public:
|
||||
protected:
|
||||
Parameters m_parameters;
|
||||
int m_blockSize;
|
||||
Peak<float> m_peakPicker;
|
||||
Peak<double> m_peakPicker;
|
||||
int **m_currentPeaks;
|
||||
int **m_prevPeaks;
|
||||
int *m_greatestChannel;
|
||||
float **m_prevInMag;
|
||||
float **m_prevInPhase;
|
||||
double **m_prevInMag;
|
||||
double **m_prevInPhase;
|
||||
double **m_prevOutPhase;
|
||||
double **m_unlocked;
|
||||
bool m_reported;
|
||||
|
||||
@@ -240,7 +240,7 @@ R3StretcherImpl::consume()
|
||||
(scale->timeDomainFrame.data(),
|
||||
scale->mag.data(),
|
||||
scale->phase.data());
|
||||
v_scale(scale->mag.data(), 1.f / float(fftSize),
|
||||
v_scale(scale->mag.data(), 1.0 / double(fftSize),
|
||||
scale->mag.size());
|
||||
}
|
||||
|
||||
@@ -291,10 +291,6 @@ R3StretcherImpl::consume()
|
||||
// copy to prevMag before filtering
|
||||
v_copy(scale->prevMag.data(), scale->mag.data(), bufSize);
|
||||
v_copy(scale->prevOutPhase.data(), scale->outPhase.data(), bufSize);
|
||||
//!!! seems wasteful
|
||||
for (int i = 0; i < bufSize; ++i) {
|
||||
scale->phase[i] = princarg(scale->outPhase[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &band : cd->guidance.fftBands) {
|
||||
@@ -302,18 +298,18 @@ R3StretcherImpl::consume()
|
||||
auto scale = cd->scales.at(fftSize);
|
||||
auto scaleData = m_scaleData.at(fftSize);
|
||||
|
||||
//!!! messy and v slow, but leave it until we've
|
||||
//!!! messy and slow, but leave it until we've
|
||||
//!!! discovered whether we need a window accumulator
|
||||
//!!! (we probably do)
|
||||
int analysisWindowSize = scaleData->analysisWindow.getSize();
|
||||
int synthesisWindowSize = scaleData->synthesisWindow.getSize();
|
||||
int offset = (analysisWindowSize - synthesisWindowSize) / 2;
|
||||
float winscale = 0.f;
|
||||
double winscale = 0.0;
|
||||
for (int i = 0; i < synthesisWindowSize; ++i) {
|
||||
winscale += scaleData->analysisWindow.getValue(i + offset) *
|
||||
scaleData->synthesisWindow.getValue(i);
|
||||
}
|
||||
winscale = float(outhop) / winscale;
|
||||
winscale = double(outhop) / winscale;
|
||||
|
||||
double factor = m_parameters.sampleRate / double(fftSize);
|
||||
for (int i = 0; i < fftSize/2 + 1; ++i) {
|
||||
@@ -333,7 +329,7 @@ R3StretcherImpl::consume()
|
||||
auto scaleData = m_scaleData.at(fftSize);
|
||||
|
||||
scaleData->fft.inversePolar(scale->mag.data(),
|
||||
scale->phase.data(),
|
||||
scale->outPhase.data(),
|
||||
scale->timeDomainFrame.data());
|
||||
|
||||
int synthesisWindowSize = scaleData->synthesisWindow.getSize();
|
||||
|
||||
@@ -127,14 +127,14 @@ protected:
|
||||
int fftSize;
|
||||
int bufSize; // size of every freq-domain array here: fftSize/2 + 1
|
||||
//!!! review later which of these we are actually using!
|
||||
FixedVector<float> timeDomainFrame;
|
||||
FixedVector<float> mag;
|
||||
FixedVector<float> phase;
|
||||
FixedVector<double> timeDomainFrame;
|
||||
FixedVector<double> mag;
|
||||
FixedVector<double> phase;
|
||||
FixedVector<double> outPhase; //!!! "advanced"?
|
||||
FixedVector<int> nextTroughs; //!!! not used in every scale
|
||||
FixedVector<float> prevMag; //!!! not used in every scale
|
||||
FixedVector<double> prevMag; //!!! not used in every scale
|
||||
FixedVector<double> prevOutPhase;
|
||||
FixedVector<float> accumulator;
|
||||
FixedVector<double> accumulator;
|
||||
|
||||
ChannelScaleData(int _fftSize, int _longestFftSize) :
|
||||
fftSize(_fftSize),
|
||||
@@ -161,7 +161,7 @@ protected:
|
||||
BinSegmenter::Segmentation prevSegmentation;
|
||||
BinSegmenter::Segmentation nextSegmentation;
|
||||
Guide::Guidance guidance;
|
||||
FixedVector<float> mixdown;
|
||||
FixedVector<double> mixdown;
|
||||
std::unique_ptr<RingBuffer<float>> inbuf;
|
||||
std::unique_ptr<RingBuffer<float>> outbuf;
|
||||
ChannelData(BinSegmenter::Parameters segmenterParameters,
|
||||
@@ -179,8 +179,8 @@ protected:
|
||||
struct ChannelAssembly {
|
||||
// Vectors of bare pointers, used to package container data
|
||||
// from different channels into arguments for PhaseAdvance
|
||||
FixedVector<float *> mag;
|
||||
FixedVector<float *> phase;
|
||||
FixedVector<double *> mag;
|
||||
FixedVector<double *> phase;
|
||||
FixedVector<Guide::Guidance *> guidance;
|
||||
FixedVector<double *> outPhase;
|
||||
ChannelAssembly(int channels) :
|
||||
@@ -190,8 +190,8 @@ protected:
|
||||
|
||||
struct ScaleData {
|
||||
FFT fft;
|
||||
Window<float> analysisWindow;
|
||||
Window<float> synthesisWindow;
|
||||
Window<double> analysisWindow;
|
||||
Window<double> synthesisWindow;
|
||||
GuidedPhaseAdvance guided;
|
||||
ScaleData(GuidedPhaseAdvance::Parameters guidedParameters) :
|
||||
fft(guidedParameters.fftSize),
|
||||
@@ -210,7 +210,7 @@ protected:
|
||||
Guide m_guide;
|
||||
Guide::Configuration m_guideConfiguration;
|
||||
ChannelAssembly m_channelAssembly;
|
||||
Peak<float, std::less<float>> m_troughPicker;
|
||||
Peak<double, std::less<double>> m_troughPicker;
|
||||
std::unique_ptr<StretchCalculator> m_calculator;
|
||||
int m_inhop;
|
||||
bool m_draining;
|
||||
|
||||
Reference in New Issue
Block a user