Esempio n. 1
0
        /// <summary>
        /// 高速フーリエ変換を行います
        /// </summary>
        /// <param name="sampleN"></param>
        /// <param name="srcArr">データバッファ、データの並び替えは不要</param>
        /// <param name="dstArr">スペクトラムの配列</param>
        private static void fft2(int sampleN, Complex[] srcArr, ref Complex[] dstArr, int intWidth = 24, int decWidth = 8)
        {
            var srcReArr = srcArr.Select(x => new SignedFixedPoint(intWidth, decWidth)
            {
                DoubleValue = x.Real
            }).ToArray();
            var ps = new SignedFixedPoint[sampleN];

            fftImpl2(sampleN, intWidth, decWidth, srcReArr, ref ps);
            for (int i = 0; i < sampleN; ++i)
            {
                dstArr[i] = new Complex(ps[i].DoubleValue, 0);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// 組み込み向けのFFT実装
        /// </summary>
        /// <param name="sampleN"></param>
        /// <param name="intWidth"></param>
        /// <param name="decWidth"></param>
        /// <param name="srcReArr"></param>
        /// <param name="powerSpectrum"></param>
        private static void fftImpl2(int sampleN, int intWidth, int decWidth, SignedFixedPoint[] srcReArr, ref SignedFixedPoint[] powerSpectrum)
        {
            //元データをビット反転してコピー
            var bitWidth      = (int)Math.Log(sampleN, 2);
            var addressingArr = generateBitReverseArr(bitWidth).ToArray();//アドレッシングテーブル
            var dstReArr      = new SignedFixedPoint[sampleN];
            var dstImArr      = new SignedFixedPoint[sampleN];

            foreach (var pair in addressingArr.Select((y, x) => new { SrcIndex = x, DstIndex = y }))
            {
                dstReArr[pair.DstIndex] = srcReArr[pair.SrcIndex];
                dstImArr[pair.DstIndex] = new SignedFixedPoint(intWidth, decWidth)
                {
                    RawData = 0x0
                };
            }
            //バタフライ演算回数
            int stageN = (int)Math.Log(sampleN, 2);//定数
            //回転子の事前計算
            var wMax     = sampleN / 2;
            var wTable   = Enumerable.Range(0, wMax).Select(n => Complex.Exp(-Complex.ImaginaryOne * 2 * Math.PI * n / sampleN)).ToArray();
            var wReTable = wTable.Select(x => x.Real).Select(x => new SignedFixedPoint(intWidth, decWidth)
            {
                DoubleValue = x
            }).ToArray();
            var wImTable = wTable.Select(x => x.Imaginary).Select(x => new SignedFixedPoint(intWidth, decWidth)
            {
                DoubleValue = x
            }).ToArray();

            /* バタフライ演算をする */
            for (int stage = 0; stage < stageN; ++stage)
            {
                //0 ~ sampleN / 2まで2個ずつ処理する
                for (int i = 0; i < sampleN / 2; ++i)
                {
                    //対象データのインデックス+サブインデックス(2次元配列等価)
                    int index1   = (i >> stage) << 1;
                    int index2   = index1 + 1;
                    int subIndex = i & ~(0xffff << stage);
                    //実データへのアドレスは {index,subIndex}
                    int addr1 = (index1 << stage) + subIndex; //元の配列の位置
                    int addr2 = (index2 << stage) + subIndex; //元の配列の位置
                    //回転子決定
                    int wIndex = (((subIndex) & ~(0xffff << stage)) << (stageN - stage - 1));
                    //Debug.WriteLine($"i:{i}\twIndex:{wIndex}\tdata1[{index1}, {subIndex}](addr:{addr1}) \t data2[{index2}, {subIndex}](addr:{addr2})");

                    //計算
                    var srcDataRe1 = dstReArr[addr1];
                    var srcDataIm1 = dstImArr[addr1];
                    var srcDataRe2 = dstReArr[addr2];
                    var srcDataIm2 = dstImArr[addr2];
                    //w * srcData2
                    var wRe       = wReTable[wIndex];
                    var wIm       = wImTable[wIndex];
                    var mulRe1Re2 = wRe * srcDataRe2;
                    var mulIm1Im2 = wIm * srcDataIm2;
                    var mulRe1Im2 = wRe * srcDataIm2;
                    var mulRe2Im1 = wIm * srcDataRe2;
                    var mulRe     = mulRe1Re2 - mulIm1Im2;
                    var mulIm     = mulRe1Im2 + mulRe2Im1;
                    //srcData1 + w * srcData2, srcData1 - w * srcData2
                    var dstDataRe1 = srcDataRe1 + mulRe;
                    var dstDataIm1 = srcDataIm1 + mulIm;
                    var dstDataRe2 = srcDataRe1 - mulRe;
                    var dstDataIm2 = srcDataIm1 - mulIm;
                    dstReArr[addr1] = dstDataRe1;
                    dstImArr[addr1] = dstDataIm1;
                    dstReArr[addr2] = dstDataRe2;
                    dstImArr[addr2] = dstDataIm2;
                }
            }
            /* 計算結果をパワースペクトルに直す */
            for (int i = 0; i < sampleN; ++i)
            {
                //最終的な値を符号無しにすれば終わり
                powerSpectrum[i] = dstReArr[i].IsSigned ? dstReArr[i].TwoComplementary : dstReArr[i];
            }
        }