Пример #1
0
        public override PcmFormat Setup(PcmFormat inputFormat)
        {
            mPcmFormat     = new PcmFormat(inputFormat);
            mFftLength     = WWUtil.NextPowerOf2(mPcmFormat.SampleRate);
            mOverlappedFft = new OverlappedFft(mFftLength);

            return(inputFormat);
        }
Пример #2
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);
        }
Пример #3
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);
        }
Пример #4
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);
        }