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