예제 #1
0
// Algorithm: first interpolate the spectral peak corresponding to fApprox,
// then locate the (near-)integer multiples of its frequency
Spectrum Analyzer::findHarmonics(const Spectrum spectrum, qreal fApprox) const
{
    Spectrum harmonics;
    if (fApprox <= 0 || std::isinf(fApprox))
        return harmonics;
    const auto peaks = spectrum.findPeaks(0.01);
    if (peaks.isEmpty())
        return harmonics;

    harmonics.reserve(peaks.size());
    const auto iFund = std::floor(fApprox / m_binFreq) + 1;
    const auto fundamental = quadraticInterpolation(&spectrum[iFund]);
    harmonics.append(fundamental);
    for (const auto peak : peaks) {
        if (peak->frequency > fundamental.frequency) {
            const Tone t = quadraticInterpolation(peak);
            const qreal ratio = t.frequency / fundamental.frequency;
            if (qAbs(1200 * std::log2(ratio / qRound(ratio))) < 10)
                harmonics.append(t);
        }
    }
    return harmonics;
}
예제 #2
0
Tone Analyzer::determineSnacFundamental(const Spectrum snac) const
{
    Tone result;
    const auto peaks = snac.findPeaks();
    if (peaks.isEmpty())
        return result;

    // First find the highest peak other than the first SNAC value, which
    // should be 1.0, then pick the first peak after the first zero crossing
    // that exceeds 0.8 times that value
    const auto maxPeak = *std::max_element(peaks.constBegin(), peaks.constEnd(), [](const Tone *t1, const Tone *t2) {
        return *t1 < *t2;
    });
    const auto zeros = snac.findZeros(1);
    auto pick = std::find_if(peaks.begin(), peaks.end(), [&](const Tone *t) {
        return t > zeros.first() && t->amplitude > 0.8 * maxPeak->amplitude;
    });
    if (pick != peaks.end()) {
        result = quadraticInterpolation(*pick);
        Q_ASSERT(result.frequency > 0);
    }
    return result;
}