/// <summary>
        /// Event handler called when DoWork completes.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void fftWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                return;
            }

            FFTData fftData = (FFTData)e.Result;

            OnFftReady(new FFTEventArgs(fftData));
        }
 public FFTEventArgs(FFTData fftData)
 {
     _scopeData = fftData;
 }
        /// <summary>
        /// Do fft calculations and averaging
        /// </summary>
        /// <param name="sender">Background worker</param>
        /// <param name="e">Arguments</param>
        private void fftWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                BackgroundWorker   worker = sender as BackgroundWorker;
                FftWorkerArguments args   = (FftWorkerArguments)e.Argument;

                lock (PropertyLock)
                {
                    if (_fftSize != args.Samples.Length || _fftAvgWant != args.WantedAverages)
                    {
                        if (_fftSize > 0)
                        {
                            MemoryPlanCleanUp(); // Plan changed, clean up
                        }
                        _fftSize    = args.Samples.Length;
                        _fftAvgWant = args.WantedAverages;
                        MemoryPlansetup(_fftSize, _fftAvgWant);
                        _fftAvgCnt = 1; // reset averages
                    }
                    if (_windowType != args.WindowType)
                    {
                        _windowType = args.WindowType;
                        _fftAvgCnt  = 1; // reset averages
                    }
                }
                int s = 0;
                for (int i = 0; i < 2 * _fftSize; i = i + 2)
                {
                    _din[i]     = args.Samples[s++]; // real part
                    _din[i + 1] = 0;                 // imaginary part
                }

                Windowing(_fftSize, _din, _windowType, 1, _din);
                fftw.execute(_fplan);

                //convert to dBm
                int    j       = 0;
                double scaling = 2 / WindowGain(_fftSize, _windowType);
                //scaling for FFT N and window gain; no window WindowGain = N*N

                for (int i = 0; i < _fftSize; i++)
                {
                    int     avgIndex = _fftAvgCnt % _fftAvgWant;
                    Complex temp     = new Complex(_dout[j], _dout[j + 1]);
                    _magnitudeSqrt[i, avgIndex] = (temp.Magnitude * temp.Magnitude) * scaling;
                    //scaling FFT output by N and windowing correction
                    if (i == 0)
                    {
                        _magnitudeSqrt[i, avgIndex] = _magnitudeSqrt[i, avgIndex] / 2;
                    }
                    //DC term Scales Differently
                    if (_magnitudeSqrt[i, avgIndex] <= 5e-14)
                    {
                        _magnitudeSqrt[i, avgIndex] = 5e-14;                                          // Clamps to -120 dBm and avoids log10 of 0;
                    }
                    _freqDomain[i, avgIndex]    = 10 * Math.Log10(_magnitudeSqrt[i, avgIndex] / .05); // Power dBm = 10*log10(volt*volt/impedance/1mW) = 10*log10(volt*volt/50/.001)
                    _magnitudeSqrt[i, avgIndex] = Math.Sqrt(_magnitudeSqrt[i, avgIndex]);
                    j += 2;
                }

                if (_fftAvgCnt >= _fftAvgWant) // Wait until wanted amount collected.
                {
                    double[] fft = new double[_fftSize / 2];
                    double[] rms = new double[_fftSize / 2];
                    if (_fftAvgWant > 1)
                    {
                        // Calculate average
                        for (int i = 0; i < fft.Length; i++)
                        {
                            double avgTempDb        = 0;
                            double avgTempMagnitude = 0;
                            for (int f = 0; f < _fftAvgWant; f++)
                            {
                                avgTempDb        += _freqDomain[i, f]; //sum up FFTAvgWant Spectra to calculate average
                                avgTempMagnitude += _magnitudeSqrt[i, f];
                            }
                            fft[i] = avgTempDb / (_fftAvgWant);
                            rms[i] = avgTempMagnitude / (_fftAvgWant);
                        }
                    }
                    else
                    {
                        for (int i = 0; i < fft.Length; i++)
                        {
                            fft[i] = _freqDomain[i, 0];
                            rms[i] = _magnitudeSqrt[i, 0];
                        }
                    }

                    if (worker == null || worker.CancellationPending)
                    {
                        e.Cancel = true;
                        return;
                    }

                    FFTData fftData = new FFTData(fft, rms, args.SamplesPerSecond);
                    e.Result = fftData;
                }
                _fftAvgCnt++; //increment pointer to ring buffer for spectra
            }
            catch (Exception) {}
            finally
            {
                _resetEvent.Set();
            }
        }