public void Process(Complex *buffer, int length)
        {
            if (_workingBuffer == null || _workingBuffer.Length < length)
            {
                _workingBuffer = new Complex[length];
            }

            for (var n = 0; n < length; n++)
            {
                _workingBuffer[n] = buffer[n];
            }

            if (_window == null || _window.Length < length)
                _window = FilterBuilder.MakeWindow(WindowType.Hamming, length);

            fixed(Complex *workingPtr = &_workingBuffer[0])
            {
                fixed(float *winPtr = &_window[0])
                Fourier.ApplyFFTWindow(workingPtr, winPtr, length);

                Fourier.ForwardTransform(workingPtr, length);
                _drawing.AddDataLine(workingPtr, length);
            }

            //_drawing.AddDataLine(buffer, length);
        }
예제 #2
0
        private void ProcessFFT(object parameter)
        {
            while (_control.IsPlaying && _fftThreadRunning)
            {
                #region Configure

                if (_sampleRate == 0.0)
                {
                    // WTF???
                    Thread.Sleep(1);
                    continue;
                }

                var fftRate = _fftBins / (_fftTimer.Interval * 0.001);
                _fftOverlapRatio = _sampleRate / fftRate;
                var samplesToConsume = (int)(_fftBins * _fftOverlapRatio);
                _fftSamplesPerFrame = Math.Min(samplesToConsume, _fftBins);
                var excessSamples = samplesToConsume - _fftSamplesPerFrame;
                _maxIQSamples = (int)(samplesToConsume / (double)_fftTimer.Interval * 100 * /*_streamControl.BufferSizeInMs **/ 1.5);

                #endregion

                #region Shift data for overlapped mode)

                if (_fftSamplesPerFrame < _fftBins)
                {
                    Utils.Memcpy(_iqPtr, _iqPtr + _fftSamplesPerFrame, (_fftBins - _fftSamplesPerFrame) * sizeof(Complex));
                }

                #endregion

                #region Read IQ data

                var targetLength = _fftSamplesPerFrame;

                var total = 0;
                while (_control.IsPlaying && total < targetLength && _fftThreadRunning)
                {
                    var len = targetLength - total;
                    total += _iqStream.Read(_iqPtr, _fftBins - targetLength + total, len);
                }

                _iqStream.Advance(excessSamples);

                #endregion

                if (!_fftSpectrumAvailable)
                {
                    #region Process FFT gain

                    // http://www.designnews.com/author.asp?section_id=1419&doc_id=236273&piddl_msgid=522392
                    var fftGain      = (float)(10.0 * Math.Log10((double)_fftBins / 2));
                    var compensation = 24.0f - fftGain + _fftOffset;

                    #endregion

                    #region Calculate FFT

                    Utils.Memcpy(_fftPtr, _iqPtr, _fftBins * sizeof(Complex));
                    Fourier.ApplyFFTWindow(_fftPtr, _fftWindowPtr, _fftBins);
                    Fourier.ForwardTransform(_fftPtr, _fftBins);
                    Fourier.SpectrumPower((Complex *)_fftPtr, (float *)_fftSpectrumPtr, (int)_fftBins, (float)compensation);

                    #endregion

                    _fftSpectrumAvailable = true;
                }

                if (_iqStream.Length <= _maxIQSamples)
                {
                    _fftBufferIsWaiting = true;
                    _fftEvent.WaitOne();
                }
            }
            _iqStream.Flush();
        }
        private void CalculatePower(Complex *buffer, int pos, int length)
        {
            var fftSize = NextPowerOfTwo(length);

            if (_window == null || _window.Length != fftSize)
            {
                _window = FilterBuilder.MakeWindow(WindowType.Hamming, fftSize);
            }

            if (_workingBuffer == null || _workingBuffer.Length != fftSize)
            {
                _workingBuffer = new Complex[fftSize];
                _powerSpectrumPanel.PointsPerSecond = (ulong)(_sampleRate / length + 0.5);
            }

            for (int n = 0; n < fftSize; n++)
            {
                if (n < length)
                {
                    _workingBuffer[n] = buffer[pos + n];
                }
                else
                {
                    _workingBuffer[n] = 0;
                }
            }

            fixed(Complex *workingPtr = &_workingBuffer[0])
            {
                fixed(float *winPtr = &_window[0])
                Fourier.ApplyFFTWindow(workingPtr, winPtr, fftSize);

                Fourier.ForwardTransform(workingPtr, fftSize);
            }

            var herzPerBin   = _sampleRate / fftSize;
            var offsetHerz   = MainControl.Frequency - MainControl.CenterFrequency;
            var offsetBins   = (int)(offsetHerz / herzPerBin + 0.5);
            var freqBinIndex = fftSize / 2 + offsetBins;
            var avgInBins    = (int)(MainControl.FilterBandwidth / herzPerBin + 0.5);

            if (avgInBins == 0)
            {
                avgInBins = 1;
            }

            int startIndex;
            int endIndex;

            switch (MainControl.DetectorType)
            {
            case DetectorType.LSB:
                startIndex = freqBinIndex - avgInBins;
                endIndex   = freqBinIndex;
                break;

            case DetectorType.USB:
                startIndex = freqBinIndex;
                endIndex   = freqBinIndex + avgInBins;
                break;

            default:
                startIndex = (int)(freqBinIndex - avgInBins / 2.0f + 0.5);
                endIndex   = (int)(freqBinIndex + avgInBins / 2.0f + 0.5);
                break;
            }

            if (startIndex < 0)
            {
                startIndex = 0;
            }

            if (endIndex >= _workingBuffer.Length)
            {
                endIndex = _workingBuffer.Length;
            }

            var totalPower = 0.0f;

            for (var n = startIndex; n < endIndex; n++)
            {
                //CheckMinMax(_workingBuffer[n]);
                totalPower += (float)(10.0 * Math.Log10(1e-60 + (_workingBuffer[n].Real * _workingBuffer[n].Real + _workingBuffer[n].Imag * _workingBuffer[n].Imag)));
            }

            var fftGain      = (float)(10.0 * Math.Log10(fftSize / 2.0));
            var compensation = 24.0f - fftGain - 40.0f;

            var dataPointValue = totalPower / avgInBins + compensation;

            if (dataPointValue >= _controlPanel.SquelchValue)
            {
                _powerTriggerCount++;
            }
            else
            {
                _powerTriggerCount = 0;
            }

            SquelchOpen = _powerTriggerCount > 1;

            if (_powerSpectrumPanel.Visible)
            {
                _powerSpectrumPanel.Draw(dataPointValue);
            }
        }
예제 #4
0
        public void Process(Complex *buffer, int length)
        {
            if (!_scanning)
            {
                return;
            }

            if (_control.Frequency == _checkedFrequency)
            {
                return;
            }

            if (_workingBuffer == null || _workingBuffer.Length < length)
            {
                _workingBuffer = new Complex[length];
            }

            for (var n = 0; n < length; n++)
            {
                _workingBuffer[n] = buffer[n];
            }

            if (_window == null || _window.Length < length)
                _window = FilterBuilder.MakeWindow(WindowType.Hamming, length);

            fixed(Complex *workingPtr = &_workingBuffer[0])
            {
                fixed(float *winPtr = &_window[0])
                Fourier.ApplyFFTWindow(workingPtr, winPtr, length);

                Fourier.ForwardTransform(workingPtr, length);

                if (_spectrum == null || _spectrum.Length < length)
                    _spectrum = new float[length];

                fixed(float *spectrumPtr = &_spectrum[0])
                Fourier.SpectrumPower(workingPtr, spectrumPtr, length);
            }

            float avg = 0.0f;

            for (var n = 0; n < length; n++)
            {
                avg += _spectrum[n];
            }

            avg /= length;

            _drawing.AddDataPoint(_control.Frequency, avg);

            if (_control.Frequency > _gui.EndFreq * 1000000 - _gui.Step * 1000)
            {
                StopScanning();
            }
            else
            {
                if (_control.IsPlaying)
                {
                    _checkedFrequency = _control.Frequency;
                    _control.SetFrequency(_control.Frequency + _gui.Step * 1000, false);
                }
            }
        }