24 Eigen::VectorXf signal = Eigen::VectorXf::Map(&inputSignal[0], inputSignal.size());
28 auto stftObj = std::make_unique<ShortTimeFourierTransform>(
48 auto distr = stftObj->processSignal(signal);
50 distr = distr.block(0, 0,
config.
fftSize / 2, distr.cols()).eval();
52 distr = distr.array().square();
54 float windowEnergy = stftObj->dftParams.window.sum();
55 windowEnergy = windowEnergy * windowEnergy;
56 distr = distr / windowEnergy;
59 auto tSupport = stftObj->getColumns();
60 tSupport = tSupport.array() - (
static_cast<float>(winFirstRelIdx) /
m_sampleRate);
67 constexpr int nFreqCorrs =
static_cast<int>(10.0f / 0.1f) + 1;
68 Eigen::VectorXf freqCorrs = Eigen::VectorXf::LinSpaced(nFreqCorrs, -5.0f, 5.0f);
69 int nInharmCoeffs =
static_cast<int>((0.001f - 0.0f) / 0.00005f) + 1;
70 Eigen::VectorXf inharmCoeffs = Eigen::VectorXf::LinSpaced(nInharmCoeffs, 0.0f, 0.001f);
74 int endIdx = tSupport.size() - 1;
75 tSupport.segment(startIdx, endIdx - startIdx + 1).array() -= tSupport(startIdx);
76 int tSize = endIdx - startIdx + 1;
77 Eigen::MatrixXf distrExtr = distr.middleCols(startIdx, endIdx - startIdx + 1);
84 auto pitchStrengthPairs = swipeObj->calculatePitchStrengthPairs(inputSignal);
85 Eigen::VectorXf estTimes = swipeObj->getTimes();
90 pitchStrengthPairs.second = pitchStrengthPairs.second.unaryExpr(
91 [](
float x) {
return std::isnan(x) ? -std::numeric_limits<float>::infinity() : x; });
94 Eigen::MatrixXf value;
95 Eigen::VectorXf fundamentalFreqs;
100 Eigen::MatrixXf estTimePitchPairs(estTimes.size(), 2);
103 estTimePitchPairs.col(0) = estTimes.array();
104 estTimePitchPairs.col(1) = pitchStrengthPairs.first;
108 fundamentalFreqs =
fevalbp(estTimePitchPairs, tSupport);
109 fundamentalFreqs.transpose();
126 Eigen::MatrixXf corrFreqsTF =
127 (fundamentalFreqs.replicate(1, nFreqCorrs).array() + freqCorrs.transpose().replicate(tSize, 1).array())
130 Eigen::MatrixXf inharmFactorsHI(
harmRep.
nHarms, nInharmCoeffs);
132 Eigen::MatrixXf repeatedColumnVectorHarms = columnVectorHarms.replicate(1, nInharmCoeffs);
133 Eigen::VectorXf squares = columnVectorHarms.array().square();
134 Eigen::MatrixXf secondTerm = ((squares * inharmCoeffs.transpose()).array() + 1).array().sqrt();
135 inharmFactorsHI = repeatedColumnVectorHarms.array() * secondTerm.array();
138 Eigen::MatrixXf reshapedCorrFreqsTF = corrFreqsTF.reshaped(tSize * nFreqCorrs, 1);
139 Eigen::MatrixXf reshapedInharmFactorsHI = inharmFactorsHI.reshaped(1,
harmRep.
nHarms * nInharmCoeffs);
140 Eigen::MatrixXf multiplied = reshapedCorrFreqsTF * reshapedInharmFactorsHI;
143 std::vector<Eigen::MatrixXf> reshapedMultiplied =
146 std::vector<Eigen::MatrixXi> fSupIdcsTFHI =
150 std::vector<Eigen::MatrixXi> distrIdcsTFHI =
154 std::vector<Eigen::MatrixXf> submatrices_cell =
157 std::vector<Eigen::MatrixXf> totalErgTFI =
161 Eigen::MatrixXf scoreTI(tSize, nInharmCoeffs);
163 for (
int i = 0; i < totalErgTFI.size(); ++i)
165 scoreTI.col(i) = totalErgTFI[i].rowwise().maxCoeff();
170 auto [maxScoreTI, inharmCoeffIdcsT] =
maxRowValues(scoreTI);
172 float threshold = 0.01f;
173 for (
int i = 0; i < maxScoreTI.size(); ++i)
175 if ((maxScoreTI(i) - scoreTI(i, 0)) / scoreTI(i, 0) <= threshold)
177 inharmCoeffIdcsT(i) = 0;
181 Eigen::VectorXi basicTimeIndices = Eigen::VectorXi::LinSpaced(tSize, 1, tSize);
182 Eigen::VectorXi basicFreqCorrIndices = Eigen::VectorXi::LinSpaced(nFreqCorrs, 1, nFreqCorrs);
184 Eigen::MatrixXi adjustedTimeIndices =
185 (basicTimeIndices.array() + tSize * nFreqCorrs * (inharmCoeffIdcsT.array())).replicate(1, nFreqCorrs);
186 Eigen::MatrixXi freqCorrRepeatIndices =
187 ((basicFreqCorrIndices.array() - 1) * tSize).replicate(1, tSize).transpose();
188 Eigen::MatrixXi combinedIndices = adjustedTimeIndices.array() + freqCorrRepeatIndices.array();
189 Eigen::MatrixXi colIdcs =
190 Eigen::Map<Eigen::MatrixXi>(combinedIndices.data(), combinedIndices.size(), 1).array() - 1;
193 Eigen::MatrixXf totalErgTF(tSize, nFreqCorrs);
194 for (
int i = 0; i < colIdcs.size(); i++)
197 int counter = std::floor(colIdcs(i) / (tSize * nFreqCorrs));
198 auto& subMatrix = totalErgTFI[counter];
200 int linearIndex = colIdcs(i) % (tSize * nFreqCorrs);
202 int row = linearIndex % subMatrix.rows();
203 int col = linearIndex / subMatrix.rows();
206 totalErgTF(i) = subMatrix(row, col);
210 Eigen::VectorXi harmonicAdjustedIndices =
211 (tSize * nFreqCorrs *
harmRep.
nHarms * (inharmCoeffIdcsT.array())).array() + basicTimeIndices.array();
212 std::vector<Eigen::MatrixXi> freqCorrectionMatrices(
harmRep.
nHarms,
213 harmonicAdjustedIndices.replicate(1, nFreqCorrs));
215 std::vector<Eigen::MatrixXi> replicated_freq_indices(
harmRep.
nHarms);
216 Eigen::MatrixXi freqCorrectionRepeatedIndices = basicFreqCorrIndices.transpose().replicate(tSize, 1);
221 Eigen::MatrixXi submatrix = Eigen::MatrixXi::Zero(tSize, nFreqCorrs);
222 for (
int j = 0; j < tSize; j++)
224 submatrix.row(j) = basicFreqCorrIndices;
226 replicated_freq_indices[i] = submatrix;
230 std::vector<Eigen::MatrixXi> replicated_harm_indices(
harmRep.
nHarms);
234 Eigen::MatrixXi submatrix = Eigen::MatrixXi::Zero(tSize, nFreqCorrs);
235 for (
int j = 0; j < tSize; j++)
237 submatrix.row(j).fill((harm_indices(i) - 1) *
240 replicated_harm_indices[i] = submatrix;
244 std::vector<Eigen::MatrixXi> combinedHarmonicFreqIndices(
harmRep.
nHarms);
245 for (
size_t i = 0; i < combinedHarmonicFreqIndices.size(); ++i)
248 Eigen::MatrixXi sum =
249 (replicated_harm_indices[i].array() + replicated_freq_indices[i].array() - 1) * tSize +
250 freqCorrectionMatrices[i].array();
251 combinedHarmonicFreqIndices[i] = sum.array() - 1 ;
255 Eigen::VectorXi colIdcsNew(
harmRep.
nHarms * tSize * nFreqCorrs);
257 for (
size_t i = 0; i < replicated_harm_indices.size(); ++i)
259 auto subMatrix = combinedHarmonicFreqIndices[i];
260 for (
int i = 0; i < subMatrix.cols(); i++)
263 colIdcsNew.segment(index, subMatrix.rows()) = subMatrix.col(i);
264 index += subMatrix.rows();
269 std::vector<Eigen::MatrixXi> fSupIdcsHTF(
harmRep.
nHarms, Eigen::MatrixXi::Zero(tSize, nFreqCorrs));
271 for (
int i = 0; i < colIdcsNew.size(); i++)
274 int counter = std::floor(colIdcsNew(i) / (tSize * nFreqCorrs));
275 auto& subMatrix = fSupIdcsTFHI[counter];
277 int linearIndex = colIdcsNew(i) % (tSize * nFreqCorrs);
279 int row = linearIndex % subMatrix.rows();
280 int col = linearIndex / subMatrix.rows();
283 if (i % (tSize * nFreqCorrs) == 0 && i > 0)
286 fSupIdcsHTF[setCounter](row, col) = subMatrix(row, col);
289 std::vector<Eigen::MatrixXi> permfSupIdcsHTF(nFreqCorrs, Eigen::MatrixXi::Zero(
harmRep.
nHarms, tSize));
292 for (
int i = 0; i < tSize; i++)
294 for (
int j = 0; j < nFreqCorrs; j++)
297 auto elem = fSupIdcsHTF[c](i, j);
299 permfSupIdcsHTF[j](c, i) = elem;
305 Eigen::VectorXi freqCorrIdcsT(totalErgTF.rows());
306 for (
int i = 0; i < totalErgTF.rows(); ++i)
308 float maxVal = totalErgTF.row(i).maxCoeff();
309 for (
int j = 0; j < totalErgTF.cols(); ++j)
311 if (totalErgTF(i, j) == maxVal)
313 freqCorrIdcsT(i) = j;
320 Eigen::MatrixXi harmonicIndicesRepeated = harm_indices.replicate(1, tSize);
321 Eigen::VectorXi freqCorrectionAdjustment = tSize * (freqCorrIdcsT.transpose().array()) - 1;
322 Eigen::VectorXi combinedIndexCalculation = (basicTimeIndices + freqCorrectionAdjustment) *
harmRep.
nHarms;
323 Eigen::MatrixXi combinedIndicesReplicated = combinedIndexCalculation.transpose().replicate(
harmRep.
nHarms, 1);
324 Eigen::MatrixXi finalIndicesMatrix = harmonicIndicesRepeated + combinedIndicesReplicated;
326 Eigen::VectorXi columnVector =
327 Eigen::Map<Eigen::VectorXi>(finalIndicesMatrix.data(), finalIndicesMatrix.size());
328 Eigen::VectorXi colIdcsNewNew = columnVector.array() - 1;
332 partialFreqs.setZero();
333 Eigen::VectorXi idxVec(colIdcsNewNew.size());
334 for (
int i = 0; i < colIdcsNewNew.size(); i++)
337 int counter = std::floor(colIdcsNewNew(i) / (tSize *
harmRep.
nHarms));
338 auto& subMatrix = permfSupIdcsHTF[counter];
340 int linearIndex = colIdcsNewNew(i) % (tSize *
harmRep.
nHarms);
342 int row = linearIndex % subMatrix.rows();
343 int col = linearIndex / subMatrix.rows();
346 idxVec(i) = subMatrix(row, col);
350 jassert(idxVec.maxCoeff() < fSupport.size() && idxVec.minCoeff() >= 0);
353 Eigen::VectorXf fSupportElems = idxVec.unaryExpr([&](
int idx) {
return fSupport(idx); });
354 partialFreqs = Eigen::Map<Eigen::MatrixXf>(fSupportElems.data(),
harmRep.
nHarms, tSize);
357 Eigen::VectorXi scaled_sequence = Eigen::VectorXi::LinSpaced(tSize, 0, tSize - 1)
363 Eigen::VectorXi summed_values = idxVec + scaled_sequence;
366 Eigen::MatrixXf partialAmps =
367 summed_values.unaryExpr([&](
int idx) {
return distr(idx); }).reshaped(
harmRep.
nHarms, tSize);
369 value.conservativeResize(partialFreqs.rows() + partialAmps.rows(), partialFreqs.cols());
370 value << partialFreqs, partialAmps;