1

最近、PHP 用の FFT (高速フーリエ変換) モジュールを作成しました。テストしようとすると、配列$this->reverseTableに定義されていないインデックスがあるというエラーが常にスローされます。この問題を解決する方法がわかりませんでした。

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 の正弦波です。

コードを実行しようとすると、このエラーがスローされます

Notice: Undefined offset: 0 in C:\Program Files (x86)\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.

どんな助けでも大歓迎です。

4

2 に答える 2

1

これがクラス全体であると仮定すると、問題は FFT コンストラクター内の次の行にあると推測されます。

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

私が言えることからreverseTable、配列として宣言しますが、この行は、要素がその配列に追加されるクラス内の唯一の場所であるため、定義されていない値reverseTable[$i+$limit]を使用して要素を設定しているという事実は、未定義のインデックス( )を使用しようとするとreverseTable[$i]、そのループの最初の最初の反復で問題が発生します。そのループに入る前に、値を指定する必要がありますwhile$ireverseTable[$i]reverseTable[0]

于 2012-12-31T03:45:20.137 に答える
1

行がどこにあるかを提供していませんが、私の推測では、次の行と関係があると思われます。

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

これはコンストラクターにあり、このビットは特に間違っているように見えます$this->reverseTable[$i] + $bit;。配列から値を求めていますreverseTableが、このキーはコンストラクターのどこにも初期化されていません。

これはあなたの側の論理エラーであるため、これを修正する方法がわかりません。

于 2012-12-31T03:48:37.197 に答える