libdspl-2.0
Библиотека алгоритмов цифровой обработки сигналов
psd_welch.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(double* 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  double *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 = (double*) malloc(nfft * sizeof(double));
175  if(!tmp)
176  return ERROR_MALLOC;
177 
178  /* window malloc */
179  w = (double*)malloc(nfft*sizeof(double));
180  if(!w)
181  {
182  err = ERROR_MALLOC;
183  goto exit_label;
184  }
185 
186  /* create window */
187  err = window(w, nfft, win_type, win_param);
188  if(err != RES_OK)
189  goto exit_label;
190 
191  /* window normalization wn = sum(w.^2) */
192  wn = 0.0;
193  for(k = 0; k < nfft; k++)
194  wn += w[k]*w[k];
195 
196 
197  if(!pfft)
198  {
199  ptr_fft = (fft_t*)malloc(sizeof(fft_t));
200  memset(ptr_fft, 0, sizeof(fft_t));
201  }
202  else
203  ptr_fft = pfft;
204 
205 
206 
207 
208  memset(ppsd, 0, nfft * sizeof(double));
209  while(pos + nfft <= n)
210  {
211  for(k = 0; k < nfft; k++)
212  tmp[k] = x[pos+k] * w[k];
213  err = fft_mag(tmp, nfft, ptr_fft, fs,
214  flag & DSPL_FLAG_FFT_SHIFT, pdgr, NULL);
215  if(err != RES_OK)
216  goto exit_label;
217  for(k = 0; k < nfft; k++)
218  ppsd[k] += pdgr[k];
219  pos += noverlap;
220  cnt++;
221  }
222 
223  if(pos < n)
224  {
225 
226  memset(tmp ,0, nfft * sizeof(double));
227  for(k = 0; k < n - pos; k++)
228  tmp[k] = x[pos+k] * w[k];
229 
230 
231  err = fft_mag(tmp, nfft, ptr_fft, fs,
232  flag & DSPL_FLAG_FFT_SHIFT, pdgr, NULL);
233  if(err != RES_OK)
234  goto exit_label;
235 
236  for(k = 0; k < nfft; k++)
237  ppsd[k] += pdgr[k];
238 
239  cnt++;
240  }
241 
242  /* fill frequency */
243  if(pfrq)
244  {
245  if(flag & DSPL_FLAG_FFT_SHIFT)
246  if(n%2)
247  err = linspace(-fs*0.5 + fs*0.5/(double)nfft,
248  fs*0.5 - fs*0.5/(double)nfft,
249  n, DSPL_SYMMETRIC, pfrq);
250  else
251  err = linspace(-fs*0.5, fs*0.5, nfft, DSPL_PERIODIC, pfrq);
252  else
253  err = linspace(0, fs, nfft, DSPL_PERIODIC, pfrq);
254  }
255 
256  /* scale magnitude */
257  if(flag & DSPL_FLAG_LOGMAG)
258  {
259  printf("wn = %f\n", wn);
260  for(k = 0; k < nfft; k++)
261  ppsd[k] = 10.0 * log10(ppsd[k] / (fs * wn * (double)cnt));
262  }
263  else
264  {
265  for(k = 0; k < nfft; k++)
266  ppsd[k] /= fs * wn * (double)cnt;
267  }
268 
269 
270 exit_label:
271  if(pdgr)
272  free(pdgr);
273  if(tmp)
274  free(tmp);
275  if(w)
276  free(w);
277  if(ptr_fft && (ptr_fft != pfft))
278  {
279  fft_free(ptr_fft);
280  free(ptr_fft);
281  }
282  return err;
283 }
int window(double *w, int n, int win_type, double param)
Расчет функции оконного взвешивания
Definition: win.c:329
void fft_free(fft_t *pfft)
Очистить структуру fft_t алгоритма БПФ
Definition: fft_free.c:61
int psd_welch(double *x, int n, int win_type, double win_param, int nfft, int noverlap, fft_t *pfft, double fs, int flag, double *ppsd, double *pfrq)
Непараметрическая оценка спектральной плотности мощности (СПМ) вещественного сигнала методом Уэлча.
Definition: psd_welch.c:156
Структура данных объекта быстрого преобразования Фурье
Definition: dspl.h:277
#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 ERROR_MALLOC
Ошибка динамического выделения памяти. Данная ошибка означает, что при динамическом выделении памяти ...
Definition: dspl.h:599