mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-02-03 09:44:01 -05:00
Spectrum frequency zoom: implementation for spectrum and waterfall only
This commit is contained in:
parent
ab0a7f2e60
commit
4d99533009
@ -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;
|
||||
}
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user