mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-31 13:00:26 -04:00 
			
		
		
		
	Scope on complex<float>: implementation
This commit is contained in:
		
							parent
							
								
									04170f2648
								
							
						
					
					
						commit
						dc205bc8e2
					
				| @ -41,6 +41,7 @@ typedef qint16 FixReal; | ||||
| 
 | ||||
| typedef float Real; | ||||
| typedef std::complex<Real> Complex; | ||||
| typedef std::vector<Complex> ComplexVector; | ||||
| 
 | ||||
| #pragma pack(push, 1) | ||||
| struct Sample | ||||
|  | ||||
| @ -70,6 +70,7 @@ ScopeVis::ScopeVis() : | ||||
| { | ||||
|     setObjectName("ScopeVis"); | ||||
|     m_traceDiscreteMemory.resize(GLScopeSettings::m_traceChunkDefaultSize); // arbitrary
 | ||||
|     m_convertBuffers.resize(GLScopeSettings::m_traceChunkDefaultSize); | ||||
| 
 | ||||
|     for (int i = 0; i < (int) Projector::nbProjectionTypes; i++) { | ||||
|         m_projectorCache[i] = 0.0; | ||||
| @ -140,6 +141,7 @@ void ScopeVis::setNbStreams(uint32_t nbStreams) | ||||
|     if (m_nbStreams != nbStreams) | ||||
|     { | ||||
|         m_traceDiscreteMemory.setNbStreams(nbStreams); | ||||
|         m_convertBuffers.setNbStreams(nbStreams); | ||||
|         m_nbStreams = nbStreams; | ||||
|     } | ||||
| } | ||||
| @ -414,6 +416,31 @@ void ScopeVis::setMemoryIndex(uint32_t memoryIndex) | ||||
| } | ||||
| 
 | ||||
| void ScopeVis::feed(const std::vector<SampleVector::const_iterator>& vbegin, int nbSamples) | ||||
| { | ||||
|     std::vector<ComplexVector::const_iterator> vcbegin; | ||||
|     std::vector<ComplexVector>& convertBuffers = m_convertBuffers.getBuffers(); | ||||
| 
 | ||||
|     if (nbSamples > (int) m_convertBuffers.size()) { | ||||
|         m_convertBuffers.resize(nbSamples); | ||||
|     } | ||||
| 
 | ||||
|     for (unsigned int s = 0; s < vbegin.size(); s++) | ||||
|     { | ||||
|         std::transform( | ||||
|             vbegin[s], | ||||
|             vbegin[s] + nbSamples, | ||||
|             convertBuffers[s].begin(), | ||||
|             [](const Sample& s) -> Complex { | ||||
|                 return Complex{s.m_real / SDR_RX_SCALEF, s.m_imag / SDR_RX_SCALEF}; | ||||
|             } | ||||
|         ); | ||||
|         vcbegin.push_back(convertBuffers[s].begin()); | ||||
|     } | ||||
| 
 | ||||
|     feed(vcbegin, nbSamples); | ||||
| } | ||||
| 
 | ||||
| void ScopeVis::feed(const std::vector<ComplexVector::const_iterator>& vbegin, int nbSamples) | ||||
| { | ||||
|     if (vbegin.size() == 0) { | ||||
|         return; | ||||
| @ -447,11 +474,11 @@ void ScopeVis::feed(const std::vector<SampleVector::const_iterator>& vbegin, int | ||||
|         m_triggerLocation = nbSamples; | ||||
|     } | ||||
| 
 | ||||
|     SampleVector::const_iterator begin(vbegin[0]); | ||||
|     ComplexVector::const_iterator begin(vbegin[0]); | ||||
|     //const SampleVector::const_iterator end = vbegin[0] + nbSamples;
 | ||||
|     int triggerPointToEnd; | ||||
|     int remainder = nbSamples; | ||||
|     std::vector<SampleVector::const_iterator> nvbegin(vbegin); | ||||
|     std::vector<ComplexVector::const_iterator> nvbegin(vbegin); | ||||
| 
 | ||||
|     //while (begin < end)
 | ||||
|     while (remainder > 0) | ||||
| @ -495,11 +522,11 @@ void ScopeVis::processMemoryTrace() | ||||
|             traceMemoryIndex += GLScopeSettings::m_nbTraceMemories; | ||||
|         } | ||||
| 
 | ||||
|         std::vector<SampleVector::const_iterator> mend; | ||||
|         std::vector<ComplexVector::const_iterator> mend; | ||||
|         m_traceDiscreteMemory.getEndPointAt(traceMemoryIndex, mend); | ||||
|         std::vector<SampleVector::const_iterator> mbegin(mend.size()); | ||||
|         std::vector<ComplexVector::const_iterator> mbegin(mend.size()); | ||||
|         TraceBackDiscreteMemory::moveIt(mend, mbegin, -m_traceSize); | ||||
|         std::vector<SampleVector::const_iterator> mbegin_tb(mbegin.size()); | ||||
|         std::vector<ComplexVector::const_iterator> mbegin_tb(mbegin.size()); | ||||
|         TraceBackDiscreteMemory::moveIt(mbegin, mbegin_tb, -m_maxTraceDelay); | ||||
|         m_nbSamples = m_traceSize + m_maxTraceDelay; | ||||
| 
 | ||||
| @ -508,9 +535,9 @@ void ScopeVis::processMemoryTrace() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void ScopeVis::processTrace(const std::vector<SampleVector::const_iterator>& vcbegin, int length, int& triggerPointToEnd) | ||||
| void ScopeVis::processTrace(const std::vector<ComplexVector::const_iterator>& vcbegin, int length, int& triggerPointToEnd) | ||||
| { | ||||
|     std::vector<SampleVector::const_iterator> vbegin(vcbegin); | ||||
|     std::vector<ComplexVector::const_iterator> vbegin(vcbegin); | ||||
|     int firstRemainder = length; | ||||
| 
 | ||||
|     // memory storage
 | ||||
| @ -579,7 +606,7 @@ void ScopeVis::processTrace(const std::vector<SampleVector::const_iterator>& vcb | ||||
|             } | ||||
| 
 | ||||
|             uint32_t triggerStreamIndex = triggerCondition->m_triggerData.m_streamIndex; | ||||
|             const Sample& s = *vbegin[triggerStreamIndex]; | ||||
|             const Complex& s = *vbegin[triggerStreamIndex]; | ||||
| 
 | ||||
|             if (m_triggerComparator.triggered(s, *triggerCondition)) // matched the current trigger
 | ||||
|             { | ||||
| @ -625,9 +652,9 @@ void ScopeVis::processTrace(const std::vector<SampleVector::const_iterator>& vcb | ||||
|     { | ||||
|         int remainder; | ||||
|         int count = firstRemainder; // number of samples in traceback buffer past the current point
 | ||||
|         std::vector<SampleVector::const_iterator> mend; | ||||
|         std::vector<ComplexVector::const_iterator> mend; | ||||
|         m_traceDiscreteMemory.getCurrent(mend); | ||||
|         std::vector<SampleVector::const_iterator> mbegin(mend.size()); | ||||
|         std::vector<ComplexVector::const_iterator> mbegin(mend.size()); | ||||
|         TraceBackDiscreteMemory::moveIt(mend, mbegin, -count); | ||||
| 
 | ||||
|         if (m_traceStart) // start of trace processing
 | ||||
| @ -644,14 +671,14 @@ void ScopeVis::processTrace(const std::vector<SampleVector::const_iterator>& vcb | ||||
| 
 | ||||
|             if (m_maxTraceDelay > 0) | ||||
|             { // trace back
 | ||||
|                 std::vector<SampleVector::const_iterator> tbegin(mbegin.size()); | ||||
|                 std::vector<ComplexVector::const_iterator> tbegin(mbegin.size()); | ||||
|                 TraceBackDiscreteMemory::moveIt(mbegin, tbegin, - m_preTriggerDelay - m_maxTraceDelay); | ||||
|                 processTraces(tbegin, m_maxTraceDelay, true); | ||||
|             } | ||||
| 
 | ||||
|             if (m_preTriggerDelay > 0) | ||||
|             { // pre-trigger
 | ||||
|                 std::vector<SampleVector::const_iterator> tbegin(mbegin.size()); | ||||
|                 std::vector<ComplexVector::const_iterator> tbegin(mbegin.size()); | ||||
|                 TraceBackDiscreteMemory::moveIt(mbegin, tbegin, -m_preTriggerDelay); | ||||
|                 processTraces(tbegin, m_preTriggerDelay); | ||||
|             } | ||||
| @ -727,16 +754,13 @@ bool ScopeVis::nextTrigger() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int ScopeVis::processTraces(const std::vector<SampleVector::const_iterator>& vcbegin, int ilength, bool traceBack) | ||||
| int ScopeVis::processTraces(const std::vector<ComplexVector::const_iterator>& vcbegin, int ilength, bool traceBack) | ||||
| { | ||||
|     std::vector<SampleVector::const_iterator> vbegin(vcbegin); | ||||
|     std::vector<ComplexVector::const_iterator> vbegin(vcbegin); | ||||
|     uint32_t shift = (m_timeOfsProMill / 1000.0) * m_traceSize; | ||||
|     uint32_t length = m_traceSize / m_timeBase; | ||||
|     int remainder = ilength; | ||||
| 
 | ||||
|     if (m_spectrumVis) { | ||||
|         m_spectrumVis->feed(vcbegin[0], vcbegin[0] + ilength, false); // TODO: use spectrum stream index
 | ||||
|     } | ||||
|     m_spectrumVis->feed(vcbegin[0], vcbegin[0] + ilength, false); | ||||
| 
 | ||||
|     while ((remainder > 0) && (m_nbSamples > 0)) | ||||
|     { | ||||
| @ -797,8 +821,8 @@ int ScopeVis::processTraces(const std::vector<SampleVector::const_iterator>& vcb | ||||
|                 } | ||||
|                 else if (projectionType == Projector::ProjectionMagDB) | ||||
|                 { | ||||
|                     Real re = vbegin[streamIndex]->m_real / SDR_RX_SCALEF; | ||||
|                     Real im = vbegin[streamIndex]->m_imag / SDR_RX_SCALEF; | ||||
|                     Real re = vbegin[streamIndex]->real(); | ||||
|                     Real im = vbegin[streamIndex]->imag(); | ||||
|                     double magsq = re*re + im*im; | ||||
|                     float pdB = log10f(magsq) * 10.0f; | ||||
|                     float p = pdB - (100.0f * itData->m_ofs); | ||||
|  | ||||
| @ -432,6 +432,7 @@ public: | ||||
|     uint32_t getNbTraces() const { return m_traces.size(); } | ||||
| 
 | ||||
|     void feed(const std::vector<SampleVector::const_iterator>& vbegin, int nbSamples); | ||||
|     void feed(const std::vector<ComplexVector::const_iterator>& vbegin, int nbSamples); | ||||
|     //virtual void start();
 | ||||
|     //virtual void stop();
 | ||||
|     bool handleMessage(const Message& message); | ||||
| @ -510,7 +511,7 @@ private: | ||||
|     /**
 | ||||
|      * Complex trace stuff | ||||
|      */ | ||||
|     typedef DoubleBufferSimple<Sample> TraceBuffer; | ||||
|     typedef DoubleBufferSimple<Complex> TraceBuffer; | ||||
| 
 | ||||
|     struct TraceBackBuffer | ||||
|     { | ||||
| @ -528,7 +529,7 @@ private: | ||||
|     	    m_traceBuffer.reset(); | ||||
|     	} | ||||
| 
 | ||||
|     	void write(const SampleVector::const_iterator begin, int nbSamples) { | ||||
|     	void write(const ComplexVector::const_iterator begin, int nbSamples) { | ||||
|     		m_traceBuffer.write(begin, nbSamples); | ||||
|     	} | ||||
| 
 | ||||
| @ -536,7 +537,7 @@ private: | ||||
|     		return m_traceBuffer.absoluteFill(); | ||||
|     	} | ||||
| 
 | ||||
|         void current(SampleVector::iterator& it) { | ||||
|         void current(ComplexVector::iterator& it) { | ||||
|             m_traceBuffer.getCurrent(it); | ||||
|         } | ||||
| 
 | ||||
| @ -578,24 +579,57 @@ private: | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         void setEndPoint(const SampleVector::const_iterator& endPoint) { | ||||
|         void setEndPoint(const ComplexVector::const_iterator& endPoint) { | ||||
|             m_endPoint = endPoint; | ||||
|         } | ||||
| 
 | ||||
|         SampleVector::const_iterator getEndPoint() { | ||||
|         ComplexVector::const_iterator getEndPoint() { | ||||
|             return m_endPoint; | ||||
|         } | ||||
| 
 | ||||
|         void getEndPoint(SampleVector::const_iterator& it) { | ||||
|         void getEndPoint(ComplexVector::const_iterator& it) { | ||||
|             it = m_endPoint; | ||||
|         } | ||||
| 
 | ||||
|     private: | ||||
|     	SampleVector::const_iterator m_endPoint; | ||||
|     	ComplexVector::const_iterator m_endPoint; | ||||
|     }; | ||||
| 
 | ||||
|     typedef std::vector<TraceBackBuffer> TraceBackBufferStream; | ||||
| 
 | ||||
|     struct ConvertBuffers | ||||
|     { | ||||
|         ConvertBuffers(uint32_t nbStreams = 1) : | ||||
|             m_convertBuffers(nbStreams) | ||||
|         {} | ||||
| 
 | ||||
|         void setNbStreams(uint32_t nbStreams) | ||||
|         { | ||||
|             m_convertBuffers.resize(nbStreams); | ||||
|             resize(m_size); | ||||
|         } | ||||
| 
 | ||||
|         void resize(unsigned int size) | ||||
|         { | ||||
|             for (unsigned int s = 0; s < m_convertBuffers.size(); s++) { | ||||
|                 m_convertBuffers[s].resize(size); | ||||
|             } | ||||
| 
 | ||||
|             m_size = size; | ||||
|         } | ||||
| 
 | ||||
|         unsigned int size() const { | ||||
|             return m_size; | ||||
|         } | ||||
| 
 | ||||
|         std::vector<ComplexVector>& getBuffers() { | ||||
|             return m_convertBuffers; | ||||
|         } | ||||
| 
 | ||||
|     private: | ||||
|         unsigned int m_size; | ||||
|         std::vector<ComplexVector> m_convertBuffers; | ||||
|     }; | ||||
|     struct TraceBackDiscreteMemory | ||||
|     { | ||||
|     	/**
 | ||||
| @ -747,20 +781,20 @@ private: | ||||
|         /**
 | ||||
|          * Get current point at current memory position (first stream) | ||||
|          */ | ||||
|         void getCurrent(SampleVector::iterator& it) { | ||||
|         void getCurrent(ComplexVector::iterator& it) { | ||||
|             current().current(it); | ||||
|         } | ||||
| 
 | ||||
|         /**
 | ||||
|          * Get current points at current memory position | ||||
|          */ | ||||
|         void getCurrent(std::vector<SampleVector::const_iterator>& vit) | ||||
|         void getCurrent(std::vector<ComplexVector::const_iterator>& vit) | ||||
|         { | ||||
|             vit.clear(); | ||||
| 
 | ||||
|             for (unsigned int is = 0; is < m_traceBackBuffersStreams.size(); is++) | ||||
|             { | ||||
|                 SampleVector::iterator it; | ||||
|                 ComplexVector::iterator it; | ||||
|                 current(is).current(it); | ||||
|                 vit.push_back(it); | ||||
|             } | ||||
| @ -769,14 +803,14 @@ private: | ||||
|         /**
 | ||||
|          * Set end point at current memory position (first stream) | ||||
|          */ | ||||
|         void setCurrentEndPoint(const SampleVector::iterator& it) { | ||||
|         void setCurrentEndPoint(const ComplexVector::iterator& it) { | ||||
|             current().setEndPoint(it); | ||||
|         } | ||||
| 
 | ||||
|         /**
 | ||||
|          * Set end points at current memory position | ||||
|          */ | ||||
|         void setCurrentEndPoint(const std::vector<SampleVector::const_iterator>& vit) | ||||
|         void setCurrentEndPoint(const std::vector<ComplexVector::const_iterator>& vit) | ||||
|         { | ||||
|             for (unsigned int is = 0; is < vit.size(); is++) | ||||
|             { | ||||
| @ -791,20 +825,20 @@ private: | ||||
|         /**
 | ||||
|          * Get end point at given memory position (first stream) | ||||
|          */ | ||||
|         void getEndPointAt(int index, SampleVector::const_iterator& mend) { | ||||
|         void getEndPointAt(int index, ComplexVector::const_iterator& mend) { | ||||
|             at(index).getEndPoint(mend); | ||||
|         } | ||||
| 
 | ||||
|         /**
 | ||||
|          * Get end points at given memory position | ||||
|          */ | ||||
|         void getEndPointAt(int index, std::vector<SampleVector::const_iterator>& vend) | ||||
|         void getEndPointAt(int index, std::vector<ComplexVector::const_iterator>& vend) | ||||
|         { | ||||
|             vend.clear(); | ||||
| 
 | ||||
|             for (unsigned int is = 0; is < m_traceBackBuffersStreams.size(); is++) | ||||
|             { | ||||
|                 SampleVector::const_iterator mend; | ||||
|                 ComplexVector::const_iterator mend; | ||||
|                 at(index, is).getEndPoint(mend); | ||||
|                 vend.push_back(mend); | ||||
|             } | ||||
| @ -813,14 +847,14 @@ private: | ||||
|         /**
 | ||||
|          * Write trace at current memory position (first stream) | ||||
|          */ | ||||
|         void writeCurrent(const SampleVector::const_iterator& begin, int length) { | ||||
|         void writeCurrent(const ComplexVector::const_iterator& begin, int length) { | ||||
|             current().write(begin, length); | ||||
|         } | ||||
| 
 | ||||
|         /**
 | ||||
|          * Write traces at current memory position | ||||
|          */ | ||||
|         void writeCurrent(const std::vector<SampleVector::const_iterator>& vbegin, int length) | ||||
|         void writeCurrent(const std::vector<ComplexVector::const_iterator>& vbegin, int length) | ||||
|         { | ||||
|             for (unsigned int i = 0; i < vbegin.size(); i++) { | ||||
|                 current().write(vbegin[i], length); | ||||
| @ -830,14 +864,14 @@ private: | ||||
|         /**
 | ||||
|          * Move buffer iterator by a certain amount (first stream) | ||||
|          */ | ||||
|         static void moveIt(const SampleVector::const_iterator& x, SampleVector::const_iterator& y, int amount) { | ||||
|         static void moveIt(const ComplexVector::const_iterator& x, ComplexVector::const_iterator& y, int amount) { | ||||
|             y = x + amount; | ||||
|         } | ||||
| 
 | ||||
|         /**
 | ||||
|          * Move buffers iterators by a certain amount | ||||
|          */ | ||||
|         static void moveIt(const std::vector<SampleVector::const_iterator>& vx, std::vector<SampleVector::const_iterator>& vy, int amount) | ||||
|         static void moveIt(const std::vector<ComplexVector::const_iterator>& vx, std::vector<ComplexVector::const_iterator>& vy, int amount) | ||||
|         { | ||||
|             for (unsigned int i = 0; i < vx.size(); i++) | ||||
|             { | ||||
| @ -1083,7 +1117,7 @@ private: | ||||
|             computeLevels(); | ||||
|         } | ||||
| 
 | ||||
|         bool triggered(const Sample& s, TriggerCondition& triggerCondition) | ||||
|         bool triggered(const Complex& s, TriggerCondition& triggerCondition) | ||||
|         { | ||||
|             if (triggerCondition.m_triggerData.m_triggerLevel != m_level) | ||||
|             { | ||||
| @ -1194,7 +1228,8 @@ private: | ||||
|     int m_triggerLocation;                         //!< Trigger location from end point
 | ||||
|     int m_sampleRate;                              //!< Actual sample rate being used
 | ||||
|     int m_liveSampleRate;                          //!< Sample rate in live mode
 | ||||
|     TraceBackDiscreteMemory m_traceDiscreteMemory; //!< Complex trace memory for triggered states TODO: vectorize when more than on input is allowed
 | ||||
|     TraceBackDiscreteMemory m_traceDiscreteMemory; //!< Complex trace memory
 | ||||
|     ConvertBuffers m_convertBuffers;               //!< Sample to Complex conversions
 | ||||
|     bool m_freeRun;                                //!< True if free running (trigger globally disabled)
 | ||||
|     int m_maxTraceDelay;                           //!< Maximum trace delay
 | ||||
|     TriggerComparator m_triggerComparator;         //!< Compares sample level to trigger level
 | ||||
| @ -1227,7 +1262,7 @@ private: | ||||
|     /**
 | ||||
|      * Process a sample trace which length is at most the trace length (m_traceSize) | ||||
|      */ | ||||
|     void processTrace(const std::vector<SampleVector::const_iterator>& vbegin, int length, int& triggerPointToEnd); | ||||
|     void processTrace(const std::vector<ComplexVector::const_iterator>& vbegin, int length, int& triggerPointToEnd); | ||||
| 
 | ||||
|     /**
 | ||||
|      * process a trace in memory at current trace index in memory | ||||
| @ -1239,7 +1274,7 @@ private: | ||||
|      * - if finished it returns the number of unprocessed samples left in the buffer | ||||
|      * - if not finished it returns -1 | ||||
|      */ | ||||
|     int processTraces(const std::vector<SampleVector::const_iterator>& vbegin, int length, bool traceBack = false); | ||||
|     int processTraces(const std::vector<ComplexVector::const_iterator>& vbegin, int length, bool traceBack = false); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Get maximum trace delay | ||||
|  | ||||
| @ -317,6 +317,56 @@ void SpectrumVis::feed(const Complex *begin, unsigned int length) | ||||
|     m_mutex.unlock(); | ||||
| } | ||||
| 
 | ||||
| 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(); | ||||
| } | ||||
| 
 | ||||
| void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleVector::const_iterator& end, bool positiveOnly) | ||||
| { | ||||
|     if (!m_running) { | ||||
| @ -333,10 +383,6 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV | ||||
|     } | ||||
| 
 | ||||
| 	SampleVector::const_iterator begin(cbegin); | ||||
|     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; | ||||
| 
 | ||||
| 	while (begin < end) | ||||
| 	{ | ||||
| @ -348,316 +394,11 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV | ||||
| 			// fill up the buffer
 | ||||
| 			std::vector<Complex>::iterator it = m_fftBuffer.begin() + m_fftBufferFill; | ||||
| 
 | ||||
| 			for (std::size_t i = 0; i < samplesNeeded; ++i, ++begin) | ||||
| 			{ | ||||
| 			for (std::size_t i = 0; i < samplesNeeded; ++i, ++begin) { | ||||
| 				*it++ = Complex(begin->real() / m_scalef, begin->imag() / m_scalef); | ||||
| 			} | ||||
| 
 | ||||
| 			// apply fft window (and copy from m_fftBuffer to m_fftIn)
 | ||||
| 			m_window.apply(&m_fftBuffer[0], m_fft->in()); | ||||
| 
 | ||||
| 			// calculate FFT
 | ||||
| 			m_fft->transform(); | ||||
| 
 | ||||
| 			// 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 | ||||
|                     ); | ||||
|                 } | ||||
| 
 | ||||
|                 // 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)) | ||||
|                         { | ||||
|                             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; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 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)) | ||||
|                         { | ||||
|                             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; | ||||
|                         } | ||||
| 
 | ||||
|                         c = fftOut[i]; | ||||
|                         v = c.real() * c.real() + c.imag() * c.imag(); | ||||
| 
 | ||||
|                         // result available
 | ||||
|                         if (m_fixedAverage.storeAndGetAvg(avg, v, i)) | ||||
|                         { | ||||
|                             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; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 // 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; | ||||
| 
 | ||||
|                 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)) | ||||
|                         { | ||||
|                             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; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 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)) | ||||
|                         { | ||||
|                             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; | ||||
|                         } | ||||
| 
 | ||||
|                         c = fftOut[i]; | ||||
|                         v = c.real() * c.real() + c.imag() * c.imag(); | ||||
| 
 | ||||
|                         // result available
 | ||||
|                         if (m_max.storeAndGetMax(max, v, i)) | ||||
|                         { | ||||
|                             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; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 // result available
 | ||||
|                 if (m_max.nextMax()) | ||||
|                 { | ||||
|                     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 | ||||
|                         ); | ||||
|                     } | ||||
|                 } | ||||
| 			} | ||||
|             processFFT(positiveOnly); | ||||
| 
 | ||||
| 			// advance buffer respecting the fft overlap factor
 | ||||
| 			std::copy(m_fftBuffer.begin() + m_refillSize, m_fftBuffer.end(), m_fftBuffer.begin()); | ||||
| @ -669,8 +410,7 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV | ||||
| 		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) | ||||
| 			{ | ||||
| 			for (std::vector<Complex>::iterator it = m_fftBuffer.begin() + m_fftBufferFill; begin < end; ++begin) { | ||||
| 				*it++ = Complex(begin->real() / m_scalef, begin->imag() / m_scalef); | ||||
| 			} | ||||
| 
 | ||||
| @ -679,7 +419,321 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	 m_mutex.unlock(); | ||||
| 	m_mutex.unlock(); | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| 
 | ||||
|     // apply fft window (and copy from m_fftBuffer to m_fftIn)
 | ||||
|     m_window.apply(&m_fftBuffer[0], m_fft->in()); | ||||
| 
 | ||||
|     // calculate FFT
 | ||||
|     m_fft->transform(); | ||||
| 
 | ||||
|     // 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 | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
|         // 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)) | ||||
|                 { | ||||
|                     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; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         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)) | ||||
|                 { | ||||
|                     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; | ||||
|                 } | ||||
| 
 | ||||
|                 c = fftOut[i]; | ||||
|                 v = c.real() * c.real() + c.imag() * c.imag(); | ||||
| 
 | ||||
|                 // result available
 | ||||
|                 if (m_fixedAverage.storeAndGetAvg(avg, v, i)) | ||||
|                 { | ||||
|                     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; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // 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; | ||||
| 
 | ||||
|         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)) | ||||
|                 { | ||||
|                     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; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         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)) | ||||
|                 { | ||||
|                     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; | ||||
|                 } | ||||
| 
 | ||||
|                 c = fftOut[i]; | ||||
|                 v = c.real() * c.real() + c.imag() * c.imag(); | ||||
| 
 | ||||
|                 // result available
 | ||||
|                 if (m_max.storeAndGetMax(max, v, i)) | ||||
|                 { | ||||
|                     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; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // result available
 | ||||
|         if (m_max.nextMax()) | ||||
|         { | ||||
|             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 | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void SpectrumVis::getZoomedPSDCopy(std::vector<Real>& copy) const | ||||
|  | ||||
| @ -151,6 +151,7 @@ public: | ||||
|     void getZoomedPSDCopy(std::vector<Real>& copy) const; | ||||
| 
 | ||||
| 	virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly); | ||||
|     void feed(const ComplexVector::const_iterator& begin, const ComplexVector::const_iterator& end, bool positiveOnly); | ||||
|     virtual void feed(const Complex *begin, unsigned int length); //!< direct FFT feed
 | ||||
| 	void feedTriggered(const SampleVector::const_iterator& triggerPoint, const SampleVector::const_iterator& end, bool positiveOnly); | ||||
| 	virtual void start(); | ||||
| @ -243,6 +244,7 @@ private: | ||||
| 
 | ||||
| 	QMutex m_mutex; | ||||
| 
 | ||||
|     void processFFT(bool positiveOnly); | ||||
|     void setRunning(bool running) { m_running = running; } | ||||
|     void applySettings(const SpectrumSettings& settings, bool force = false); | ||||
|     void handleConfigureDSP(uint64_t centerFrequency, int sampleRate); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user