Attempt to "fade in" phase resets on return to unity, so as to return to an approximate pass-through without too audible a click
This commit is contained in:
@@ -147,37 +147,37 @@ public:
|
||||
const BinSegmenter::Segmentation &segmentation,
|
||||
const BinSegmenter::Segmentation &prevSegmentation,
|
||||
const BinSegmenter::Segmentation &nextSegmentation,
|
||||
bool specialCaseUnity,
|
||||
double meanMagnitude,
|
||||
int unityCount,
|
||||
Guidance &guidance) const {
|
||||
|
||||
bool hadPhaseReset = guidance.phaseReset.present;
|
||||
|
||||
guidance.phaseReset.present = false;
|
||||
guidance.kick.present = false;
|
||||
guidance.preKick.present = false;
|
||||
guidance.highUnlocked.present = false;
|
||||
guidance.phaseReset.present = false;
|
||||
guidance.channelLock.present = false;
|
||||
|
||||
double nyquist = m_parameters.sampleRate / 2.0;
|
||||
|
||||
guidance.fftBands[0].fftSize = roundUp(int(ceil(nyquist/8.0)));
|
||||
guidance.fftBands[1].fftSize = roundUp(int(ceil(nyquist/16.0)));
|
||||
guidance.fftBands[2].fftSize = roundUp(int(ceil(nyquist/32.0)));
|
||||
|
||||
if (specialCaseUnity && (fabs(ratio - 1.0) < 1.0e-6)) {
|
||||
guidance.fftBands[0].f0 = 0.0;
|
||||
guidance.fftBands[0].f1 = 0.0;
|
||||
guidance.fftBands[1].f0 = 0.0;
|
||||
guidance.fftBands[1].f1 = m_minHigher;
|
||||
guidance.fftBands[2].f0 = m_minHigher;
|
||||
guidance.fftBands[2].f1 = nyquist;
|
||||
for (int i = 0; i < int(sizeof(guidance.phaseLockBands) /
|
||||
sizeof(guidance.phaseLockBands[0])); ++i) {
|
||||
guidance.phaseLockBands[i].p = 0;
|
||||
guidance.phaseLockBands[i].beta = 1.0;
|
||||
guidance.phaseLockBands[i].f0 = nyquist;
|
||||
guidance.phaseLockBands[i].f1 = nyquist;
|
||||
}
|
||||
guidance.phaseLockBands[0].f0 = 0.0;
|
||||
guidance.phaseLockBands[0].f1 = nyquist;
|
||||
guidance.channelLock.present = false;
|
||||
// This is a vital stop case for PhaseAdvance
|
||||
guidance.phaseLockBands[3].f1 = nyquist;
|
||||
|
||||
if (meanMagnitude < 1.0e-6) {
|
||||
updateForSilence(guidance);
|
||||
return;
|
||||
}
|
||||
|
||||
if (unityCount > 0) {
|
||||
updateForUnity(guidance,
|
||||
hadPhaseReset,
|
||||
unityCount,
|
||||
magnitudes,
|
||||
segmentation);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -351,7 +351,69 @@ protected:
|
||||
value = 1 << bits;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
void updateForSilence(Guidance &guidance) const {
|
||||
// std::cout << "phase reset on silence" << std::endl;
|
||||
double nyquist = m_parameters.sampleRate / 2.0;
|
||||
guidance.fftBands[0].f0 = 0.0;
|
||||
guidance.fftBands[0].f1 = 0.0;
|
||||
guidance.fftBands[1].f0 = 0.0;
|
||||
guidance.fftBands[1].f1 = nyquist;
|
||||
guidance.fftBands[2].f0 = nyquist;
|
||||
guidance.fftBands[2].f1 = nyquist;
|
||||
guidance.phaseReset.present = true;
|
||||
guidance.phaseReset.f0 = 0.0;
|
||||
guidance.phaseReset.f1 = nyquist;
|
||||
}
|
||||
|
||||
void updateForUnity(Guidance &guidance,
|
||||
bool hadPhaseReset,
|
||||
uint32_t unityCount,
|
||||
const double *const magnitudes,
|
||||
const BinSegmenter::Segmentation &segmentation) const {
|
||||
|
||||
// std::cout << "unity" << std::endl;
|
||||
|
||||
double nyquist = m_parameters.sampleRate / 2.0;
|
||||
|
||||
guidance.fftBands[0].f0 = 0.0;
|
||||
guidance.fftBands[0].f1 = m_minLower;
|
||||
guidance.fftBands[1].f0 = m_minLower;
|
||||
guidance.fftBands[1].f1 = m_minHigher;
|
||||
guidance.fftBands[2].f0 = m_minHigher;
|
||||
guidance.fftBands[2].f1 = nyquist;
|
||||
|
||||
guidance.phaseReset.present = true;
|
||||
|
||||
if (!hadPhaseReset) {
|
||||
guidance.phaseReset.f0 = 16000.0;
|
||||
guidance.phaseReset.f1 = nyquist;
|
||||
// std::cout << "f0 = " << guidance.phaseReset.f0 << std::endl;
|
||||
return;
|
||||
} else {
|
||||
guidance.phaseReset.f0 *= 0.9;
|
||||
guidance.phaseReset.f1 *= 1.1;
|
||||
}
|
||||
|
||||
if (guidance.phaseReset.f0 < segmentation.residualAbove) {
|
||||
guidance.phaseReset.f0 = std::min(guidance.phaseReset.f0,
|
||||
segmentation.percussiveAbove);
|
||||
}
|
||||
|
||||
if (guidance.phaseReset.f1 > 16000.0) {
|
||||
guidance.phaseReset.f1 = nyquist;
|
||||
}
|
||||
|
||||
if (guidance.phaseReset.f0 < 100.0) {
|
||||
guidance.phaseReset.f0 = 0.0;
|
||||
}
|
||||
|
||||
// if (guidance.phaseReset.f0 > 0.0) {
|
||||
// std::cout << unityCount << ": f0 = " << guidance.phaseReset.f0
|
||||
// << ", f1 = " << guidance.phaseReset.f1 << std::endl;
|
||||
// }
|
||||
}
|
||||
|
||||
bool checkPotentialKick(const double *const magnitudes,
|
||||
const double *const prevMagnitudes) const {
|
||||
int b = binForFrequency(200.0, m_configuration.classificationFftSize,
|
||||
|
||||
@@ -186,19 +186,20 @@ public:
|
||||
++phaseLockBand;
|
||||
}
|
||||
double ph = 0.0;
|
||||
if (inhop == outhop) {
|
||||
ph = m_unlocked[c][i];
|
||||
} else if (inRange(f, g->phaseReset) || inRange(f, g->kick)) {
|
||||
if (inRange(f, g->phaseReset) || inRange(f, g->kick)) {
|
||||
ph = phase[c][i];
|
||||
} else if (inhop == outhop) {
|
||||
ph = m_unlocked[c][i];
|
||||
} else if (inRange (f, g->highUnlocked)) {
|
||||
ph = m_unlocked[c][i];
|
||||
} else {
|
||||
int peak = m_currentPeaks[c][i];
|
||||
int prevPeak = m_prevPeaks[c][peak];
|
||||
int peakCh = c;
|
||||
if (inRange (f, g->channelLock)) {
|
||||
if (inRange(f, g->channelLock)) {
|
||||
int other = m_greatestChannel[i];
|
||||
if (other != c) {
|
||||
if (other != c &&
|
||||
inRange(f, guidance[other]->channelLock)) {
|
||||
int otherPeak = m_currentPeaks[other][i];
|
||||
int otherPrevPeak = m_prevPeaks[other][otherPeak];
|
||||
if (otherPrevPeak == prevPeak) {
|
||||
@@ -216,7 +217,7 @@ public:
|
||||
double(g->phaseLockBands[phaseLockBand].beta);
|
||||
ph = peakNew + beta * diff;
|
||||
}
|
||||
outPhase[c][i] = ph;
|
||||
outPhase[c][i] = princarg(ph);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,9 @@ R3StretcherImpl::R3StretcherImpl(Parameters parameters,
|
||||
m_guideConfiguration(m_guide.getConfiguration()),
|
||||
m_channelAssembly(m_parameters.channels),
|
||||
m_inhop(1),
|
||||
m_prevInhop(1),
|
||||
m_prevOuthop(1),
|
||||
m_unityCount(0),
|
||||
m_startSkip(0),
|
||||
m_studyInputDuration(0),
|
||||
m_totalTargetDuration(0),
|
||||
@@ -826,9 +828,16 @@ R3StretcherImpl::analyseChannel(int c, int inhop, int prevInhop, int prevOuthop)
|
||||
std::cout << std::endl;
|
||||
}
|
||||
*/
|
||||
bool specialCaseUnity = true;
|
||||
|
||||
double ratio = getEffectiveRatio();
|
||||
|
||||
if (fabs(ratio - 1.0) < 1.0e-6) {
|
||||
++m_unityCount;
|
||||
} else {
|
||||
m_unityCount = 0;
|
||||
}
|
||||
|
||||
m_guide.updateGuidance(getEffectiveRatio(),
|
||||
m_guide.updateGuidance(ratio,
|
||||
prevOuthop,
|
||||
classifyScale->mag.data(),
|
||||
classifyScale->prevMag.data(),
|
||||
@@ -836,7 +845,8 @@ R3StretcherImpl::analyseChannel(int c, int inhop, int prevInhop, int prevOuthop)
|
||||
cd->segmentation,
|
||||
cd->prevSegmentation,
|
||||
cd->nextSegmentation,
|
||||
specialCaseUnity,
|
||||
v_mean(classifyScale->mag.data() + 1, classify/2),
|
||||
m_unityCount,
|
||||
cd->guidance);
|
||||
/*
|
||||
if (c == 0) {
|
||||
|
||||
@@ -281,6 +281,7 @@ protected:
|
||||
std::atomic<int> m_inhop;
|
||||
int m_prevInhop;
|
||||
int m_prevOuthop;
|
||||
uint32_t m_unityCount;
|
||||
int m_startSkip;
|
||||
|
||||
size_t m_studyInputDuration;
|
||||
|
||||
Reference in New Issue
Block a user