示例#1
0
        /// <summary>
        /// Построение комплексной сонограммы
        /// </summary>
        /// <param name="FFT_S"> Вектор входных данных
        /// ("левый" и "правый" каналы - чет./нечет.). </param>
        /// <param name="FFT_S_Offset"> Смещение данных для анализа во
        /// входном векторе FFT_S. </param>
        /// <param name="useTaperWindow"> Использовать взвешивающее окно? </param>
        /// <param name="recoverAfterTaperWindow"> Аннигилировать действие
        /// взвешивающего окна на обратном проходе? </param>
        /// <param name="useNorm"> Использовать нормализацию 1/N? </param>
        /// <param name="direction"> Направление преобразования (true - прямое). </param>
        /// <param name="usePolyphase"> Использовать полифазное FFT? </param>
        /// <param name="remainArrayItemsLRCount"> Остаток необработанных данных в исходном
        /// массиве (количество элементов, включая Re/Im). </param>
        /// <param name="fftObj"> Объект FFT, для которого вызывается функция. </param>
        /// <returns> Сонограмма. </returns>
        public static double[][] Process(double[] FFT_S, int FFT_S_Offset,
                                         bool useTaperWindow, bool recoverAfterTaperWindow,
                                         bool useNorm, bool direction, bool usePolyphase,
                                         out int remainArrayItemsLRCount,
                                         ExactFFT.CFFT_Object fftObj)
        {
            int plotRowsCount, frameOffset;

            double[][] FFT_T;

            if (FFT_S == null)
            {
                throw new Exception("ExactPlotter::Process(): (FFT_S == null)");
            }

            // Вычисляем количество строк сонограммы...
            plotRowsCount = GetPlotRowsCount(FFT_S, FFT_S_Offset, out remainArrayItemsLRCount, fftObj);

            // Обрабатываем все фреймы...
            FFT_T = new double[plotRowsCount][];
            Parallel.For(0, plotRowsCount, frame =>
            {
                // Умножение на 2 треб. для real -> complex
                FFT_T[frame] = new double[fftObj.N << 1];
                frameOffset  = FFT_S_Offset + frame * fftObj.WindowStep << 1;
                ExactFFT.CFFT_Process(FFT_S, frameOffset, FFT_T[frame], useTaperWindow,
                                      recoverAfterTaperWindow, useNorm, direction, usePolyphase,
                                      fftObj);
            });

            return(FFT_T);
        }
示例#2
0
        private static void Main(string[] args)
        {
            int i, j, frameWidth, polyDiv2, windowStep, N, N2, depth;
            // double kaiserBeta;
            double ACH_Difference, sampFreq, trueFreq, exactFreq, exactFreqDiff;

            double[] FFT_S, FFT_T, MagC, MagL, MagR, ACH, ArgC, ArgL, ArgR, PhaseLR;
            int      FFT_S_Offset;

            bool useTaperWindow, recoverAfterTaperWindow, useNorm, direction, usePolyphase, isMirror, isComplex;

            ExactFFT.CFFT_Object         fftObj;
            ExactFFT.CFFT_SelfTestResult selfTestResult;
            ExactFFT.IsDumpMode = true;

            // ***************************************************

            Console.WriteLine("ExactFFT TEST \"C#\" 8.40, (c) DrAF, 2016");

            // ***************************************************
            // * КОНСТРУКТОР
            // ***************************************************
            frameWidth = 4096;
            //kaiserBeta = 28; // 28
            polyDiv2   = 1;
            windowStep = frameWidth / 3;
            isComplex  = false;
            ExactFFT.TaperWindow taperWindow = ExactFFT.TaperWindow.BLACKMAN_HARRIS_92dbPS;
            fftObj = ExactFFT.CFFT_Constructor_Cosine(frameWidth, taperWindow, polyDiv2, windowStep, isComplex);
            //fftObj = ExactFFT.CFFT_Constructor_Kaiser(frameWidth, beta, polyDiv2, windowStep, isComplex);

            // ***************************************************
            // * САМОДИАГНОСТИКА
            // ***************************************************
            ACH_Difference = 1000;
            selfTestResult = ExactFFT.SelfTest_RND(ACH_Difference, fftObj);
            Console.WriteLine("Process & Explore: {0} ms / {1} ms", (selfTestResult.CFFT_Process_time * 1000).ToString("F4"), (selfTestResult.CFFT_Explore_time * 1000).ToString("F4"));
            Console.WriteLine("Self-test result: {0}", selfTestResult.AllOK);

            // Источник и приемник
            FFT_S = new double[frameWidth << 1];
            FFT_T = new double[frameWidth << 1];

            // (Количество точек FFT / 2) - количество гармоник вместе с нулевой
            N  = fftObj.N;
            N2 = N >> 1;

            // Массивы результатов Фурье-анализа
            MagC    = new double[N];
            MagL    = new double[N2];
            MagR    = new double[N2];
            ACH     = new double[N2];
            ArgC    = new double[N];
            ArgL    = new double[N2];
            ArgR    = new double[N2];
            PhaseLR = new double[N2];

            // Читаем все данные из файла с тестовым сигналом
            if (!File.Exists("3600_Hz_STEREO_36000_SampleRate_36_deg_65536.raw"))
            {
                Console.WriteLine("\nCan't open 3600_Hz_STEREO_36000_SampleRate_36_deg_65536.raw!");
                return;
            }

            byte[] testSignalBytes = File.ReadAllBytes("3600_Hz_STEREO_36000_SampleRate_36_deg_65536.raw");
            for (i = 0, j = 0; i < (frameWidth << 1); ++i, j += 2)
            {
                FFT_S[i] = (double)BitConverter.ToInt16(testSignalBytes, j);
            }
            DebugHelper.WriteDoubles(ExactFFT.DumpName, "FFT_S.double", FFT_S);

            // Прямой прогон FFT
            useTaperWindow          = true;
            FFT_S_Offset            = 0;
            recoverAfterTaperWindow = false;
            useNorm      = true;
            direction    = true;
            usePolyphase = false;
            isMirror     = true;

            ExactFFT.CFFT_Process(FFT_S, FFT_S_Offset, FFT_T, useTaperWindow,
                                  recoverAfterTaperWindow, useNorm, direction,
                                  usePolyphase, fftObj);
            DebugHelper.WriteDoubles(ExactFFT.DumpName, "FFT_T.double", FFT_T);

            ExactFFT.CFFT_Explore(FFT_T, MagL, MagR, ACH, ArgL, ArgR, PhaseLR,
                                  usePolyphase, fftObj);
            DebugHelper.WriteDoubles(ExactFFT.DumpName, "MagL.double", MagL);
            DebugHelper.WriteDoubles(ExactFFT.DumpName, "MagR.double", MagR);
            DebugHelper.WriteDoubles(ExactFFT.DumpName, "PhaseLR.double", PhaseLR);

            ExactFFT.CFFT_ComplexExplore(FFT_T, MagC, ArgC, usePolyphase, isMirror, fftObj);
            DebugHelper.WriteDoubles(ExactFFT.DumpName, "MagC.double", MagC);
            DebugHelper.WriteDoubles(ExactFFT.DumpName, "ArgC.double", ArgC);

            // Вычисление точной частоты
            sampFreq      = 36000;
            trueFreq      = 3600;
            depth         = 20;
            exactFreq     = ExactFFT.ExactFreqAuto(MagL, depth, sampFreq, fftObj);
            exactFreqDiff = Math.Abs(exactFreq - trueFreq);

            DebugHelper.WriteDouble(ExactFFT.DumpName, "exactFreq.double", exactFreq);
            DebugHelper.WriteDouble(ExactFFT.DumpName, "trueFreq.double", trueFreq);
            DebugHelper.WriteDouble(ExactFFT.DumpName, "exactFreqDiff.double", exactFreqDiff);

            // ***************************************************
            // * ДЕСТРУКТОР
            // ***************************************************
            FFT_S   = null;
            FFT_T   = null;
            MagC    = null;
            MagL    = null;
            MagR    = null;
            ACH     = null;
            ArgC    = null;
            ArgL    = null;
            ArgR    = null;
            PhaseLR = null;

            ExactFFT.CFFT_Destructor(fftObj);
        }