예제 #1
0
        /// <summary>
        /// Linear Convolution x ** h を計算。
        /// </summary>
        /// <param name="h">コンボリューションカーネル。左右反転される。</param>
        /// <param name="x">入力数列。</param>
        public WWComplex[] ConvolutionFft(WWComplex[] h, WWComplex[] x) {
            var r = new WWComplex[h.Length + x.Length - 1];
            int fftSize = Functions.NextPowerOf2(r.Length);
            
            var h2 = new WWComplex[fftSize];
            Array.Copy(h, 0, h2, 0, h.Length);
            for (int i = h.Length; i < h2.Length; ++i) {
                h2[i] = WWComplex.Zero();
            }

            var x2 = new WWComplex[fftSize];
            Array.Copy(x, 0, x2, 0, x.Length);
            for (int i = x.Length; i < x2.Length; ++i) {
                x2[i] = WWComplex.Zero();
            }

            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;
        }
예제 #2
0
        /// <summary>
        /// 連続FFT オーバーラップアド法でLinear convolution x ** hする。
        /// </summary>
        /// <param name="h">コンボリューションカーネル。左右反転される。</param>
        /// <param name="x">入力数列。</param>
        /// <param name="fragmentSz">個々のFFTに入力するxの断片サイズ。</param>
        public WWComplex[] ConvolutionContinuousFft(WWComplex[] h, WWComplex[] x, int fragmentSz) {
            System.Diagnostics.Debug.Assert(2 <= fragmentSz);

            if (x.Length < h.Length) {
                // swap x and h
                var tmp = h;
                h = x;
                x = tmp;
            }

            // h.Len <= x.Len

            int fullConvLen = h.Length + x.Length - 1;

            var r = new WWComplex[fullConvLen];
            for (int i = 0; i < r.Length; ++i) {
                r[i] = WWComplex.Zero();
            }

            // hをFFTしてHを得る。
            int fragConvLen = h.Length + fragmentSz - 1;
            int fftSize = Functions.NextPowerOf2(fragConvLen);
            var h2 = new WWComplex[fftSize];
            Array.Copy(h, 0, h2, 0, h.Length);
            for (int i = h.Length; i < h2.Length; ++i) {
                h2[i] = WWComplex.Zero();
            }
            var fft = new WWRadix2Fft(fftSize);
            var H = fft.ForwardFft(h2);

            for (int offs = 0; offs < x.Length; offs += fragmentSz) {
                // xFをFFTしてXを得る。
                var xF = WWComplex.ZeroArray(fftSize);
                for (int i=0; i<fragmentSz; ++i) {
                    if (i + offs < x.Length) {
                        xF[i] = x[offs + i];
                    } else {
                        break;
                    }
                }
                var X = fft.ForwardFft(xF);

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

                // オーバーラップアド法。FFT結果を足し合わせる。
                for (int i = 0; i <fragConvLen; ++i) {
                    r[offs + i] = WWComplex.Add(r[offs + i], y[i]);
                }
            }

            return r;
        }
        /// <summary>
        /// Short-time Fourier Transform for frequency domain DSP.
        /// time domain data → freq domain data.
        /// </summary>
        /// <param name="processBlockSize">FFT size</param>
        public WWTimeDependentForwardFourierTransform(int processBlockSize, WindowType windowType)
        {
            if (!Functions.IsPowerOfTwo(processBlockSize) || processBlockSize < 4)
            {
                throw new ArgumentException("processBlockSize should be power of two and 4 or larger int");
            }

            mProcessBlockSize = processBlockSize;
            mOutputCounter    = 0;

            PrepareWindow(processBlockSize + 1, windowType);

            mFFT = new WWRadix2Fft(processBlockSize);
        }
        public WWTimeDependentInverseFourierTransform(int processBlockSize)
        {
            if (!Functions.IsPowerOfTwo(processBlockSize) || processBlockSize < 4)
            {
                throw new ArgumentException("processBlockSize should be power of two and 4 or larger int");
            }

            mProcessBlockSize = processBlockSize;
            mProcessCounter   = 0;
            mProcessedSamples = 0;

            mFFT = new WWRadix2Fft(processBlockSize);

            mOverlapBuff = new double[WantSamples];
        }