#include <QMenu>
#include <QPainter>
+#include <QMouseEvent>
-// Linear interpolation.
-//#include <iostream>
-//#include <fstream>
+#include <iostream>
+#include <fstream>
bool fileWritten = false;
+const QString AudioSpectrum::directions[] = {"North", "Northeast", "East", "Southeast"};
+
AudioSpectrum::AudioSpectrum(QWidget *parent) :
- AbstractAudioScopeWidget(true, parent)
+ AbstractAudioScopeWidget(false, parent),
+ m_rescaleMinDist(12),
+ m_rescaleVerticalThreshold(2.0f),
+ m_rescaleActive(false),
+ m_rescalePropertiesLocked(false),
+ m_rescaleScale(1)
{
ui = new Ui::AudioSpectrum_UI;
ui->setupUi(this);
m_agScale->addAction(m_aLin);
m_agScale->addAction(m_aLog);
- m_menu->addSeparator()->setText(i18n("Scale"));
- m_menu->addAction(m_aLin);
- m_menu->addAction(m_aLog);
+ m_aLockHz = new QAction(i18n("Lock maximum frequency"), this);
+ m_aLockHz->setCheckable(true);
+ m_aLockHz->setEnabled(false);
+
+
+// m_menu->addSeparator()->setText(i18n("Scale"));
+// m_menu->addAction(m_aLin);
+// m_menu->addAction(m_aLog);
+ m_menu->addSeparator();
+ m_menu->addAction(m_aLockHz);
+
ui->windowSize->addItem("256", QVariant(256));
ui->windowSize->addItem("512", QVariant(512));
delete m_agScale;
delete m_aLin;
delete m_aLog;
+ delete m_aLockHz;
}
void AudioSpectrum::readConfig()
} else {
m_aLog->setChecked(true);
}
+ m_aLockHz->setChecked(scopeConfig.readEntry("lockHz", false));
ui->windowSize->setCurrentIndex(scopeConfig.readEntry("windowSize", 0));
}
}
scopeConfig.writeEntry("scale", scale);
scopeConfig.writeEntry("windowSize", ui->windowSize->currentIndex());
+ scopeConfig.writeEntry("lockHz", m_aLockHz->isChecked());
scopeConfig.sync();
}
}
// freqSpectrum values range from 0 to -inf as they are relative dB values.
- qDebug() << val << "/" << (1 - (val - m_dBmax)/(m_dBmin-m_dBmax));
+// qDebug() << val << "/" << (1 - (val - m_dBmax)/(m_dBmin-m_dBmax));
for (uint y = 0; y < h*(1 - (val - m_dBmax)/(m_dBmin-m_dBmax)) && y < h; y++) {
spectrum.setPixel(i, h-y-1, qRgba(225, 182, 255, 255));
}
} else {
qDebug() << "File already written.";
}
- */
+ //*/
if (customCfg) {
free(myCfg);
for (int db = -dbDiff; db > m_dBmin; db -= dbDiff) {
y = rect.height() * ((float)db)/(m_dBmin - m_dBmax);
davinci.drawLine(0, y, rect.width()-1, y);
- davinci.drawText(rect.width() + textDist, y + 8, i18n("%1 dB", db));
+ davinci.drawText(rect.width() + textDist, y + 8, i18n("%1 dB", m_dBmax + db));
}
free(m_cfg);
m_cfg = kiss_fftr_alloc(ui->windowSize->itemData(ui->windowSize->currentIndex()).toInt(), 0,0,0);
}
+
+
+///// EVENTS /////
+
+void AudioSpectrum::mouseMoveEvent(QMouseEvent *event)
+{
+// qDebug() << "Mouse moved; Modifier: " << event->modifiers() << ", xy: " << event->x() << "/" << event->y()
+// << ", Buttons: " << event->buttons();
+
+ QPoint movement = event->pos()-m_rescaleStartPoint;
+
+ if (m_rescaleActive) {
+ if (m_rescalePropertiesLocked) {
+ // Direction is known, now adjust parameters
+
+ // Reset the starting point to make the next moveEvent relative to the current one
+ m_rescaleStartPoint = event->pos();
+
+
+ if (!m_rescaleFirstRescaleDone) {
+ // We have just learned the desired direction; Normalize the movement to one pixel
+ // to avoid a jump by m_rescaleMinDist
+
+ if (movement.x() != 0) {
+ movement.setX(movement.x() / abs(movement.x()));
+ }
+ if (movement.y() != 0) {
+ movement.setY(movement.y() / abs(movement.y()));
+ }
+
+ m_rescaleFirstRescaleDone = true;
+ }
+
+ if (m_rescaleClockDirection == AudioSpectrum::North) {
+ // Nort-South direction: Adjust the dB scale
+
+ if ((m_rescaleModifiers & Qt::ShiftModifier) == 0) {
+
+ // By default adjust the min dB value
+ m_dBmin += movement.y();
+
+ } else {
+
+ // Adjust max dB value if Shift is pressed.
+ m_dBmax += movement.y();
+
+ }
+
+ // Ensure the dB values lie in [-100, 0]
+ // 0 is the upper bound, everything below -70 dB is most likely noise
+ if (m_dBmax > 0) {
+ m_dBmax = 0;
+ }
+ if (m_dBmin < -100) {
+ m_dBmin = -100;
+ }
+ // Ensure there is at least 6 dB between the minimum and the maximum value;
+ // lower values hardly make sense
+ if (m_dBmax - m_dBmin < 6) {
+ if ((m_rescaleModifiers & Qt::ShiftModifier) == 0) {
+ // min was adjusted; Try to adjust the max value to maintain the
+ // minimum dB difference of 6 dB
+ m_dBmax = m_dBmin + 6;
+ if (m_dBmax > 0) {
+ m_dBmax = 0;
+ m_dBmin = -6;
+ }
+ } else {
+ // max was adjusted, adjust min
+ m_dBmin = m_dBmax - 6;
+ if (m_dBmin < -100) {
+ m_dBmin = -100;
+ m_dBmax = -100+6;
+ }
+ }
+ }
+
+ forceUpdateHUD();
+ forceUpdateScope();
+
+ }
+
+
+ } else {
+ // Detect the movement direction here.
+ // This algorithm relies on the aspect ratio of dy/dx (size and signum).
+ if (movement.manhattanLength() > m_rescaleMinDist) {
+ float diff = ((float) movement.y())/movement.x();
+
+ if (abs(diff) > m_rescaleVerticalThreshold || movement.x() == 0) {
+ m_rescaleClockDirection = AudioSpectrum::North;
+ } else if (abs(diff) < 1/m_rescaleVerticalThreshold) {
+ m_rescaleClockDirection = AudioSpectrum::East;
+ } else if (diff < 0) {
+ m_rescaleClockDirection = AudioSpectrum::Northeast;
+ } else {
+ m_rescaleClockDirection = AudioSpectrum::Southeast;
+ }
+// qDebug() << "Diff is " << diff << "; chose " << directions[m_rescaleClockDirection] << " as direction";
+ m_rescalePropertiesLocked = true;
+ }
+ }
+ } else {
+ AbstractAudioScopeWidget::mouseMoveEvent(event);
+ }
+}
+
+void AudioSpectrum::mousePressEvent(QMouseEvent *event)
+{
+ if (event->button() == Qt::LeftButton) {
+ // Rescaling mode starts
+ m_rescaleActive = true;
+ m_rescalePropertiesLocked = false;
+ m_rescaleFirstRescaleDone = false;
+ m_rescaleStartPoint = event->pos();
+ m_rescaleModifiers = event->modifiers();
+
+ } else {
+ AbstractAudioScopeWidget::mousePressEvent(event);
+ }
+}
+
+void AudioSpectrum::mouseReleaseEvent(QMouseEvent *event)
+{
+ m_rescaleActive = false;
+ m_rescalePropertiesLocked = false;
+
+ AbstractAudioScopeWidget::mouseReleaseEvent(event);
+}
// Implemented virtual methods
QString widgetName() const;
+ static const QString directions[]; // Mainly for debug output
+ enum RescaleDirection { North, Northeast, East, Southeast };
+ enum RescaleDimension { Min_dB, Max_dB, Max_Hz };
+
+
protected:
///// Implemented methods /////
QRect scopeRect();
virtual void readConfig();
void writeConfig();
+ void mouseMoveEvent(QMouseEvent *event);
+ void mousePressEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+
private:
Ui::AudioSpectrum_UI *ui;
kiss_fftr_cfg m_cfg;
+ QAction *m_aLockHz;
QAction *m_aLin;
QAction *m_aLog;
QActionGroup *m_agScale;
/** Upper bound (max: 0) */
int m_dBmax;
+ /** Maximum frequency (depends on the sampling rate)
+ Stored for the HUD painter */
uint m_freqMax;
+
+ ///// Movement detection /////
+ const int m_rescaleMinDist;
+ const float m_rescaleVerticalThreshold;
+
+ bool m_rescaleActive;
+ bool m_rescalePropertiesLocked;
+ bool m_rescaleFirstRescaleDone;
+ short m_rescaleScale;
+ Qt::KeyboardModifiers m_rescaleModifiers;
+ AudioSpectrum::RescaleDirection m_rescaleClockDirection;
+ QPoint m_rescaleStartPoint;
+
+
+
private slots:
void slotUpdateCfg();