最近、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.
どんな助けでも大歓迎です。