1

私は現在 Java でギター チューナー プログラムに取り組んでおり、基本周波数を決定するためにハーモニック プロダクト スペクトル アルゴリズムを実装しようとしています。

とりあえず、スペクトルを係数fでダウンサンプリングするメソッドを作成しました。

私は今、すべての異なるダウンサンプリングされたスペクトルを一緒に乗算しようとしています。私はJavaでコーディングし、配列を操作しています。その結果、ダウンサンプリングされたインデックスの配列と、スペクトルのさまざまな値の配列があります。私は今、すべての異なる配列を同じサイズに配置し、それらの値を整理して、正しいダウンサンプリングされたインデックスに対応するようにしています。私はサイズと値に多くの問題を抱えています....

さらに、紙にある例に基づいてこのアルゴリズムを実装しようとしています...したがって、このアルゴリズムは4つのダウンサンプリングされたスペクトルでのみ実装できますが、実際の音声信号を実際に使用する場合、これで十分であるとは思えません.

downsample メソッドのコードは次のとおりです。

import org.jfree.ui.RefineryUtilities;

public class SousEchantillonnage {

public static double[] valuesDownSample(double[] tab, int factor){

    int N = tab.length;

    double[] values = new double[N];

    for (int i = 0; i < N; i++){
        values[i] = tab[i];
    }

    int lengthDownSample = N + (facteur - 1) * (N - 1);

    double[] valuesDownSample = new double[lengthDownSample];
    for (int i = 0; i < N; i++){
        valuesDownSample[i] = values[i];
    }
    for (int i = N; i < lengthDownSample; i ++){
        valuesDownSample[i] = 0;
    }

    return valuesDownSample;
}

public static double[] indexDownSample(double[] tab, int factor){

    int N = tab.length;

    double[] indexes = new double[N];

    for (int i = 0; i < N; i++){
        indexes[i] = i;
    }

    int lengthDownSample = N + (factor - 1) * (N - 1);

    double[] indexDownSample = new double [lengthDownSample];
    for (int i = 0; i < lengthDownSample; i++){
        indexDownSample[i] = i / factor;
    }

    return indexDownSample;
}

この方法は有効のようです。

これまでのところ、HPSアルゴリズムの私の方法は次のとおりです。

public static double[] hps(double[] tab){

    int N = tab.length;

    int factor2 = 2;
    int factor3 = 3;
    int factor4 = 4;
    int lengthDownSample2 = N/2 + (factor2 - 1) * (N/2 - 1);
    int lengthDownSample3 = N/2 + (factor3 - 1) * (N/2 - 1);
    int lengthDownSample4 = N/2 + (factor4 - 1) * (N/2 - 1);

            // Gives us the spectrogram of the signal tab
    double[] spectrogram = new double[N];                       
    spectrogramme = FFT.calculFFT(tab);

            // We only need the first values of the spectrogram. The other half is the same.
    double[] spectrogramCut = new double[N/2];          
    for (int i = 0; i < N/2; i++){
        spectrogramCut[i] = spectrogram[i];
    }

            // We create the array that contains the values of spectrogramCut that we downsample by a factor 2
       double[] valuesSpect2 = new double [sizeDownSamp2];  
       valuesSpect2 = SousEchantillonnage.valuesDownSample(spectrogramCut, factor2);

          // We create an array of the indexes of spectrogramCut that we downsample by a factor 2
      double[] indexSpect2 = new double[sizeDownSamp2];
      indexSpect2 = SousEchantillonnage.indexDownSample(spectrogramCut, factor2);

         // We create the array that contains the values of spectrogramCut that we downsample by a factor 3
       double[] valuesSpect3 = new double [sizeDownSamp3];  
       valuesSpect3 = SousEchantillonnage.valuesDownSample(spectrogramCut, factor3);

         // We create an array of the indexes of spectrogramCut that we downsample by a factor 3
    double[] indexSpect3 = new double[sizeDownSamp3];
    indexSpect3 = SousEchantillonnage.indexDownSample(spectrogramCut, factor3);;

       // We create the array that contains the values of spectrogramCut that we            downsample by a factor 4
   double[] valuesSpect4 = new double [sizeDownSamp4];  
   valuesSpect4 = SousEchantillonnage.valuesDownSample(spectrogramCut, factor4);

       // We create an array of the indexes of spectrogramCut that we downsample by a factor 4
    double[] indexSpect4 = new double[sizeDownSamp4];
    indexSpect4 = SousEchantillonnage.indexDownSample(spectrogramCut, factor4);

        int sizeIndex = N/2 + 5 * (N/2 - 1); // size of the array that contains all the       indexes of the downsamples

        // We create this array
    double[] indexDowSamp = new double[sizeIndex];
    indexDowSamp[0] = 0;
    indexDowSamp[1] = 0.25;
    indexDowSamp[2] = 0.333;
    indexDowSamp[3] = 0.5;
    indexDowSamp[4] = 0.666;
    indexDowSamp[5] = 0.75;

    int q = sizeIndex / 6;      // quantity of packets of 6 we can do
    int r = sizeIndex%6;        // what we are left with.

    for (int i = 6; i < q * 6; i += 6){
        for (int j = 0; j < 6; j++){
        indexDowSamp[i + j] = indexDowSamp[i + j - 6] + 1;
        }
    }
    for (int i = 0; i < r; i++){
        indexDowSamp[q * 6 + i] = indexDowSamp[q * 6 + i - 6] + 1;
    }

私はここで立ち往生しています。長さの異なる 2 つの配列を乗算するメソッドを実行したいと思います。

基本的に、ご覧のとおり、スペクトログラムをダウンサンプリングすると、次の 2 つの配列が得られます。

  • ダウンサンプルされたインデックスを持つもの
  • もう 1 つはダウンサンプル後の値です。

私がやりたいのは、 : と同じサイズの配列を作成することindexDownSampleですvaluesDownSample。たとえば、 がありますindexDownSample[0] = 0。これらの配列はすべてインデックス 0 ( 、 ) に対応する値を持っているためvaluesDownSample[0]、 の積が必要です。valuesSpectCut[0] *valuesSpect2[0]*valuesSpect3[0]*valuesSpect4[0]indexSpectCut[0] = 0indexSpect2[0] = 0 = indexSpect3[0] = indexSpect4[0]

for の場合、 デフォルトで 0 forindexDownSample[1]=0.25しかないことがわかります。indexSpect4[1]= indexDownSample[1] = 0.25valuesDownSample[1]

そして、配列がいっぱいになるまでこれを続けます。

すべてがスムーズに進むと、最後に次のようになります。

  • 製品のさまざまな値を含む valuesDownSample
  • 異なるダウンサンプリングされたインデックスを含む indexDownSample。

基本周波数を見つけるには、最大ピークを見つける必要があります。

私の唯一の問題は、乗算の方法がわからないことです.....

誰かがアイデアを持っているなら、私はそれを大いに感謝します!

4

1 に答える 1