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