2012-06-10 3 views
1

콤 필터/변환을 사용하여 java에서 wav 파일의 기본 주파수를 감지해야합니다. 또한 ZCR을 구현해야했지만 쉽습니다. 콤 필터로 기본 주파수 감지

지금 나는이 있습니다

  int best = 0, best_step = 0; 
      for (int step = 3; step < 400; ++step) { 
       int sum = 0; 
       for (i = 1; i < 10 && i * step < spectrum.length; ++i) { 
        for (int di = 0; di < i; ++di) { 
         sum += spectrum[i * step + di]/i; 
        } 
       } 


       sum *= 100; 
       comb.add(sum); 
      } 
      int sum = 0; 

      for (i = 0; i < comb.size(); ++i) { 
       sum = comb.get(i); // 3 * comb[i] - comb[i-1] - comb[i+1]; 
       System.out.println(i + " - " + sum); 
       if (sum > best) { 
        best_step = i; 
        best = sum; 
       } 
      } 

을 그리고 내 문제는이 코드가 잘못된 주파수를 감지한다는 것입니다. (나는 어떤 언어 (알고리즘/구현을위한 수색)하지만 아무것도 발견하지 않았습니다

주, 난 등은 콤 필터링해야합니다, autocorelation을 사용할 수 없습니다

편집 :를했다.. 내 코드의 좀 더 설명 :.

내가 wav 파일을로드하고 배열 프레임에 프레임을 넣어 그 때 나는 그것을 FFT를하고 (복잡한 숫자를 처리 할 수있는 간단한 구조) 단지의 배열 (widmo 이름)가

.

이제 복소수 복소수를 배열 스펙트럼에 넣습니다 :

double[] spectrum = new double[widmo.length]; 

      for (i = 0; i + 1 < widmo.length; ++i) { 
       spectrum[i] = widmo[i].abs(); 
      } 


      ArrayList<Integer> comb = new ArrayList<Integer>(); 
      int best = 0, best_step = 0; 
      for (int step = 3; step < 400; ++step) { 
       int sum = 0; 
       for (i = 1; i < 10 && i * step < spectrum.length; ++i) { 
        for (int di = 0; di < i; ++di) { 
         sum += spectrum[i * step + di]/i; 
        } 
       } 

       // sum /= step + 100; // ta linijka pozwala usunąć sporo 
       // niespodziewanych skoków częstotliwości 

       sum *= 100; 
       comb.add(sum); 
      } 
      int sum = 0; 

      for (i = 0; i < comb.size(); ++i) { 
       sum = comb.get(i); // 3 * comb[i] - comb[i-1] - comb[i+1]; 
       // ctx.fillRect(i, canvas.height, 1, -sum); 
       System.out.println(i + " - " + sum); 
       // tmp.add(new freqTime(sum,)); 
       if (sum > best) { 
        best_step = i; 
        best = sum; 
       } 
      } 
      System.out.println(); 
      System.out.println(best_step); 
      System.out.println(4 * 44100); 
      System.out.println((frames.length/numChanels)); 
      System.out.println(best_step * 44100 
        /(frames.length/numChanels)); 

마지막 println은 내 근본적인 빈도를 보여 주어야하지만 그렇지 않습니다.

나는 이것을 내 친구에게서 자바 스크립트로 받았다.

+0

구현하려는 알고리즘에 대한 참조를 게시 할 수 있습니까? 또한, 어떤 테스트와 디버깅을 했습니까? –

+0

더 많은 코드를 포함하도록이 코드를 편집해야한다고 생각합니다. 나는 모든 vars의 데이터 유형에 대해 명확하지 않습니다. –

+0

추가 설명 :) –

답변

1

나는 그것을 이해한다 (나는 생각한다 : P). 마지막 println은 기본 주파수를 제공합니다 :). 어쩌면 누군가가 그것을 필요로하거나 심지어 imporve :

ArrayList<double[]> okna = new ArrayList<>(); 
      ArrayList<freqTime> lista = new ArrayList<freqTime>(); 

      int po2 = (int) Math.pow(2, 
        Integer.parseInt((String) potega2Input.getText())); 

      po2 /= 2; 
      double[] triangles = new double[po2]; 
      double maxWykres = 0; 
      int licznik = 0; 
      int licznik2 = 0; 
      int T = frames.length; 

      boolean wykresFlaga = false; 

      for (int k = 0; k < T; k += po2) { 

       licznik = 0; 
       licznik2 = 0; 
       double[] tmp = new double[po2]; 

       Complex[] zespolone = new Complex[po2]; 

       for (int i = k; i < k + po2; i++) { 

        if (i < T) { 
         tmp[licznik] = frames[i]; 
         zespolone[licznik] = new Complex(frames[i], 0); 
         licznik2 = licznik; 
        } else { 
         tmp[licznik] = frames[licznik2]; 
         zespolone[licznik] = zespolone[licznik2]; 

        } 
        licznik++; 
       } 

       okna.add(tmp); 

       FFT fft = new FFT(); 

       zespolone = fft.fft(zespolone); 

       double maxF = 0; 
       double maxFI = 0; 

       double maxH = findMaxComp(zespolone); 
       double[] doWykresu = new double[zespolone.length]; 
       for (int a = 2; a < 100; a++) { 

        for (int i = 0; i < po2; i++) { 
         doWykresu[i] = zespolone[i].abs(); 
         triangles[i] = Math.abs(i % (2 * a) - a) 
           * (maxH)/a; 

         // triangles[i] = Math.abs(i % (2 * a) - a) * (maxH) 
         ///a; 

        } 

        double sumT = 0; 
        for (int i = 0; i < po2/2; i++) { 

         sumT += triangles[i] * doWykresu[i]; 
        } 

        if (sumT > maxF) { 
         maxF = sumT; 
         maxFI = a; 
        } 

       } 
       // 
       // maxFI /= 2; 
       // 
       if (wykresFlaga == false) { 
        maxWykres = maxH; 
       } 
       for (int i = 0; i < po2; i++) { 
        doWykresu[i] = zespolone[i].abs(); 
        triangles[i] = Math.abs(i % (2 * maxFI) - maxFI) 
          * (maxWykres)/maxFI; 

       } 
       if (wykresFlaga == false) { 
        System.out.println("Max w widmie: " + maxWykres); 
        new Wykres(doWykresu, 1, triangles); 
        wykresFlaga = true; 
       } 
       // System.out.println((2 * 44100/po2) * maxFI); 
       System.out.println((float) (44100/(float) po2) 
         * 2*(float) maxFI + " Znalzione a: " + maxFI); 

       lista.add(new freqTime(
         (int) ((float) (44100/(float) po2) *2* (float) maxFI), 
         (double) ((double) po2/44100))); 

       /* 
       * System.out.println((44100/po2) * maxFI + " " + maxFI + 
       * " " + maxFI/44100 + " " + 44100/(maxFI/po2 * 44100) 
       * + " " + 44100 * maxFI/T); 
       */ 
       // System.out.println(zespolone[(int) maxFI/2].abs()); 
      }