An attempt to do the right thing when the hop changes - but this is not enough
This commit is contained in:
@@ -119,7 +119,6 @@ public:
|
||||
m_maxLower(1100.0), m_maxHigher(7000.0)
|
||||
{
|
||||
double rate = m_parameters.sampleRate;
|
||||
double nyquist = rate / 2.0;
|
||||
|
||||
int bandFftSize = roundUp(int(ceil(rate/16.0)));
|
||||
m_configuration.fftBandLimits[0] =
|
||||
|
||||
@@ -91,6 +91,7 @@ R3StretcherImpl::R3StretcherImpl(Parameters parameters,
|
||||
|
||||
calculateHop();
|
||||
|
||||
m_prevInhop = m_inhop;
|
||||
m_prevOuthop = int(round(m_inhop * getEffectiveRatio()));
|
||||
|
||||
if (!m_inhop.is_lock_free()) {
|
||||
@@ -101,6 +102,36 @@ R3StretcherImpl::R3StretcherImpl(Parameters parameters,
|
||||
}
|
||||
}
|
||||
|
||||
WindowType
|
||||
R3StretcherImpl::ScaleData::analysisWindowShape(int fftSize)
|
||||
{
|
||||
//!!! return HannWindow;
|
||||
if (fftSize == 4096) return HannWindow;
|
||||
else return NiemitaloForwardWindow;
|
||||
}
|
||||
|
||||
int
|
||||
R3StretcherImpl::ScaleData::analysisWindowLength(int fftSize)
|
||||
{
|
||||
return fftSize;
|
||||
}
|
||||
|
||||
WindowType
|
||||
R3StretcherImpl::ScaleData::synthesisWindowShape(int fftSize)
|
||||
{
|
||||
//!!! return HannWindow;
|
||||
if (fftSize == 4096) return HannWindow;
|
||||
else return NiemitaloReverseWindow;
|
||||
}
|
||||
|
||||
int
|
||||
R3StretcherImpl::ScaleData::synthesisWindowLength(int fftSize)
|
||||
{
|
||||
//!!! return fftSize/2;
|
||||
if (fftSize == 4096) return fftSize/2;
|
||||
else return fftSize;
|
||||
}
|
||||
|
||||
void
|
||||
R3StretcherImpl::setTimeRatio(double ratio)
|
||||
{
|
||||
@@ -133,6 +164,8 @@ R3StretcherImpl::calculateHop()
|
||||
}
|
||||
|
||||
m_inhop = int(round(inhop));
|
||||
|
||||
std::cout << "R3StretcherImpl::calculateHop: inhop " << m_inhop << ", mean outhop " << m_inhop * ratio << std::endl;
|
||||
}
|
||||
|
||||
double
|
||||
@@ -168,6 +201,7 @@ R3StretcherImpl::reset()
|
||||
size_t
|
||||
R3StretcherImpl::getSamplesRequired() const
|
||||
{
|
||||
if (available() != 0) return 0;
|
||||
int longest = m_guideConfiguration.longestFftSize;
|
||||
size_t rs = m_channelData[0]->inbuf->getReadSpace();
|
||||
if (rs < longest) {
|
||||
@@ -260,6 +294,15 @@ R3StretcherImpl::consume()
|
||||
|
||||
// std::cout << "outhop = " << outhop << std::endl;
|
||||
|
||||
if (inhop != m_prevInhop) {
|
||||
std::cout << "Note: inhop has changed from " << m_prevInhop
|
||||
<< " to " << inhop << std::endl;
|
||||
}
|
||||
if (outhop != m_prevOuthop) {
|
||||
std::cout << "Note: outhop has changed from " << m_prevOuthop
|
||||
<< " to " << outhop << std::endl;
|
||||
}
|
||||
|
||||
while (m_channelData.at(0)->outbuf->getWriteSpace() >= outhop) {
|
||||
|
||||
// NB our ChannelData, ScaleData, and ChannelScaleData maps
|
||||
@@ -282,7 +325,7 @@ R3StretcherImpl::consume()
|
||||
// Analysis
|
||||
|
||||
for (int c = 0; c < channels; ++c) {
|
||||
analyseChannel(c, inhop, m_prevOuthop);
|
||||
analyseChannel(c, inhop, m_prevInhop, m_prevOuthop);
|
||||
}
|
||||
|
||||
// Phase update. This is synchronised across all channels
|
||||
@@ -303,7 +346,7 @@ R3StretcherImpl::consume()
|
||||
m_channelAssembly.phase.data(),
|
||||
m_guideConfiguration,
|
||||
m_channelAssembly.guidance.data(),
|
||||
inhop,
|
||||
m_prevInhop, //!!! or inhop?
|
||||
outhop);
|
||||
}
|
||||
|
||||
@@ -351,11 +394,12 @@ R3StretcherImpl::consume()
|
||||
}
|
||||
}
|
||||
|
||||
m_prevInhop = inhop;
|
||||
m_prevOuthop = outhop;
|
||||
}
|
||||
|
||||
void
|
||||
R3StretcherImpl::analyseChannel(int c, int inhop, int prevOuthop)
|
||||
R3StretcherImpl::analyseChannel(int c, int inhop, int prevInhop, int prevOuthop)
|
||||
{
|
||||
int longest = m_guideConfiguration.longestFftSize;
|
||||
int classify = m_guideConfiguration.classificationFftSize;
|
||||
@@ -387,11 +431,7 @@ R3StretcherImpl::analyseChannel(int c, int inhop, int prevOuthop)
|
||||
}
|
||||
|
||||
// The classification scale has a one-hop readahead, so populate
|
||||
// its current data from the readahead and the readahead from
|
||||
// further down the long unwindowed frame.
|
||||
|
||||
//!!! (This causes us to get out of sync when inhop changes - is
|
||||
//!!! it better to vary outhop?)
|
||||
// the readahead from further down the long unwindowed frame.
|
||||
|
||||
auto &classifyScale = cd->scales.at(classify);
|
||||
ClassificationReadaheadData &readahead = cd->readahead;
|
||||
@@ -399,6 +439,17 @@ R3StretcherImpl::analyseChannel(int c, int inhop, int prevOuthop)
|
||||
m_scaleData.at(classify)->analysisWindow.cut
|
||||
(buf + (longest - classify) / 2 + inhop,
|
||||
readahead.timeDomain.data());
|
||||
|
||||
// If inhop has changed since the previous frame, we'll have to
|
||||
// populate the classification scale (but for analysis/resynthesis
|
||||
// rather than classification) anew rather than reuse the previous
|
||||
// readahead. Pity...
|
||||
|
||||
if (inhop != prevInhop) {
|
||||
m_scaleData.at(classify)->analysisWindow.cut
|
||||
(buf + (longest - classify) / 2,
|
||||
classifyScale->timeDomain.data());
|
||||
}
|
||||
|
||||
// Finally window the longest scale
|
||||
m_scaleData.at(longest)->analysisWindow.cut(buf);
|
||||
@@ -406,20 +457,22 @@ R3StretcherImpl::analyseChannel(int c, int inhop, int prevOuthop)
|
||||
// FFT shift, forward FFT, and carry out cartesian-polar
|
||||
// conversion for each FFT size.
|
||||
|
||||
// For the classification scale we need magnitudes for the
|
||||
// full range (polar only in a subset) and we operate in
|
||||
// the readahead, pulling current values from the existing
|
||||
// readahead
|
||||
// For the classification scale we need magnitudes for the full
|
||||
// range (polar only in a subset) and we operate in the readahead,
|
||||
// pulling current values from the existing readahead (except
|
||||
// where the inhop has changed as above, in which case we need to
|
||||
// do both readahead and current)
|
||||
|
||||
v_fftshift(readahead.timeDomain.data(), classify);
|
||||
|
||||
v_copy(classifyScale->mag.data(),
|
||||
readahead.mag.data(),
|
||||
classifyScale->bufSize);
|
||||
|
||||
v_copy(classifyScale->phase.data(),
|
||||
readahead.phase.data(),
|
||||
classifyScale->bufSize);
|
||||
if (inhop == prevInhop) {
|
||||
v_copy(classifyScale->mag.data(),
|
||||
readahead.mag.data(),
|
||||
classifyScale->bufSize);
|
||||
v_copy(classifyScale->phase.data(),
|
||||
readahead.phase.data(),
|
||||
classifyScale->bufSize);
|
||||
}
|
||||
|
||||
m_scaleData.at(classify)->fft.forward(readahead.timeDomain.data(),
|
||||
classifyScale->real.data(),
|
||||
@@ -455,12 +508,13 @@ R3StretcherImpl::analyseChannel(int c, int inhop, int prevOuthop)
|
||||
}
|
||||
}
|
||||
|
||||
// For the others we operate directly in the scale data
|
||||
// and restrict the range for cartesian-polar conversion
|
||||
// For the others (and the classify if the inhop has changed) we
|
||||
// operate directly in the scale data and restrict the range for
|
||||
// cartesian-polar conversion
|
||||
|
||||
for (auto &it: cd->scales) {
|
||||
int fftSize = it.first;
|
||||
if (fftSize == classify) continue;
|
||||
if (fftSize == classify && inhop == prevInhop) continue;
|
||||
auto &scale = it.second;
|
||||
|
||||
v_fftshift(scale->timeDomain.data(), fftSize);
|
||||
|
||||
@@ -182,21 +182,10 @@ protected:
|
||||
synthesisWindowLength(fftSize)),
|
||||
guided(guidedParameters) { }
|
||||
|
||||
WindowType analysisWindowShape(int fftSize) {
|
||||
if (fftSize == 4096) return HannWindow;
|
||||
else return NiemitaloForwardWindow;
|
||||
}
|
||||
int analysisWindowLength(int fftSize) {
|
||||
return fftSize;
|
||||
}
|
||||
WindowType synthesisWindowShape(int fftSize) {
|
||||
if (fftSize == 4096) return HannWindow;
|
||||
else return NiemitaloReverseWindow;
|
||||
}
|
||||
int synthesisWindowLength(int fftSize) {
|
||||
if (fftSize == 4096) return fftSize/2;
|
||||
else return fftSize;
|
||||
}
|
||||
WindowType analysisWindowShape(int fftSize);
|
||||
int analysisWindowLength(int fftSize);
|
||||
WindowType synthesisWindowShape(int fftSize);
|
||||
int synthesisWindowLength(int fftSize);
|
||||
};
|
||||
|
||||
Parameters m_parameters;
|
||||
@@ -213,12 +202,13 @@ protected:
|
||||
std::unique_ptr<StretchCalculator> m_calculator;
|
||||
std::unique_ptr<Resampler> m_resampler;
|
||||
std::atomic<int> m_inhop;
|
||||
int m_prevInhop;
|
||||
int m_prevOuthop;
|
||||
bool m_draining;
|
||||
|
||||
void consume();
|
||||
void calculateHop();
|
||||
void analyseChannel(int channel, int inhop, int prevOuthop);
|
||||
void analyseChannel(int channel, int inhop, int prevInhop, int prevOuthop);
|
||||
void synthesiseChannel(int channel, int outhop);
|
||||
|
||||
double getEffectiveRatio() const {
|
||||
|
||||
Reference in New Issue
Block a user