예제 #1
0
        public WWRadix2Fft(int numPoints)
        {
            if (!WWUtil.IsPowerOfTwo(numPoints) || numPoints < 2)
            {
                throw new ArgumentException("numPoints must be power of two integer and larger than 2");
            }
            mNumPoints = numPoints;

            mWn = new WWComplex[mNumPoints];
            for (int i = 0; i < mNumPoints; ++i)
            {
                double angle = -2.0 * Math.PI * i / mNumPoints;
                mWn[i] = new WWComplex(Math.Cos(angle), Math.Sin(angle));
            }

            // mNumStage == log_2(mNumPoints)
            int t = mNumPoints;

            for (int i = 0; 0 < t; ++i)
            {
                t       >>= 1;
                mNumStage = i;
            }

            mBitReversalTable = new uint[mNumPoints];
            for (uint i = 0; i < mNumPoints; ++i)
            {
                mBitReversalTable[i] = BitReversal(mNumStage, i);
            }
        }
예제 #2
0
        public override PcmFormat Setup(PcmFormat inputFormat)
        {
            mPcmFormat     = new PcmFormat(inputFormat);
            mFftLength     = WWUtil.NextPowerOf2(mPcmFormat.SampleRate);
            mOverlappedFft = new OverlappedFft(mFftLength);

            return(inputFormat);
        }
예제 #3
0
        public WWComplex[] ConvolutionContinuousFft(WWComplex[] h, WWComplex[] x)
        {
            int fftSize      = WWUtil.NextPowerOf2(h.Length * 4);
            int fragmentSize = fftSize - h.Length + 1;

            if (x.Length <= fragmentSize)
            {
                // 1回のFFTで計算する。
                return(ConvolutionFft(h, x));
            }

            var fft = new WWRadix2Fft(fftSize);

            var r = new WWComplex[h.Length + x.Length - 1];

            var h2 = new WWComplex[fftSize];

            Array.Copy(h, 0, h2, 0, h.Length);
            var Hf = fft.ForwardFft(h2);

            // x(n)をfragmentSize要素ごとのデータ列に分解し、
            // それぞれ長さfftSizeになるように末尾に0を追加してx0(n)、x1(n)を得る。
            //Parallel.For(0, x.Length / fragmentSize, i => {
            for (int i = 0; i < (x.Length + fragmentSize - 1) / fragmentSize; ++i)
            {
                var xf    = new WWComplex[fftSize];
                int count = fragmentSize;
                if (x.Length < (i + 1) * fragmentSize)
                {
                    count = x.Length - i * fragmentSize;
                }
                Array.Copy(x, i * fragmentSize, xf, 0, count);
                var Xf = fft.ForwardFft(xf);
                var Yf = WWComplex.Mul(Hf, Xf);
                var yf = fft.InverseFft(Yf);

                for (int j = 0; j < fftSize; ++j)
                {
                    if (r.Length <= i * fragmentSize + j)
                    {
                        break;
                    }
                    r[i * fragmentSize + j].Add(yf[j]);
                }
            }
            ;

            return(r);
        }
예제 #4
0
        public override double[] FilterDo(double[] inPcm)
        {
            // この計算で求めるのは、mChannelId==0のとき左耳, mChannelId==1のとき右耳の音。mChannelIdは耳のチャンネル番号。
            // 入力データとしてmPcmAllChannelsが使用できる。mPcmAllChannels[0]==左スピーカーの音、mPcmAllChannels[1]==右スピーカーの音。

            int fftLength = ((int)mNumSamples < mCoeffs[0].Length) ? mCoeffs[0].Length : (int)mNumSamples;

            fftLength = WWUtil.NextPowerOf2(fftLength);

            // 左スピーカーの音=mPcmAllChannels[0]
            // 左スピーカーと耳chの相互作用のCoeff==mCoeffs[ch]
            var leftSpeaker = FFTFir(mPcmAllChannels[0], mCoeffs[mChannelId + 0], fftLength);

            // 右スピーカーの音=mPcmAllChannels[1]
            // 右スピーカーと耳chの相互作用のCoeff==mCoeffs[ch+2]
            var rightSpeaker = FFTFir(mPcmAllChannels[1], mCoeffs[mChannelId + 2], fftLength);

            var mixed = Add(leftSpeaker, rightSpeaker);

            return(mixed);
        }
예제 #5
0
        public WWComplex[] ConvolutionFft(WWComplex[] h, WWComplex[] x)
        {
            var r       = new WWComplex[h.Length + x.Length - 1];
            int fftSize = WWUtil.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);
        }
예제 #6
0
 public override string ToSaveText()
 {
     return(string.Format(CultureInfo.InvariantCulture, "{0}", WWUtil.EscapeString(FilterFilePath)));
 }
예제 #7
0
 public override string ToSaveText()
 {
     return(string.Format(CultureInfo.InvariantCulture, "{0} {1}", TagType, WWUtil.EscapeString(Text)));
 }