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); }
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); } }
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); } } }