Ejemplo n.º 1
0
        public WWComplex[] ConvolutionFft(WWComplex[] h, WWComplex[] x)
        {
            var r       = new WWComplex[h.Length + x.Length - 1];
            int fftSize = WWRadix2Fft.NextPowerOf2(r.Length);
            var h2      = new WWComplex[fftSize];

            Array.Copy(h, 0, h2, 0, h.Length);
            var x2 = new WWComplex[fftSize];

            Array.Copy(x, 0, x2, 0, x.Length);

            var fft = new WWRadix2Fft(fftSize);
            var H   = fft.ForwardFft(h2);
            var X   = fft.ForwardFft(x2);

            var Y = WWComplex.Mul(H, X);

            var y = fft.InverseFft(Y);

            Array.Copy(y, 0, r, 0, r.Length);
            return(r);
        }
Ejemplo n.º 2
0
        private void FftStageN(int stageNr, WWComplex[] x, WWComplex[] y)
        {
            /*
             * stage0: 2つの入力データにバタフライ演算 (length=8の時) 4回 (nRepeat=4, nSubRepeat=2)
             * y[0] = x[0] + w_n^(0*4) * x[1]
             * y[1] = x[0] + w_n^(1*4) * x[1]
             *
             * y[2] = x[2] + w_n^(0*4) * x[3]
             * y[3] = x[2] + w_n^(1*4) * x[3]
             *
             * y[4] = x[4] + w_n^(0*4) * x[5]
             * y[5] = x[4] + w_n^(1*4) * x[5]
             *
             * y[6] = x[6] + w_n^(0*4) * x[7]
             * y[7] = x[6] + w_n^(1*4) * x[7]
             */

            /*
             * stage1: 4つの入力データにバタフライ演算 (length=8の時) 2回 (nRepeat=2, nSubRepeat=4)
             * y[0] = x[0] + w_n^(0*2) * x[2]
             * y[1] = x[1] + w_n^(1*2) * x[3]
             * y[2] = x[0] + w_n^(2*2) * x[2]
             * y[3] = x[1] + w_n^(3*2) * x[3]
             *
             * y[4] = x[4] + w_n^(0*2) * x[6]
             * y[5] = x[5] + w_n^(1*2) * x[7]
             * y[6] = x[4] + w_n^(2*2) * x[6]
             * y[7] = x[5] + w_n^(3*2) * x[7]
             */

            /*
             * stage2: 8つの入力データにバタフライ演算 (length=8の時) 1回 (nRepeat=1, nSubRepeat=8)
             * y[0] = x[0] + w_n^(0*1) * x[4]
             * y[1] = x[1] + w_n^(1*1) * x[5]
             * y[2] = x[2] + w_n^(2*1) * x[6]
             * y[3] = x[3] + w_n^(3*1) * x[7]
             * y[4] = x[0] + w_n^(4*1) * x[4]
             * y[5] = x[1] + w_n^(5*1) * x[5]
             * y[6] = x[2] + w_n^(6*1) * x[6]
             * y[7] = x[3] + w_n^(7*1) * x[7]
             */

            /*
             * stageN:
             */

            int nRepeat    = Pow2(mNumStage - stageNr - 1);
            int nSubRepeat = mNumPoints / nRepeat;
            var t          = new WWComplex();

            for (int i = 0; i < nRepeat; ++i)
            {
                int offsBase = i * nSubRepeat;

                bool allZero = true;
                for (int j = 0; j < nSubRepeat / 2; ++j)
                {
                    int offs = offsBase + (j % (nSubRepeat / 2));
                    if (Double.Epsilon < x[offs].Magnitude())
                    {
                        allZero = false;
                        break;
                    }
                    if (Double.Epsilon < x[offs + nSubRepeat / 2].Magnitude())
                    {
                        allZero = false;
                        break;
                    }
                }

                if (allZero)
                {
                    for (int j = 0; j < nSubRepeat / 2; ++j)
                    {
                        y[j + offsBase].Set(0, 0);
                    }
                }
                else
                {
                    for (int j = 0; j < nSubRepeat; ++j)
                    {
                        int offs = offsBase + (j % (nSubRepeat / 2));
                        y[j + offsBase].CopyFrom(x[offs]);

                        t.CopyFrom(mWn[j * nRepeat]);
                        t.Mul(x[offs + nSubRepeat / 2]);

                        y[j + offsBase].Add(t);
                    }
                }
            }
        }
Ejemplo n.º 3
0
        public override double[] FilterDo(double[] inPcm)
        {
            System.Diagnostics.Debug.Assert(inPcm.LongLength <= NumOfSamplesNeeded());
            var fft = new WWRadix2Fft(FFT_LEN);

            // Overlap and add continuous FFT

            var inTime = new WWComplex[FFT_LEN];

            for (int i = 0; i < inPcm.Length; ++i)
            {
                inTime[i].real = inPcm[i];
            }

            // FFTでinTimeをinFreqに変換
            var inFreq = fft.ForwardFft(inTime);

            inTime = null;

            // FFT後、フィルターHの周波数ドメインデータを掛ける
            var mulFreq = WWComplex.Mul(inFreq, mFilterFreq);

            inFreq = null;

            // inFreqをIFFTしてoutTimeに変換
            var outTime = fft.InverseFft(mulFreq);

            mulFreq = null;

            double [] outReal;
            if (mFirstFilterDo)
            {
                // 最初のFilterDo()のとき、フィルタの遅延サンプル数だけ先頭サンプルを削除する。
                outReal = new double[NumOfSamplesNeeded() - FILTER_DELAY];
                for (int i = 0; i < outReal.Length; ++i)
                {
                    outReal[i] = outTime[i + FILTER_DELAY].real;
                }
                mFirstFilterDo = false;
            }
            else
            {
                outReal = new double[NumOfSamplesNeeded()];
                for (int i = 0; i < outReal.Length; ++i)
                {
                    outReal[i] = outTime[i].real;
                }
            }

            // 前回のIFFT結果の最後のFILTER_LENGTH-1サンプルを先頭に加算する
            if (null != mIfftAddBuffer)
            {
                for (int i = 0; i < mIfftAddBuffer.Length; ++i)
                {
                    outReal[i] += mIfftAddBuffer[i];
                }
            }

            // 今回のIFFT結果の最後のFILTER_LENGTH-1サンプルをmIfftAddBufferとして保存する
            mIfftAddBuffer = new double[FILTER_LENP1];
            for (int i = 0; i < mIfftAddBuffer.Length; ++i)
            {
                mIfftAddBuffer[i] = outTime[outTime.Length - mIfftAddBuffer.Length + i].real;
            }
            outTime = null;

            return(outReal);
        }
Ejemplo n.º 4
0
 public static WWComplex Mul(WWComplex a, WWComplex b)
 {
     var r = new WWComplex(a);
     r.Mul(b);
     return r;
 }
Ejemplo n.º 5
0
        private void FftStageN(int stageNr, WWComplex[] x, WWComplex[] y)
        {
            /*
             * stage0: 2つの入力データにバタフライ演算 (length=8の時) 4回 (nRepeat=4, nSubRepeat=2)
             * y[0] = x[0] + w_n^(0*4) * x[1]
             * y[1] = x[0] + w_n^(1*4) * x[1]
             *
             * y[2] = x[2] + w_n^(0*4) * x[3]
             * y[3] = x[2] + w_n^(1*4) * x[3]
             *
             * y[4] = x[4] + w_n^(0*4) * x[5]
             * y[5] = x[4] + w_n^(1*4) * x[5]
             *
             * y[6] = x[6] + w_n^(0*4) * x[7]
             * y[7] = x[6] + w_n^(1*4) * x[7]
             */

            /*
             * stage1: 4つの入力データにバタフライ演算 (length=8の時) 2回 (nRepeat=2, nSubRepeat=4)
             * y[0] = x[0] + w_n^(0*2) * x[2]
             * y[1] = x[1] + w_n^(1*2) * x[3]
             * y[2] = x[0] + w_n^(2*2) * x[2]
             * y[3] = x[1] + w_n^(3*2) * x[3]
             *
             * y[4] = x[4] + w_n^(0*2) * x[6]
             * y[5] = x[5] + w_n^(1*2) * x[7]
             * y[6] = x[4] + w_n^(2*2) * x[6]
             * y[7] = x[5] + w_n^(3*2) * x[7]
             */

            /*
             * stage2: 8つの入力データにバタフライ演算 (length=8の時) 1回 (nRepeat=1, nSubRepeat=8)
             * y[0] = x[0] + w_n^(0*1) * x[4]
             * y[1] = x[1] + w_n^(1*1) * x[5]
             * y[2] = x[2] + w_n^(2*1) * x[6]
             * y[3] = x[3] + w_n^(3*1) * x[7]
             * y[4] = x[0] + w_n^(4*1) * x[4]
             * y[5] = x[1] + w_n^(5*1) * x[5]
             * y[6] = x[2] + w_n^(6*1) * x[6]
             * y[7] = x[3] + w_n^(7*1) * x[7]
             */

            /*
             * stageN:
             */

            int nRepeat    = Pow2(mNumStage - stageNr - 1);
            int nSubRepeat = mNumPoints / nRepeat;
            var t = new WWComplex();

            for (int i=0; i<nRepeat; ++i) {
                int offsBase = i * nSubRepeat;

                bool allZero = true;
                for (int j=0; j < nSubRepeat/2; ++j) {
                    int offs = offsBase + (j % (nSubRepeat/2));
                    if (Double.Epsilon < x[offs].Magnitude()) {
                        allZero = false;
                        break;
                    }
                    if (Double.Epsilon < x[offs + nSubRepeat / 2].Magnitude()) {
                        allZero = false;
                        break;
                    }
                }

                if (allZero) {
                    for (int j=0; j < nSubRepeat / 2; ++j) {
                        y[j + offsBase].Set(0, 0);
                    }
                } else {
                    for (int j=0; j < nSubRepeat; ++j) {
                        int offs = offsBase + (j % (nSubRepeat / 2));
                        y[j + offsBase].CopyFrom(x[offs]);

                        t.CopyFrom(mWn[j * nRepeat]);
                        t.Mul(x[offs + nSubRepeat / 2]);

                        y[j + offsBase].Add(t);
                    }
                }
            }
        }