1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-25 17:28:50 -05:00

Merge pull request #1437 from srcejon/spectrum_peak

Spectrum: Add peak power and frequency in info bar
This commit is contained in:
Edouard Griffiths 2022-09-22 14:15:38 +02:00 committed by GitHub
commit 31565b5caf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 155 additions and 1 deletions

View File

@ -593,7 +593,6 @@ void GLSpectrum::newSpectrum(const Real *spectrum, int nbBins, int fftSize)
QMutexLocker mutexLocker(&m_mutex); QMutexLocker mutexLocker(&m_mutex);
m_displayChanged = true; m_displayChanged = true;
if (m_changesPending) if (m_changesPending)
{ {
m_fftSize = fftSize; m_fftSize = fftSize;
@ -1651,6 +1650,17 @@ void GLSpectrum::paintGL()
m_glShaderInfo.drawSurface(m_glInfoBoxMatrix, tex1, vtx1, 4); m_glShaderInfo.drawSurface(m_glInfoBoxMatrix, tex1, vtx1, 4);
} }
// Find and display peak in info line
{
if (m_currentSpectrum)
{
float power, frequency;
findPeak(power, frequency);
drawPeakText(power, (int64_t)frequency);
}
}
m_mutex.unlock(); m_mutex.unlock();
} }
@ -2632,6 +2642,18 @@ void GLSpectrum::applyChanges()
m_glShaderInfo.initTexture(m_infoPixmap.toImage()); m_glShaderInfo.initTexture(m_infoPixmap.toImage());
// Peak details in top info line
QString minFrequencyStr = displayFull(m_centerFrequency - m_sampleRate/2); // This can be wider if negative, while max is positive
QString maxFrequencyStr = displayFull(m_centerFrequency + m_sampleRate/2);
QString widestFrequencyStr = minFrequencyStr.size() > maxFrequencyStr.size() ? minFrequencyStr : maxFrequencyStr;
widestFrequencyStr = widestFrequencyStr.append("Hz");
m_peakLabelStr = "Peak:";
m_peakSpaceWidth = fm.width(" ");
m_peakSpaceMidWidth = ((widestFrequencyStr.size() > 10) ? 3 : 1) * m_peakSpaceWidth; // Extra space when lots of digits
m_peakLabelWidth = fm.width(m_peakLabelStr);
m_peakPowerMaxWidth = m_linear ? fm.width("8.000e-10") : fm.width("-100.0dB");
m_peakFrequencyMaxWidth = fm.width(widestFrequencyStr);
bool fftSizeChanged = true; bool fftSizeChanged = true;
if (m_waterfallBuffer) { if (m_waterfallBuffer) {
@ -3792,6 +3814,46 @@ void GLSpectrum::cleanup()
//doneCurrent(); //doneCurrent();
} }
// Display number with full precision, group separators and eng. unit suffixes
// E.g:
// -1.505,123,304G
// 456.034,123M
// 300.345k
// 789
QString GLSpectrum::displayFull(int64_t value)
{
if (value == 0) {
return "0";
}
int64_t absValue = std::abs(value);
QString digits = QString::number(absValue);
int cnt = digits.size();
QString point = QLocale::system().decimalPoint();
QString group = QLocale::system().groupSeparator();
int i;
for (i = cnt - 3; i >= 4; i -= 3)
{
digits = digits.insert(i, group);
}
if (absValue >= 1000) {
digits = digits.insert(i, point);
}
if (cnt > 9) {
digits = digits.append("G");
} else if (cnt > 6) {
digits = digits.append("M");
} else if (cnt > 3) {
digits = digits.append("k");
}
if (value < 0) {
digits = digits.insert(0, "-");
}
return digits;
}
QString GLSpectrum::displayScaled(int64_t value, char type, int precision, bool showMult) QString GLSpectrum::displayScaled(int64_t value, char type, int precision, bool showMult)
{ {
int64_t posValue = (value < 0) ? -value : value; int64_t posValue = (value < 0) ? -value : value;
@ -3867,6 +3929,88 @@ int GLSpectrum::getPrecision(int value)
} }
} }
// Find power and frequency of max peak in current spectrum
void GLSpectrum::findPeak(float &power, float &frequency) const
{
int bin;
bin = 0;
power = m_currentSpectrum[0];
for (int i = 1; i < m_nbBins; i++)
{
if (m_currentSpectrum[i] > power)
{
power = m_currentSpectrum[i];
bin = i;
}
}
power = m_linear ?
power * (m_useCalibration ? m_calibrationGain : 1.0f):
power + (m_useCalibration ? m_calibrationShiftdB : 0.0f);
float hzPerBin = (float) m_sampleRate / m_fftSize;
frequency = m_centerFrequency + (bin - (m_fftSize/2)) * hzPerBin;
}
// Draws peak power and frequency right justified in top info bar
void GLSpectrum::drawPeakText(float power, int64_t frequency, bool units)
{
QFontMetrics fm(font());
m_infoPixmap.fill(Qt::transparent);
QPainter painter(&m_infoPixmap);
painter.setPen(Qt::NoPen);
painter.setBrush(Qt::black);
painter.setBrush(Qt::transparent);
painter.drawRect(m_leftMargin, 0, width() - m_leftMargin, m_infoHeight);
painter.setPen(QColor(0xf0, 0xf0, 0xff));
painter.setFont(font());
QString powerStr = displayPower(
power,
m_linear ? 'e' : 'f',
m_linear ? 3 : 1
);
QString frequencyStr = displayFull(frequency);
if (units)
{
if (!m_linear) {
powerStr = powerStr.append("dB");
}
frequencyStr = frequencyStr.append("Hz");
}
int powerWidth = fm.width(powerStr);
int frequencyWidth = fm.width(frequencyStr);
int x = width() - m_rightMargin;
int y = fm.height() + fm.ascent() / 2 - 2;
painter.drawText(QPointF(x - frequencyWidth, y), frequencyStr);
x -= m_peakFrequencyMaxWidth + m_peakSpaceMidWidth;
painter.drawText(QPointF(x - powerWidth, y), powerStr);
x -= m_peakPowerMaxWidth + m_peakSpaceWidth;
painter.drawText(QPointF(x - m_peakLabelWidth, y), m_peakLabelStr);
m_glShaderTextOverlay.initTexture(m_infoPixmap.toImage());
GLfloat vtx1[] = {
0, 1,
1, 1,
1, 0,
0, 0
};
GLfloat tex1[] = {
0, 1,
1, 1,
1, 0,
0, 0
};
m_glShaderTextOverlay.drawSurface(m_glInfoBoxMatrix, tex1, vtx1, 4);
}
void GLSpectrum::drawTextOverlay( void GLSpectrum::drawTextOverlay(
const QString &text, const QString &text,
const QColor &color, const QColor &color,

View File

@ -294,6 +294,13 @@ private:
QMatrix4x4 m_glLeftScaleBoxMatrix; QMatrix4x4 m_glLeftScaleBoxMatrix;
QMatrix4x4 m_glInfoBoxMatrix; QMatrix4x4 m_glInfoBoxMatrix;
QString m_peakLabelStr;
int m_peakLabelWidth;
int m_peakSpaceWidth;
int m_peakSpaceMidWidth;
int m_peakPowerMaxWidth;
int m_peakFrequencyMaxWidth;
QRgb m_waterfallPalette[240]; QRgb m_waterfallPalette[240];
QImage* m_waterfallBuffer; QImage* m_waterfallBuffer;
int m_waterfallBufferPos; int m_waterfallBufferPos;
@ -402,10 +409,13 @@ private:
void enterEvent(QEvent* event); void enterEvent(QEvent* event);
void leaveEvent(QEvent* event); void leaveEvent(QEvent* event);
static QString displayFull(int64_t value);
static QString displayScaled(int64_t value, char type, int precision, bool showMult); static QString displayScaled(int64_t value, char type, int precision, bool showMult);
static QString displayScaledF(float value, char type, int precision, bool showMult); static QString displayScaledF(float value, char type, int precision, bool showMult);
static QString displayPower(float value, char type, int precision); static QString displayPower(float value, char type, int precision);
int getPrecision(int value); int getPrecision(int value);
void findPeak(float &power, float &frequency) const;
void drawPeakText(float power, int64_t frequency, bool units=true);
void drawTextOverlay( //!< Draws a text overlay void drawTextOverlay( //!< Draws a text overlay
const QString& text, const QString& text,
const QColor& color, const QColor& color,