v2.0.0
Loading...
Searching...
No Matches
spectrogram.cpp
Go to the documentation of this file.
1//=============================================================================================================
12
13//=============================================================================================================
14// INCLUDES
15//=============================================================================================================
16
17#include "spectrogram.h"
18
19//=============================================================================================================
20// EIGEN INCLUDES
21//=============================================================================================================
22
23#include <Eigen/SparseCore>
24#include <unsupported/Eigen/FFT>
25
26//=============================================================================================================
27// QT INCLUDES
28//=============================================================================================================
29
30#include <QDebug>
31#include <QElapsedTimer>
32#include <QThread>
33#include <QtConcurrent>
34
35//=============================================================================================================
36// USED NAMESPACES
37//=============================================================================================================
38
39using namespace UTILSLIB;
40using namespace Eigen;
41
42//=============================================================================================================
43// DEFINE MEMBER METHODS
44//=============================================================================================================
45
46MatrixXd Spectrogram::makeSpectrogram(VectorXd signal, qint32 windowSize = 0)
47{
48 //QElapsedTimer timer;
49 //timer.start();
50
51 signal.array() -= signal.mean();
52 QList<SpectogramInputData> lData;
53 int iThreadSize = QThread::idealThreadCount()*2;
54 int iStepsSize = signal.rows()/iThreadSize;
55 int iResidual = signal.rows()%iThreadSize;
56
57 SpectogramInputData dataTemp;
58 dataTemp.vecInputData = signal;
59 dataTemp.window_size = windowSize;
60 if(dataTemp.window_size == 0) {
61 dataTemp.window_size = signal.rows()/15;
62 }
63
64 for (int i = 0; i < iThreadSize; ++i) {
65 dataTemp.iRangeLow = i*iStepsSize;
66 dataTemp.iRangeHigh = i*iStepsSize+iStepsSize;
67 lData.append(dataTemp);
68 }
69
70 dataTemp.iRangeLow = iThreadSize*iStepsSize;
71 dataTemp.iRangeHigh = iThreadSize*iStepsSize+iResidual;
72 lData.append(dataTemp);
73
74 QFuture<MatrixXd> resultMat = QtConcurrent::mappedReduced(lData,
75 compute,
76 reduce);
77 resultMat.waitForFinished();
78
79 //qDebug() << "Spectrogram::make_spectrogram - timer.elapsed()" << timer.elapsed();
80 return resultMat.result();
81}
82
83//=============================================================================================================
84
85VectorXd Spectrogram::gaussWindow(qint32 sample_count, qreal scale, quint32 translation)
86{
87 VectorXd gauss = VectorXd::Zero(sample_count);
88
89 for(qint32 n = 0; n < sample_count; n++)
90 {
91 qreal t = (qreal(n) - translation) / scale;
92 gauss[n] = exp(-3.14 * pow(t, 2))*pow(sqrt(scale),(-1))*pow(qreal(2),(0.25));
93 }
94
95 return gauss;
96}
97
98//=============================================================================================================
99
100MatrixXd Spectrogram::compute(const SpectogramInputData& inputData)
101{
102 #ifdef EIGEN_FFTW_DEFAULT
103 fftw_make_planner_thread_safe();
104 #endif
105
106 Eigen::FFT<double> fft;
107 MatrixXd tf_matrix = MatrixXd::Zero(inputData.vecInputData.rows()/2, inputData.vecInputData.rows());
108 VectorXd envelope, windowed_sig, real_coeffs;
109 VectorXcd fft_win_sig;
110 qint32 window_size = inputData.window_size;
111
112 for(quint32 translate = inputData.iRangeLow; translate < inputData.iRangeHigh; translate++) {
113 envelope = gaussWindow(inputData.vecInputData.rows(), window_size, translate);
114
115 windowed_sig = VectorXd::Zero(inputData.vecInputData.rows());
116 fft_win_sig = VectorXcd::Zero(inputData.vecInputData.rows());
117
118 windowed_sig = inputData.vecInputData.array() * envelope.array();\
119
120 fft.fwd(fft_win_sig, windowed_sig);
121
122 real_coeffs = fft_win_sig.segment(0,inputData.vecInputData.rows()/2).array().abs2();
123
124 tf_matrix.col(translate) = real_coeffs;
125 }
126
127 return tf_matrix;
128}
129
130//=============================================================================================================
131
132void Spectrogram::reduce(MatrixXd &resultData,
133 const MatrixXd &data)
134{
135 if(resultData.size() == 0) {
136 resultData = data;
137 } else {
138 resultData += data;
139 }
140}
Gaussian-windowed short-time Fourier transform (STFT) spectrogram.
Shared utilities (I/O helpers, spectral analysis, layout management, warp algorithms).
Input parameters for short-time Fourier transform spectrogram computation.
Definition spectrogram.h:53
static Eigen::MatrixXd makeSpectrogram(Eigen::VectorXd signal, qint32 windowSize)