1 #include "audiospectrum.h"
2 #include "tools/kiss_fftr.h"
9 bool fileWritten = false;
11 AudioSpectrum::AudioSpectrum(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent) :
12 AbstractAudioScopeWidget(projMonitor, clipMonitor, true, parent)
14 ui = new Ui::AudioSpectrum_UI;
17 m_cfg = kiss_fftr_alloc(512, 0,0,0);
19 m_aLin = new QAction(i18n("Linear scale"), this);
20 m_aLin->setCheckable(true);
21 m_aLog = new QAction(i18n("Logarithmic scale"), this);
22 m_aLog->setCheckable(true);
24 m_agScale = new QActionGroup(this);
25 m_agScale->addAction(m_aLin);
26 m_agScale->addAction(m_aLog);
28 m_menu->addSeparator()->setText(i18n("Scale"));
29 m_menu->addAction(m_aLin);
30 m_menu->addAction(m_aLog);
34 AudioSpectrum::~AudioSpectrum()
42 void AudioSpectrum::readConfig()
44 AbstractAudioScopeWidget::readConfig();
46 KSharedConfigPtr config = KGlobal::config();
47 KConfigGroup scopeConfig(config, configName());
48 QString scale = scopeConfig.readEntry("scale");
50 m_aLin->setChecked(true);
52 m_aLog->setChecked(true);
56 void AudioSpectrum::writeConfig()
58 KSharedConfigPtr config = KGlobal::config();
59 KConfigGroup scopeConfig(config, configName());
61 if (m_aLin->isChecked()) {
66 scopeConfig.writeEntry("scale", scale);
70 QString AudioSpectrum::widgetName() const { return QString("audiospectrum"); }
72 bool AudioSpectrum::isBackgroundDependingOnInput() const { return false; }
73 bool AudioSpectrum::isScopeDependingOnInput() const { return true; }
74 bool AudioSpectrum::isHUDDependingOnInput() const { return false; }
76 QImage AudioSpectrum::renderBackground(uint) { return QImage(); }
77 QImage AudioSpectrum::renderScope(uint, const QVector<int16_t> audioFrame, const int freq, const int num_channels, const int num_samples)
79 QTime start = QTime::currentTime();
82 // The resulting FFT vector is only half as long
83 kiss_fft_cpx freqData[256];
85 // Copy the first channel's audio into a vector for the FFT display
86 // (only one channel handled at the moment)
87 for (int i = 0; i < 512; i++) {
88 data[i] = (float) audioFrame.data()[i*num_channels];
90 // Calculate the Fast Fourier Transform for the input data
91 kiss_fftr(m_cfg, data, freqData);
93 // qDebug() << num_samples << " samples at " << freq << " Hz";
94 // qDebug() << "FFT Freq: " << freqData[0].r << " " << freqData[1].r << ", " << freqData[2].r;
95 // qDebug() << "FFT imag: " << freqData[0].i << " " << freqData[1].i << ", " << freqData[2].i;
102 // Get the minimum and the maximum value of the Fourier transformed (for scaling)
103 for (int i = 0; i < 256; i++) {
105 val = pow(pow(fabs(freqData[i].r),2) + pow(fabs(freqData[i].i),2), .5);
106 if (maxSignal < val) { maxSignal = val; }
107 if (!m_aLin->isChecked()) {
109 val = log(pow(pow(fabs(freqData[i].r),2) + pow(fabs(freqData[i].i),2), .5)/512.0f);
111 max = (max > val) ? max : val;
112 min = (min < val) ? min : val;
114 qDebug() << "MAX: " << max << " (" << maxSignal << "), MIN: " << min;
117 float factor = 100./(max-min);
120 QImage spectrum(512, 100, QImage::Format_ARGB32);
121 spectrum.fill(qRgba(0,0,0,0));
122 for (int i = 0; i < 256; i++) {
123 if (m_aLin->isChecked()) {
124 val = pow(pow(fabs(freqData[i].r),2) + pow(fabs(freqData[i].i),2), .5);
126 val = log(pow(pow(fabs(freqData[i].r),2) + pow(fabs(freqData[i].i),2), .5)/512.0f);
129 val = factor * (val-min);
131 for (int y = 0; y < val && y < 100; y++) {
132 spectrum.setPixel(2*i, 99-y, qRgba(225, 182, 255, 255));
133 spectrum.setPixel(2*i+1, 99-y, qRgba(225, 182, 255, 255));
137 emit signalScopeRenderingFinished(start.elapsed(), 1);
140 if (!fileWritten || true) {
142 mFile.open("/tmp/freq.m");
144 qDebug() << "Opening file failed.";
148 for (int sample = 0; sample < 256; sample++) {
149 mFile << data[sample] << " ";
153 mFile << "freq = [ ";
154 for (int sample = 0; sample < 256; sample++) {
155 mFile << freqData[sample].r << "+" << freqData[sample].i << "*i ";
161 qDebug() << "File written.";
164 qDebug() << "File already written.";
170 QImage AudioSpectrum::renderHUD(uint) { return QImage(); }
172 QRect AudioSpectrum::scopeRect() {
173 return QRect(0,0,40,40);