fft.c

来自「speech signal process tools」· C语言 代码 · 共 763 行 · 第 1/2 页

C
763
字号
/* * This material contains proprietary software of Entropic Speech, Inc. * Any reproduction, distribution, or publication without the prior * written permission of Entropic Speech, Inc. is strictly prohibited. * Any public distribution of copies of this work authorized in writing by * Entropic Speech, Inc. must bear the notice * *   "Copyright (c) 1988, 1990 Entropic Speech, Inc. All rights reserved." * * Program: fft.c (FEA_SPEC version) * * This program computes FFTs from SD files to FEA_SPEC files * *  Rodney Johnson, Entropic Speech, Inc.		 *  Modified by John Shore to add various options, and remove ndrec  *  dependence; *  Modified for ESPS 3.0 by John Shore *  Revised by Shore for overlapping frames and windowing. *  Converted from SPEC to FEA_SPEC output by Rod Johnson. *  Converted from SD to FEA_SD input by David Burton */#ifndef lint    static char *sccs_id = "@(#)fft.c	3.30	7/8/96	 ESI";  #endifchar *Version = "3.30";char *Date = "7/8/96";#include <stdio.h>#include <esps/esps.h>#include <esps/unix.h>#include <esps/limits.h>#include <esps/feaspec.h>#include <esps/fea.h>#include <esps/feasd.h>#include <esps/window.h>#define ERROR_EXIT(text) {(void) fprintf(stderr, "%s: %s - exiting\n", \		ProgName, text); exit(1);}#define Fprintf (void)fprintf#define SYNTAX \USAGE("fft [-c] [-l frame_len] [-o order] [-{pr} range] [-w window_type]\n [-x debug_level] [-z] [-P param] [-S step] [-O freq. offset] sdfile specfile")#define WT_PREFIX "WT_"/* * global variables */char	*ProgName = "fft";int	debug_level = 0;		/* debug level */void	get_range();void	pr_farray();/*   * external functions */double  log10(), pow(), ceil(), sqrt();char	*get_cmd_line();void	lrange_switch();char    *eopen();void	get_rfft();void    get_fft();long	atol();#if !defined(DEC_ALPHA) && !defined(HP700)char    *calloc();char    *malloc();#endif#ifndef DEC_ALPHAchar	*strcat();#endif/* * main program */main(argc, argv)    int	    argc;    char    **argv;{    char    *param_file = NULL;	/* parameter file name */    FILE    *ifile = stdin,	/* input and output file streams */            *ofile = stdout;    struct header  		/* input and output file headers */            *ih, *oh;    char    *iname, 		/* input and output file names */	    *oname;	        struct feaspec *spec_rec;   /* record for spectral data */    struct feasd *sd_rec;       /* record for input data */    extern int            optind;    extern char            *optarg;    int     ch;    int     order;		/* order of fft */    char    *prange = NULL;	/* string for range specification (-p) */    int	    zflag = 0;		/* flag for -z (silent) option */    int     oflag = 0;		/* flag for order option */    int	    pflag = 0;		/* flag for range option */    int	    cflag = 0;		/* flag for complex option */    int	    wflag = 0;		/* flag for window option */    int     lflag = 0;		/* flag for -l frame_len option */    int	    Sflag = 0;		/* flag for -S option (step size) */    char    *window_type;	/* name of type of window to apply to data */    char    *pref_w_type;	/* window type name with added prefix */    long    i, j;    short   freq_format;    short   spec_type;    long    num_freqs;    long    frame_len = -1;	/* number of sampled data points */    long    tr_length;		/* number of points in transform */    long    hf;			/* half number of frequencies */    float   sf;    int	    actsize;		/* actual number points read */    int	    data_length;	/* actual number points transformed */    long    nframes = 1;	/* number fixed length frames to process */    float   fpow;		/* power at one frequency */    float   tot_power;		/* total power */    float   *x, *wx, *y, *wy;	/* arrays for data, windowed data, and fft */    float   scale;		/* scaling constant */    int	    more = 1;		/* flag to indicate more sampled data */    long    position;		/* current position in SD file */    long    step;		/* step size for shifting frames */    long    start = 1;    long    nan = 0;     int	    win;		/* window type code */    extern char	    *window_types[];	/* standard window type names */    int	    init_err;		/* return code from init_sd_rec */    int	    complex;		/* NO or YES for data type */    int	    in_type;		/* input data type */    int	    num_channels;	/* number of input data channels */    float   *fdata;		/* pointer to data in fea_sd record */    float_cplx	    *cdata;		/* pointer to data in fea_sd record */     double	offset;		/* frequency offset (-O option) */     int	Oflag = 0;	/* offset was specified via -O */     float	*freqs = NULL;	/* vector of freqs for freq. offset */     double	freq;    /*     * process command line options     */    while ((ch = getopt(argc, argv, "cl:o:p:r:w:x:O:P:S:z")) != EOF)        switch (ch)  {	case 'c':	    cflag++;	    break;	case 'l':	    frame_len = atoi(optarg);	    lflag++;	    break;        case 'o':            order = atoi(optarg);	    oflag++;	    break;        case 'p':         case 'r':             prange = optarg;	    pflag++;            break;	case 'w':	    window_type = optarg;	    wflag++;	    break;	case 'x':	    debug_level = atoi(optarg);	    break; 	case 'O': 	    offset = atof(optarg); 	    Oflag++; 	    break;	case 'z':	    zflag++;	    break;	case 'P':	    param_file = optarg;	    break;	case 'S':	    step = atol(optarg);	    Sflag++;	    break;        default:             SYNTAX;            break;        }/* * check number of range specifications */    if(pflag > 1){	Fprintf(stderr,		"fft: range should only be specified once - exiting.\n");	exit(1);    }/* * process file arguments */    if (optind < argc)	iname = eopen(ProgName,		      argv[optind++], "r", FT_FEA, FEA_SD, &ih, &ifile);    else    {	Fprintf(stderr, "fft: no input sampled data file specified.\n");	SYNTAX;    }    if (debug_level)	Fprintf(stderr, "Input file is %s\n", iname);/*  * check if input file is multichannel */    if ((num_channels = 	 get_fea_siz("samples", ih,(short *) NULL, (long **) NULL)) != 1)    {        Fprintf(stderr, "fft: Multichannel data not supported yet\n");	exit(1);    }/* * Check if input data is complex */    in_type = get_fea_type("samples", ih);    switch (in_type)    {    case DOUBLE:    case FLOAT:    case LONG:    case SHORT:    case BYTE:        complex = NO;        break;    case DOUBLE_CPLX:    case FLOAT_CPLX:    case LONG_CPLX:    case SHORT_CPLX:    case BYTE_CPLX:        complex = YES;        break;    default:        Fprintf(stderr, "%s: bad type code (%d) in input file header.\n",                ProgName, in_type);        exit(1);        break;    }/* * setup output fea file */    if (optind < argc)	oname = eopen(ProgName, argv[optind++], "w", NONE, NONE, &oh, &ofile);    else {	Fprintf(stderr, "%s: no output FEA_SPEC file specified.\n", ProgName);	SYNTAX;    }    if (debug_level)	Fprintf(stderr, "Output file is %s\n", oname);/* * process parameters */    if (strcmp(iname, "<stdin>") != 0)	(void) read_params(param_file, SC_CHECK_FILE, iname);    else        (void) read_params(param_file, SC_NOCOMMON, iname);    if (!oflag)	order = 	    (symtype("order") != ST_UNDEF)	    ? getsym_i("order")	    : 10;        if ((order >= 20) && !zflag)	Fprintf(stderr,		"%s: WARNING - HEY!!!, order = %ld makes for a huge transform\n",		ProgName, order);    tr_length = LROUND(pow(2.0, (double) order));    get_range(&start, &nan, &frame_len, &step, &nframes, prange, 	      pflag, lflag, Sflag, tr_length, ih, zflag);    if (!wflag)	window_type =	    (symtype("window_type") != ST_UNDEF)	    ? getsym_s("window_type")	    : "RECT";    pref_w_type = 	malloc((unsigned)(strlen(WT_PREFIX) + strlen(window_type) + 1));    spsassert(pref_w_type, "can't allocate space for window type name");    (void) strcpy(pref_w_type, WT_PREFIX);    (void) strcat(pref_w_type, window_type);    win = lin_search(window_types, pref_w_type);    spsassert(win > -1, "window type not recognized");    if (debug_level)	Fprintf(stderr, "%s: window_type = %s, win = %d\n",		ProgName, window_type, win);    if (debug_level)	Fprintf(stderr,		"%s: start = %ld, nan = %ld, order = %d, tr_length = %d\n", 		ProgName, start, nan, order, tr_length);    if (debug_level) 	Fprintf(stderr, "%s: frame size = %ld, step = %ld, nframes = %ld\n",		ProgName, frame_len, step, nframes);/* * Allocate data arrays */    x = (float *) calloc((unsigned) MAX(frame_len, tr_length), sizeof(float));    y = (float *) calloc((unsigned) MAX(frame_len, tr_length), sizeof(float));    spsassert(x != NULL && y != NULL, 	      "fft: couldn't allocate enough memory");    wx=(float *) calloc((unsigned) MAX(frame_len, tr_length), sizeof(float));     wy=(float *) calloc((unsigned) MAX(frame_len, tr_length), sizeof(float));     spsassert(wx != NULL && wy != NULL, 	      "fft: couldn't allocate enough memory");    if (start < 1)	ERROR_EXIT("can't have negative starting point");    /*     * only read as many points as length of transform     */    if ((tr_length < frame_len) && !zflag) {	Fprintf(stderr, 	    "fft: WARNING - transform length %ld less than frame length %ld\n",	    tr_length, frame_len);	Fprintf(stderr,"\t\t(framing determined by step size)\n");    }	    if ((tr_length > frame_len) && !zflag) {	Fprintf(stderr, 		"fft: WARNING - transform length (%ld) greater than frame length (%ld)\n",		tr_length, frame_len);	Fprintf(stderr,		"\t %ld zeros padded for each frame\n", tr_length-frame_len);    }    /*     * create, fill in, and write output file header     */    oh = new_header(FT_FEA);    add_source_file(oh, iname, ih);    oh->common.tag = YES;    (void) strcpy(oh->common.prog, ProgName);    (void) strcpy(oh->common.vers, Version);    (void) strcpy(oh->common.progdate, Date);    oh->variable.refer = iname;    add_comment(oh, get_cmd_line(argc, argv));    update_waves_gen(ih, oh, (float) (start + frame_len/2), (float)step);    sf = *get_genhd_d("record_freq", ih);      if (cflag)	{	  freq_format = SPFMT_ASYM_EDGE;	  spec_type = SPTYP_CPLX;	  num_freqs = tr_length + 1;	  hf = tr_length/2;	}      else if(complex) {	if (Oflag) {	  freq_format = SPFMT_ARB_FIXED;	  spec_type = SPTYP_DB;	  num_freqs = tr_length + 1;	  hf = tr_length/2;	  freqs = (float *) malloc(num_freqs * sizeof(float));	  /* DEBUG */	  if (debug_level) fprintf(stderr, "offset %g, sf %g\n", offset, sf);	  for (freq = offset - sf/2.0, i = 0; i < num_freqs; i++, freq += sf/tr_length)	    freqs[i] = freq;	} else {	  freq_format = SPFMT_ASYM_EDGE;	  spec_type = SPTYP_DB;	  num_freqs = tr_length + 1;	  hf = tr_length/2;	}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?