const QColor light(250, 238, 226, 255);
const QColor dark(40, 40, 39, 255);
const QColor dark2(25, 25, 23, 255);
-
-const QPen AbstractScopeWidget::penThick(QBrush(QColor(250, 250, 250)), 2, Qt::SolidLine);
-const QPen AbstractScopeWidget::penThin(QBrush(QColor(250, 250, 250)), 1, Qt::SolidLine);
-const QPen AbstractScopeWidget::penLight(QBrush(QColor(200, 200, 250, 150)), 1, Qt::SolidLine);
-const QPen AbstractScopeWidget::penLightDots(QBrush(QColor(200, 200, 250, 150)), 1, Qt::DotLine);
-const QPen AbstractScopeWidget::penLighter(QBrush(QColor(225, 225, 250, 225)), 1, Qt::SolidLine);
-const QPen AbstractScopeWidget::penDark(QBrush(QColor(0, 0, 20, 250)), 1, Qt::SolidLine);
-const QPen AbstractScopeWidget::penDarkDots(QBrush(QColor(0, 0, 20, 250)), 1, Qt::DotLine);
-const QPen AbstractScopeWidget::penBackground(QBrush(dark2), 1, Qt::SolidLine);
+const QColor AbstractScopeWidget::colHighlightLight(18, 130, 255, 255);
+const QColor AbstractScopeWidget::colHighlightDark(255, 64, 19, 255);
+const QColor AbstractScopeWidget::colDarkWhite(250, 250, 250);
+
+const QPen AbstractScopeWidget::penThick(QBrush(AbstractScopeWidget::colDarkWhite.rgb()), 2, Qt::SolidLine);
+const QPen AbstractScopeWidget::penThin(QBrush(AbstractScopeWidget::colDarkWhite.rgb()), 1, Qt::SolidLine);
+const QPen AbstractScopeWidget::penLight(QBrush(QColor(200, 200, 250, 150)), 1, Qt::SolidLine);
+const QPen AbstractScopeWidget::penLightDots(QBrush(QColor(200, 200, 250, 150)), 1, Qt::DotLine);
+const QPen AbstractScopeWidget::penLighter(QBrush(QColor(225, 225, 250, 225)), 1, Qt::SolidLine);
+const QPen AbstractScopeWidget::penDark(QBrush(QColor(0, 0, 20, 250)), 1, Qt::SolidLine);
+const QPen AbstractScopeWidget::penDarkDots(QBrush(QColor(0, 0, 20, 250)), 1, Qt::DotLine);
+const QPen AbstractScopeWidget::penBackground(QBrush(dark2), 1, Qt::SolidLine);
const QString AbstractScopeWidget::directions[] = {"North", "Northeast", "East", "Southeast"};
virtual QString widgetName() const = 0;
///// Variables /////
+ static const QColor colHighlightLight;
+ static const QColor colHighlightDark;
+ static const QColor colDarkWhite;
+
static const QPen penThick;
static const QPen penThin;
static const QPen penLight;
#define MIN_DB_VALUE -120
#define MAX_FREQ_VALUE 96000
#define MIN_FREQ_VALUE 1000
+#define ALPHA_MOVING_AVG 0.125
AudioSpectrum::AudioSpectrum(QWidget *parent) :
- AbstractAudioScopeWidget(true, parent),
- m_fftTools(),
- m_lastFFT(),
- m_lastFFTLock(1)
+ AbstractAudioScopeWidget(true, parent),
+ m_fftTools(),
+ m_lastFFT(),
+ m_lastFFTLock(1),
+ m_peaks()
#ifdef DEBUG_AUDIOSPEC
- ,m_timeTotal(0)
- ,m_showTotal(0)
+ ,m_timeTotal(0)
+ ,m_showTotal(0)
#endif
{
ui = new Ui::AudioSpectrum_UI;
m_aResetHz = new QAction(i18n("Reset maximum frequency to sampling rate"), this);
m_aTrackMouse = new QAction(i18n("Track mouse"), this);
m_aTrackMouse->setCheckable(true);
+ m_aShowMax = new QAction(i18n("Show maximum"), this);
+ m_aShowMax->setCheckable(true);
m_menu->addSeparator();
m_menu->addAction(m_aResetHz);
m_menu->addAction(m_aTrackMouse);
+ m_menu->addAction(m_aShowMax);
m_menu->removeAction(m_aRealtime);
ui->windowSize->setCurrentIndex(scopeConfig.readEntry("windowSize", 0));
ui->windowFunction->setCurrentIndex(scopeConfig.readEntry("windowFunction", 0));
m_aTrackMouse->setChecked(scopeConfig.readEntry("trackMouse", true));
+ m_aShowMax->setChecked(scopeConfig.readEntry("showMax", true));
m_dBmax = scopeConfig.readEntry("dBmax", 0);
m_dBmin = scopeConfig.readEntry("dBmin", -70);
m_freqMax = scopeConfig.readEntry("freqMax", 0);
scopeConfig.writeEntry("windowSize", ui->windowSize->currentIndex());
scopeConfig.writeEntry("windowFunction", ui->windowFunction->currentIndex());
scopeConfig.writeEntry("trackMouse", m_aTrackMouse->isChecked());
+ scopeConfig.writeEntry("showMax", m_aShowMax->isChecked());
scopeConfig.writeEntry("dBmax", m_dBmax);
scopeConfig.writeEntry("dBmin", m_dBmin);
if (m_customFreq) {
m_lastFFTLock.release();
+#ifdef DEBUG_AUDIOSPEC
QTime drawTime = QTime::currentTime();
+#endif
// Draw the spectrum
QImage spectrum(m_scopeRect.size(), QImage::Format_ARGB32);
#endif
}
+ // Calculate the peak values. Use the new value if it is bigger, otherwise adapt to lower
+ // values using the Moving Average formula
+ if (m_aShowMax->isChecked()) {
+ davinci.setPen(QPen(QBrush(AbstractScopeWidget::colHighlightLight), 2));
+ if (m_peaks.size() != fftWindow/2) {
+ m_peaks = QVector<float>(m_lastFFT);
+ } else {
+ for (int i = 0; i < fftWindow/2; i++) {
+ if (m_lastFFT[i] > m_peaks[i]) {
+ m_peaks[i] = m_lastFFT[i];
+ } else {
+ m_peaks[i] = ALPHA_MOVING_AVG * m_lastFFT[i] + (1-ALPHA_MOVING_AVG) * m_peaks[i];
+ }
+ }
+ }
+ int prev = 0;
+ m_peakMap = FFTTools::interpolatePeakPreserving(m_peaks, m_innerScopeRect.width(), 0, right, -180);
+ for (uint i = 0; i < w; i++) {
+ yMax = (m_peakMap[i] - m_dBmin) / (m_dBmax-m_dBmin) * (h-1);
+ if (yMax < 0) {
+ yMax = 0;
+ } else if (yMax >= (int)h) {
+ yMax = h-1;
+ }
+
+ davinci.drawLine(leftDist + i-1, topDist + h-prev-1, leftDist + i, topDist + h-yMax-1);
+ spectrum.setPixel(leftDist + i, topDist + h-yMax-1, AbstractScopeWidget::colHighlightLight.rgba());
+ prev = yMax;
+ }
+ }
+
#ifdef DEBUG_AUDIOSPEC
m_showTotal++;
m_timeTotal += drawTime.elapsed();
forceUpdateScope();
}
}
-
-
-#ifdef DEBUG_AUDIOSPEC
-#undef DEBUG_AUDIOSPEC
-#endif
-
-#undef MIN_DB_VALUE
-#undef MAX_FREQ_VALUE
-#undef MIN_FREQ_VALUE
QAction *m_aResetHz;
QAction *m_aTrackMouse;
+ QAction *m_aShowMax;
FFTTools m_fftTools;
QVector<float> m_lastFFT;
QSemaphore m_lastFFTLock;
+ QVector<float> m_peaks;
+ QVector<float> m_peakMap;
+
/** Contains the plot only; m_scopeRect contains text and widgets as well */
QRect m_innerScopeRect;