This commit is contained in:
Chris Cannam
2022-05-26 15:09:40 +01:00
2 changed files with 42 additions and 61 deletions

View File

@@ -48,18 +48,23 @@ public:
GuidedPhaseAdvance(Parameters parameters) : GuidedPhaseAdvance(Parameters parameters) :
m_parameters(parameters), m_parameters(parameters),
m_blockSize(parameters.fftSize / 2 + 1), m_binCount(parameters.fftSize / 2 + 1),
m_peakPicker(m_blockSize), m_peakPicker(m_binCount),
m_reported(false) { m_reported(false) {
size_t ch = m_parameters.channels; size_t ch = m_parameters.channels;
m_currentPeaks = allocate_and_zero_channels<int>(ch, m_blockSize); m_currentPeaks = allocate_and_zero_channels<int>(ch, m_binCount);
m_prevPeaks = allocate_and_zero_channels<int>(ch, m_blockSize); m_prevPeaks = allocate_and_zero_channels<int>(ch, m_binCount);
m_greatestChannel = allocate_and_zero<int>(m_blockSize); m_greatestChannel = allocate_and_zero<int>(m_binCount);
//!!! there is also a prevMag in R3StretcherImpl which could be passed in to here instead m_prevInMag = allocate_and_zero_channels<double>(ch, m_binCount);
m_prevInMag = allocate_and_zero_channels<double>(ch, m_blockSize); m_prevInPhase = allocate_and_zero_channels<double>(ch, m_binCount);
m_prevInPhase = allocate_and_zero_channels<double>(ch, m_blockSize); m_prevOutPhase = allocate_and_zero_channels<double>(ch, m_binCount);
m_prevOutPhase = allocate_and_zero_channels<double>(ch, m_blockSize); m_unlocked = allocate_and_zero_channels<double>(ch, m_binCount);
m_unlocked = allocate_and_zero_channels<double>(ch, m_blockSize);
for (int c = 0; c < ch; ++c) {
for (int i = 0; i < m_binCount; ++i) {
m_prevPeaks[c][i] = i;
}
}
} }
~GuidedPhaseAdvance() { ~GuidedPhaseAdvance() {
@@ -127,27 +132,10 @@ public:
nullptr); nullptr);
} }
m_peakPicker.findNearestAndNextPeaks(m_prevInMag[c], // m_peakPicker.findNearestAndNextPeaks(m_prevInMag[c],
lowest, highest - lowest + 1, // lowest, highest - lowest + 1,
2, m_prevPeaks[c], // 2, m_prevPeaks[c],
nullptr); // nullptr);
/*
static int counter = 0;
if (c == 0) {
if (++counter > 140 && counter < 150) {
std::cout << "Magnitudes and peaks (fftSize = " << m_parameters.fftSize << "):" << std::endl;
for (int i = 0; i < bs; ++i) {
if (m_currentPeaks[c][i] == i) {
std::cout << "*";
}
std::cout << mag[c][i] << ", ";
}
std::cout << std::endl;
}
}
*/
} }
if (channels > 1) { if (channels > 1) {
@@ -230,20 +218,15 @@ public:
m_prevOutPhase[c][i] = outPhase[c][i]; m_prevOutPhase[c][i] = outPhase[c][i];
} }
} }
//!!! NB in the original we use a different value of p for
//!!! peak-picking the prior magnitudes - this isn't carried
//!!! over here - it is now but I don't think this was the
//!!! full cause of our burbling
// int **tmp = m_prevPeaks; int **tmp = m_prevPeaks;
// m_prevPeaks = m_currentPeaks; m_prevPeaks = m_currentPeaks;
// m_currentPeaks = tmp; m_currentPeaks = tmp;
} }
protected: protected:
Parameters m_parameters; Parameters m_parameters;
int m_blockSize; int m_binCount;
Peak<double> m_peakPicker; Peak<double> m_peakPicker;
int **m_currentPeaks; int **m_currentPeaks;
int **m_prevPeaks; int **m_prevPeaks;

View File

@@ -415,12 +415,12 @@ R3StretcherImpl::analyseChannel(int c, int inhop, int prevInhop, int prevOuthop)
cd->inbuf->peek(buf, longest); cd->inbuf->peek(buf, longest);
} }
// We have a single unwindowed frame at the longest FFT // We have a single unwindowed frame at the longest FFT size
// size ("scale"). Populate the shorter FFT sizes from the // ("scale"). Populate the shorter FFT sizes from the centre of
// centre of it, windowing as we copy. The classification // it, windowing as we copy. The classification scale is handled
// scale is handled separately because it has readahead, // separately because it has readahead, so skip it here as well as
// so skip it here as well as the longest. (In practice // the longest. (In practice this means we are probably only
// this means we are probably only populating one scale) // populating one scale)
for (auto &it: cd->scales) { for (auto &it: cd->scales) {
int fftSize = it.first; int fftSize = it.first;
@@ -539,9 +539,8 @@ R3StretcherImpl::analyseChannel(int c, int inhop, int prevInhop, int prevOuthop)
} }
} }
// Use the classification scale to get a bin segmentation // Use the classification scale to get a bin segmentation and
// and calculate the adaptive frequency guide for this // calculate the adaptive frequency guide for this channel
// channel
cd->prevSegmentation = cd->segmentation; cd->prevSegmentation = cd->segmentation;
cd->segmentation = cd->nextSegmentation; cd->segmentation = cd->nextSegmentation;
cd->nextSegmentation = cd->segmenter->segment(readahead.mag.data()); cd->nextSegmentation = cd->segmenter->segment(readahead.mag.data());
@@ -595,9 +594,9 @@ R3StretcherImpl::synthesiseChannel(int c, int outhop)
} }
winscale = double(outhop) / winscale; winscale = double(outhop) / winscale;
// The frequency filter is applied naively in the // The frequency filter is applied naively in the frequency
// frequency domain. Aliasing is reduced by the // domain. Aliasing is reduced by the shorter resynthesis
// shorter resynthesis window // window
double factor = m_parameters.sampleRate / double(fftSize); double factor = m_parameters.sampleRate / double(fftSize);
for (int i = 0; i < fftSize/2 + 1; ++i) { for (int i = 0; i < fftSize/2 + 1; ++i) {
@@ -611,9 +610,9 @@ R3StretcherImpl::synthesiseChannel(int c, int outhop)
} }
} }
// Resynthesise each FFT size (scale) individually, then // Resynthesise each FFT size (scale) individually, then sum. This
// sum. This is easier to manage scaling for in situations // is easier to manage scaling for in situations with a varying
// with a varying resynthesis hop // resynthesis hop
for (auto &it : cd->scales) { for (auto &it : cd->scales) {
int fftSize = it.first; int fftSize = it.first;
@@ -641,12 +640,11 @@ R3StretcherImpl::synthesiseChannel(int c, int outhop)
v_fftshift(scale->timeDomain.data(), fftSize); v_fftshift(scale->timeDomain.data(), fftSize);
// Synthesis window is shorter than analysis window, // Synthesis window may be shorter than analysis window, so
// so copy and cut only from the middle of the // copy and cut only from the middle of the time-domain frame;
// time-domain frame; and the accumulator length // and the accumulator length always matches the longest FFT
// always matches the longest FFT size, so as to make // size, so as to make mixing straightforward, so there is an
// mixing straightforward, so there is an additional // additional offset needed for the target
// offset needed for the target
int synthesisWindowSize = scaleData->synthesisWindow.getSize(); int synthesisWindowSize = scaleData->synthesisWindow.getSize();
int fromOffset = (fftSize - synthesisWindowSize) / 2; int fromOffset = (fftSize - synthesisWindowSize) / 2;