Является ли моя Java-реализация алгоритма Harmonic Product Spectrum неправильной?

Я строил реализацию алгоритма спектра гармонического произведения для транскрипции аудио в миди для гитарных инструментов, результаты, похоже, неверны. Я использую частоту дискретизации 44100 и размер буфера от 1024 до 131072, но пока не повезло. Я использовал этот алгоритм для своего проекта, однако результаты совершенно другие по сравнению с другими детекторами основного тона, такими как YIN или MPM. Возможно, у меня есть алгоритмическая ошибка, если да, то я был бы признателен, если бы ее можно было указать и исправить.

 public double getPitch(double[] audioBuffer){
    int n = audioBuffer.length;
        // zero-pad the data 16x
        double[] fft = new double[16*n];

        for(int k=0; k < n; k++){
            fft[k] = audioBuffer[k];
        }

        //apply hanning window
        fft = hanning(fft);

        //apply fft
        RealDoubleFFT transformer = new RealDoubleFFT(fft.length);
       transformer.ft(fft);

       //slice the array to get only the first half
        double[] fft1 = new double[8*n];
        double[]fft2 = new double[8*n];
        System.arraycopy(fft, 0, fft1, 0, fft1.length);
        System.arraycopy(fft, fft1.length, fft2, 0, fft2.length);

        //get absolute values of the first half of fft
        fft1 = getAbs(fft1);


        // Downsample x2
        double[] times2 = this.fft.downSample(fft1, 2);


        // Downsample x3
        double[] times3 = this.fft.downSample(fft1, 3);

        // Calculate the Harmonic Product Spectrum
        int max = this.fft.HPSMax(fft1, times2, times3, minIdx, maxIdx);

        // Convert the index to frequency.
        freq[0] = this.fft.indexToFrequency(RATE, fft.length, max);
            return freq[0];

}

Это метод HPSMax и downsample:

public double[] downSample(double[] spectrum, int factor) {
    int downsampleLength = spectrum.length / factor;
    double[] d = new double[spectrum.length];

    // Load the new array with the average of factor consecutive samples
    // of the original.  Remainder should be set to 1.
    for (int i = 0; i < spectrum.length; i ++) {
        if (i < downsampleLength) {
            for (int j = 0; j < factor; j++) {     
                d[i] += spectrum[(i * factor) + j];
            }
            d[i] = d[i] / factor;                   // and average them.
        } else {
            d[i] = 1;
        }
    }
    return d;
}


public int HPSMax(
    double[] original, double[] times2, double[] times3, int min, int max) {
    double[] d = new double[original.length];

    // Calculate the product of the spectrums.
    for (int i = min; i < max; i++) {
        d[i] = original[i] * times2[i] * times3[i];
    }

    // Find the index with the highest value.
    int maxIdx = 0;

    for (int i = 0; i < original.length; i++) {
        if (d[i] > d[maxIdx]) {
            maxIdx = i;
        }
    }
    return maxIdx;
}

0 ответов

Другие вопросы по тегам