Spectrum frequency zoom: implementation for spectrum and waterfall only

This commit is contained in:
f4exb 2021-02-15 21:29:27 +01:00
parent ab0a7f2e60
commit 4d99533009
4 changed files with 101 additions and 48 deletions

View File

@ -26,9 +26,10 @@ class GLSpectrumInterface
public:
GLSpectrumInterface() {}
virtual ~GLSpectrumInterface() {}
virtual void newSpectrum(const Real* spectrum, int fftSize)
virtual void newSpectrum(const Real* spectrum, int nbBins, int fftSize)
{
(void) spectrum;
(void) nbBins;
(void) fftSize;
}
};

View File

@ -127,7 +127,7 @@ void SpectrumVis::feed(const Complex *begin, unsigned int length)
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;
m_settings.m_fftSize : (m_frequencyZoomPos + (0.5f / m_frequencyZoomFactor)) * m_settings.m_fftSize;
if (m_settings.m_averagingMode == GLSpectrumSettings::AvgModeNone)
{
@ -146,8 +146,13 @@ void SpectrumVis::feed(const Complex *begin, unsigned int length)
}
// send new data to visualisation
if (m_glSpectrum) {
m_glSpectrum->newSpectrum(m_powerSpectrum.data(), m_settings.m_fftSize);
if (m_glSpectrum)
{
m_glSpectrum->newSpectrum(
&m_powerSpectrum.data()[fftMin],
fftMax - fftMin,
m_settings.m_fftSize
);
}
// web socket spectrum connections
@ -182,8 +187,13 @@ void SpectrumVis::feed(const Complex *begin, unsigned int length)
}
// send new data to visualisation
if (m_glSpectrum) {
m_glSpectrum->newSpectrum(m_powerSpectrum.data(), m_settings.m_fftSize);
if (m_glSpectrum)
{
m_glSpectrum->newSpectrum(
&m_powerSpectrum.data()[fftMin],
fftMax - fftMin,
m_settings.m_fftSize
);
}
// web socket spectrum connections
@ -229,8 +239,13 @@ void SpectrumVis::feed(const Complex *begin, unsigned int length)
if (m_fixedAverage.nextAverage())
{
// send new data to visualisation
if (m_glSpectrum) {
m_glSpectrum->newSpectrum(m_powerSpectrum.data(), m_settings.m_fftSize);
if (m_glSpectrum)
{
m_glSpectrum->newSpectrum(
&m_powerSpectrum.data()[fftMin],
fftMax - fftMin,
m_settings.m_fftSize
);
}
// web socket spectrum connections
@ -275,8 +290,13 @@ void SpectrumVis::feed(const Complex *begin, unsigned int length)
if (m_max.nextMax())
{
// send new data to visualisation
if (m_glSpectrum) {
m_glSpectrum->newSpectrum(m_powerSpectrum.data(), m_settings.m_fftSize);
if (m_glSpectrum)
{
m_glSpectrum->newSpectrum(
&m_powerSpectrum.data()[fftMin],
fftMax - fftMin,
m_settings.m_fftSize
);
}
// web socket spectrum connections
@ -314,6 +334,10 @@ 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)
{
@ -380,8 +404,13 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV
}
// send new data to visualisation
if (m_glSpectrum) {
m_glSpectrum->newSpectrum(m_powerSpectrum.data(), m_settings.m_fftSize);
if (m_glSpectrum)
{
m_glSpectrum->newSpectrum(
&m_powerSpectrum.data()[fftMin],
fftMax - fftMin,
m_settings.m_fftSize
);
}
// web socket spectrum connections
@ -439,8 +468,13 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV
}
// send new data to visualisation
if (m_glSpectrum) {
m_glSpectrum->newSpectrum(m_powerSpectrum.data(), m_settings.m_fftSize);
if (m_glSpectrum)
{
m_glSpectrum->newSpectrum(
&m_powerSpectrum.data()[fftMin],
fftMax - fftMin,
m_settings.m_fftSize
);
}
// web socket spectrum connections
@ -518,8 +552,13 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV
m_specMax = specMax;
// send new data to visualisation
if (m_glSpectrum) {
m_glSpectrum->newSpectrum(m_powerSpectrum.data(), m_settings.m_fftSize);
if (m_glSpectrum)
{
m_glSpectrum->newSpectrum(
&m_powerSpectrum.data()[fftMin],
fftMax - fftMin,
m_settings.m_fftSize
);
}
// web socket spectrum connections
@ -596,8 +635,13 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV
m_specMax = specMax;
// send new data to visualisation
if (m_glSpectrum) {
m_glSpectrum->newSpectrum(m_powerSpectrum.data(), m_settings.m_fftSize);
if (m_glSpectrum)
{
m_glSpectrum->newSpectrum(
&m_powerSpectrum.data()[fftMin],
fftMax - fftMin,
m_settings.m_fftSize
);
}
// web socket spectrum connections

View File

@ -52,6 +52,7 @@ GLSpectrum::GLSpectrum(QWidget* parent) :
m_sampleRate(500000),
m_timingRate(1),
m_fftSize(512),
m_nbBins(512),
m_displayGrid(true),
m_displayGridIntensity(5),
m_displayTraceIntensity(50),
@ -413,7 +414,7 @@ void GLSpectrum::removeChannelMarker(ChannelMarker* channelMarker)
m_mutex.unlock();
}
void GLSpectrum::newSpectrum(const Real *spectrum, int fftSize)
void GLSpectrum::newSpectrum(const Real *spectrum, int nbBins, int fftSize)
{
QMutexLocker mutexLocker(&m_mutex);
@ -422,12 +423,14 @@ void GLSpectrum::newSpectrum(const Real *spectrum, int fftSize)
if (m_changesPending)
{
m_fftSize = fftSize;
m_nbBins = nbBins;
return;
}
if (fftSize != m_fftSize)
if ((fftSize != m_fftSize) || (m_nbBins != nbBins))
{
m_fftSize = fftSize;
m_nbBins = nbBins;
m_changesPending = true;
return;
}
@ -446,7 +449,7 @@ void GLSpectrum::updateWaterfall(const Real *spectrum)
{
quint32* pix = (quint32*)m_waterfallBuffer->scanLine(m_waterfallBufferPos);
for (int i = 0; i < m_fftSize; i++)
for (int i = 0; i < m_nbBins; i++)
{
int v = (int)((spectrum[i] - m_referenceLevel) * 2.4 * 100.0 / m_powerRange + 240.0);
@ -466,7 +469,7 @@ void GLSpectrum::updateWaterfall(const Real *spectrum)
void GLSpectrum::updateHistogram(const Real *spectrum)
{
quint8* b = m_histogram;
int fftMulSize = 100 * m_fftSize;
int fftMulSize = 100 * m_nbBins;
if ((m_displayHistogram || m_displayMaxHold) && (m_decay != 0))
{
@ -557,7 +560,7 @@ void GLSpectrum::updateHistogram(const Real *spectrum)
}
}
#else
for (int i = 0; i < m_fftSize; i++)
for (int i = 0; i < m_nbBins; i++)
{
int v = (int)((spectrum[i] - m_referenceLevel) * 100.0 / m_powerRange + 100.0);
@ -626,7 +629,7 @@ void GLSpectrum::clearSpectrumHistogram()
return;
}
memset(m_histogram, 0x00, 100 * m_fftSize);
memset(m_histogram, 0x00, 100 * m_nbBins);
m_mutex.unlock();
update();
@ -644,7 +647,7 @@ void GLSpectrum::paintGL()
m_changesPending = false;
}
if (m_fftSize <= 0)
if (m_nbBins <= 0)
{
m_mutex.unlock();
return;
@ -668,15 +671,15 @@ void GLSpectrum::paintGL()
if (m_waterfallTexturePos + m_waterfallBufferPos < m_waterfallTextureHeight)
{
m_glShaderWaterfall.subTexture(0, m_waterfallTexturePos, m_fftSize, m_waterfallBufferPos, m_waterfallBuffer->scanLine(0));
m_glShaderWaterfall.subTexture(0, m_waterfallTexturePos, m_nbBins, m_waterfallBufferPos, m_waterfallBuffer->scanLine(0));
m_waterfallTexturePos += m_waterfallBufferPos;
}
else
{
int breakLine = m_waterfallTextureHeight - m_waterfallTexturePos;
int linesLeft = m_waterfallTexturePos + m_waterfallBufferPos - m_waterfallTextureHeight;
m_glShaderWaterfall.subTexture(0, m_waterfallTexturePos, m_fftSize, breakLine, m_waterfallBuffer->scanLine(0));
m_glShaderWaterfall.subTexture(0, 0, m_fftSize, linesLeft, m_waterfallBuffer->scanLine(breakLine));
m_glShaderWaterfall.subTexture(0, m_waterfallTexturePos, m_nbBins, breakLine, m_waterfallBuffer->scanLine(0));
m_glShaderWaterfall.subTexture(0, 0, m_nbBins, linesLeft, m_waterfallBuffer->scanLine(breakLine));
m_waterfallTexturePos = linesLeft;
}
@ -756,7 +759,7 @@ void GLSpectrum::paintGL()
quint8* b = bs;
pix = (quint32*)m_histogramBuffer->scanLine(99 - y);
for (int x = 0; x < m_fftSize; x++)
for (int x = 0; x < m_nbBins; x++)
{
*pix = m_histogramPalette[*b];
pix++;
@ -779,7 +782,7 @@ void GLSpectrum::paintGL()
0, 1
};
m_glShaderHistogram.subTexture(0, 0, m_fftSize, 100, m_histogramBuffer->scanLine(0));
m_glShaderHistogram.subTexture(0, 0, m_nbBins, 100, m_histogramBuffer->scanLine(0));
m_glShaderHistogram.drawSurface(m_glHistogramBoxMatrix, tex1, vtx1, 4);
}
}
@ -917,11 +920,11 @@ void GLSpectrum::paintGL()
// paint max hold lines on top of histogram
if (m_displayMaxHold)
{
if (m_maxHold.size() < (uint) m_fftSize) {
m_maxHold.resize(m_fftSize);
if (m_maxHold.size() < (uint) m_nbBins) {
m_maxHold.resize(m_nbBins);
}
for (int i = 0; i < m_fftSize; i++)
for (int i = 0; i < m_nbBins; i++)
{
int j;
quint8* bs = m_histogram + i * 100;
@ -940,7 +943,7 @@ void GLSpectrum::paintGL()
{
GLfloat *q3 = m_q3FFT.m_array;
for (int i = 0; i < m_fftSize; i++)
for (int i = 0; i < m_nbBins; i++)
{
Real v = m_maxHold[i] - m_referenceLevel;
@ -955,7 +958,7 @@ void GLSpectrum::paintGL()
}
QVector4D color(1.0f, 0.0f, 0.0f, (float) m_displayTraceIntensity / 100.0f);
m_glShaderSimple.drawPolyline(m_glHistogramSpectrumMatrix, color, q3, m_fftSize);
m_glShaderSimple.drawPolyline(m_glHistogramSpectrumMatrix, color, q3, m_nbBins);
}
}
@ -966,7 +969,7 @@ void GLSpectrum::paintGL()
Real bottom = -m_powerRange;
GLfloat *q3 = m_q3FFT.m_array;
for (int i = 0; i < m_fftSize; i++)
for (int i = 0; i < m_nbBins; i++)
{
Real v = m_currentSpectrum[i] - m_referenceLevel;
@ -981,7 +984,7 @@ void GLSpectrum::paintGL()
}
QVector4D color(1.0f, 1.0f, 0.25f, (float) m_displayTraceIntensity / 100.0f);
m_glShaderSimple.drawPolyline(m_glHistogramSpectrumMatrix, color, q3, m_fftSize);
m_glShaderSimple.drawPolyline(m_glHistogramSpectrumMatrix, color, q3, m_nbBins);
}
}
@ -1265,7 +1268,7 @@ void GLSpectrum::stopDrag()
void GLSpectrum::applyChanges()
{
if (m_fftSize <= 0) {
if (m_nbBins <= 0) {
return;
}
@ -1371,7 +1374,7 @@ void GLSpectrum::applyChanges()
1.0f - ((float)(2*histogramTop) / (float) height())
);
m_glHistogramSpectrumMatrix.scale(
((float) 2 * (width() - m_leftMargin - m_rightMargin)) / ((float) width() * (float)(m_fftSize - 1)),
((float) 2 * (width() - m_leftMargin - m_rightMargin)) / ((float) width() * (float)(m_nbBins - 1)),
((float) 2*m_histogramHeight / height()) / m_powerRange
);
@ -1497,7 +1500,7 @@ void GLSpectrum::applyChanges()
1.0f - ((float)(2*histogramTop) / (float) height())
);
m_glHistogramSpectrumMatrix.scale(
((float) 2 * (width() - m_leftMargin - m_rightMargin)) / ((float) width() * (float)(m_fftSize - 1)),
((float) 2 * (width() - m_leftMargin - m_rightMargin)) / ((float) width() * (float)(m_nbBins - 1)),
((float) 2*(height() - m_topMargin - m_frequencyScaleHeight)) / (height()*m_powerRange)
);
@ -1837,7 +1840,7 @@ void GLSpectrum::applyChanges()
bool fftSizeChanged = true;
if (m_waterfallBuffer) {
fftSizeChanged = m_waterfallBuffer->width() != m_fftSize;
fftSizeChanged = m_waterfallBuffer->width() != m_nbBins;
}
bool windowSizeChanged = m_waterfallTextureHeight != m_waterfallHeight;
@ -1848,7 +1851,7 @@ void GLSpectrum::applyChanges()
delete m_waterfallBuffer;
}
m_waterfallBuffer = new QImage(m_fftSize, m_waterfallHeight, QImage::Format_ARGB32);
m_waterfallBuffer = new QImage(m_nbBins, m_waterfallHeight, QImage::Format_ARGB32);
m_waterfallBuffer->fill(qRgb(0x00, 0x00, 0x00));
m_glShaderWaterfall.initTexture(*m_waterfallBuffer);
@ -1868,15 +1871,15 @@ void GLSpectrum::applyChanges()
m_histogram = nullptr;
}
m_histogramBuffer = new QImage(m_fftSize, 100, QImage::Format_RGB32);
m_histogramBuffer = new QImage(m_nbBins, 100, QImage::Format_RGB32);
m_histogramBuffer->fill(qRgb(0x00, 0x00, 0x00));
m_glShaderHistogram.initTexture(*m_histogramBuffer, QOpenGLTexture::ClampToEdge);
m_histogram = new quint8[100 * m_fftSize];
memset(m_histogram, 0x00, 100 * m_fftSize);
m_histogram = new quint8[100 * m_nbBins];
memset(m_histogram, 0x00, 100 * m_nbBins);
m_q3FFT.allocate(2*m_fftSize);
m_q3FFT.allocate(2*m_nbBins);
}
if (fftSizeChanged || windowSizeChanged)
@ -2217,12 +2220,16 @@ void GLSpectrum::frequencyZoom(QWheelEvent *event)
{
if (m_frequencyZoomFactor < m_maxFrequencyZoom) {
m_frequencyZoomFactor += 0.5f;
} else {
return;
}
}
else
{
if (m_frequencyZoomFactor > 1.0f) {
m_frequencyZoomFactor -= 0.5f;
} else {
return;
}
}

View File

@ -104,7 +104,7 @@ public:
void removeChannelMarker(ChannelMarker* channelMarker);
void setMessageQueueToGUI(MessageQueue* messageQueue) { m_messageQueueToGUI = messageQueue; }
virtual void newSpectrum(const Real* spectrum, int fftSize);
virtual void newSpectrum(const Real* spectrum, int nbBins, int fftSize);
void clearSpectrumHistogram();
Real getWaterfallShare() const { return m_waterfallShare; }
@ -253,7 +253,8 @@ private:
quint32 m_timingRate;
int m_fftOverlap;
int m_fftSize;
int m_fftSize; //!< FFT size in number of bins
int m_nbBins; //!< Number of visible FFT bins (zoom support)
bool m_displayGrid;
int m_displayGridIntensity;