2012-12-31 2 views
1

PHP 용 FFT (Fast Fourier Transform) 모듈을 최근 작성했습니다. 테스트를 시도했을 때, 배열 $this->reverseTable에 정의되지 않은 인덱스가 있다는 오류가 항상 발생합니다. 이 문제를 해결하는 방법에 대한 단서가 없습니다.PHP FFT 모듈 오류

다음은 PHP 코드입니다 :

<?php 
class FourierTransform { 
    public $bufferSize; 
    public $sampleRate; 
    public $bandwidth; 
    public $spectrum = array(); 
    public $real = array(); 
    public $imag = array(); 
    public $peakBand = 0; 
    public $peak = 0; 

    public function __construct($bufferSize,$sampleRate){ 
     $this->bufferSize = $bufferSize; 
     $this->sampleRate = $sampleRate; 
     $this->bandwidth = 2/$bufferSize * $sampleRate/2; 
    } 

    public function getBandFrequency($index){ 
     return $this->bandwidth * $index + $this->bandwidth/2; 
    } 

    public function calculateSpectrum(){ 
     $bSi = 2/$this->bufferSize; 
     for($i = 0,$N = $this->bufferSize/2; $i < $N; $i++){ 
      $rval = $this->real[$i]; 
      $ival = $this->imag[$i]; 
      $mag = $bSi * sqrt($rval * $rval + $ival * $ival); 
      if($mag > $this->peak){ 
       $this->peakBand = $i; 
       $this->peak = $mag; 
      } 
      $this->spectrum[$i] = $mag; 
     } 
    } 
} 

class FFT extends FourierTransform { 
    public $reverseTable = array(); 
    public $sinTable = array(); 
    public $cosTable = array(); 

    public function __construct($bufferSize,$sampleRate){ 
     parent::__construct($bufferSize,$sampleRate); 
     $limit = 1; 
     $bit = $bufferSize >> 1; 
     while($limit < $bufferSize){ 
      for($i = 0; $i < $limit; $i++){ 
       $this->reverseTable[$i + $limit] = $this->reverseTable[$i] + $bit; 
      } 
      $limit = $limit << 1; 
      $bit = $bit >> 1; 
     } 
     for($i = 0; $i < $bufferSize; $i++){ 
      $this->sinTable[$i] = sin(-M_PI/$i); 
      $this->cosTable[$i] = cos(-M_PI/$i); 
     } 
    } 

    public function foward($buffer){ 
     $k = floor(log($this->bufferSize,2)); 
     if(pow(2,$k) !== $this->bufferSize) throw new Exception('Invalid buffer size, must be a power of 2.'); 
     if($this->bufferSize !== count($buffer)) throw new Exception('Supplied buffer is not the same size as defined FFT.'); 

     $halfSize = 1; 
     for($i = 0; $i < $this->bufferSize; $i++){ 
      $this->real[$i] = $buffer[$this->reverseTable[$i]]; 
      $this->imag[$i] = 0; 
     } 
     while($halfSize < $this->bufferSize){ 
      $phaseShiftReal = $this->cosTable[$halfSize]; 
      $phaseShiftImag = $this->sinTable[$halfSize]; 
      $currentPhaseShiftReal = 1; 
      $currentPhaseShiftImag = 0; 
      for($fftStep = 0; $fftStep < $halfSize; $fftStep++){ 
       while($fftStep < $this->bufferSize){ 
        $off = $fftStep + $halfSize; 
        $tr = ($currentPhaseShiftReal * $this->real[$off]) - ($currentPhaseShiftImag * $this->imag[$off]); 
        $ti = ($currentPhaseShiftReal * $this->imag[$off]) + ($currentPhaseShiftImag * $this->real[$off]); 
        $this->real[$off] = $this->real[$fftStep] - $tr; 
        $this->imag[$off] = $this->imag[$fftStep] - $ti; 
        $this->real[$fftStep] += $tr; 
        $this->imag[$fftStep] += $ti; 
        $fftStep += $halfSize << 1; 
       } 
       $tmpReal = $currentPhaseShiftReal; 
       $currentPhaseShiftReal = ($tmpReal * $phaseShiftReal) - ($currentPhaseShiftImag * $phaseShiftImag); 
       $currentPhaseShiftImag = ($tmpReal * $phaseShiftImag) + ($currentPhaseShiftImag * $phaseShiftReal); 
      } 
      $halfSize = $halfSize << 1; 
     } 
     $this->calculateSpectrum(); 
    } 
} 
?> 

시험 시료는 440Hz로에서 사인파이다. 내가 코드를 실행하려고 할 때

은,이 오류를

공지 사항을 던졌습니다 : 정의되지 않은 오프셋 : 0 C에서 : 라인 \ 프로그램 파일 (86) \ EasyPHP - 12.1 \ www가 \의 fft.php을 48

연속적으로. 문제가

배열은 다음과 같이 데이터가 :

Array 
(
    [1] => 512 
    [2] => 256 
    [3] => 768 
    [4] => 128 
    [5] => 640 
    [6] => 384 
    [7] => 896 
    [8] => 64 
    [9] => 576 
    [10] => 320 
    [11] => 832 
    [12] => 192 
    [13] => 704 
    [14] => 448 
    [15] => 960 
    [16] => 32 
    [17] => 544 
    [18] => 288 
    [19] => 800 
    [20] => 160 
    [21] => 672 
    [22] => 416 
    [23] => 928 
    [24] => 96 
    [25] => 608 
    [26] => 352 
    [27] => 864 
    [28] => 224 
    [29] => 736 
    [30] => 480 
    [31] => 992 
    [32] => 16 
    [33] => 528 
    [34] => 272 
    [35] => 784 
    [36] => 144 
    [37] => 656 
    [38] => 400 
    [39] => 912 
    [40] => 80 
    [41] => 592 
    [42] => 336 
    [43] => 848 
    [44] => 208 
    [45] => 720 
    ... 
    [978] => 303 
    [979] => 815 
    [980] => 175 
    [981] => 687 
    [982] => 431 
    [983] => 943 
    [984] => 111 
    [985] => 623 
    [986] => 367 
    [987] => 879 
    [988] => 239 
    [989] => 751 
    [990] => 495 
    [991] => 1007 
    [992] => 31 
    [993] => 543 
    [994] => 287 
    [995] => 799 
    [996] => 159 
    [997] => 671 
    [998] => 415 
    [999] => 927 
    [1000] => 95 
    [1001] => 607 
    [1002] => 351 
    [1003] => 863 
    [1004] => 223 
    [1005] => 735 
    [1006] => 479 
    [1007] => 991 
    [1008] => 63 
    [1009] => 575 
    [1010] => 319 
    [1011] => 831 
    [1012] => 191 
    [1013] => 703 
    [1014] => 447 
    [1015] => 959 
    [1016] => 127 
    [1017] => 639 
    [1018] => 383 
    [1019] => 895 
    [1020] => 255 
    [1021] => 767 
    [1022] => 511 
    [1023] => 1023 
) 

편집을 : 이전 문제는 해결하지만 지금은 또 다른 문제가 발생합니다. 함수 forward()에서 잡히지 않은 예외가 발생합니다. Invalid buffer size, must be a power of 2. 버퍼 크기가 맞더라도.

도움이 될 것입니다.

+0

우리가 당신을 도울 수 있기 전에 문제를 좁혀 야합니다. 우리는 당신의 함수에서 던질 데이터의 샘플 버퍼조차 가지고 있지 않습니다. 당신은 배열의 인덱스 또는 그 이상을 지나갈 것입니다. – Brad

+0

이들은 수업입니다. 어떻게 부르죠? –

+0

@ shiplu.mokadd.im 방금 다음과 같이 호출합니다. ' foward ($ buffer); ?>' – Licson

답변

1

, 나는 문제가 당신의 FFT 생성자 내에서이 라인에 놓여 있다는 가정이 전체 클래스라고 가정하면, 당신이 배열로 reverseTable을 선언 무엇을 말할 수에서

$this->reverseTable[$i + $limit] = $this->reverseTable[$i] + $bit; 

하지만,이 라인은있다 해당 배열에 요소가 추가 된 클래스에만 배치하십시오. 정의되지 않은 reverseTable[$i] 값을 사용하여 reverseTable[$i+$limit] 요소를 설정한다는 사실은 while 루프의 첫 번째 반복에서 문제를 일으킬 것입니다 정의되지 않은 인덱스 $i (reverseTable[$i])을 사용하십시오. 루프를 입력하기 전에 reverseTable[0] 값을 주어야합니다.

1

라인이 장소를 제공하지 않았지만, 내 생각은이 라인을 함께 할 수있는 뭔가가있다 :

$this->reverseTable[$i + $limit] = $this->reverseTable[$i] + $bit; 

이 생성자에, 그리고이 비트는 특히 잘못된 $this->reverseTable[$i] + $bit; 보인다. reverseTable 배열의 값을 요청했지만이 키는 생성자의 어느 위치에서나 초기화되지 않습니다.

나는 당신의 논리 오류이기 때문에 이것을 고치는 방법을 모르겠습니다.