11 const float log2PitchStep,
const float ERBStep,
12 const float normOverlap,
const float strenThresh)
35 Eigen::Vector2f logWinSizeLimsEigen;
39 size_t vectorSize =
static_cast<size_t>(logWinSizeLimsEigen[0] - logWinSizeLimsEigen[1]) + 1;
41 for (
size_t i = 0; i < vectorSize; i++)
43 m_winSizes[i] = std::pow(2.0f, logWinSizeLimsEigen[0] - i);
47 Eigen::VectorXf winSizeOptPitchesEigen(
m_winSizes.size());
55 for (
size_t i = 0; i < log2PitchCands.size(); ++i)
63 size_t size =
static_cast<size_t>((end - start) /
m_ERBStep) + 1;
64 Eigen::VectorXf erbsRangeEigen = Eigen::VectorXf::LinSpaced(size, start, end);
71 std::vector<float>& signalSTL)
78 Eigen::VectorXf signal = Eigen::VectorXf::Map(&signalSTL[0], signalSTL.size());
86 globStrenMtrx.setZero();
89 Eigen::MatrixXf distr;
91 Eigen::VectorXf fSupport, tSupport;
94 std::pair<Eigen::VectorXf, Eigen::VectorXf> candidates;
97 for (
size_t winSizeIdx = 0; winSizeIdx <
m_winSizes.size(); winSizeIdx++)
104 size_t padSize =
static_cast<size_t>(
m_winSizes[winSizeIdx] / 2);
106 Eigen::VectorXf paddedSignal(signal.size() + padSize);
107 paddedSignal << Eigen::VectorXf::Zero(padSize), signal;
111 std::unique_ptr<ShortTimeFourierTransform> stftObj = std::make_unique<ShortTimeFourierTransform>(
117 distr = stftObj->processSignal(paddedSignal);
122 tSupport = stftObj->getColumns();
132 ERBsDistrValues = ERBsDistrValues.unaryExpr([](
float val) {
return std::sqrt(std::max(0.0f, val)); });
136 Eigen::VectorXf selectedPitchCands;
137 for (
int i = 0; i < candidates.first.size(); ++i)
139 int index =
static_cast<int>(candidates.first[i]);
144 selectedPitchCands.conservativeResize(selectedPitchCands.size() + 1);
145 selectedPitchCands(selectedPitchCands.size() - 1) =
m_pitchCands[index - 1];
149 Eigen::MatrixXf locStrenMtrxEigen =
153 Eigen::MatrixXf locStrenMtrxInterpEigen;
154 if (locStrenMtrxEigen.size() > 1)
156 locStrenMtrxEigen.transposeInPlace();
158 locStrenMtrxInterpEigen.transposeInPlace();
162 locStrenMtrxInterpEigen.resize(candidates.first.size(),
m_times.size());
163 locStrenMtrxInterpEigen.setConstant(std::numeric_limits<float>::quiet_NaN());
167 Eigen::VectorXf currWinRelStrenEigen(candidates.first.size());
168 currWinRelStrenEigen.setOnes();
169 Eigen::VectorXf log2DistCurrWinOptPitchAndOptPitchCandsEigen;
171 auto optPitchCandsIdcs = candidates.first.cast<
int>().array() - 1;
172 auto imperfectFitIdcs = candidates.second.cast<
int>().array() - 1;
173 auto log2DistCurrWinOptPitchAndOptPitchCands =
176 currWinRelStrenEigen(imperfectFitIdcs) = (1 - log2DistCurrWinOptPitchAndOptPitchCands.abs().array());
179 globStrenMtrx(optPitchCandsIdcs, Eigen::all) =
180 globStrenMtrx(optPitchCandsIdcs, Eigen::all).array() +
181 (currWinRelStrenEigen.replicate(1, locStrenMtrxInterpEigen.cols()).array() *
182 locStrenMtrxInterpEigen.array());
191 int vectorSize =
static_cast<int>((std::log2(
m_pitchLims[1]) - std::log2(
m_pitchLims[0])) / log2PitchStep) + 1;
194 Eigen::VectorXf log2PitchCands(vectorSize);
197 for (
int i = 0; i < vectorSize; ++i)
199 log2PitchCands(i) = std::log2(
m_pitchLims[0]) + (float)i * log2PitchStep;
202 return log2PitchCands;
207 Eigen::VectorXf pitchCands(log2PitchCands.size());
210 pitchCands = Eigen::pow(2.0f, log2PitchCands.array());
217 Eigen::VectorXf optPitchCandsIdcs;
218 Eigen::VectorXf imperfectFitIdcs;
231 optPitchCandsIdcs.conservativeResize(optPitchCandsIdcs.size() + 1);
232 optPitchCandsIdcs(optPitchCandsIdcs.size() - 1) = j + 1.0f;
236 for (
size_t j = 0; j < optPitchCandsIdcs.size(); ++j)
239 static_cast<float>(winSizeIDx) <
242 imperfectFitIdcs.conservativeResize(imperfectFitIdcs.size() + 1);
243 imperfectFitIdcs(imperfectFitIdcs.size() - 1) = j + 1.0f;
247 else if (winSizeIDx == 1)
253 optPitchCandsIdcs.conservativeResize(optPitchCandsIdcs.size() + 1);
254 optPitchCandsIdcs(optPitchCandsIdcs.size() - 1) = j + 1.0f;
258 for (
size_t j = 0; j < optPitchCandsIdcs.size(); ++j)
261 static_cast<float>(winSizeIDx) >
264 imperfectFitIdcs.conservativeResize(imperfectFitIdcs.size() + 1);
265 imperfectFitIdcs(imperfectFitIdcs.size() - 1) = j + 1.0f;
275 optPitchCandsIdcs.conservativeResize(optPitchCandsIdcs.size() + 1);
276 optPitchCandsIdcs(optPitchCandsIdcs.size() - 1) = j + 1.0f;
279 imperfectFitIdcs = Eigen::VectorXf::LinSpaced(optPitchCandsIdcs.size(), 1.0f,
280 static_cast<float>(optPitchCandsIdcs.size()));
283 return {optPitchCandsIdcs, imperfectFitIdcs};
288 float threshold =
m_pitchCands[
static_cast<int>(pitchCandsSubset[0])] / 4.0f;
291 Eigen::VectorXf::Index startIndex = -1;
292 for (Eigen::VectorXf::Index i = 0; i <
m_ERBs.size(); ++i)
294 if (
m_ERBs(i) > threshold)
302 Eigen::VectorXf ERBsSubset;
303 if (startIndex != -1)
305 ERBsSubset =
m_ERBs.segment(startIndex,
m_ERBs.size() - startIndex);
312 Eigen::MatrixXf& _ERBsDistrValues,
313 const Eigen::VectorXf& _pitchCands)
316 Eigen::MatrixXf locStrenMtrx(_pitchCands.size(), _ERBsDistrValues.cols());
317 locStrenMtrx.setZero();
320 Eigen::VectorXf k(_pitchCands.size() + 1);
323 for (
int j = 0; j < k.size() - 1; ++j)
326 auto startIdx =
static_cast<size_t>(k[j]);
327 auto it = std::find_if(_ERBs.data() + startIdx, _ERBs.data() + _ERBs.size(),
328 [&](
float erb) { return erb > _pitchCands[j] / 4.0f; });
331 if (it != _ERBs.data() + _ERBs.size())
333 float dist =
static_cast<float>(std::distance(_ERBs.data(), it));
343 Eigen::VectorXf kKeep = k.segment(1, k.size() - 1);
346 auto N =
computeN(_ERBsDistrValues);
348 for (
size_t j = 0; j < _pitchCands.size(); j++)
351 auto n = N.row(kKeep[j]).transpose();
354 n.begin(), n.end(), [](
float val) { return val == 0; }, INFINITY);
356 Eigen::MatrixXf NL = _ERBsDistrValues.bottomRows(_ERBsDistrValues.rows() - kKeep[j]);
357 NL.array().rowwise() /= n.transpose().array();
368 const Eigen::MatrixXf& normERBsDistrValues,
371 int n =
static_cast<int>(std::floor(ERBS[ERBS.size() - 1] / pitchCand - 0.75));
375 return Eigen::VectorXf::Constant(normERBsDistrValues.cols(), std::numeric_limits<float>::quiet_NaN());
378 Eigen::VectorXf k = Eigen::VectorXf::Zero(ERBS.size());
381 Eigen::VectorXf q = ERBS.array() / pitchCand;
383 auto primesVec =
primes(n);
385 for (
int i : primesVec)
387 Eigen::VectorXf a = (q.array() -
static_cast<float>(i)).cwiseAbs();
390 for (
size_t p = 0; p < a.size(); ++p)
394 k[p] = std::cos(2.0f *
M_PI * q[p]);
399 for (
size_t v = 0; v < a.size(); ++v)
401 if (a[v] > 0.25f && a[v] < 0.75f)
403 k[v] += std::cos(2.0f *
M_PI * q[v]) / 2.0f;
409 k.array() *= (1.0f / ERBS.array()).array().sqrt();
412 Eigen::VectorXf nonZeroElements;
413 for (
size_t i = 0; i < k.size(); i++)
417 nonZeroElements.conservativeResize(nonZeroElements.size() + 1);
418 nonZeroElements(nonZeroElements.size() - 1) = k[i];
421 float normNonZero = nonZeroElements.norm();
422 k.array() /= normNonZero;
425 Eigen::VectorXf locStrenLine = k.transpose() * normERBsDistrValues;
431 size_t numTimes = globStrMatrix.cols();
432 size_t numPitches = globStrMatrix.rows();
434 Eigen::VectorXf pitches(numTimes);
435 pitches.setConstant(std::numeric_limits<float>::quiet_NaN());
437 Eigen::VectorXf strengths(numTimes);
438 strengths.setConstant(std::numeric_limits<float>::quiet_NaN());
440 for (
size_t timeIdx = 0; timeIdx < numTimes; ++timeIdx)
444 Eigen::VectorXf column = globStrMatrix.col(timeIdx);
449 float maxStrength = std::numeric_limits<float>::quiet_NaN();
450 Eigen::Index maxStrenPitchIdx = 0;
451 for (Eigen::Index i = 0; i < column.size(); ++i)
453 if (!std::isnan(column[i]))
455 if (std::isnan(maxStrength) || column[i] > maxStrength)
457 maxStrength = column[i];
458 maxStrenPitchIdx = i;
463 strengths[timeIdx] = maxStrength;
470 if (maxStrenPitchIdx == 0 || maxStrenPitchIdx == numPitches - 1)
477 Eigen::VectorXf maxStrenPitchLocIdcs(3);
478 maxStrenPitchLocIdcs << maxStrenPitchIdx - 1.0f, maxStrenPitchIdx, maxStrenPitchIdx + 1.0f;
480 Eigen::VectorXf tc(maxStrenPitchLocIdcs.size());
481 Eigen::VectorXf ntc(tc.size());
483 for (
size_t i = 0; i < tc.size(); ++i)
488 for (
size_t i = 0; i < tc.size(); ++i)
490 ntc[i] = ((tc[i] / tc[1]) - 1.0f) * (2.0f *
static_cast<float>(
M_PI));
495 for (
size_t i = 0; i < maxStrenPitchLocIdcs.size(); i++)
497 y.conservativeResize(y.size() + 1);
498 y(y.size() - 1) = globStrMatrix.row(maxStrenPitchLocIdcs[i])[timeIdx];
500 Eigen::VectorXf c =
polyfit(ntc, y, 2);
503 float startVal = std::log2(
m_pitchCands[maxStrenPitchLocIdcs[0]]);
504 float endVal = std::log2(
m_pitchCands[maxStrenPitchLocIdcs[2]]);
505 int numSteps =
static_cast<int>((endVal - startVal) / (1.0f / 12.0f / 100.0f) + 1);
506 Eigen::VectorXf ftc = Eigen::VectorXf::LinSpaced(numSteps, startVal, endVal);
507 ftc = Eigen::pow(2.0f, ftc.array());
508 ftc = 1.0f / ftc.array();
511 Eigen::VectorXf nftc(ftc.size());
512 nftc = (ftc.array() / tc(1) - 1.0f) * 2.0f *
M_PI;
515 Eigen::VectorXf polyValRes(nftc.size());
516 for (
int i = 0; i < nftc.size(); i++)
518 polyValRes[i] = Eigen::poly_eval(c, nftc[i]);
522 auto maxIt = std::max_element(polyValRes.begin(), polyValRes.end());
523 strengths[timeIdx] = *maxIt;
524 size_t maxPolyFitIdcs = std::distance(polyValRes.begin(), maxIt);
526 float pitchValue =
m_pitchCands[
static_cast<size_t>(maxStrenPitchLocIdcs[0])];
527 float maxPolyFitValue =
static_cast<float>(maxPolyFitIdcs) / 12.0f / 100.0f;
529 pitches[timeIdx] = std::pow(2.0f, (std::log2(pitchValue) + maxPolyFitValue));
533 return {pitches, strengths};
539 Eigen::MatrixXf squaredValues = ERBsDistrValues.array().square();
542 Eigen::MatrixXf flipSquaredValues = squaredValues.colwise().reverse().eval();
545 Eigen::MatrixXf cumSumFlipSquaredValues =
cumsum(flipSquaredValues);
548 Eigen::MatrixXf flipCumSumFlipSquaredValues = cumSumFlipSquaredValues.colwise().reverse().eval();
551 Eigen::MatrixXf rootValues = flipCumSumFlipSquaredValues.array().sqrt();
558 Eigen::VectorXi primesList(2);
561 for (
int i = 3; i <= n; ++i)
563 Eigen::VectorXi range = Eigen::VectorXi::LinSpaced(i - 2, 2, i - 1);
564 Eigen::VectorXi remainder = range.unaryExpr([&](
int x) {
return i % x; });
566 bool isPrime = remainder.all();
570 primesList.conservativeResize(primesList.size() + 1);
571 primesList(primesList.size() - 1) = i;
580 jassert(x.size() == y.size());
582 Eigen::MatrixXf xs(x.size(), n + 1);
584 for (
int i = 1; i <= n; ++i)
586 xs.col(i).array() = xs.col(i - 1).array() * x.array();
589 Eigen::VectorXf result(n + 1);
593 auto decomposition = xs.householderQr();
594 result = decomposition.solve(y);
603 Eigen::MatrixXf result(input.rows(), input.cols());
605 for (
int col = 0; col < input.cols(); ++col)
607 result(0, col) = input(0, col);
608 for (
int row = 1; row < input.rows(); ++row)
610 result(row, col) = result(row - 1, col) + input(row, col);
static std::vector< float > hz2Erbs(const std::vector< float > &hzVector)
Definition ERB_FFTSpectrogram.cpp:403
static std::vector< float > erbs2Hz(const std::vector< float > &erbsVector)
Definition ERB_FFTSpectrogram.cpp:388
static Eigen::MatrixXf interpolate2DEigen(const Eigen::VectorXf &xValues, const Eigen::MatrixXf &yValues, const Eigen::VectorXf &vals)
Definition KrotosIntrepolators.cpp:413
float m_normOverlap
Definition SWIPE_PitchEstimation.h:101
Eigen::VectorXf getERBsSubset(const Eigen::VectorXf &pitchCandsSubset)
Definition SWIPE_PitchEstimation.cpp:286
Eigen::MatrixXf cumsum(const Eigen::MatrixXf &input)
Definition SWIPE_PitchEstimation.cpp:601
Eigen::VectorXf m_times
Definition SWIPE_PitchEstimation.h:106
Eigen::VectorXf m_ERBs
Definition SWIPE_PitchEstimation.h:110
std::pair< Eigen::VectorXf, Eigen::VectorXf > calculatePitchStrengthPairs(std::vector< float > &signal)
Definition SWIPE_PitchEstimation.cpp:70
Eigen::VectorXf polyfit(const Eigen::VectorXf &x, const Eigen::VectorXf &y, int n)
Definition SWIPE_PitchEstimation.cpp:578
Eigen::Vector2f m_pitchLims
Definition SWIPE_PitchEstimation.h:105
Eigen::VectorXi primes(int n)
Definition SWIPE_PitchEstimation.cpp:556
void initVectors()
Definition SWIPE_PitchEstimation.cpp:26
Eigen::VectorXf calculateLog2PitchCands(float log2PitchStep)
Definition SWIPE_PitchEstimation.cpp:188
float m_log2PitchStep
Definition SWIPE_PitchEstimation.h:101
Eigen::VectorXf m_log2DistWin1OptPitchAndPitchCands
Definition SWIPE_PitchEstimation.h:109
std::pair< Eigen::VectorXf, Eigen::VectorXf > fineTunePitch(Eigen::MatrixXf globStrMatrix)
Definition SWIPE_PitchEstimation.cpp:429
float m_strenThresh
Definition SWIPE_PitchEstimation.h:102
Eigen::MatrixXf pitchStrengthAllCandidates(const Eigen::VectorXf &ERBs, Eigen::MatrixXf &ERBsDistrValues, const Eigen::VectorXf &pitchCands)
Definition SWIPE_PitchEstimation.cpp:311
Eigen::MatrixXf computeN(const Eigen::MatrixXf &ERBsDistrValues)
Definition SWIPE_PitchEstimation.cpp:536
Eigen::VectorXf m_winSizes
Definition SWIPE_PitchEstimation.h:108
SWIPE_PitchEstimation(const float sampleRate, const float timeStep, const float log2PitchStep, const float ERBStep, const float normOverlap, const float strenThresh)
Definition SWIPE_PitchEstimation.cpp:10
Eigen::VectorXf calculatePitchCands(const Eigen::VectorXf &log2PitchCands)
Definition SWIPE_PitchEstimation.cpp:205
std::pair< Eigen::VectorXf, Eigen::VectorXf > selectCandidatesForWindowSize(size_t winSizeIDx)
Definition SWIPE_PitchEstimation.cpp:215
float m_timeStep
Definition SWIPE_PitchEstimation.h:101
float m_sampleRate
Definition SWIPE_PitchEstimation.h:101
Eigen::VectorXf m_pitchCands
Definition SWIPE_PitchEstimation.h:107
Eigen::VectorXf pitchStrengthOneCandidate(const Eigen::VectorXf &ERBS, const Eigen::MatrixXf &normERBsDistrValues, float pitchCand)
Definition SWIPE_PitchEstimation.cpp:367
float m_ERBStep
Definition SWIPE_PitchEstimation.h:101
static Eigen::MatrixXf interpolate2DEigen(const Eigen::VectorXf &xValues, const Eigen::MatrixXf yValues, const Eigen::VectorXf &vals)
Definition KrotosIntrepolators.cpp:133
Definition AirAbsorptionFilter.cpp:2
#define M_PI
Definition windowing.h:9