| 
									
										
										
										
											2020-04-28 18:44:03 +02:00
										 |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // Copyright (C) 2015-2020 Edouard Griffiths, F4EXB                              //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // This program is free software; you can redistribute it and/or modify          //
 | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by          //
 | 
					
						
							|  |  |  | // the Free Software Foundation as version 3 of the License, or                  //
 | 
					
						
							|  |  |  | // (at your option) any later version.                                           //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful,               //
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of                //
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                  //
 | 
					
						
							|  |  |  | // GNU General Public License V3 for more details.                               //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU General Public License             //
 | 
					
						
							|  |  |  | // along with this program. If not, see <http://www.gnu.org/licenses/>.          //
 | 
					
						
							|  |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 18:58:18 +02:00
										 |  |  | #include "SWGGLSpectrum.h"
 | 
					
						
							|  |  |  | #include "SWGSpectrumServer.h"
 | 
					
						
							| 
									
										
										
										
											2020-05-06 09:50:43 +02:00
										 |  |  | #include "SWGSuccessResponse.h"
 | 
					
						
							| 
									
										
										
										
											2020-05-05 18:58:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-28 18:44:03 +02:00
										 |  |  | #include "glspectruminterface.h"
 | 
					
						
							|  |  |  | #include "dspcommands.h"
 | 
					
						
							|  |  |  | #include "dspengine.h"
 | 
					
						
							|  |  |  | #include "fftfactory.h"
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | #include "util/messagequeue.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-28 18:44:03 +02:00
										 |  |  | #include "spectrumvis.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 15:10:22 +01:00
										 |  |  | #ifndef LINUX
 | 
					
						
							| 
									
										
										
										
											2021-02-10 08:34:42 +01:00
										 |  |  | inline double log2(double n) | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	return log(n) / log(2.0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-18 02:47:14 +02:00
										 |  |  | MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgConfigureSpectrumVis, Message) | 
					
						
							| 
									
										
										
										
											2019-10-26 22:30:53 +02:00
										 |  |  | MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgConfigureScalingFactor, Message) | 
					
						
							| 
									
										
										
										
											2020-04-30 09:57:05 +02:00
										 |  |  | MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgConfigureWSpectrumOpenClose, Message) | 
					
						
							|  |  |  | MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgConfigureWSpectrum, Message) | 
					
						
							| 
									
										
										
										
											2020-07-05 10:03:41 +02:00
										 |  |  | MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgStartStop, Message) | 
					
						
							| 
									
										
										
										
											2021-02-15 13:49:51 +01:00
										 |  |  | MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgFrequencyZooming, Message) | 
					
						
							| 
									
										
										
										
											2015-08-18 02:47:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-10 08:34:42 +01:00
										 |  |  | const Real SpectrumVis::m_mult = (10.0f / log2(10.0f)); | 
					
						
							| 
									
										
										
										
											2018-06-28 23:47:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 09:57:05 +02:00
										 |  |  | SpectrumVis::SpectrumVis(Real scalef) : | 
					
						
							| 
									
										
										
										
											2016-10-02 22:29:04 +02:00
										 |  |  | 	BasebandSampleSink(), | 
					
						
							| 
									
										
										
										
											2020-07-05 10:03:41 +02:00
										 |  |  |     m_running(true), | 
					
						
							| 
									
										
										
										
											2020-03-12 06:27:38 +01:00
										 |  |  | 	m_fft(nullptr), | 
					
						
							|  |  |  |     m_fftEngineSequence(0), | 
					
						
							| 
									
										
										
										
											2021-04-20 11:54:58 +02:00
										 |  |  | 	m_fftBuffer(4096), | 
					
						
							|  |  |  | 	m_powerSpectrum(4096), | 
					
						
							|  |  |  |     m_psd(4096), | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 	m_fftBufferFill(0), | 
					
						
							| 
									
										
										
										
											2015-07-15 01:19:39 +02:00
										 |  |  | 	m_needMoreSamples(false), | 
					
						
							| 
									
										
										
										
											2021-02-15 13:49:51 +01:00
										 |  |  |     m_frequencyZoomFactor(1.0f), | 
					
						
							|  |  |  |     m_frequencyZoomPos(0.5f), | 
					
						
							| 
									
										
										
										
											2018-01-22 14:07:24 +01:00
										 |  |  | 	m_scalef(scalef), | 
					
						
							| 
									
										
										
										
											2020-04-30 09:57:05 +02:00
										 |  |  | 	m_glSpectrum(nullptr), | 
					
						
							| 
									
										
										
										
											2020-07-16 16:58:45 +02:00
										 |  |  |     m_specMax(0.0f), | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |     m_centerFrequency(0), | 
					
						
							|  |  |  |     m_sampleRate(48000), | 
					
						
							| 
									
										
										
										
											2018-06-30 22:30:42 +02:00
										 |  |  | 	m_ofs(0), | 
					
						
							| 
									
										
										
										
											2018-07-06 01:34:05 +02:00
										 |  |  |     m_powFFTDiv(1.0), | 
					
						
							| 
									
										
										
										
											2021-03-02 08:49:40 +01:00
										 |  |  |     m_guiMessageQueue(nullptr), | 
					
						
							| 
									
										
										
										
											2015-10-22 02:27:56 +02:00
										 |  |  | 	m_mutex(QMutex::Recursive) | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-08-12 09:03:02 +02:00
										 |  |  | 	setObjectName("SpectrumVis"); | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |     applySettings(m_settings, true); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SpectrumVis::~SpectrumVis() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-03-12 06:27:38 +01:00
										 |  |  |     FFTFactory *fftFactory = DSPEngine::instance()->getFFTFactory(); | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |     fftFactory->releaseEngine(m_settings.m_fftSize, false, m_fftEngineSequence); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  | void SpectrumVis::setScalef(Real scalef) | 
					
						
							| 
									
										
										
										
											2019-10-26 22:30:53 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     MsgConfigureScalingFactor* cmd = new MsgConfigureScalingFactor(scalef); | 
					
						
							|  |  |  |     getInputMessageQueue()->push(cmd); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 09:57:05 +02:00
										 |  |  | void SpectrumVis::configureWSSpectrum(const QString& address, uint16_t port) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     MsgConfigureWSpectrum* cmd = new MsgConfigureWSpectrum(address, port); | 
					
						
							|  |  |  |     getInputMessageQueue()->push(cmd); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-25 20:13:34 +02:00
										 |  |  | void SpectrumVis::feedTriggered(const SampleVector::const_iterator& triggerPoint, const SampleVector::const_iterator& end, bool positiveOnly) | 
					
						
							| 
									
										
										
										
											2015-07-15 01:19:39 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-07-21 22:52:52 +02:00
										 |  |  | 	feed(triggerPoint, end, positiveOnly); // normal feed from trigger point
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2015-07-15 01:19:39 +02:00
										 |  |  | 	if (triggerPoint == end) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		// the following piece of code allows to terminate the FFT that ends past the end of scope captured data
 | 
					
						
							|  |  |  | 		// that is the spectrum will include the captured data
 | 
					
						
							|  |  |  | 		// just do nothing if you want the spectrum to be included inside the scope captured data
 | 
					
						
							|  |  |  | 		// that is to drop the FFT that dangles past the end of captured data
 | 
					
						
							|  |  |  | 		if (m_needMoreSamples) { | 
					
						
							|  |  |  | 			feed(begin, end, positiveOnly); | 
					
						
							|  |  |  | 			m_needMoreSamples = false;      // force finish
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		feed(triggerPoint, end, positiveOnly); // normal feed from trigger point
 | 
					
						
							| 
									
										
										
										
											2015-07-21 22:52:52 +02:00
										 |  |  | 	}*/ | 
					
						
							| 
									
										
										
										
											2015-07-15 01:19:39 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  | void SpectrumVis::feed(const Complex *begin, unsigned int length) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!m_glSpectrum && !m_wsSpectrum.socketOpened()) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!m_mutex.tryLock(0)) { // prevent conflicts with configuration process
 | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Complex c; | 
					
						
							|  |  |  |     Real v; | 
					
						
							| 
									
										
										
										
											2021-02-15 13:49:51 +01:00
										 |  |  |     int fftMin = (m_frequencyZoomFactor == 1.0f) ? | 
					
						
							|  |  |  |         0 : (m_frequencyZoomPos - (0.5f / m_frequencyZoomFactor)) * m_settings.m_fftSize; | 
					
						
							|  |  |  |     int fftMax = (m_frequencyZoomFactor == 1.0f) ? | 
					
						
							| 
									
										
										
										
											2021-02-15 21:29:27 +01:00
										 |  |  |         m_settings.m_fftSize : (m_frequencyZoomPos + (0.5f / m_frequencyZoomFactor)) * m_settings.m_fftSize; | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-20 10:32:21 +02:00
										 |  |  |     if (m_settings.m_averagingMode == SpectrumSettings::AvgModeNone) | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-02-08 23:40:28 +01:00
										 |  |  |         for (int i = 0; i < m_settings.m_fftSize; i++) | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2021-02-08 23:40:28 +01:00
										 |  |  |             if (i < (int) length) { | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |                 c = begin[i]; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 c = Complex{0,0}; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             v = c.real() * c.real() + c.imag() * c.imag(); | 
					
						
							| 
									
										
										
										
											2021-02-10 08:34:42 +01:00
										 |  |  |             m_psd[i] = v/m_powFFTDiv; | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |             v = m_settings.m_linear ? v/m_powFFTDiv : m_mult * log2f(v) + m_ofs; | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |             m_powerSpectrum[i] = v; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // send new data to visualisation
 | 
					
						
							| 
									
										
										
										
											2021-02-15 21:29:27 +01:00
										 |  |  |         if (m_glSpectrum) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             m_glSpectrum->newSpectrum( | 
					
						
							|  |  |  |                 &m_powerSpectrum.data()[fftMin], | 
					
						
							|  |  |  |                 fftMax - fftMin, | 
					
						
							|  |  |  |                 m_settings.m_fftSize | 
					
						
							|  |  |  |             ); | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // web socket spectrum connections
 | 
					
						
							|  |  |  |         if (m_wsSpectrum.socketOpened()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             m_wsSpectrum.newSpectrum( | 
					
						
							|  |  |  |                 m_powerSpectrum, | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |                 m_settings.m_fftSize, | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |                 m_centerFrequency, | 
					
						
							|  |  |  |                 m_sampleRate, | 
					
						
							| 
									
										
										
										
											2020-11-12 01:22:48 +01:00
										 |  |  |                 m_settings.m_linear, | 
					
						
							|  |  |  |                 m_settings.m_ssb, | 
					
						
							|  |  |  |                 m_settings.m_usb | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |             ); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-04-20 10:32:21 +02:00
										 |  |  |     else if (m_settings.m_averagingMode == SpectrumSettings::AvgModeMoving) | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-02-08 23:40:28 +01:00
										 |  |  |         for (int i = 0; i < m_settings.m_fftSize; i++) | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2021-02-08 23:40:28 +01:00
										 |  |  |             if (i < (int) length) { | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |                 c = begin[i]; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 c = Complex{0,0}; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             v = c.real() * c.real() + c.imag() * c.imag(); | 
					
						
							|  |  |  |             v = m_movingAverage.storeAndGetAvg(v, i); | 
					
						
							| 
									
										
										
										
											2021-02-10 08:34:42 +01:00
										 |  |  |             m_psd[i] = v/m_powFFTDiv; | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |             v = m_settings.m_linear ? v/m_powFFTDiv : m_mult * log2f(v) + m_ofs; | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |             m_powerSpectrum[i] = v; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // send new data to visualisation
 | 
					
						
							| 
									
										
										
										
											2021-02-15 21:29:27 +01:00
										 |  |  |         if (m_glSpectrum) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             m_glSpectrum->newSpectrum( | 
					
						
							|  |  |  |                 &m_powerSpectrum.data()[fftMin], | 
					
						
							|  |  |  |                 fftMax - fftMin, | 
					
						
							|  |  |  |                 m_settings.m_fftSize | 
					
						
							|  |  |  |             ); | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // web socket spectrum connections
 | 
					
						
							|  |  |  |         if (m_wsSpectrum.socketOpened()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             m_wsSpectrum.newSpectrum( | 
					
						
							|  |  |  |                 m_powerSpectrum, | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |                 m_settings.m_fftSize, | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |                 m_centerFrequency, | 
					
						
							|  |  |  |                 m_sampleRate, | 
					
						
							| 
									
										
										
										
											2020-11-12 01:22:48 +01:00
										 |  |  |                 m_settings.m_linear, | 
					
						
							|  |  |  |                 m_settings.m_ssb, | 
					
						
							|  |  |  |                 m_settings.m_usb | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |             ); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         m_movingAverage.nextAverage(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-04-20 10:32:21 +02:00
										 |  |  |     else if (m_settings.m_averagingMode == SpectrumSettings::AvgModeFixed) | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         double avg; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-08 23:40:28 +01:00
										 |  |  |         for (int i = 0; i < m_settings.m_fftSize; i++) | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2021-02-08 23:40:28 +01:00
										 |  |  |             if (i < (int) length) { | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |                 c = begin[i]; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 c = Complex{0,0}; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             v = c.real() * c.real() + c.imag() * c.imag(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // result available
 | 
					
						
							|  |  |  |             if (m_fixedAverage.storeAndGetAvg(avg, v, i)) | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2021-02-10 08:34:42 +01:00
										 |  |  |                 m_psd[i] = avg/m_powFFTDiv; | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |                 avg = m_settings.m_linear ? avg/m_powFFTDiv : m_mult * log2f(avg) + m_ofs; | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |                 m_powerSpectrum[i] = avg; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // result available
 | 
					
						
							|  |  |  |         if (m_fixedAverage.nextAverage()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // send new data to visualisation
 | 
					
						
							| 
									
										
										
										
											2021-02-15 21:29:27 +01:00
										 |  |  |             if (m_glSpectrum) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 m_glSpectrum->newSpectrum( | 
					
						
							|  |  |  |                     &m_powerSpectrum.data()[fftMin], | 
					
						
							|  |  |  |                     fftMax - fftMin, | 
					
						
							|  |  |  |                     m_settings.m_fftSize | 
					
						
							|  |  |  |                 ); | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // web socket spectrum connections
 | 
					
						
							|  |  |  |             if (m_wsSpectrum.socketOpened()) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 m_wsSpectrum.newSpectrum( | 
					
						
							|  |  |  |                     m_powerSpectrum, | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |                     m_settings.m_fftSize, | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |                     m_centerFrequency, | 
					
						
							|  |  |  |                     m_sampleRate, | 
					
						
							| 
									
										
										
										
											2020-11-12 01:22:48 +01:00
										 |  |  |                     m_settings.m_linear, | 
					
						
							|  |  |  |                     m_settings.m_ssb, | 
					
						
							|  |  |  |                     m_settings.m_usb | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |                 ); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-04-20 10:32:21 +02:00
										 |  |  |     else if (m_settings.m_averagingMode == SpectrumSettings::AvgModeMax) | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         double max; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-08 23:40:28 +01:00
										 |  |  |         for (int i = 0; i < m_settings.m_fftSize; i++) | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2021-02-08 23:40:28 +01:00
										 |  |  |             if (i < (int) length) { | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |                 c = begin[i]; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 c = Complex{0,0}; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             v = c.real() * c.real() + c.imag() * c.imag(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // result available
 | 
					
						
							|  |  |  |             if (m_max.storeAndGetMax(max, v, i)) | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2021-02-10 08:34:42 +01:00
										 |  |  |                 m_psd[i] = max/m_powFFTDiv; | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |                 max = m_settings.m_linear ? max/m_powFFTDiv : m_mult * log2f(max) + m_ofs; | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |                 m_powerSpectrum[i] = max; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // result available
 | 
					
						
							|  |  |  |         if (m_max.nextMax()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // send new data to visualisation
 | 
					
						
							| 
									
										
										
										
											2021-02-15 21:29:27 +01:00
										 |  |  |             if (m_glSpectrum) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 m_glSpectrum->newSpectrum( | 
					
						
							|  |  |  |                     &m_powerSpectrum.data()[fftMin], | 
					
						
							|  |  |  |                     fftMax - fftMin, | 
					
						
							|  |  |  |                     m_settings.m_fftSize | 
					
						
							|  |  |  |                 ); | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // web socket spectrum connections
 | 
					
						
							|  |  |  |             if (m_wsSpectrum.socketOpened()) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 m_wsSpectrum.newSpectrum( | 
					
						
							|  |  |  |                     m_powerSpectrum, | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |                     m_settings.m_fftSize, | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |                     m_centerFrequency, | 
					
						
							|  |  |  |                     m_sampleRate, | 
					
						
							| 
									
										
										
										
											2020-11-12 01:22:48 +01:00
										 |  |  |                     m_settings.m_linear, | 
					
						
							|  |  |  |                     m_settings.m_ssb, | 
					
						
							|  |  |  |                     m_settings.m_usb | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |                 ); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_mutex.unlock(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  | void SpectrumVis::feed(const ComplexVector::const_iterator& cbegin, const ComplexVector::const_iterator& end, bool positiveOnly) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!m_running) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// if no visualisation is set, send the samples to /dev/null
 | 
					
						
							|  |  |  | 	if (!m_glSpectrum && !m_wsSpectrum.socketOpened()) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!m_mutex.tryLock(0)) { // prevent conflicts with configuration process
 | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ComplexVector::const_iterator begin(cbegin); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (begin < end) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		std::size_t todo = end - begin; | 
					
						
							|  |  |  | 		std::size_t samplesNeeded = m_refillSize - m_fftBufferFill; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (todo >= samplesNeeded) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			// fill up the buffer
 | 
					
						
							|  |  |  |             std::copy(begin, begin + samplesNeeded, m_fftBuffer.begin() + m_fftBufferFill); | 
					
						
							|  |  |  |             begin += samplesNeeded; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             processFFT(positiveOnly); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// advance buffer respecting the fft overlap factor
 | 
					
						
							|  |  |  | 			std::copy(m_fftBuffer.begin() + m_refillSize, m_fftBuffer.end(), m_fftBuffer.begin()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// start over
 | 
					
						
							|  |  |  | 			m_fftBufferFill = m_overlapSize; | 
					
						
							|  |  |  | 			m_needMoreSamples = false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			// not enough samples for FFT - just fill in new data and return
 | 
					
						
							|  |  |  |             std::copy(begin, end, m_fftBuffer.begin() + m_fftBufferFill); | 
					
						
							|  |  |  |             begin = end; | 
					
						
							|  |  |  | 			m_fftBufferFill += todo; | 
					
						
							|  |  |  | 			m_needMoreSamples = true; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m_mutex.unlock(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-25 08:24:23 +02:00
										 |  |  | void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleVector::const_iterator& end, bool positiveOnly) | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-07-05 10:03:41 +02:00
										 |  |  |     if (!m_running) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-08-25 08:24:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-05 10:03:41 +02:00
										 |  |  | 	// if no visualisation is set, send the samples to /dev/null
 | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  | 	if (!m_glSpectrum && !m_wsSpectrum.socketOpened()) { | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2015-08-25 08:24:23 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 08:58:33 +01:00
										 |  |  |     if (!m_mutex.tryLock(0)) { // prevent conflicts with configuration process
 | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-25 08:24:23 +02:00
										 |  |  | 	SampleVector::const_iterator begin(cbegin); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (begin < end) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2015-08-17 08:29:34 +02:00
										 |  |  | 		std::size_t todo = end - begin; | 
					
						
							|  |  |  | 		std::size_t samplesNeeded = m_refillSize - m_fftBufferFill; | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-25 08:24:23 +02:00
										 |  |  | 		if (todo >= samplesNeeded) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 			// fill up the buffer
 | 
					
						
							|  |  |  | 			std::vector<Complex>::iterator it = m_fftBuffer.begin() + m_fftBufferFill; | 
					
						
							| 
									
										
										
										
											2015-08-25 08:24:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  | 			for (std::size_t i = 0; i < samplesNeeded; ++i, ++begin) { | 
					
						
							| 
									
										
										
										
											2018-01-22 14:07:24 +01:00
										 |  |  | 				*it++ = Complex(begin->real() / m_scalef, begin->imag() / m_scalef); | 
					
						
							| 
									
										
										
										
											2015-08-25 08:24:23 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |             processFFT(positiveOnly); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  | 			// advance buffer respecting the fft overlap factor
 | 
					
						
							|  |  |  | 			std::copy(m_fftBuffer.begin() + m_refillSize, m_fftBuffer.end(), m_fftBuffer.begin()); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  | 			// start over
 | 
					
						
							|  |  |  | 			m_fftBufferFill = m_overlapSize; | 
					
						
							|  |  |  | 			m_needMoreSamples = false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			// not enough samples for FFT - just fill in new data and return
 | 
					
						
							|  |  |  | 			for (std::vector<Complex>::iterator it = m_fftBuffer.begin() + m_fftBufferFill; begin < end; ++begin) { | 
					
						
							|  |  |  | 				*it++ = Complex(begin->real() / m_scalef, begin->imag() / m_scalef); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-06-15 09:32:25 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  | 			m_fftBufferFill += todo; | 
					
						
							|  |  |  | 			m_needMoreSamples = true; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-07-16 16:58:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  | 	m_mutex.unlock(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-07-01 22:36:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  | void SpectrumVis::processFFT(bool positiveOnly) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int fftMin = (m_frequencyZoomFactor == 1.0f) ? | 
					
						
							|  |  |  |         0 : (m_frequencyZoomPos - (0.5f / m_frequencyZoomFactor)) * m_settings.m_fftSize; | 
					
						
							|  |  |  |     int fftMax = (m_frequencyZoomFactor == 1.0f) ? | 
					
						
							|  |  |  |         m_settings.m_fftSize : (m_frequencyZoomPos + (0.5f / m_frequencyZoomFactor)) * m_settings.m_fftSize; | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |     // apply fft window (and copy from m_fftBuffer to m_fftIn)
 | 
					
						
							|  |  |  |     m_window.apply(&m_fftBuffer[0], m_fft->in()); | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |     // calculate FFT
 | 
					
						
							|  |  |  |     m_fft->transform(); | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |     // extract power spectrum and reorder buckets
 | 
					
						
							|  |  |  |     const Complex* fftOut = m_fft->out(); | 
					
						
							|  |  |  |     Complex c; | 
					
						
							|  |  |  |     Real v; | 
					
						
							|  |  |  |     std::size_t halfSize = m_settings.m_fftSize / 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_settings.m_averagingMode == SpectrumSettings::AvgModeNone) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_specMax = 0.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ( positiveOnly ) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             for (std::size_t i = 0; i < halfSize; i++) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 c = fftOut[i]; | 
					
						
							|  |  |  |                 v = c.real() * c.real() + c.imag() * c.imag(); | 
					
						
							|  |  |  |                 m_psd[i] = v/m_powFFTDiv; | 
					
						
							|  |  |  |                 m_specMax = v > m_specMax ? v : m_specMax; | 
					
						
							|  |  |  |                 v = m_settings.m_linear ? v/m_powFFTDiv : m_mult * log2f(v) + m_ofs; | 
					
						
							|  |  |  |                 m_powerSpectrum[i * 2] = v; | 
					
						
							|  |  |  |                 m_powerSpectrum[i * 2 + 1] = v; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             for (std::size_t i = 0; i < halfSize; i++) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 c = fftOut[i + halfSize]; | 
					
						
							|  |  |  |                 v = c.real() * c.real() + c.imag() * c.imag(); | 
					
						
							|  |  |  |                 m_psd[i] = v/m_powFFTDiv; | 
					
						
							|  |  |  |                 m_specMax = v > m_specMax ? v : m_specMax; | 
					
						
							|  |  |  |                 v = m_settings.m_linear ? v/m_powFFTDiv : m_mult * log2f(v) + m_ofs; | 
					
						
							|  |  |  |                 m_powerSpectrum[i] = v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 c = fftOut[i]; | 
					
						
							|  |  |  |                 v = c.real() * c.real() + c.imag() * c.imag(); | 
					
						
							|  |  |  |                 m_psd[i + halfSize] = v/m_powFFTDiv; | 
					
						
							|  |  |  |                 m_specMax = v > m_specMax ? v : m_specMax; | 
					
						
							|  |  |  |                 v = m_settings.m_linear ? v/m_powFFTDiv : m_mult * log2f(v) + m_ofs; | 
					
						
							|  |  |  |                 m_powerSpectrum[i + halfSize] = v; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // send new data to visualisation
 | 
					
						
							|  |  |  |         if (m_glSpectrum) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             m_glSpectrum->newSpectrum( | 
					
						
							|  |  |  |                 &m_powerSpectrum.data()[fftMin], | 
					
						
							|  |  |  |                 fftMax - fftMin, | 
					
						
							|  |  |  |                 m_settings.m_fftSize | 
					
						
							|  |  |  |             ); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-07-01 02:16:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |         // web socket spectrum connections
 | 
					
						
							|  |  |  |         if (m_wsSpectrum.socketOpened()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             m_wsSpectrum.newSpectrum( | 
					
						
							|  |  |  |                 m_powerSpectrum, | 
					
						
							|  |  |  |                 m_settings.m_fftSize, | 
					
						
							|  |  |  |                 m_centerFrequency, | 
					
						
							|  |  |  |                 m_sampleRate, | 
					
						
							|  |  |  |                 m_settings.m_linear, | 
					
						
							|  |  |  |                 m_settings.m_ssb, | 
					
						
							|  |  |  |                 m_settings.m_usb | 
					
						
							|  |  |  |             ); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (m_settings.m_averagingMode == SpectrumSettings::AvgModeMoving) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_specMax = 0.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ( positiveOnly ) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             for (std::size_t i = 0; i < halfSize; i++) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 c = fftOut[i]; | 
					
						
							|  |  |  |                 v = c.real() * c.real() + c.imag() * c.imag(); | 
					
						
							|  |  |  |                 v = m_movingAverage.storeAndGetAvg(v, i); | 
					
						
							|  |  |  |                 m_psd[i] = v/m_powFFTDiv; | 
					
						
							|  |  |  |                 m_specMax = v > m_specMax ? v : m_specMax; | 
					
						
							|  |  |  |                 v = m_settings.m_linear ? v/m_powFFTDiv : m_mult * log2f(v) + m_ofs; | 
					
						
							|  |  |  |                 m_powerSpectrum[i * 2] = v; | 
					
						
							|  |  |  |                 m_powerSpectrum[i * 2 + 1] = v; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             for (std::size_t i = 0; i < halfSize; i++) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 c = fftOut[i + halfSize]; | 
					
						
							|  |  |  |                 v = c.real() * c.real() + c.imag() * c.imag(); | 
					
						
							|  |  |  |                 v = m_movingAverage.storeAndGetAvg(v, i+halfSize); | 
					
						
							|  |  |  |                 m_psd[i] = v/m_powFFTDiv; | 
					
						
							|  |  |  |                 m_specMax = v > m_specMax ? v : m_specMax; | 
					
						
							|  |  |  |                 v = m_settings.m_linear ? v/m_powFFTDiv : m_mult * log2f(v) + m_ofs; | 
					
						
							|  |  |  |                 m_powerSpectrum[i] = v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 c = fftOut[i]; | 
					
						
							|  |  |  |                 v = c.real() * c.real() + c.imag() * c.imag(); | 
					
						
							|  |  |  |                 v = m_movingAverage.storeAndGetAvg(v, i); | 
					
						
							|  |  |  |                 m_psd[i + halfSize] = v/m_powFFTDiv; | 
					
						
							|  |  |  |                 m_specMax = v > m_specMax ? v : m_specMax; | 
					
						
							|  |  |  |                 v = m_settings.m_linear ? v/m_powFFTDiv : m_mult * log2f(v) + m_ofs; | 
					
						
							|  |  |  |                 m_powerSpectrum[i + halfSize] = v; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // send new data to visualisation
 | 
					
						
							|  |  |  |         if (m_glSpectrum) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             m_glSpectrum->newSpectrum( | 
					
						
							|  |  |  |                 &m_powerSpectrum.data()[fftMin], | 
					
						
							|  |  |  |                 fftMax - fftMin, | 
					
						
							|  |  |  |                 m_settings.m_fftSize | 
					
						
							|  |  |  |             ); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // web socket spectrum connections
 | 
					
						
							|  |  |  |         if (m_wsSpectrum.socketOpened()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             m_wsSpectrum.newSpectrum( | 
					
						
							|  |  |  |                 m_powerSpectrum, | 
					
						
							|  |  |  |                 m_settings.m_fftSize, | 
					
						
							|  |  |  |                 m_centerFrequency, | 
					
						
							|  |  |  |                 m_sampleRate, | 
					
						
							|  |  |  |                 m_settings.m_linear, | 
					
						
							|  |  |  |                 m_settings.m_ssb, | 
					
						
							|  |  |  |                 m_settings.m_usb | 
					
						
							|  |  |  |             ); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         m_movingAverage.nextAverage(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (m_settings.m_averagingMode == SpectrumSettings::AvgModeFixed) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         double avg; | 
					
						
							|  |  |  |         Real specMax = 0.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ( positiveOnly ) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             for (std::size_t i = 0; i < halfSize; i++) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 c = fftOut[i]; | 
					
						
							|  |  |  |                 v = c.real() * c.real() + c.imag() * c.imag(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // result available
 | 
					
						
							|  |  |  |                 if (m_fixedAverage.storeAndGetAvg(avg, v, i)) | 
					
						
							| 
									
										
										
										
											2018-07-01 02:16:59 +02:00
										 |  |  |                 { | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |                     m_psd[i] = avg/m_powFFTDiv; | 
					
						
							|  |  |  |                     specMax = avg > specMax ? avg : specMax; | 
					
						
							|  |  |  |                     avg = m_settings.m_linear ? avg/m_powFFTDiv : m_mult * log2f(avg) + m_ofs; | 
					
						
							|  |  |  |                     m_powerSpectrum[i * 2] = avg; | 
					
						
							|  |  |  |                     m_powerSpectrum[i * 2 + 1] = avg; | 
					
						
							| 
									
										
										
										
											2018-07-01 02:16:59 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             for (std::size_t i = 0; i < halfSize; i++) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 c = fftOut[i + halfSize]; | 
					
						
							|  |  |  |                 v = c.real() * c.real() + c.imag() * c.imag(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // result available
 | 
					
						
							|  |  |  |                 if (m_fixedAverage.storeAndGetAvg(avg, v, i+halfSize)) | 
					
						
							| 
									
										
										
										
											2018-07-01 02:16:59 +02:00
										 |  |  |                 { | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |                     m_psd[i] = avg/m_powFFTDiv; | 
					
						
							|  |  |  |                     specMax = avg > specMax ? avg : specMax; | 
					
						
							|  |  |  |                     avg = m_settings.m_linear ? avg/m_powFFTDiv : m_mult * log2f(avg) + m_ofs; | 
					
						
							|  |  |  |                     m_powerSpectrum[i] = avg; | 
					
						
							| 
									
										
										
										
											2018-07-01 02:16:59 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |                 c = fftOut[i]; | 
					
						
							|  |  |  |                 v = c.real() * c.real() + c.imag() * c.imag(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |                 // result available
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |                 if (m_fixedAverage.storeAndGetAvg(avg, v, i)) | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |                 { | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |                     m_psd[i + halfSize] = avg/m_powFFTDiv; | 
					
						
							|  |  |  |                     specMax = avg > specMax ? avg : specMax; | 
					
						
							|  |  |  |                     avg = m_settings.m_linear ? avg/m_powFFTDiv : m_mult * log2f(avg) + m_ofs; | 
					
						
							|  |  |  |                     m_powerSpectrum[i + halfSize] = avg; | 
					
						
							| 
									
										
										
										
											2018-10-12 08:47:14 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // result available
 | 
					
						
							|  |  |  |         if (m_fixedAverage.nextAverage()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             m_specMax = specMax; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // send new data to visualisation
 | 
					
						
							|  |  |  |             if (m_glSpectrum) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 m_glSpectrum->newSpectrum( | 
					
						
							|  |  |  |                     &m_powerSpectrum.data()[fftMin], | 
					
						
							|  |  |  |                     fftMax - fftMin, | 
					
						
							|  |  |  |                     m_settings.m_fftSize | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // web socket spectrum connections
 | 
					
						
							|  |  |  |             if (m_wsSpectrum.socketOpened()) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 m_wsSpectrum.newSpectrum( | 
					
						
							|  |  |  |                     m_powerSpectrum, | 
					
						
							|  |  |  |                     m_settings.m_fftSize, | 
					
						
							|  |  |  |                     m_centerFrequency, | 
					
						
							|  |  |  |                     m_sampleRate, | 
					
						
							|  |  |  |                     m_settings.m_linear, | 
					
						
							|  |  |  |                     m_settings.m_ssb, | 
					
						
							|  |  |  |                     m_settings.m_usb | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (m_settings.m_averagingMode == SpectrumSettings::AvgModeMax) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         double max; | 
					
						
							|  |  |  |         Real specMax = 0.0f; | 
					
						
							| 
									
										
										
										
											2018-10-12 08:47:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |         if ( positiveOnly ) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             for (std::size_t i = 0; i < halfSize; i++) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 c = fftOut[i]; | 
					
						
							|  |  |  |                 v = c.real() * c.real() + c.imag() * c.imag(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // result available
 | 
					
						
							|  |  |  |                 if (m_max.storeAndGetMax(max, v, i)) | 
					
						
							| 
									
										
										
										
											2018-10-12 08:47:14 +02:00
										 |  |  |                 { | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |                     m_psd[i] = max/m_powFFTDiv; | 
					
						
							|  |  |  |                     specMax = max > specMax ? max : specMax; | 
					
						
							|  |  |  |                     max = m_settings.m_linear ? max/m_powFFTDiv : m_mult * log2f(max) + m_ofs; | 
					
						
							|  |  |  |                     m_powerSpectrum[i * 2] = max; | 
					
						
							|  |  |  |                     m_powerSpectrum[i * 2 + 1] = max; | 
					
						
							| 
									
										
										
										
											2018-10-12 08:47:14 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             for (std::size_t i = 0; i < halfSize; i++) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 c = fftOut[i + halfSize]; | 
					
						
							|  |  |  |                 v = c.real() * c.real() + c.imag() * c.imag(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // result available
 | 
					
						
							|  |  |  |                 if (m_max.storeAndGetMax(max, v, i+halfSize)) | 
					
						
							| 
									
										
										
										
											2018-10-12 08:47:14 +02:00
										 |  |  |                 { | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |                     m_psd[i] = max/m_powFFTDiv; | 
					
						
							|  |  |  |                     specMax = max > specMax ? max : specMax; | 
					
						
							|  |  |  |                     max = m_settings.m_linear ? max/m_powFFTDiv : m_mult * log2f(max) + m_ofs; | 
					
						
							|  |  |  |                     m_powerSpectrum[i] = max; | 
					
						
							| 
									
										
										
										
											2018-10-12 08:47:14 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |                 c = fftOut[i]; | 
					
						
							|  |  |  |                 v = c.real() * c.real() + c.imag() * c.imag(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |                 // result available
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |                 if (m_max.storeAndGetMax(max, v, i)) | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  |                 { | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |                     m_psd[i + halfSize] = max/m_powFFTDiv; | 
					
						
							|  |  |  |                     specMax = max > specMax ? max : specMax; | 
					
						
							|  |  |  |                     max = m_settings.m_linear ? max/m_powFFTDiv : m_mult * log2f(max) + m_ofs; | 
					
						
							|  |  |  |                     m_powerSpectrum[i + halfSize] = max; | 
					
						
							| 
									
										
										
										
											2018-07-01 02:16:59 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |         // result available
 | 
					
						
							|  |  |  |         if (m_max.nextMax()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             m_specMax = specMax; | 
					
						
							| 
									
										
										
										
											2015-08-25 08:24:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |             // send new data to visualisation
 | 
					
						
							|  |  |  |             if (m_glSpectrum) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 m_glSpectrum->newSpectrum( | 
					
						
							|  |  |  |                     &m_powerSpectrum.data()[fftMin], | 
					
						
							|  |  |  |                     fftMax - fftMin, | 
					
						
							|  |  |  |                     m_settings.m_fftSize | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-11-21 08:58:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 21:09:11 +02:00
										 |  |  |             // web socket spectrum connections
 | 
					
						
							|  |  |  |             if (m_wsSpectrum.socketOpened()) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 m_wsSpectrum.newSpectrum( | 
					
						
							|  |  |  |                     m_powerSpectrum, | 
					
						
							|  |  |  |                     m_settings.m_fftSize, | 
					
						
							|  |  |  |                     m_centerFrequency, | 
					
						
							|  |  |  |                     m_sampleRate, | 
					
						
							|  |  |  |                     m_settings.m_linear, | 
					
						
							|  |  |  |                     m_settings.m_ssb, | 
					
						
							|  |  |  |                     m_settings.m_usb | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-18 06:23:12 +01:00
										 |  |  | void SpectrumVis::getZoomedPSDCopy(std::vector<Real>& copy) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int fftMin = (m_frequencyZoomFactor == 1.0f) ? | 
					
						
							|  |  |  |         0 : (m_frequencyZoomPos - (0.5f / m_frequencyZoomFactor)) * m_settings.m_fftSize; | 
					
						
							|  |  |  |     int fftMax = (m_frequencyZoomFactor == 1.0f) ? | 
					
						
							|  |  |  |         m_settings.m_fftSize : (m_frequencyZoomPos + (0.5f / m_frequencyZoomFactor)) * m_settings.m_fftSize; | 
					
						
							|  |  |  |     copy.assign(m_psd.begin() + fftMin, m_psd.begin() + fftMax); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | void SpectrumVis::start() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-07-10 00:08:42 +02:00
										 |  |  |     setRunning(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (getMessageQueueToGUI()) // propagate to GUI if any
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         MsgStartStop *msg = MsgStartStop::create(true); | 
					
						
							|  |  |  |         getMessageQueueToGUI()->push(msg); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void SpectrumVis::stop() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-07-10 00:08:42 +02:00
										 |  |  |     setRunning(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (getMessageQueueToGUI()) // propagate to GUI if any
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         MsgStartStop *msg = MsgStartStop::create(false); | 
					
						
							|  |  |  |         getMessageQueueToGUI()->push(msg); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-14 05:00:28 +02:00
										 |  |  | bool SpectrumVis::handleMessage(const Message& message) | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-04-30 09:57:05 +02:00
										 |  |  |     if (DSPSignalNotification::match(message)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // This is coming from device engine and will apply to main spectrum
 | 
					
						
							|  |  |  |         DSPSignalNotification& notif = (DSPSignalNotification&) message; | 
					
						
							|  |  |  |         qDebug() << "SpectrumVis::handleMessage: DSPSignalNotification:" | 
					
						
							|  |  |  |             << " centerFrequency: " << notif.getCenterFrequency() | 
					
						
							|  |  |  |             << " sampleRate: " << notif.getSampleRate(); | 
					
						
							|  |  |  |         handleConfigureDSP(notif.getCenterFrequency(), notif.getSampleRate()); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 	else if (MsgConfigureSpectrumVis::match(message)) | 
					
						
							| 
									
										
										
										
											2015-08-14 05:00:28 +02:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |         MsgConfigureSpectrumVis& cfg = (MsgConfigureSpectrumVis&) message; | 
					
						
							|  |  |  |         qDebug() << "SpectrumVis::handleMessage: MsgConfigureSpectrumVis"; | 
					
						
							|  |  |  |         applySettings(cfg.getSettings(), cfg.getForce()); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-26 22:30:53 +02:00
										 |  |  |     else if (MsgConfigureScalingFactor::match(message)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         MsgConfigureScalingFactor& conf = (MsgConfigureScalingFactor&) message; | 
					
						
							|  |  |  |         handleScalef(conf.getScalef()); | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2020-04-30 09:57:05 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     else if (MsgConfigureWSpectrumOpenClose::match(message)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         MsgConfigureWSpectrumOpenClose& conf = (MsgConfigureWSpectrumOpenClose&) message; | 
					
						
							|  |  |  |         handleWSOpenClose(conf.getOpenClose()); | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2020-04-30 09:57:05 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     else if (MsgConfigureWSpectrum::match(message)) { | 
					
						
							|  |  |  |         MsgConfigureWSpectrum& conf = (MsgConfigureWSpectrum&) message; | 
					
						
							|  |  |  |         handleConfigureWSSpectrum(conf.getAddress(), conf.getPort()); | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2019-10-26 22:30:53 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-07-10 00:08:42 +02:00
										 |  |  |     else if (MsgStartStop::match(message)) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-07-05 10:03:41 +02:00
										 |  |  |         MsgStartStop& cmd = (MsgStartStop&) message; | 
					
						
							| 
									
										
										
										
											2020-07-10 00:08:42 +02:00
										 |  |  |         setRunning(cmd.getStartStop()); | 
					
						
							| 
									
										
										
										
											2021-02-15 13:49:51 +01:00
										 |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (MsgFrequencyZooming::match(message)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         MsgFrequencyZooming& cmd = (MsgFrequencyZooming&) message; | 
					
						
							|  |  |  |         m_frequencyZoomFactor = cmd.getFrequencyZoomFactor(); | 
					
						
							|  |  |  |         m_frequencyZoomPos = cmd.getFrequencyZoomPos(); | 
					
						
							| 
									
										
										
										
											2020-07-05 10:03:41 +02:00
										 |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-08-14 05:00:28 +02:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2015-06-23 20:05:28 +02:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2015-08-14 05:00:28 +02:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2015-06-23 20:05:28 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-20 10:32:21 +02:00
										 |  |  | void SpectrumVis::applySettings(const SpectrumSettings& settings, bool force) | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |     QMutexLocker mutexLocker(&m_mutex); | 
					
						
							| 
									
										
										
										
											2015-08-14 05:00:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-20 11:54:58 +02:00
										 |  |  |     int fftSize = settings.m_fftSize > (1<<SpectrumSettings::m_log2FFTSizeMax) ? | 
					
						
							|  |  |  |         (1<<SpectrumSettings::m_log2FFTSizeMax) : | 
					
						
							|  |  |  |         settings.m_fftSize < (1<<SpectrumSettings::m_log2FFTSizeMin) ? | 
					
						
							|  |  |  |             (1<<SpectrumSettings::m_log2FFTSizeMin) : | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |             settings.m_fftSize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     qDebug() << "SpectrumVis::applySettings:" | 
					
						
							|  |  |  |         << " m_fftSize: " << fftSize | 
					
						
							|  |  |  |         << " m_fftWindow: " << settings.m_fftWindow | 
					
						
							| 
									
										
										
										
											2021-02-08 23:40:28 +01:00
										 |  |  |         << " m_fftOverlap: " << settings.m_fftOverlap | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |         << " m_averagingIndex: " << settings.m_averagingIndex | 
					
						
							|  |  |  |         << " m_averagingMode: " << settings.m_averagingMode | 
					
						
							|  |  |  |         << " m_refLevel: " << settings.m_refLevel | 
					
						
							|  |  |  |         << " m_powerRange: " << settings.m_powerRange | 
					
						
							| 
									
										
										
										
											2021-02-12 00:53:18 +01:00
										 |  |  |         << " m_fpsPeriodMs: " << settings.m_fpsPeriodMs | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |         << " m_linear: " << settings.m_linear | 
					
						
							| 
									
										
										
										
											2020-11-12 01:22:48 +01:00
										 |  |  |         << " m_ssb: " << settings.m_ssb | 
					
						
							|  |  |  |         << " m_usb: " << settings.m_usb | 
					
						
							| 
									
										
										
										
											2020-05-01 11:06:56 +02:00
										 |  |  |         << " m_wsSpectrumAddress: " << settings.m_wsSpectrumAddress | 
					
						
							|  |  |  |         << " m_wsSpectrumPort: " << settings.m_wsSpectrumPort | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |         << " force: " << force; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((fftSize != m_settings.m_fftSize) || force) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         FFTFactory *fftFactory = DSPEngine::instance()->getFFTFactory(); | 
					
						
							| 
									
										
										
										
											2020-05-01 04:57:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // release previous engine allocation if any
 | 
					
						
							|  |  |  |         if (m_fft) { | 
					
						
							|  |  |  |             fftFactory->releaseEngine(m_settings.m_fftSize, false, m_fftEngineSequence); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |         m_fftEngineSequence = fftFactory->getEngine(fftSize, false, &m_fft); | 
					
						
							|  |  |  |         m_ofs = 20.0f * log10f(1.0f / fftSize); | 
					
						
							|  |  |  |         m_powFFTDiv = fftSize * fftSize; | 
					
						
							| 
									
										
										
										
											2021-04-20 11:54:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (fftSize > m_settings.m_fftSize) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             m_fftBuffer.resize(fftSize); | 
					
						
							|  |  |  |             m_powerSpectrum.resize(fftSize); | 
					
						
							|  |  |  |             m_psd.resize(fftSize); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |     if ((fftSize != m_settings.m_fftSize) | 
					
						
							|  |  |  |      || (settings.m_fftWindow != m_settings.m_fftWindow) || force) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_window.create(settings.m_fftWindow, fftSize); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |     if ((fftSize != m_settings.m_fftSize) | 
					
						
							| 
									
										
										
										
											2021-02-08 23:40:28 +01:00
										 |  |  |      || (settings.m_fftOverlap != m_settings.m_fftOverlap) || force) | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-02-09 07:12:32 +01:00
										 |  |  |         m_overlapSize = settings.m_fftOverlap < 0 ? 0 : | 
					
						
							|  |  |  |             settings.m_fftOverlap < fftSize/2 ? settings.m_fftOverlap : (fftSize/2) - 1; | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |         m_refillSize = fftSize - m_overlapSize; | 
					
						
							|  |  |  |         m_fftBufferFill = m_overlapSize; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((fftSize != m_settings.m_fftSize) | 
					
						
							|  |  |  |      || (settings.m_averagingIndex != m_settings.m_averagingIndex) | 
					
						
							|  |  |  |      || (settings.m_averagingMode != m_settings.m_averagingMode) || force) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-04-20 10:32:21 +02:00
										 |  |  |         unsigned int averagingValue = SpectrumSettings::getAveragingValue(settings.m_averagingIndex, settings.m_averagingMode); | 
					
						
							| 
									
										
										
										
											2021-04-20 23:08:56 +02:00
										 |  |  |         averagingValue = averagingValue > SpectrumSettings::getMaxAveragingValue(fftSize, settings.m_averagingMode) ? | 
					
						
							|  |  |  |             SpectrumSettings::getMaxAveragingValue(fftSize, settings.m_averagingMode) : averagingValue; // Capping to avoid out of memory condition
 | 
					
						
							|  |  |  |         m_movingAverage.resize(fftSize, averagingValue); | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |         m_fixedAverage.resize(fftSize, averagingValue); | 
					
						
							|  |  |  |         m_max.resize(fftSize, averagingValue); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-01 11:06:56 +02:00
										 |  |  |     if ((settings.m_wsSpectrumAddress != m_settings.m_wsSpectrumAddress) | 
					
						
							|  |  |  |      || (settings.m_wsSpectrumPort != m_settings.m_wsSpectrumPort) || force) { | 
					
						
							|  |  |  |          handleConfigureWSSpectrum(settings.m_wsSpectrumAddress, settings.m_wsSpectrumPort); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-01 02:12:30 +02:00
										 |  |  |     m_settings = settings; | 
					
						
							|  |  |  |     m_settings.m_fftSize = fftSize; | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-10-26 22:30:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-29 17:41:17 +02:00
										 |  |  | void SpectrumVis::handleConfigureDSP(uint64_t centerFrequency, int sampleRate) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QMutexLocker mutexLocker(&m_mutex); | 
					
						
							|  |  |  |     m_centerFrequency = centerFrequency; | 
					
						
							|  |  |  |     m_sampleRate = sampleRate; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-26 22:30:53 +02:00
										 |  |  | void SpectrumVis::handleScalef(Real scalef) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QMutexLocker mutexLocker(&m_mutex); | 
					
						
							|  |  |  |     m_scalef = scalef; | 
					
						
							| 
									
										
										
										
											2020-04-30 09:57:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void SpectrumVis::handleWSOpenClose(bool openClose) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QMutexLocker mutexLocker(&m_mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (openClose) { | 
					
						
							|  |  |  |         m_wsSpectrum.openSocket(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         m_wsSpectrum.closeSocket(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void SpectrumVis::handleConfigureWSSpectrum(const QString& address, uint16_t port) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-06 17:01:59 +02:00
										 |  |  |     m_wsSpectrum.setListeningAddress(address); | 
					
						
							|  |  |  |     m_wsSpectrum.setPort(port); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 09:57:05 +02:00
										 |  |  |     if (m_wsSpectrum.socketOpened()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_wsSpectrum.closeSocket(); | 
					
						
							|  |  |  |         m_wsSpectrum.openSocket(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-11-11 11:24:55 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-05 18:58:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | int SpectrumVis::webapiSpectrumSettingsGet(SWGSDRangel::SWGGLSpectrum& response, QString& errorMessage) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) errorMessage; | 
					
						
							|  |  |  |     response.init(); | 
					
						
							|  |  |  |     webapiFormatSpectrumSettings(response, m_settings); | 
					
						
							|  |  |  |     return 200; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 01:38:23 +02:00
										 |  |  | int SpectrumVis::webapiSpectrumSettingsPutPatch( | 
					
						
							|  |  |  |     bool force, | 
					
						
							|  |  |  |     const QStringList& spectrumSettingsKeys, | 
					
						
							|  |  |  |     SWGSDRangel::SWGGLSpectrum& response, // query + response
 | 
					
						
							|  |  |  |     QString& errorMessage) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) errorMessage; | 
					
						
							| 
									
										
										
										
											2021-04-20 10:32:21 +02:00
										 |  |  |     SpectrumSettings settings = m_settings; | 
					
						
							| 
									
										
										
										
											2020-05-06 01:38:23 +02:00
										 |  |  |     webapiUpdateSpectrumSettings(settings, spectrumSettingsKeys, response); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     MsgConfigureSpectrumVis *msg = MsgConfigureSpectrumVis::create(settings, force); | 
					
						
							|  |  |  |     m_inputMessageQueue.push(msg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (getMessageQueueToGUI()) // forward to GUI if any
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         MsgConfigureSpectrumVis *msgToGUI = MsgConfigureSpectrumVis::create(settings, force); | 
					
						
							|  |  |  |         getMessageQueueToGUI()->push(msgToGUI); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     webapiFormatSpectrumSettings(response, settings); | 
					
						
							|  |  |  |     return 200; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 18:58:18 +02:00
										 |  |  | int SpectrumVis::webapiSpectrumServerGet(SWGSDRangel::SWGSpectrumServer& response, QString& errorMessage) const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-06 01:38:23 +02:00
										 |  |  |     (void) errorMessage; | 
					
						
							| 
									
										
										
										
											2020-05-05 18:58:18 +02:00
										 |  |  |     bool serverRunning = m_wsSpectrum.socketOpened(); | 
					
						
							|  |  |  |     QList<QHostAddress> peerHosts; | 
					
						
							|  |  |  |     QList<quint16> peerPorts; | 
					
						
							|  |  |  |     m_wsSpectrum.getPeers(peerHosts, peerPorts); | 
					
						
							|  |  |  |     response.init(); | 
					
						
							|  |  |  |     response.setRun(serverRunning ? 1 : 0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 17:01:59 +02:00
										 |  |  |     QHostAddress serverAddress = m_wsSpectrum.getListeningAddress(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (serverAddress != QHostAddress::Null) { | 
					
						
							|  |  |  |         response.setListeningAddress(new QString(serverAddress.toString())); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     uint16_t serverPort = m_wsSpectrum.getListeningPort(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (serverPort != 0) { | 
					
						
							|  |  |  |         response.setListeningPort(serverPort); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 18:58:18 +02:00
										 |  |  |     if (peerHosts.size() > 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         response.setClients(new QList<SWGSDRangel::SWGSpectrumServer_clients*>); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (int i = 0; i < peerHosts.size(); i++) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             response.getClients()->push_back(new SWGSDRangel::SWGSpectrumServer_clients); | 
					
						
							|  |  |  |             response.getClients()->back()->setAddress(new QString(peerHosts.at(i).toString())); | 
					
						
							|  |  |  |             response.getClients()->back()->setPort(peerPorts.at(i)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-05-06 01:38:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return 200; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int SpectrumVis::webapiSpectrumServerPost(SWGSDRangel::SWGSuccessResponse& response, QString& errorMessage) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) errorMessage; | 
					
						
							|  |  |  |     MsgConfigureWSpectrumOpenClose *msg = MsgConfigureWSpectrumOpenClose::create(true); | 
					
						
							|  |  |  |     m_inputMessageQueue.push(msg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (getMessageQueueToGUI()) // forward to GUI if any
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         MsgConfigureWSpectrumOpenClose *msgToGui = MsgConfigureWSpectrumOpenClose::create(true); | 
					
						
							|  |  |  |         getMessageQueueToGUI()->push(msgToGui); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 09:50:43 +02:00
										 |  |  |     response.setMessage(new QString("Websocket spectrum server started")); | 
					
						
							| 
									
										
										
										
											2020-05-06 01:38:23 +02:00
										 |  |  |     return 200; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int SpectrumVis::webapiSpectrumServerDelete(SWGSDRangel::SWGSuccessResponse& response, QString& errorMessage) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) errorMessage; | 
					
						
							|  |  |  |     MsgConfigureWSpectrumOpenClose *msg = MsgConfigureWSpectrumOpenClose::create(false); | 
					
						
							|  |  |  |     m_inputMessageQueue.push(msg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (getMessageQueueToGUI()) // forward to GUI if any
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         MsgConfigureWSpectrumOpenClose *msgToGui = MsgConfigureWSpectrumOpenClose::create(false); | 
					
						
							|  |  |  |         getMessageQueueToGUI()->push(msgToGui); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 09:50:43 +02:00
										 |  |  |     response.setMessage(new QString("Websocket spectrum server stopped")); | 
					
						
							| 
									
										
										
										
											2020-05-06 01:38:23 +02:00
										 |  |  |     return 200; | 
					
						
							| 
									
										
										
										
											2020-05-05 18:58:18 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-20 10:32:21 +02:00
										 |  |  | void SpectrumVis::webapiFormatSpectrumSettings(SWGSDRangel::SWGGLSpectrum& response, const SpectrumSettings& settings) | 
					
						
							| 
									
										
										
										
											2020-05-05 18:58:18 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-01-15 19:19:47 +01:00
										 |  |  |     settings.formatTo(&response); | 
					
						
							| 
									
										
										
										
											2020-05-05 18:58:18 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-06 01:38:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | void SpectrumVis::webapiUpdateSpectrumSettings( | 
					
						
							| 
									
										
										
										
											2021-04-20 10:32:21 +02:00
										 |  |  |     SpectrumSettings& settings, | 
					
						
							| 
									
										
										
										
											2020-05-06 01:38:23 +02:00
										 |  |  |     const QStringList& spectrumSettingsKeys, | 
					
						
							|  |  |  |     SWGSDRangel::SWGGLSpectrum& response) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-01-15 19:19:47 +01:00
										 |  |  |     QStringList prefixedKeys; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (const auto &key : spectrumSettingsKeys) { | 
					
						
							|  |  |  |         prefixedKeys.append(tr("spectrumConfig.%1").arg(key)); | 
					
						
							| 
									
										
										
										
											2020-05-06 01:38:23 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-01-15 19:19:47 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     settings.updateFrom(prefixedKeys, &response); | 
					
						
							| 
									
										
										
										
											2020-05-06 01:38:23 +02:00
										 |  |  | } |