File indexing completed on 2025-01-05 04:25:40

0001 /*
0002  * Copyright 2018  Malte Veerman <malte.veerman@gmail.com>
0003  *
0004  * This program is free software; you can redistribute it and/or
0005  * modify it under the terms of the GNU General Public License as
0006  * published by the Free Software Foundation; either version 2 of
0007  * the License or (at your option) version 3 or any later version
0008  * accepted by the membership of KDE e.V. (or its successor approved
0009  * by the membership of KDE e.V.), which shall act as a proxy
0010  * defined in Section 14 of version 3 of the license.
0011  *
0012  * This program is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0015  * GNU General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU General Public License
0018  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0019  */
0020 
0021 #ifndef ANALYZERWORKER_H
0022 #define ANALYZERWORKER_H
0023 
0024 #include "AnalyzerBase.h"
0025 
0026 #include <phonon/audiodataoutput.h>
0027 
0028 #include <QElapsedTimer>
0029 #include <QMutex>
0030 #include <QObject>
0031 #include <QTime>
0032 
0033 #include <complex>
0034 #include <fftw3.h>
0035 
0036 
0037 class QTimer;
0038 
0039 namespace Analyzer
0040 {
0041 
0042 /**
0043  * Base worker class for all analyzers
0044  * All compute heavy tasks should be offloaded to this.
0045  */
0046 class Worker : public QObject
0047 {
0048     friend class Base;
0049 
0050     Q_OBJECT
0051 
0052 public:
0053     const static int PROCESSING_INTERVAL = 5; // Interval between new data lookups
0054     const static int DATA_BUFFER_SIZE = 8; // Higher values increase latency, lower values increase risk of missing frames
0055 
0056     Worker();
0057     ~Worker() override;
0058 
0059 protected:
0060     /**
0061      * @return The current scope data.
0062      */
0063     const QVector<double>& scope() const { return m_currentScope; }
0064 
0065     /**
0066      * This function is being called after new scope data is ready.
0067      * Get the scope to be analyzed by calling scope().
0068      * Subclasses must implement this function.
0069      */
0070     virtual void analyze() = 0;
0071 
0072 private:
0073     struct BandInfo
0074     {
0075         double lowerFreq;
0076         double midFreq;
0077         double upperFreq;
0078         double lowerK;
0079         double midK;
0080         double upperK;
0081         int scopeIndex;
0082     };
0083 
0084     /**
0085      * This function is thread-safe.
0086      */
0087     void receiveData( const QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > &newData );
0088 
0089     // None of the following functions are thread-safe. Only connect with queued connections to them.
0090     void processData();
0091     void applyWindowFunction();
0092     void makeScope();
0093     void setSampleSize( uint size );
0094     void setWindowFunction( Base::WindowFunction windowFunction );
0095     void setScopeSize( int size );
0096     void calculateExpFactor( qreal minFreq, qreal maxFreq, int sampleRate );
0097     void resetDemo() { m_demoT = 201; }
0098     void playbackStateChanged();
0099 
0100     /**
0101      * Override this function for your custom idle animation.
0102      */
0103     virtual void demo();
0104 
0105     fftw_plan m_plan;
0106     mutable QMutex m_rawInMutex;
0107     QList<double> m_rawIn;
0108     double *m_in;
0109     std::complex<double> *m_out;
0110     QVector<double> m_currentScope;
0111     QVector<BandInfo> m_interpolatedScopeBands;
0112     QVector<BandInfo> m_notInterpolatedScopeBands;
0113     uint m_size;
0114     double m_expFactor;
0115     Base::WindowFunction m_windowFunction;
0116     int m_expectedDataTime;
0117     int m_demoT;
0118     QElapsedTimer m_lastUpdate;
0119     QTimer *m_demoTimer;
0120     QTimer *m_processTimer;
0121 };
0122 
0123 }
0124 
0125 #endif // ANALYZERWORKER_H