libdspl-2.0
Библиотека алгоритмов цифровой обработки сигналов
psd_welch_cmplx.c
1 /*
2 * Copyright (c) 2015-2024 Sergey Bakhurin
3 * Digital Signal Processing Library [http://dsplib.org]
4 *
5 * This file is part of libdspl-2.0.
6 *
7 * is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * DSPL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <float.h>
25 #include "dspl.h"
26 
27 
28 #ifdef DOXYGEN_ENGLISH
29 
30 #endif
31 #ifdef DOXYGEN_RUSSIAN
32 
155 #endif
156 int DSPL_API psd_welch_cmplx(complex_t* x, int n,
157  int win_type, double win_param,
158  int nfft, int noverlap, fft_t* pfft, double fs,
159  int flag, double* ppsd, double* pfrq)
160 {
161  int err, pos, cnt, k;
162  double *pdgr = NULL;
163  complex_t *tmp = NULL;
164  double *w = NULL;
165  fft_t *ptr_fft = NULL;
166  double wn;
167 
168  pos = cnt = 0;
169 
170  pdgr = (double*)malloc(nfft * sizeof(double));
171  if(!pdgr)
172  return ERROR_MALLOC;
173 
174  tmp = (complex_t*) malloc(nfft * sizeof(complex_t));
175  if(!tmp)
176  return ERROR_MALLOC;
177 
178 
179  /* window malloc */
180  w = (double*)malloc(nfft*sizeof(double));
181  if(!w)
182  {
183  err = ERROR_MALLOC;
184  goto exit_label;
185  }
186 
187  /* create window */
188  err = window(w, nfft, win_type, win_param);
189  if(err != RES_OK)
190  goto exit_label;
191 
192  /* window normalization wn = sum(w.^2) */
193  wn = 0.0;
194  for(k = 0; k < nfft; k++)
195  wn += w[k]*w[k];
196 
197 
198  if(!pfft)
199  {
200  ptr_fft = (fft_t*)malloc(sizeof(fft_t));
201  memset(ptr_fft, 0, sizeof(fft_t));
202  }
203  else
204  ptr_fft = pfft;
205 
206 
207 
208 
209  memset(ppsd, 0, nfft * sizeof(double));
210  while(pos + nfft <= n)
211  {
212  for(k = 0; k < nfft; k++)
213  {
214  RE(tmp[k]) = RE(x[pos+k]) * w[k];
215  IM(tmp[k]) = IM(x[pos+k]) * w[k];
216  }
217  err = fft_mag_cmplx(tmp, nfft, ptr_fft, fs,
218  flag & DSPL_FLAG_FFT_SHIFT, pdgr, NULL);
219  if(err != RES_OK)
220  goto exit_label;
221  for(k = 0; k < nfft; k++)
222  ppsd[k] += pdgr[k];
223  pos += noverlap;
224  cnt++;
225  }
226 
227  if(pos < n)
228  {
229 
230  memset(tmp ,0, nfft * sizeof(complex_t));
231  for(k = 0; k < n - pos; k++)
232  {
233  RE(tmp[k]) = RE(x[pos+k]) * w[k];
234  IM(tmp[k]) = IM(x[pos+k]) * w[k];
235  }
236 
237  err = fft_mag_cmplx(tmp, nfft, ptr_fft, fs,
238  flag & DSPL_FLAG_FFT_SHIFT, pdgr, NULL);
239  if(err != RES_OK)
240  goto exit_label;
241 
242  for(k = 0; k < nfft; k++)
243  ppsd[k] += pdgr[k];
244 
245  cnt++;
246  }
247 
248  /* fill frequency */
249  if(pfrq)
250  {
251  if(flag & DSPL_FLAG_FFT_SHIFT)
252  if(n%2)
253  err = linspace(- fs * 0.5 + fs * 0.5 / (double)nfft,
254  fs * 0.5 - fs * 0.5 / (double)nfft,
255  n, DSPL_SYMMETRIC, pfrq);
256  else
257  err = linspace(-fs*0.5, fs*0.5, nfft, DSPL_PERIODIC, pfrq);
258  else
259  err = linspace(0, fs, nfft, DSPL_PERIODIC, pfrq);
260  }
261 
262  /* scale magnitude */
263  if(flag & DSPL_FLAG_LOGMAG)
264  {
265  for(k = 0; k < nfft; k++)
266  ppsd[k] = 10.0 * log10(ppsd[k] / (fs * wn * (double)cnt));
267  }
268  else
269  {
270  for(k = 0; k < nfft; k++)
271  ppsd[k] /= fs * wn * (double)cnt;
272  }
273 
274 
275 exit_label:
276  if(pdgr)
277  free(pdgr);
278  if(tmp)
279  free(tmp);
280  if(w)
281  free(w);
282  if(ptr_fft && (ptr_fft != pfft))
283  {
284  fft_free(ptr_fft);
285  free(ptr_fft);
286  }
287  return err;
288 }
289 
int window(double *w, int n, int win_type, double param)
Расчет функции оконного взвешивания
Definition: win.c:329
#define RE(x)
Макрос определяющий реальную часть комплексного числа.
Definition: dspl.h:420
int psd_welch_cmplx(complex_t *x, int n, int win_type, double win_param, int nfft, int noverlap, fft_t *pfft, double fs, int flag, double *ppsd, double *pfrq)
Непараметрическая оценка спектральной плотности мощности (СПМ) комплексного сигнала методом Уэлча.
void fft_free(fft_t *pfft)
Очистить структуру fft_t алгоритма БПФ
Definition: fft_free.c:61
Структура данных объекта быстрого преобразования Фурье
Definition: dspl.h:277
double complex_t[2]
Описание комплексного типа данных.
Definition: dspl.h:86
#define RES_OK
Функция завершилась корректно. Ошибки отсутствуют.
Definition: dspl.h:558
int linspace(double x0, double x1, int n, int type, double *x)
Функция заполняет массив линейно-нарастающими, равноотстоящими значениями от x0 до x1
Definition: linspace.c:169
#define IM(x)
Макрос определяющий мнимую часть комплексного числа.
Definition: dspl.h:478
#define ERROR_MALLOC
Ошибка динамического выделения памяти. Данная ошибка означает, что при динамическом выделении памяти ...
Definition: dspl.h:599