SigPack - the C++ signal processing library
spectrum.h
Go to the documentation of this file.
1 // This Source Code Form is subject to the terms of the Mozilla Public
2 // License, v. 2.0. If a copy of the MPL was not distributed with this
3 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 #ifndef SP_SPECTRUM_H
5 #define SP_SPECTRUM_H
6 namespace sp
7 {
12 
22 template <class T1>
23 arma::cx_vec spectrum(const arma::Col<T1> &x, const arma::vec &W)
24 {
25  arma::cx_vec Pxx(x.size());
26  double wc = sum(W); // Window correction factor
27  Pxx = fft(x % W) / wc; // FFT calc
28  return Pxx;
29 }
30 
37 template <class T1> arma::vec psd(const arma::Col<T1> &x, const arma::vec &W)
38 {
39  arma::cx_vec X(x.size());
40  arma::vec Pxx(x.size());
41  X = spectrum(x, W); // FFT calc
42  Pxx = real(X % conj(X)); // Calc power spectra
43  return Pxx;
44 }
45 
51 template <class T1> arma::vec psd(const arma::Col<T1> &x)
52 {
53  arma::vec W;
54  W = hamming(x.size());
55  return psd(x, W);
56 }
57 
67 template <class T1>
68 arma::cx_mat specgram_cx(const arma::Col<T1> &x, const arma::uword Nfft = 512,
69  const arma::uword Noverl = 256)
70 {
71  arma::cx_mat Pw;
72 
73  // Def params
74  arma::uword N = x.size();
75  arma::uword D = Nfft - Noverl;
76  arma::uword m = 0;
77  if (N > Nfft)
78  {
79  arma::Col<T1> xk(Nfft);
80  arma::vec W(Nfft);
81 
82  W = hamming(Nfft);
83  arma::uword U = static_cast<arma::uword>(floor((N - Noverl) / double(D)));
84  Pw.set_size(Nfft, U);
85  Pw.zeros();
86 
87  // Avg loop
88  for (arma::uword k = 0; k < N - Nfft; k += D)
89  {
90  xk = x.rows(k, k + Nfft - 1); // Pick out chunk
91  Pw.col(m++) = spectrum(xk, W); // Calculate spectrum
92  }
93  }
94  else
95  {
96  arma::vec W(N);
97  W = hamming(N);
98  Pw.set_size(N, 1);
99  Pw = spectrum(x, W);
100  }
101  return Pw;
102 }
103 
113 template <class T1>
114 arma::mat specgram(const arma::Col<T1> &x, const arma::uword Nfft = 512,
115  const arma::uword Noverl = 256)
116 {
117  arma::cx_mat Pw;
118  arma::mat Sg;
119  Pw = specgram_cx(x, Nfft, Noverl);
120  Sg = real(Pw % conj(Pw)); // Calculate power spectrum
121  return Sg;
122 }
123 
133 template <class T1>
134 arma::mat specgram_ph(const arma::Col<T1> &x, const arma::uword Nfft = 512,
135  const arma::uword Noverl = 256)
136 {
137  arma::cx_mat Pw;
138  arma::mat Sg;
139  Pw = specgram_cx(x, Nfft, Noverl);
140  Sg = angle(Pw); // Calculate phase spectrum
141  return Sg;
142 }
143 
154 template <class T1>
155 arma::vec pwelch_ph(const arma::Col<T1> &x, const arma::uword Nfft = 512,
156  const arma::uword Noverl = 256)
157 {
158  arma::mat Ph;
159  Ph = specgram_ph(x, Nfft, Noverl);
160  return arma::mean(Ph, 1);
161 }
162 
174 template <class T1>
175 arma::vec pwelch(const arma::Col<T1> &x, const arma::uword Nfft = 512,
176  const arma::uword Noverl = 256)
177 {
178  arma::mat Pxx;
179  Pxx = specgram(x, Nfft, Noverl);
180  return arma::mean(Pxx, 1);
181 }
182 
192 template <class T1>
193 std::complex<double> goertzel(const arma::Col<T1> &x, const double f)
194 {
195  // Constants
196  arma::uword N = x.size();
197  double Q = f / N;
198  double A = PI_2 * Q;
199  double B = 2 * cos(A);
200  std::complex<double> C(cos(A), -sin(A));
201  // States
202  T1 s0 = 0;
203  T1 s1 = 0;
204  T1 s2 = 0;
205 
206  // Accumulate data
207  for (arma::uword n = 0; n < N; n++)
208  {
209  // Update filter
210  s0 = x(n) + B * s1 - s2;
211 
212  // Shift buffer
213  s2 = s1;
214  s1 = s0;
215  }
216  // Update output state
217  s0 = B * s1 - s2;
218 
219  // Return the complex DFT output
220  return s0 - s1 * C;
221 }
222 
232 template <class T1>
233 arma::cx_vec goertzel(const arma::Col<T1> &x, const arma::vec f)
234 {
235  arma::uword N = f.size();
236  arma::cx_vec P(N);
237  for (arma::uword n = 0; n < N; n++)
238  {
239  P(n) = goertzel(x, f(n));
240  }
241 
242  // Return the complex DFT output vector
243  return P;
244 }
245 
247 } // namespace sp
248 #endif
arma::mat specgram(const arma::Col< T1 > &x, const arma::uword Nfft=512, const arma::uword Noverl=256)
Power spectrogram calculation.
Definition: spectrum.h:114
arma::vec pwelch_ph(const arma::Col< T1 > &x, const arma::uword Nfft=512, const arma::uword Noverl=256)
Phase spectrum calculation using Welch&#39;s method.
Definition: spectrum.h:155
double angle(const std::complex< T > &x)
Calculates angle in radians for complex input.
Definition: base.h:67
Definition: base.h:7
arma_inline arma::vec hamming(const arma::uword N)
Hamming window.
Definition: window.h:44
arma::mat specgram_ph(const arma::Col< T1 > &x, const arma::uword Nfft=512, const arma::uword Noverl=256)
Phase spectrogram calculation.
Definition: spectrum.h:134
arma::cx_vec spectrum(const arma::Col< T1 > &x, const arma::vec &W)
Windowed spectrum calculation.
Definition: spectrum.h:23
arma::vec pwelch(const arma::Col< T1 > &x, const arma::uword Nfft=512, const arma::uword Noverl=256)
Power spectrum calculation using Welch&#39;s method.
Definition: spectrum.h:175
arma::vec psd(const arma::Col< T1 > &x, const arma::vec &W)
Power spectrum density calculation using windowed data.
Definition: spectrum.h:37
std::complex< double > goertzel(const arma::Col< T1 > &x, const double f)
DFT calculation of a single frequency using Goertzel&#39;s method.
Definition: spectrum.h:193
arma::cx_mat specgram_cx(const arma::Col< T1 > &x, const arma::uword Nfft=512, const arma::uword Noverl=256)
Spectrogram calculation using Hamming windowed data.
Definition: spectrum.h:68
const double PI_2
Definition: base.h:15