📄 spec.c
字号:
/**********Copyright 1994 Macquarie University, Sydney Australia. All rights reserved.Author: 1994 Anthony E. Parker, Department of Electronics, Macquarie Uni.$Id: spec.c,v 1.5 2005/05/30 20:28:30 sjborley Exp $**********//* * Code to do fourier transforms on data. */#include "ngspice.h"#include "ftedefs.h"#include "dvec.h"#include "sim.h"#include "spec.h"#include "variable.h"voidcom_spec(wordlist *wl){ complex **fdvec; double **tdvec; double *freq, *win, *time, *dc; double startf, stopf, stepf, span; int fpts, i, j, k, tlen, ngood; bool trace; char *s; struct dvec *f, *vlist, *lv = NULL, *vec; struct pnode *names, *first_name; if (!plot_cur || !plot_cur->pl_scale) { fprintf(cp_err, "Error: no vectors loaded.\n"); return; } if (!isreal(plot_cur->pl_scale) || ((plot_cur->pl_scale)->v_type != SV_TIME)) { fprintf(cp_err, "Error: spec needs real time scale\n"); return; } s = wl->wl_word; tlen = (plot_cur->pl_scale)->v_length; if (!(freq = ft_numparse(&s, FALSE)) || (*freq < 0.0)) { fprintf(cp_err, "Error: bad start freq %s\n", wl->wl_word); return; } startf = *freq; wl = wl->wl_next; s = wl->wl_word; if (!(freq = ft_numparse(&s, FALSE)) || (*freq <= startf)) { fprintf(cp_err, "Error: bad stop freq %s\n", wl->wl_word); return; } stopf = *freq; wl = wl->wl_next; s = wl->wl_word; if (!(freq = ft_numparse(&s, FALSE)) || !(*freq <= (stopf-startf))) { fprintf(cp_err, "Error: bad step freq %s\n", wl->wl_word); return; } stepf = *freq; wl = wl->wl_next; time = (plot_cur->pl_scale)->v_realdata; span = time[tlen-1] - time[0]; if (stopf > 0.5*tlen/span) { fprintf(cp_err, "Error: nyquist limit exceeded, try stop freq less than %e Hz\n", tlen/2/span); return; } span = ((int)(span*stepf*1.000000000001))/stepf; if (span > 0) { startf = (int)(startf/stepf*1.000000000001) * stepf; fpts = (stopf - startf)/stepf + 1; if (stopf > startf + (fpts-1)*stepf) fpts++; } else { fprintf(cp_err,"Error: time span limits step freq to %1.1e Hz\n", 1/(time[tlen-1] - time[0])); return; } win = (double *) tmalloc(tlen * sizeof (double)); { char window[BSIZE_SP]; double maxt = time[tlen-1]; if (!cp_getvar("specwindow", VT_STRING, window)) strcpy(window,"hanning"); if (eq(window, "none")) for(i=0; i<tlen; i++) { win[i] = 1; } else if (eq(window, "rectangular")) for(i=0; i<tlen; i++) { if (maxt-time[i] > span) { win[i] = 0; } else { win[i] = 1; } } else if (eq(window, "hanning") || eq(window, "cosine")) for(i=0; i<tlen; i++) { if (maxt-time[i] > span) { win[i] = 0; } else { win[i] = 1 - cos(2*M_PI*(time[i]-maxt)/span); } } else if (eq(window, "hamming")) for(i=0; i<tlen; i++) { if (maxt-time[i] > span) { win[i] = 0; } else { win[i] = 1 - 0.92/1.08*cos(2*M_PI*(time[i]-maxt)/span); } } else if (eq(window, "triangle") || eq(window, "bartlet")) for(i=0; i<tlen; i++) { if (maxt-time[i] > span) { win[i] = 0; } else { win[i] = 2 - fabs(2+4*(time[i]-maxt)/span); } } else if (eq(window, "blackman")) { int order; if (!cp_getvar("specwindoworder", VT_NUM, &order)) order = 2; if (order < 2) order = 2; /* only order 2 supported here */ for(i=0; i<tlen; i++) { if (maxt-time[i] > span) { win[i] = 0; } else { win[i] = 1; win[i] -= 0.50/0.42*cos(2*M_PI*(time[i]-maxt)/span); win[i] += 0.08/0.42*cos(4*M_PI*(time[i]-maxt)/span); } } } else if (eq(window, "gaussian")) { int order; double scale; if (!cp_getvar("specwindoworder", VT_NUM, &order)) order = 2; if (order < 2) order = 2; scale = pow(2*M_PI/order,0.5)*(0.5-erfc(pow(order,0.5))); for(i=0; i<tlen; i++) { if (maxt-time[i] > span) { win[i] = 0; } else { win[i] = exp(-0.5*order*(1-2*(maxt-time[i])/span) *(1-2*(maxt-time[i])/span))/scale; } } } else { fprintf(cp_err, "Warning: unknown window type %s\n", window); tfree(win); return; } } names = ft_getpnames(wl, TRUE); first_name = names; vlist = NULL; ngood = 0; while (names) { vec = ft_evaluate(names); names = names->pn_next; while (vec) { if (vec->v_length != tlen) { fprintf(cp_err, "Error: lengths don't match: %d, %d\n", vec->v_length, tlen); vec = vec->v_link2; continue; } if (!isreal(vec)) { fprintf(cp_err, "Error: %s isn't real!\n", vec->v_name); vec = vec->v_link2; continue; } if (vec->v_type == SV_TIME) { vec = vec->v_link2; continue; } if (!vlist) vlist = vec; else lv->v_link2 = vec; lv = vec; vec = vec->v_link2; ngood++; } } free_pnode(first_name); if (!ngood) { tfree(win); return; } plot_cur = plot_alloc("spectrum"); plot_cur->pl_next = plot_list; plot_list = plot_cur; plot_cur->pl_title = copy((plot_cur->pl_next)->pl_title); plot_cur->pl_name = copy("Spectrum"); plot_cur->pl_date = copy(datestring( )); freq = (double *) tmalloc(fpts * sizeof(double)); f = alloc(struct dvec); ZERO(f, struct dvec); f->v_name = copy("frequency"); f->v_type = SV_FREQUENCY; f->v_flags = (VF_REAL | VF_PERMANENT | VF_PRINT); f->v_length = fpts; f->v_realdata = freq; vec_new(f); tdvec = (double **) tmalloc(ngood * sizeof(double *)); fdvec = (complex **) tmalloc(ngood * sizeof(complex *)); for (i = 0, vec = vlist; i<ngood; i++) { tdvec[i] = vec->v_realdata; fdvec[i] = (complex *) tmalloc(fpts * sizeof(complex)); f = alloc(struct dvec); ZERO(f, struct dvec); f->v_name = vec_basename(vec); f->v_type = vec->v_type; f->v_flags = (VF_COMPLEX | VF_PERMANENT); f->v_length = fpts; f->v_compdata = fdvec[i]; vec_new(f); vec = vec->v_link2; } dc = (double *) tmalloc(ngood * sizeof(double)); for (i = 0; i<ngood; i++) { dc[i] = 0; } for (k = 1; k<tlen; k++) { double amp = win[k]/(tlen-1); for (i = 0; i<ngood; i++) { dc[i] += tdvec[i][k]*amp; } } cp_getvar("spectrace", VT_BOOL, &trace); for (j = (startf==0 ? 1 : 0); j<fpts; j++) { freq[j] = startf + j*stepf; if(trace) fprintf(cp_err, "spec: %e Hz: \r",freq[j]); for (i = 0; i<ngood; i++) { fdvec[i][j].cx_real = 0; fdvec[i][j].cx_imag = 0; } for (k = 1; k<tlen; k++) { double amp = 2*win[k]/(tlen-1), rad = 2*M_PI*time[k]*freq[j], cosa = amp*cos(rad), sina = amp*sin(rad); for (i = 0; i<ngood; i++) { double value = tdvec[i][k]-dc[i]; fdvec[i][j].cx_real += value*cosa; fdvec[i][j].cx_imag += value*sina; } } } if (startf==0) { freq[0] = 0; for (i = 0; i<ngood; i++) { fdvec[i][0].cx_real = dc[i]; fdvec[i][0].cx_imag = 0; } } if(trace) fprintf(cp_err, " \r"); tfree(dc); tfree(tdvec); tfree(fdvec);#ifdef KEEPWINDOW f = alloc(struct dvec); ZERO(f, struct dvec); f->v_name = copy("win"); f->v_type = SV_NOTYPE; f->v_flags = (VF_REAL | VF_PERMANENT); f->v_length = tlen; f->v_realdata = win; vec_new(f);#else tfree(win);#endif return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -