Contour<float> DioF0Estimator::estimate(const Signal &signal, double msFramePeriod)
{
    int decimationRatio = qMax(1, qMin(12, (int)(signal.samplingFrequency() / decimatedFs)));
    int decimatedLength = 1 + signal.size() / decimationRatio;
    fft = new Fft(Fft::suitableLength(decimatedLength), Fft::Real);

    Spectrum decimatedSpectrum(createDecimatedSpectrum(signal, decimationRatio));

    Contour<float> result(estimate(decimatedSpectrum, signal.size(), signal.samplingFrequency(), msFramePeriod));

    delete fft;

    return result;
}
DioF0Estimator::Spectrum DioF0Estimator::createDecimatedSpectrum(const Signal &signal, int decimationRatio)
{
    int decimatedLength = 1 + signal.size() / decimationRatio;
    int fftLength = fft->fftLength;
    double *decimatedWave = new double[fftLength];
    Decimator::decimate(signal, decimationRatio, decimatedWave, decimatedLength);
    double mean = 0.0;
    for(int i = 0; i < decimatedLength; i++)
    {
        mean += decimatedWave[i];
    }
    mean /= decimatedLength;
    for(int i = 0; i < decimatedLength; i++)
    {
        decimatedWave[i] -= mean;
    }
    for(int i = decimatedLength; i < fftLength; i++)
    {
        decimatedWave[i] = 0.0;
    }
    fft->execute(Fft::Forward, decimatedWave);
    return Spectrum(decimatedWave, decimatedLength, fftLength, (double)signal.samplingFrequency() / decimationRatio);
}