Pull out per-channel analysis and resynthesis functions
This commit is contained in:
@@ -179,9 +179,7 @@ void
|
||||
R3StretcherImpl::consume()
|
||||
{
|
||||
double ratio = getEffectiveRatio();
|
||||
|
||||
int longest = m_guideConfiguration.longestFftSize;
|
||||
int classify = m_guideConfiguration.classificationFftSize;
|
||||
|
||||
m_calculator->setDebugLevel(3);
|
||||
|
||||
@@ -194,11 +192,14 @@ R3StretcherImpl::consume()
|
||||
|
||||
std::cout << "outhop = " << outhop << std::endl;
|
||||
|
||||
double instantaneousRatio = double(m_prevOuthop) / double(m_inhop);
|
||||
m_prevOuthop = outhop;
|
||||
|
||||
while (m_channelData.at(0)->outbuf->getWriteSpace() >= outhop) {
|
||||
|
||||
// NB our ChannelData, ScaleData, and ChannelScaleData maps
|
||||
// contain shared_ptrs; whenever we retain one of them in a
|
||||
// variable, we do so by reference to avoid copying the
|
||||
// shared_ptr (as that is not realtime safe). Same goes for
|
||||
// the map iterators
|
||||
|
||||
int readSpace = m_channelData.at(0)->inbuf->getReadSpace();
|
||||
if (readSpace < longest) {
|
||||
if (m_draining) {
|
||||
@@ -210,20 +211,54 @@ R3StretcherImpl::consume()
|
||||
}
|
||||
}
|
||||
|
||||
// Analysis. This is per channel
|
||||
// Analysis
|
||||
|
||||
for (int c = 0; c < m_parameters.channels; ++c) {
|
||||
analyseChannel(c, m_prevOuthop);
|
||||
}
|
||||
|
||||
// Our ChannelData, ScaleData, and ChannelScaleData maps
|
||||
// contain shared_ptrs; whenever we retain one of them in
|
||||
// a variable here, we do so by reference to avoid copying
|
||||
// the shared_ptr (as that is not realtime safe). Same
|
||||
// goes for the map iterators
|
||||
// Phase update. This is synchronised across all channels
|
||||
|
||||
for (auto &it : m_channelData[0]->scales) {
|
||||
int fftSize = it.first;
|
||||
for (int c = 0; c < m_parameters.channels; ++c) {
|
||||
auto &cd = m_channelData.at(c);
|
||||
auto &scale = cd->scales.at(fftSize);
|
||||
m_channelAssembly.mag[c] = scale->mag.data();
|
||||
m_channelAssembly.phase[c] = scale->phase.data();
|
||||
m_channelAssembly.guidance[c] = &cd->guidance;
|
||||
m_channelAssembly.outPhase[c] = scale->advancedPhase.data();
|
||||
}
|
||||
m_scaleData.at(fftSize)->guided.advance
|
||||
(m_channelAssembly.outPhase.data(),
|
||||
m_channelAssembly.mag.data(),
|
||||
m_channelAssembly.phase.data(),
|
||||
m_guideConfiguration,
|
||||
m_channelAssembly.guidance.data(),
|
||||
m_inhop,
|
||||
outhop);
|
||||
}
|
||||
|
||||
// Resynthesis
|
||||
|
||||
for (int c = 0; c < m_parameters.channels; ++c) {
|
||||
synthesiseChannel(c, outhop);
|
||||
}
|
||||
}
|
||||
|
||||
m_prevOuthop = outhop;
|
||||
}
|
||||
|
||||
void
|
||||
R3StretcherImpl::analyseChannel(int c, int prevOuthop)
|
||||
{
|
||||
int longest = m_guideConfiguration.longestFftSize;
|
||||
int classify = m_guideConfiguration.classificationFftSize;
|
||||
|
||||
auto &cd = m_channelData.at(c);
|
||||
auto &longestScale = cd->scales.at(longest);
|
||||
double *buf = longestScale->timeDomain.data();
|
||||
double *buf = cd->scales.at(longest)->timeDomain.data();
|
||||
|
||||
int readSpace = cd->inbuf->getReadSpace();
|
||||
if (readSpace < longest) {
|
||||
cd->inbuf->peek(buf, readSpace);
|
||||
v_zero(buf + readSpace, longest - readSpace);
|
||||
@@ -354,6 +389,7 @@ R3StretcherImpl::consume()
|
||||
(classifyScale->mag.data(), 3, nullptr,
|
||||
classifyScale->troughs.data());
|
||||
|
||||
double instantaneousRatio = double(prevOuthop) / double(m_inhop);
|
||||
m_guide.calculate(instantaneousRatio,
|
||||
classifyScale->mag.data(),
|
||||
classifyScale->troughs.data(),
|
||||
@@ -364,31 +400,10 @@ R3StretcherImpl::consume()
|
||||
cd->guidance);
|
||||
}
|
||||
|
||||
// Phase update. This is synchronised across all channels
|
||||
|
||||
for (auto &it : m_channelData[0]->scales) {
|
||||
int fftSize = it.first;
|
||||
for (int c = 0; c < m_parameters.channels; ++c) {
|
||||
auto &cd = m_channelData.at(c);
|
||||
auto &classifyScale = cd->scales.at(fftSize);
|
||||
m_channelAssembly.mag[c] = classifyScale->mag.data();
|
||||
m_channelAssembly.phase[c] = classifyScale->phase.data();
|
||||
m_channelAssembly.guidance[c] = &cd->guidance;
|
||||
m_channelAssembly.outPhase[c] = classifyScale->advancedPhase.data();
|
||||
}
|
||||
m_scaleData.at(fftSize)->guided.advance
|
||||
(m_channelAssembly.outPhase.data(),
|
||||
m_channelAssembly.mag.data(),
|
||||
m_channelAssembly.phase.data(),
|
||||
m_guideConfiguration,
|
||||
m_channelAssembly.guidance.data(),
|
||||
m_inhop,
|
||||
outhop);
|
||||
}
|
||||
|
||||
// Resynthesis. This is per channel
|
||||
|
||||
for (int c = 0; c < m_parameters.channels; ++c) {
|
||||
void
|
||||
R3StretcherImpl::synthesiseChannel(int c, int outhop)
|
||||
{
|
||||
int longest = m_guideConfiguration.longestFftSize;
|
||||
|
||||
auto &cd = m_channelData.at(c);
|
||||
|
||||
@@ -474,8 +489,7 @@ R3StretcherImpl::consume()
|
||||
|
||||
int synthesisWindowSize = scaleData->synthesisWindow.getSize();
|
||||
int fromOffset = (fftSize - synthesisWindowSize) / 2;
|
||||
int toOffset = (m_guideConfiguration.longestFftSize -
|
||||
synthesisWindowSize) / 2;
|
||||
int toOffset = (longest - synthesisWindowSize) / 2;
|
||||
|
||||
scaleData->synthesisWindow.cutAndAdd
|
||||
(scale->timeDomain.data() + fromOffset,
|
||||
@@ -504,6 +518,7 @@ R3StretcherImpl::consume()
|
||||
v_zero(accptr + n, outhop);
|
||||
}
|
||||
|
||||
int readSpace = cd->inbuf->getReadSpace();
|
||||
if (readSpace < m_inhop) {
|
||||
// This should happen only when draining
|
||||
cd->inbuf->skip(readSpace);
|
||||
@@ -511,9 +526,6 @@ R3StretcherImpl::consume()
|
||||
cd->inbuf->skip(m_inhop);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -248,6 +248,8 @@ protected:
|
||||
|
||||
void consume();
|
||||
void calculateHop();
|
||||
void analyseChannel(int channel, int prevOuthop);
|
||||
void synthesiseChannel(int channel, int outhop);
|
||||
|
||||
double getEffectiveRatio() const {
|
||||
return m_timeRatio * m_pitchScale;
|
||||
|
||||
Reference in New Issue
Block a user