Flesh out the implementation a bit

This commit is contained in:
Chris Cannam
2022-05-23 15:04:34 +01:00
parent af97c70e69
commit 5cc4833820
7 changed files with 408 additions and 48 deletions

View File

@@ -56,7 +56,9 @@ public:
R3StretcherImpl(Parameters parameters) :
m_parameters(parameters),
m_guide(Guide::Parameters(m_parameters.sampleRate)),
m_guideConfiguration(m_guide.getConfiguration())
m_guideConfiguration(m_guide.getConfiguration()),
m_channelAssembly(m_parameters.channels),
m_troughPicker(m_guideConfiguration.classificationFftSize / 2 + 1)
{
BinSegmenter::Parameters segmenterParameters
(m_guideConfiguration.classificationFftSize,
@@ -64,7 +66,9 @@ public:
BinClassifier::Parameters classifierParameters
(m_guideConfiguration.classificationFftSize / 2 + 1,
9, 1, 10, 2.0, 2.0, 1.0e-7);
int ringBufferSize = m_guideConfiguration.longestFftSize * 2;
for (int c = 0; c < m_parameters.channels; ++c) {
m_channelData.push_back(std::make_shared<ChannelData>
(segmenterParameters,
@@ -72,11 +76,18 @@ public:
ringBufferSize));
for (auto band: m_guideConfiguration.fftBandLimits) {
int fftSize = band.fftSize;
m_ffts[fftSize] = std::make_shared<FFT>(fftSize);
m_channelData[c]->scales[fftSize] =
std::make_shared<ChannelScaleData>(fftSize);
}
}
for (auto band: m_guideConfiguration.fftBandLimits) {
int fftSize = band.fftSize;
GuidedPhaseAdvance::Parameters guidedParameters
(fftSize, m_parameters.sampleRate, m_parameters.channels,
m_parameters.logger);
m_scaleData[fftSize] = std::make_shared<ScaleData>(guidedParameters);
}
}
~R3StretcherImpl() { }
@@ -89,29 +100,39 @@ public:
double getTimeRatio() const;
double getPitchScale() const;
size_t getSamplesRequired() const;
void process(const float *const *input, size_t samples, bool final);
int available() const;
size_t retrieve(float *const *output, size_t samples) const;
size_t getLatency() const;
size_t getChannelCount() const;
protected:
struct ChannelScaleData {
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<int> nearestPeaks;
FixedVector<int> nearestTroughs;
FixedVector<float> prevOutMag;
FixedVector<double> outPhase; //!!! "advanced"?
FixedVector<int> nextTroughs; //!!! not used in every scale
FixedVector<float> prevMag; //!!! not used in every scale
FixedVector<double> prevOutPhase;
FixedVector<int> prevNearestPeaks;
FixedVector<float> timeDomainFrame;
Window<float> analysisWindow;
Window<float> synthesisWindow;
FixedVector<float> accumulator;
ChannelScaleData(int _fftSize) :
fftSize(_fftSize), bufSize(fftSize/2 + 1),
mag(bufSize, 0.f), phase(bufSize, 0.f),
nearestPeaks(bufSize, 0), nearestTroughs(bufSize, 0),
prevOutMag(bufSize, 0.f), prevOutPhase(bufSize, 0.f),
prevNearestPeaks(bufSize, 0), timeDomainFrame(fftSize, 0.f),
analysisWindow(HannWindow, fftSize),
synthesisWindow(HannWindow, fftSize/2)
fftSize(_fftSize),
bufSize(fftSize/2 + 1),
timeDomainFrame(fftSize, 0.f),
mag(bufSize, 0.f),
phase(bufSize, 0.f),
outPhase(bufSize, 0.f),
nextTroughs(bufSize, 0),
prevMag(bufSize, 0.f),
prevOutPhase(bufSize, 0.f),
accumulator(fftSize, 0.f)
{ }
private:
@@ -126,8 +147,9 @@ protected:
BinSegmenter::Segmentation prevSegmentation;
BinSegmenter::Segmentation nextSegmentation;
Guide::Guidance guidance;
RingBuffer<float> inbuf;
RingBuffer<float> outbuf;
FixedVector<float> mixdown;
std::unique_ptr<RingBuffer<float>> inbuf;
std::unique_ptr<RingBuffer<float>> outbuf;
ChannelData(BinSegmenter::Parameters segmenterParameters,
BinClassifier::Parameters classifierParameters,
int ringBufferSize) :
@@ -135,19 +157,49 @@ protected:
segmenter(new BinSegmenter(segmenterParameters,
classifierParameters)),
segmentation(), prevSegmentation(), nextSegmentation(),
inbuf(ringBufferSize), outbuf(ringBufferSize) { }
mixdown(ringBufferSize, 0.f), //!!! could be much shorter (bound is the max outhop)
inbuf(new RingBuffer<float>(ringBufferSize)),
outbuf(new RingBuffer<float>(ringBufferSize)) { }
};
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<Guide::Guidance *> guidance;
FixedVector<double *> outPhase;
ChannelAssembly(int channels) :
mag(channels, nullptr), phase(channels, nullptr),
guidance(channels, nullptr), outPhase(channels, nullptr) { }
};
struct ScaleData {
FFT fft;
Window<float> analysisWindow;
Window<float> synthesisWindow;
GuidedPhaseAdvance guided;
ScaleData(GuidedPhaseAdvance::Parameters guidedParameters) :
fft(guidedParameters.fftSize),
analysisWindow(HannWindow, guidedParameters.fftSize),
synthesisWindow(HannWindow, guidedParameters.fftSize/2),
guided(guidedParameters) { }
};
Parameters m_parameters;
double m_timeRatio;
double m_pitchScale;
std::vector<std::shared_ptr<ChannelData>> m_channelData;
std::map<int, std::shared_ptr<FFT>> m_ffts;
std::map<int, std::shared_ptr<ScaleData>> m_scaleData;
Guide m_guide;
Guide::Configuration m_guideConfiguration;
ChannelAssembly m_channelAssembly;
Peak<float, std::less<float>> m_troughPicker;
void consume();
static void logCerr(const std::string &message) {
std::cerr << "RubberBandStretcher: " << message << std::endl;
}