Esempio n. 1
0
        /// <summary>
        /// 入力データが完全に復元できる特殊な窓関数を使用したオーバーラップ・アドFFT。
        /// あらかじめSetNumSamples()を呼ぶと入出力サンプル数が一致する。
        /// </summary>
        /// <param name="fftLength">Forward FFT長。</param>
        /// <param name="ifftLength">Inverse FFT長。0のときForward FFT長を使用。</param>
        public WWOverlappedFft(int fftLength, int ifftLength = 0)
        {
            mFFTfwd = new WWTimeDependentForwardFourierTransform(fftLength, WWTimeDependentForwardFourierTransform.WindowType.Hann);

            if (ifftLength == 0)
            {
                ifftLength = fftLength;
            }
            mFFTinv = new WWTimeDependentInverseFourierTransform(ifftLength);
        }
        public void TimeDependentFourierTransformTestImpulse()
        {
            var t = new WWTimeDependentForwardFourierTransform(4, WWTimeDependentForwardFourierTransform.WindowType.Bartlett);
            var f = new WWTimeDependentInverseFourierTransform(4);

            var x = new double[20];

            x[0] = 1;

            Test(t, f, x, 1);
        }
        public void TimeDependentFourierTransformTestDClong()
        {
            var t = new WWTimeDependentForwardFourierTransform(4, WWTimeDependentForwardFourierTransform.WindowType.Bartlett);
            var f = new WWTimeDependentInverseFourierTransform(4);
            var x = new double[20];

            for (int i = 0; i < x.Length; ++i)
            {
                x[i] = 1;
            }

            Test(t, f, x, x.Length);
        }
        public void TimeDependentFourierTransformTestSine()
        {
            var t = new WWTimeDependentForwardFourierTransform(4, WWTimeDependentForwardFourierTransform.WindowType.Bartlett);
            var f = new WWTimeDependentInverseFourierTransform(4);

            var x = new double[20];

            for (int i = 0; i < x.Length; ++i)
            {
                x[0] = Math.Sin(i * 2.0 * Math.PI / x.Length);
            }

            Test(t, f, x, 1);
        }
        public void TimeDependentFourierTransformTestHannDC()
        {
            var t = new WWTimeDependentForwardFourierTransform(8, WWTimeDependentForwardFourierTransform.WindowType.Hann);
            var f = new WWTimeDependentInverseFourierTransform(8);
            var x = new double[19];

            for (int i = 0; i < x.Length; ++i)
            {
                x[i] = 1;
            }

            f.SetNumSamples(x.Length);

            Test(t, f, x, 1);
        }
        //
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        private void Test(WWTimeDependentForwardFourierTransform t, WWTimeDependentInverseFourierTransform f, double [] x, int fragmentSize)
        {
            int iPos = 0;
            int oPos = 0;

            // Processのテスト。
            while (iPos < x.Length)
            {
                int size = fragmentSize;
                if (x.Length - iPos < size)
                {
                    size = x.Length - iPos;
                }

                var xF = new double[size];
                Array.Copy(x, iPos, xF, 0, size);
                iPos += size;

                var X = t.Process(xF);
                if (0 < X.Length)
                {
                    var xR = f.Process(X);
                    if (0 <= xR.Length)
                    {
                        for (int j = 0; j < xR.Length; ++j)
                        {
                            Assert.IsTrue(Math.Abs(xR[j] - x[oPos]) < 1e-8);
                            ++oPos;
                        }
                    }
                }
            }

            {
                // Drainのテスト。
                var X  = t.Drain();
                var xR = f.Process(X);
                for (int j = 0; j < xR.Length; ++j)
                {
                    if (x.Length <= oPos)
                    {
                        break;
                    }
                    Assert.IsTrue(Math.Abs(xR[j] - x[oPos]) < 1e-8);
                    ++oPos;
                }
            }
        }
        public override PcmFormat Setup(PcmFormat inputFormat)
        {
            mPcmFormat = new PcmFormat(inputFormat);

            /* 周波数の精度 = メインローブの幅/2
             * Bartlett窓やHann窓のとき 4π/M ラジアン、M == FFTsize
             * 人間の耳は、超低音域の音程は長3音(=1.26倍)ずれていても気にならないという。
             */
            mFftLength = Functions.NextPowerOf2(mPcmFormat.SampleRate);
            mFFTfwd    = new WWTimeDependentForwardFourierTransform(mFftLength,
                                                                    WWTimeDependentForwardFourierTransform.WindowType.Hann);
            mFFTinv = new WWTimeDependentInverseFourierTransform(mFftLength);

            mTotalSamples     = inputFormat.NumSamples;
            mProcessedSamples = 0;

            return(inputFormat);
        }