Use atomics for inhop and ratio, and read inhop once at start of consume in case it changes within
This commit is contained in:
@@ -92,6 +92,13 @@ R3StretcherImpl::R3StretcherImpl(Parameters parameters,
|
|||||||
calculateHop();
|
calculateHop();
|
||||||
|
|
||||||
m_prevOuthop = int(round(m_inhop * getEffectiveRatio()));
|
m_prevOuthop = int(round(m_inhop * getEffectiveRatio()));
|
||||||
|
|
||||||
|
if (!m_inhop.is_lock_free()) {
|
||||||
|
m_parameters.logger("WARNING: std::atomic<int> is not lock-free");
|
||||||
|
}
|
||||||
|
if (!m_timeRatio.is_lock_free()) {
|
||||||
|
m_parameters.logger("WARNING: std::atomic<double> is not lock-free");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -113,19 +120,19 @@ R3StretcherImpl::calculateHop()
|
|||||||
{
|
{
|
||||||
double ratio = getEffectiveRatio();
|
double ratio = getEffectiveRatio();
|
||||||
double proposedOuthop = 256;
|
double proposedOuthop = 256;
|
||||||
|
double inhop = 1.0;
|
||||||
|
|
||||||
if (ratio > 1.0) {
|
if (ratio > 1.0) {
|
||||||
double inhop = proposedOuthop / ratio;
|
inhop = proposedOuthop / ratio;
|
||||||
if (inhop < 1.0) {
|
if (inhop < 1.0) {
|
||||||
m_parameters.logger("WARNING: Extreme ratio yields ideal inhop < 1, results may be suspect");
|
m_parameters.logger("WARNING: Extreme ratio yields ideal inhop < 1, results may be suspect");
|
||||||
m_inhop = 1;
|
inhop = 1.0;
|
||||||
} else {
|
|
||||||
m_inhop = int(round(inhop));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
double inhop = std::min(proposedOuthop / ratio, 340.0);
|
inhop = std::min(proposedOuthop / ratio, 340.0);
|
||||||
m_inhop = int(round(inhop));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_inhop = int(round(inhop));
|
||||||
}
|
}
|
||||||
|
|
||||||
double
|
double
|
||||||
@@ -237,19 +244,21 @@ void
|
|||||||
R3StretcherImpl::consume()
|
R3StretcherImpl::consume()
|
||||||
{
|
{
|
||||||
double ratio = getEffectiveRatio();
|
double ratio = getEffectiveRatio();
|
||||||
|
int inhop = m_inhop;
|
||||||
|
|
||||||
int longest = m_guideConfiguration.longestFftSize;
|
int longest = m_guideConfiguration.longestFftSize;
|
||||||
int channels = m_parameters.channels;
|
int channels = m_parameters.channels;
|
||||||
|
|
||||||
m_calculator->setDebugLevel(3);
|
// m_calculator->setDebugLevel(3);
|
||||||
|
|
||||||
int outhop = m_calculator->calculateSingle(ratio,
|
int outhop = m_calculator->calculateSingle(ratio,
|
||||||
1.0 / m_pitchScale,
|
1.0 / m_pitchScale,
|
||||||
1.f,
|
1.f,
|
||||||
m_inhop,
|
inhop,
|
||||||
longest,
|
longest,
|
||||||
longest);
|
longest);
|
||||||
|
|
||||||
std::cout << "outhop = " << outhop << std::endl;
|
// std::cout << "outhop = " << outhop << std::endl;
|
||||||
|
|
||||||
while (m_channelData.at(0)->outbuf->getWriteSpace() >= outhop) {
|
while (m_channelData.at(0)->outbuf->getWriteSpace() >= outhop) {
|
||||||
|
|
||||||
@@ -273,7 +282,7 @@ R3StretcherImpl::consume()
|
|||||||
// Analysis
|
// Analysis
|
||||||
|
|
||||||
for (int c = 0; c < channels; ++c) {
|
for (int c = 0; c < channels; ++c) {
|
||||||
analyseChannel(c, m_prevOuthop);
|
analyseChannel(c, inhop, m_prevOuthop);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Phase update. This is synchronised across all channels
|
// Phase update. This is synchronised across all channels
|
||||||
@@ -294,7 +303,7 @@ R3StretcherImpl::consume()
|
|||||||
m_channelAssembly.phase.data(),
|
m_channelAssembly.phase.data(),
|
||||||
m_guideConfiguration,
|
m_guideConfiguration,
|
||||||
m_channelAssembly.guidance.data(),
|
m_channelAssembly.guidance.data(),
|
||||||
m_inhop,
|
inhop,
|
||||||
outhop);
|
outhop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,11 +342,11 @@ R3StretcherImpl::consume()
|
|||||||
}
|
}
|
||||||
|
|
||||||
int readSpace = cd->inbuf->getReadSpace();
|
int readSpace = cd->inbuf->getReadSpace();
|
||||||
if (readSpace < m_inhop) {
|
if (readSpace < inhop) {
|
||||||
// This should happen only when draining
|
// This should happen only when draining
|
||||||
cd->inbuf->skip(readSpace);
|
cd->inbuf->skip(readSpace);
|
||||||
} else {
|
} else {
|
||||||
cd->inbuf->skip(m_inhop);
|
cd->inbuf->skip(inhop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -346,7 +355,7 @@ R3StretcherImpl::consume()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
R3StretcherImpl::analyseChannel(int c, int prevOuthop)
|
R3StretcherImpl::analyseChannel(int c, int inhop, int prevOuthop)
|
||||||
{
|
{
|
||||||
int longest = m_guideConfiguration.longestFftSize;
|
int longest = m_guideConfiguration.longestFftSize;
|
||||||
int classify = m_guideConfiguration.classificationFftSize;
|
int classify = m_guideConfiguration.classificationFftSize;
|
||||||
@@ -377,16 +386,18 @@ R3StretcherImpl::analyseChannel(int c, int prevOuthop)
|
|||||||
(buf + offset, it.second->timeDomain.data());
|
(buf + offset, it.second->timeDomain.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
// The classification scale has a one-hop readahead (note
|
// The classification scale has a one-hop readahead, so populate
|
||||||
// that inhop is fixed), so populate its current data from
|
// its current data from the readahead and the readahead from
|
||||||
// the readahead and the readahead from further down the
|
// further down the long unwindowed frame.
|
||||||
// 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;
|
||||||
|
|
||||||
m_scaleData.at(classify)->analysisWindow.cut
|
m_scaleData.at(classify)->analysisWindow.cut
|
||||||
(buf + (longest - classify) / 2 + m_inhop,
|
(buf + (longest - classify) / 2 + inhop,
|
||||||
readahead.timeDomain.data());
|
readahead.timeDomain.data());
|
||||||
|
|
||||||
// Finally window the longest scale
|
// Finally window the longest scale
|
||||||
@@ -485,7 +496,7 @@ R3StretcherImpl::analyseChannel(int c, int prevOuthop)
|
|||||||
(classifyScale->mag.data(), 3, nullptr,
|
(classifyScale->mag.data(), 3, nullptr,
|
||||||
classifyScale->troughs.data());
|
classifyScale->troughs.data());
|
||||||
|
|
||||||
double instantaneousRatio = double(prevOuthop) / double(m_inhop);
|
double instantaneousRatio = double(prevOuthop) / double(inhop);
|
||||||
m_guide.calculate(instantaneousRatio,
|
m_guide.calculate(instantaneousRatio,
|
||||||
classifyScale->mag.data(),
|
classifyScale->mag.data(),
|
||||||
classifyScale->troughs.data(),
|
classifyScale->troughs.data(),
|
||||||
|
|||||||
@@ -181,8 +181,8 @@ protected:
|
|||||||
|
|
||||||
Parameters m_parameters;
|
Parameters m_parameters;
|
||||||
|
|
||||||
double m_timeRatio;
|
std::atomic<double> m_timeRatio;
|
||||||
double m_pitchScale;
|
std::atomic<double> m_pitchScale;
|
||||||
|
|
||||||
std::vector<std::shared_ptr<ChannelData>> m_channelData;
|
std::vector<std::shared_ptr<ChannelData>> m_channelData;
|
||||||
std::map<int, std::shared_ptr<ScaleData>> m_scaleData;
|
std::map<int, std::shared_ptr<ScaleData>> m_scaleData;
|
||||||
@@ -192,13 +192,13 @@ protected:
|
|||||||
Peak<double, std::less<double>> m_troughPicker;
|
Peak<double, std::less<double>> m_troughPicker;
|
||||||
std::unique_ptr<StretchCalculator> m_calculator;
|
std::unique_ptr<StretchCalculator> m_calculator;
|
||||||
std::unique_ptr<Resampler> m_resampler;
|
std::unique_ptr<Resampler> m_resampler;
|
||||||
int m_inhop;
|
std::atomic<int> m_inhop;
|
||||||
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 prevOuthop);
|
void analyseChannel(int channel, int inhop, 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