fftinv.c

来自「speech signal process tools」· C语言 代码 · 共 409 行

C
409
字号
/* * 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) 1987 Entropic Speech, Inc.; All rights reserved" * * Program: fftinv.c	 * * Written by:  John Shore * Checked by: * * This program computes inverse FFTs from FEA_SPEC files to SD files */#ifndef lintstatic char *sccs_id = "@(#)fftinv.c	1.13	8/31/95 ESI";  #endifchar *Version = "1.13";char *Date = "8/31/95";char *ProgName = "fftinv";#include <stdio.h>#include <esps/esps.h>#include <esps/unix.h>#include <esps/feasd.h>#include <esps/feaspec.h>#include <esps/fea.h>#define ERROR_EXIT(text) {(void) fprintf(stderr, "%s: %s - exiting\n", \		ProgName, text); exit(1);}#define REQUIRE(test,text) {if (!(test)) {(void) fprintf(stderr, \"%s: %s - exiting\n", ProgName, text); exit(1);}}#define SYNTAX \ USAGE("fftinv [-r range] [-t output_type] [-x debug_level] specfile sdfile")/* Globals*/int	    debug_level = 0;		/* debug level *//* * system functions */double  log(), sqrt();/* * ESPS library functions */void	set_sd_type();char	*eopen();char	*get_cmd_line();void	lrange_switch(), get_fft_inv();void    update_waves_gen();struct feasd  *allo_feasd_recs();int	is_type_complex();/* * local functions */static int is_type_numeric();/* * main program */main(argc, argv)    int  argc;    char **argv;{    FILE    *specstrm = stdin,	/* input and output file streams */            *sdstrm = stdout;    struct header  		/* input and output file headers */            *ih, *oh;    char    *specfile, 		/* input and output file names */	    *sdfile;	        struct feaspec  *spec_rec;   /* record for spectral data */    struct feasd    *sd_rec;     /* record for feasd data */    extern int	    optind;    extern char            *optarg;    int	    c;    long    srec, erec;		/* start and end records */    double  log2 = log(2.0);	/* needed for base 2 logs */    char    *range = NULL;	/* string for range specification (-r) */    int	    r_flag = 0;		/* flag for range option */    float   *x, *y;		/* arrays for get_fftinv */    float   scale;		/* scale factor from continuous to discrete */    long    nan, hf, j;    long    length;		/* transform length */    int	    order;    float   *fdata;		/* pointer to real data in feasd record */    float_cplx	    *cdata;		/* pointer to complex data in feasd record */    long    *frame_len;		/* pointer to frame length */    double  record_freq;	/* record_freq header item in input */    double  sf;			/* sample frequency in original sampled data */    double  start_time;         /* start time of beginning of first frame */    int	    t_flag = NO;	/* -t option specified? */    char    *output_type;	/* name of output data type */    int	    type = FLOAT_CPLX;	/* type code for output data type */    int	    real = NO;          /* YES for real inverse Xform; NO for complex */    /*     * process command line options     */    while ((c = getopt(argc, argv, "r:t:x:")) != EOF)        switch (c)            {	case 'x':	    debug_level = atoi(optarg);	    break;        case 'r':             range = optarg;	    r_flag++;            break;	case 't':	    output_type = optarg;	    t_flag++;	    break;        default:             SYNTAX;            break;        }    srec = 1;    erec = LONG_MAX;    if (r_flag) 	lrange_switch (range, &srec, &erec, 1);	    if (srec < 1)	ERROR_EXIT("can't have negative starting point");    if (srec > erec)	ERROR_EXIT("range must specify at least one record");    nan = erec - srec + 1;    if (debug_level) 	Fprintf(stderr, "fftinv: range is %ld - %ld\n", srec, erec);    /*     * process file arguments - first, input file     */    if (optind < argc)	specfile = 	   eopen("fftinv", argv[optind++], "r", FT_FEA, FEA_SPEC, &ih, &specstrm);    else {	Fprintf(stderr, "fft: no input FEA_SPEC file specified.\n");	SYNTAX;    }        if (debug_level)	Fprintf(stderr, "Input file is %s\n", specfile);    if (t_flag)    {	type = lin_search(type_codes, output_type);	if (!is_type_numeric(type))	{	    Fprintf(stderr,	    	    "fftinv: invalid output type %s\n", output_type);	    exit(1);	}    }    else if (genhd_type("input_data", (int *) NULL, ih) == CHAR	     && strcmp(get_genhd_c("input_data", ih), "real") == 0)	type = FLOAT;    else	type = FLOAT_CPLX;    /*     * allocate spectral record     */    spec_rec = allo_feaspec_rec(ih, FLOAT);     /*     * set up output file     */    if (optind < argc)	sdfile = 	    eopen("fftinv", argv[optind++], "w", NONE, NONE, &oh, &sdstrm);    else {	Fprintf(stderr, "fftinv: no output SD file specified.\n");	SYNTAX;    }    if (debug_level)	Fprintf(stderr, "Output file is %s\n", sdfile);    REQUIRE(genhd_type("spec_type", (int *) NULL, ih) == CODED,           "Header item \"spec_type\" undefined or wrong type");    if (*get_genhd_s("spec_type", ih) != SPTYP_CPLX) 	ERROR_EXIT("FEA_SPEC file spec_type is not complex (SPTYP_CPLX)");    REQUIRE(genhd_type("freq_format", (int *) NULL, ih) == CODED,           "Header item \"spec_type\" undefined or wrong type");    if (*get_genhd_s("freq_format", ih) != SPFMT_ASYM_EDGE) 	ERROR_EXIT("FEA_SPEC file freq_format is not SPTYP_ASYM_EDGE");    length = *get_genhd_l("num_freqs", ih) - 1;    hf = length / 2;    order = ROUND(log((double) length) / log2);    if (debug_level) 	Fprintf(stderr, 	    "fftinv: transform length = %ld, order = %ld, num_freqs = %ld\n", 	    length, order, *get_genhd_l("num_freqs", ih));    if (genhd_type("fft_length", (int *) NULL, ih) != HD_UNDEF)    {	if (get_genhd_val("fft_length", ih, -1.0) != (double) length)	    Fprintf(stderr,		"%s: fft_length + 1 not equal to num_freqs.\n",		ProgName);    }    x = (float *) calloc((unsigned) length, sizeof(float));    y = (float *) calloc((unsigned) length, sizeof(float));    spsassert(x != NULL && y != NULL, 	"fftinv: couldn't allocate enough memory");    /*     * create and fill in FEA_SD file header     */    oh = new_header(FT_FEA);    add_source_file(oh, specfile, ih);    add_comment(oh, get_cmd_line(argc, argv));    oh->common.tag = NO;    oh->variable.refer = ih->variable.refer;    (void) strcpy(oh->common.prog, ProgName);    (void) strcpy(oh->common.vers, Version);    (void) strcpy(oh->common.progdate, Date);    *add_genhd_l("inv_fft_length", (long *) NULL, 1, oh) = length;    /*     * compute frequency and start_time generics     */    sf = get_genhd_val("sf", ih, 8000.0);    REQUIRE(genhd_type("frame_meth", (int *) NULL, ih) == CODED,	    "Header item \"frame_meth\" undefined or wrong type");    switch (*get_genhd_s("frame_meth", ih))    {    case SPFRM_FIXED:    case SPFRM_VARIABLE:	frame_len = spec_rec->frame_len;	break;    case SPFRM_NONE:	/* Frame length not available.	   Use transform length for lack of anything better. */	frame_len = &length;	break;    default:	REQUIRE(NO, "Unrecognized value of \"frame_meth\" in input header");	break;    }    /* read record for length of first frame */    REQUIRE(get_feaspec_rec(spec_rec, ih, specstrm) != EOF,	    "Can't get first record of input file");    start_time = 	get_genhd_val("start_time", ih, 0.0)	- (double) (*frame_len)/(2*sf);    record_freq = get_genhd_val("record_freq", ih, 0.0);    if (record_freq != 0.0)	start_time += (srec - 1)/record_freq;        /* move to starting position */    if (srec > 1)    {	if (srec > 2)	    fea_skiprec(specstrm, srec - 2, ih);	REQUIRE(get_feaspec_rec(spec_rec, ih, specstrm) != EOF,		"Can't get first input record of specified range");    }    nan--;    /*     * initialize FEA_SD header, allocate data structures,     * and write output file header     */    real = !is_type_complex(type);    REQUIRE(init_feasd_hd(oh, type, 1, &start_time, NO, sf) == 0,	    "Couldn't initialize output FEA_SD header");    sd_rec = allo_feasd_recs(oh, type, length, (char *) NULL, NO);    REQUIRE(sd_rec != NULL, "Couldn't allocate FEA_SD data record");    if (type == FLOAT_CPLX)	cdata = (float_cplx *) sd_rec->data;    else if (!real)	cdata = (float_cplx *) malloc(length * sizeof(float_cplx));	    write_header(oh, sdstrm);    /*     * main loop     */    do    {	long	frmlen = *frame_len;	if (debug_level) Fprintf(stderr, "fftinv: frame %ld\n", srec++);	if (debug_level > 1) {	    Fprintf(stderr, 		"fftinv: real and imag components in spectral record:\n");	    for (j = 0; j < length + 1; j++) 		Fprintf(stderr, "%f\t%f\n", 		    spec_rec->re_spec_val[j], spec_rec->im_spec_val[j]);	}		/*	 * compute factor to get from continuous density to discrete	 * spectral distribution	 */	scale = sqrt(frmlen * sf);	/*	 * reorder spectral components to get_fftinv order	 * remember that ASYM_EDGE stores frequencies (-hf, ..., 0, ..., hf),	 * hf = length / 2	 */	for (j = 0; j < length; j++) {	    if (j < hf) {		    x[j] = scale * spec_rec->re_spec_val[j + hf];		    y[j] = scale * spec_rec->im_spec_val[j + hf];		}	    else {		    x[j] = scale * spec_rec->re_spec_val[j - hf];		    y[j] = scale * spec_rec->im_spec_val[j - hf];	    }	}	if (debug_level > 1) {	    Fprintf(stderr, 		"fftinv: real and imag spectral components input to get_fftinv:\n");	    for (j = 0; j < length; j++) 		Fprintf(stderr, "%f\t%f\n", x[j], y[j]);	}		/* do inverse fft */	get_fft_inv(x, y, order);	if (debug_level > 1) {	    Fprintf(stderr, "fftinv: sampled data output from get_fft_inv:\n");	    for (j = 0; j < length; j++) 		Fprintf(stderr, "%f\n", x[j]);	}	/* pack the data into the output record */	if (real)	    type_convert(frmlen, (char *) x, FLOAT,			 (char *) sd_rec->data, type, (void (*)()) NULL);	else	{	    for(j = 0; j < frmlen; j++)	    {		cdata[j].real = x[j];	  		cdata[j].imag = y[j];	    }	    if (type != FLOAT_CPLX)		type_convert(frmlen, (char *) cdata, FLOAT_CPLX,			     (char *) sd_rec->data, type, (void (*)()) NULL);	}	REQUIRE((put_feasd_recs(sd_rec, 0L, frmlen, oh, sdstrm) == 0),	 "Couldn't write output record");    } while (nan-- && get_feaspec_rec(spec_rec, ih, specstrm) != EOF);    exit(0);    /*NOTREACHED*/}static intis_type_numeric(type)    int	    type;{    switch (type)    {    case BYTE:    case SHORT:    case LONG:    case FLOAT:    case DOUBLE:    case BYTE_CPLX:    case SHORT_CPLX:    case LONG_CPLX:    case FLOAT_CPLX:    case DOUBLE_CPLX:        return YES;    default:        return NO;    }}

⌨️ 快捷键说明

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