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 的正弦波。

当我尝试运行代码时,它会抛出此错误

注意:未定义的偏移量:第 48 行 C:\Program Files (x86)\EasyPHP-12.1\www\fft.php 中的 0

不断地。

有问题的数组有这样的数据:

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 回答