📄 xspectrum.c
字号:
/* * This material contains unpublished, proprietary software of * Entropic Research Laboratory, Inc. Any reproduction, distribution, * or publication of this work must be authorized in writing by Entropic * Research Laboratory, Inc., and must bear the notice: * * "Copyright (c) 1987-1990 AT&T, Inc. * "Copyright (c) 1986-1990 Entropic Speech, Inc. * "Copyright (c) 1990-1996 Entropic Research Laboratory, Inc. * All rights reserved" * * The copyright notice above does not evidence any actual or intended * publication of this source code. * * Written by: David Talkin, ATT * Checked by: * Revised by: Rod Johnson, John Shore, Alan Parker, David Talkin ERL * * FURTHER MODIFIED BY: * LEE HETHERINGTON, MIT-LCS-SLS * * Modified a LOT MORE by: * David Talkin, ERL * * xspectrum.c * a spectrum analysis and inverse filter attachment for "xwaves" */static char *sccs_id = "@(#)xspectrum.c 1.37 1/18/97 ATT/ESI/ERL";/* This program, apart from providing some useful functions, serves as a reasonably well documented example of an attachment for the "xwaves" program. See $WAVES_DOC/attachments.help for a general discussion. Spectrum computes and displays log magnitude spectra (of time series and inverse LPC models). Optionally, a reference spectrum may be saved for comparison purposes and the (possibly integrated) residual resulting from the application of an inverse LPC model may be computed and displayed (see the section on "spectrum" in $WAVES_DOC/attachments.help). */#include <stdio.h> #include <xview/font.h>#if !defined(APOLLO_68K) && !defined(DS3100)#include <malloc.h>#endif#include <xview/notice.h>#include <esps/esps.h>#include <esps/unix.h>#include <esps/ana_methods.h>#include <esps/window.h>#include <esps/fea.h>#include <sys/param.h>#include <Objects.h>#include <esps/exview.h>#define _NO_PROTO#include <Xp.h>#include <Xp_pw.h>#include <xprint_util.h>/* display scale types */#define SCALE_DB 0#define SCALE_MAG 1#define SCALE_PWR 2/* max number of (current & reference) traces */#define TRACE_MAX 5/* max number of vertical (harmonic) cursors */#define X_CURS_MAX 20/* max number of horizontal (current & reference) cursors */#define Y_CURS_MAX TRACE_MAX#define NOT_SET -1e-30int debug_level = 0;int command_paused = 0; /* referenced in globals.c */int use_dsp32, da_location = 0;extern int w_verbose; extern int fea_sd_special;double image_clip = 7.0, image_range = 40.0;double range_db = 200.0, reference_level = 0.0;extern char *Version;static int fft_tablesize = 1048576; /* limit to avoid excessive comp. times */static char *wave_pro = ".wave_pro"; /* .wave_pro file name from command line */#define MAX_LPC_ORDER 200#ifdef STARDENT_3000extern char WAVES_MISC[];#endifchar *savestring();Signal *get_any_signal();/* see copheader.c, signal.c and read_data.c *//*global font declarations*/Xv_Font def_font;int def_font_height, def_font_width;/* These globals are a means of control via the .wave_pro */int xsp_datwin_height = -1; /* initial height of xspectrum plot window */int xsp_datwin_width = -1; /* initial width of xspectrum plot window */int xsp_datwin_y = -1; /* initial Y pos of (1st ob) xspectrum plot window */int xsp_datwin_x = -1; /* initial X pos of (1st ob) xspectrum plot window */int xsp_ctlwin_y = -1; /* initial Y pos of xspectrum control window */int xsp_ctlwin_x = -1; /* initial X pos of xspectrum control window */int xsp_datwin_forw = 1; /* bring plot window forward on new plot; 0: don't*/int xsp_max_lpc_order = 200; /* maximum permitted LPC order */extern int print_graphic_printer;extern int print_graphic_resolution;extern char print_graphic_orientation[];extern char print_graphic_type[];extern char print_graphic_file[];extern char print_graphic_command[];extern double print_graphic_scale;/* Other globals */ static double m_time, rstart, rend, sec_cm, start; static int color, width, height, loc_x, loc_y; static char name[NAMELEN], file[NAMELEN], signame[NAMELEN];/* +++++++ Global analysis parameters. +++++++ */double w_size = .025, /* window duration in sec. */ preemp = .0, /* H(z) = 1 - preemp*z^(-1); preemphasis */ i_f_dur = .05, /* duration of segment to inverse filter */ i_f_int = .99; /* integrator for residual */int scale_type = SCALE_DB, /* scaling for display */ weight_type = 3, /* temporal weighting type (3 = Hanning) */ /* given that default func is dft */ order = 14, /* order of analysis for LPC, etc. */ do_region = 0, /* initialize with window limits set locally */ reticle_on = 1, /* initialize reticle to be on */ hcurs_on = 0, /* initialize harmonic cursors to be off */ horiz_c_on = 1, /* horizontal (ampl.) cursors */ f_autozoom = 1, /* auto. zoom freq. if markers are changed */ a_autozoom = 1, /* auto. zoom ampl. if markers are changed */ fb_flag = 0, /* initialize formant/bandwidth printing off */ def_fft_size = 128, def_order = 7;int current_analysis_type = 0; /* default: number of log_mag_dft *//* MIT */double cep_cutoff = 0.006, cep_trans = .008;int cep_liftering = 1; /* no liftering, 1 = lowpass, 2 = highpass */static Selector g72 = {"xspectrum_max_lpc_order", "%d", (char *) &xsp_max_lpc_order,NULL}, g71 = {"xspectrum_datwin_forward", "%d", (char *) &xsp_datwin_forw, &g72}, g68 = {"xspectrum_datwin_height", "%d", (char *) &xsp_datwin_height, &g71}, g67 = {"xspectrum_datwin_width", "%d", (char *) &xsp_datwin_width, &g68}, g66 = {"xspectrum_datwin_y", "%d", (char *) &xsp_datwin_y, &g67}, g65 = {"xspectrum_datwin_x", "%d", (char *) &xsp_datwin_x, &g66}, g64 = {"xspectrum_ctlwin_y", "%d", (char *) &xsp_ctlwin_y, &g65}, g63 = {"xspectrum_ctlwin_x", "%d", (char *) &xsp_ctlwin_x, &g64}, gg15 = {"xspectrum_cep_liftering", "%d", (char*)&cep_liftering, &g63}, gg14b = {"xspectrum_cep_trans", "%lf", (char*)&cep_trans, &gg15}, gg14 = {"xspectrum_cep_cutoff", "%lf", (char*)&cep_cutoff, &gg14b}, gg13 = {"xspectrum_window_type", "%d", (char*)&weight_type, &gg14}, gg11 = {"xspectrum_lpc_order", "%d", (char*)&order, &gg13}, gg10 = {"xspectrum_window_size", "%lf", (char*)&w_size, &gg11}, gg9 = {"xspectrum_inv_filt_dur", "%lf", (char*)&i_f_dur, &gg10}, gg8 = {"xspectrum_inv_filt_integ", "%lf", (char*)&i_f_int, &gg9}, gg7 = {"xspectrum_preemp", "%lf", (char*)&preemp, &gg8}, gg6 = {"xspectrum_analysis_type", "%d", (char*)¤t_analysis_type, &gg7}, gg5e = {"xspectrum_reference_level", "%lf", (char*)&reference_level, &gg6}, gg5d = {"xspectrum_range_db", "%lf", (char*)&range_db, &gg5e}, gg5c = {"xspectrum_max_fft_size", "%d", (char*)&fft_tablesize, &gg5d}, gg5 = {"xspectrum_formants", "%d", (char*)&fb_flag, &gg5c}, gg4b = {"xspectrum_horiz_cursors", "%d", (char*)&horiz_c_on, &gg5}, gg4 = {"xspectrum_reticle", "%d", (char*)&reticle_on, &gg4b}, gg3 = {"xspectrum_plot_scale", "%d", (char*)&scale_type, &gg4}, gg2c = {"xspectrum_a_autozoom", "%d", (char*)&a_autozoom, &gg3}, gg2b = {"xspectrum_f_autozoom", "%d", (char*)&f_autozoom, &gg2c}, gg2 = {"xspectrum_harmonic_cursors", "%d", (char*)&hcurs_on, &gg2b}, g1 = {"xspectrum_window_limits", "%d", (char*)&do_region, &gg2}, /* The duplicate forms below are retained for backwards compatibility. */ g15 = {"cep_liftering", "%d", (char*)&cep_liftering, &g1}, g14 = {"cep_cutoff", "%lf", (char*)&cep_cutoff, &g15}, g13 = {"window_type", "%d", (char*)&weight_type, &g14}, g11 = {"lpc_order", "%d", (char*)&order, &g13}, g10 = {"window_size", "%lf", (char*)&w_size, &g11}, g9 = {"inv_filt_dur", "%lf", (char*)&i_f_dur, &g10}, g8 = {"inv_filt_integ", "%lf", (char*)&i_f_int, &g9}, g7 = {"preemp", "%lf", (char*)&preemp, &g8}, g6 = {"analysis_type", "%d", (char*)¤t_analysis_type, &g7}, g5d = {"range_db", "%lf", (char*)&range_db, &g6}, g5c = {"max_fft_size", "%d", (char*)&fft_tablesize, &g5d}, g5 = {"formants", "%d", (char*)&fb_flag, &g5c}, g4b = {"horiz_cursors", "%d", (char*)&horiz_c_on, &g5}, g4 = {"reticle", "%d", (char*)&reticle_on, &g4b}, g3 = {"plot_scale", "%d", (char*)&scale_type, &g4}, g2c = {"a_autozoom", "%d", (char*)&a_autozoom, &g3}, g2b = {"f_autozoom", "%d", (char*)&f_autozoom, &g2c}, g2 = {"harmonic_cursors", "%d", (char*)&hcurs_on, &g2b}, gg1 = {"window_limits", "%d", (char*)&do_region, &g2}; /* This selector list specifies all keywords to be recognized for the make and mark commands. */ static Selector a9 = {"sec/cm", "%lf", (char*)&sec_cm, NULL}, a8 = {"start", "%lf", (char*)&start, &a9}, a7 = {"width", "%d", (char*)&width, &a8}, a6 = {"height", "%d", (char*)&height, &a7}, a5 = {"loc_y", "%d", (char*)&loc_y, &a6}, a4 = {"loc_x", "%d", (char*)&loc_x, &a5}, a3 = {"color", "%d", (char*)&color, &a4}, a2c = {"rstart", "%lf", (char*)&rstart, &a3}, a2b = {"rend", "%lf", (char*)&rend, &a2c}, a2 = {"time", "%lf", (char*)&m_time, &a2b}, a1 = {"name", "#qstr", name, &a2}, a0b = {"signal", "#qstr", file, &a1}, a0 = {"file", "#qstr", file, &a0b};/* This "Objects" structure can be defined as you like. It should have at least "name," "next" and "methods" fields. */typedef struct { int n; /* number of data elements */ double *data; /* spectral amplitude data pointer */ double *freqs; /* NULL or n freq values */ double band_low, /* lower frequency limit of data */ band; /* width of data frequency band */ int scale_type; /* DB, MAG, or PWR? */} Trace;typedef struct objects { char *name; /* the (ASCII) name of the object */ Canvas view; /* a display handle */ Methods *methods; /* a list of things this object can do */ Signal *sig; /* the Signal being analyzed */ Trace *trace[TRACE_MAX]; /* spectral traces ([0] current, [1]... ref) */ int trace_num; double data2[300]; /* LPC coefficients, if any */ Reticle *ret; /* reticle definition for the display */ int vers; /* i.f. segment name distinguisher */ int init_located; /* Has been positioned relative to host sig. */ double xhigh, xlow; /* frequency display limits */ double yhigh, ylow; /* amplitude display limits */ int x_off, y_off, xloc, yloc, width, height; /* etc., etc. */ double sec_cm, start, time; double l_marker, r_marker, /* freq. and ampl. markers */ t_marker, b_marker; double cursorx[X_CURS_MAX], cursory[Y_CURS_MAX]; int x_curs_num, y_curs_num; int current_harmonic; int first_display; struct objects *next; /* linkage to next list member */} Objects;Trace *new_trace();Objects *objlist = NULL; /* head of the list of objects to receive commands */Notify_value destroy_func();Notify_value sigint_func();Notify_value sigtrm_func();Notify_value sigbus_func();Notify_value sigfpe_func();Notify_value sigill_func();Notify_value sigseg_func();Menu menu, make_menu();/* declarations for menu callback functions */static void e_ref_save(), e_inv_filt(), e_clear_traces(), e_zoom_out(), e_bracket_markers(), e_clear_non_ref_traces(), e_set_ref_level(), e_print_graphic();static void print_EPS_temp();char *Ok="ok", *Null="null";/*********************************************************************//* Here are the definitions of items which appear in the control panel: */Panel panel;Frame frame;Frame daddy = XV_NULL; /* this global is used by some common routines */Panel_item newFunct_item, order_item, reticle_item, weightType_item, wsize_item, fb_item, limits_item, preemp_item, hcurs_item, horiz_c_item, fsize_item, scale_item, int_c_item, man_item, quit_item;/* MIT */Panel_item cep_trans_item, cep_cutoff_item, cep_liftering_item;/* Here are some procedures invoked by manipulating the panel items: */void quit_proc(), double_proc(), int_proc(), newFunction(), newWindType();int exv_get_help();/* available analysis functions */int log_mag_dft(), log_mag_dftr(), use_sig_data();int esps_compute_spect();/* MIT */int log_cepstrally_smoothed();/* a structure for relating function names to program entry points */typedef struct funlist { char *name; int (*funct)(); int esps_method; struct funlist *next;} Funlist;/* In the following, the original LPC autocorrelation and covariance methods (DFT-LPC and DFT-CLPS) have been removed, with their functions taken over withing the ESPS compute_rc(). Also, the latter were easier to generalize for non-SHORT input *//* Enter any new functions you want to add here (and in main()). fun0 should remain at the head of the list. */Funlist fun12 = {"data-from-signal", use_sig_data, AM_NONE, NULL}, fun13 = {"CEPST", log_cepstrally_smoothed, AM_NONE, &fun12}, fun11 = {"STRCOV1", esps_compute_spect, AM_STRCOV1, &fun13}, fun10 = {"STRCOV", esps_compute_spect, AM_STRCOV, &fun11}, fun9 = {"VBURG", esps_compute_spect, AM_VBURG, &fun10}, fun8 = {"FBURG", esps_compute_spect, AM_FBURG, &fun9}, fun7 = {"MBURG", esps_compute_spect, AM_MBURG, &fun8}, fun6 = {"BURG", esps_compute_spect, AM_BURG, &fun7}, fun5 = {"COV", esps_compute_spect, AM_COV, &fun6}, fun4 = {"AUTOC", esps_compute_spect, AM_AUTOC, &fun5}, fun1 = {"DFTR", log_mag_dftr, AM_NONE, &fun4}, fun0 = {"DFT", log_mag_dft, AM_NONE, &fun1};/* We make the default window (weight) type to be Hanning for DFT, DFTR, AUTOC, and COV, but rectangular for all other (Burg and maxent) analysis methods; however, we reset the default each time a weight_type is changed -- thus, user settings are "sticky" with respect to analysis type. */int def_weight_type[11] = {3,3,3,3,0,0,0,0,0,0,3};/* generic spectral analysis function pointer function(ob); sets up ob->trace for plotting; uses global parameters. */int (*function)() = log_mag_dft; /* init. value should match panel item */int esps_spect_method = AM_NONE; #define SYNTAX USAGE("xspectrum [-w wave_pro] [-n<waves or other host program>] [-c<registry name of host>] ");char *host = "waves", *thisprog = "xspectrum";/*********************************************************************/doing_cepstral_smoothing(){ return(function == log_cepstrally_smoothed);}/*********************************************************************/intdo_function(ob) Objects *ob;{ return ((ob->sig->type & SPECIAL_SIGNALS) == SIG_SPECTROGRAM && use_sig_data(ob)) || (*function)(ob);}/*********************************************************************//* The interface routines get_receiver_name(), get_methods() and get_receiver()give the message library access to your locally-defined "Objects." Theroutine make_new_object() must exist, but may simply return NULL.Alternately, make_new_object() can try to create an object based on thefirst (blank- or newline-separated) string in the character array whichis pointed to by its argument. *//*********************************************************************//* Return a pointer to the name of the object. */char *get_receiver_name(ob) Objects *ob;{ return(ob->name);}/*********************************************************************//* Return the head of the methods list for the object. */char *get_methods(ob) Objects *ob;{ extern Methods base_methods; if(ob) return((char*)(ob->methods)); return((char*)&base_methods); /* assumes the program's methods are wanted */}/*********************************************************************/window_wash(handle) caddr_t handle;{ if (handle) return; fprintf(stderr, "Can't create window---exiting.\n"); fprintf(stdout,"Can't create window---exiting.\n"); /* Clean up before exiting. */ cleanup(); kill_proc();}/*********************************************************************//* Return a pointer to the object whose name (str) is specified. */char *get_receiver(str) char *str;{ Objects *ob; static char name[50]; ob = objlist; if(str && strlen(str)) { sscanf(str,"%s",name); while(ob) { if(ob->name && (! strcmp(ob->name, name))) { return((char*)ob); } ob = ob->next; } } return(NULL);}/*********************************************************************/#define SET_PANEL_DOUBLE(item,val) sprintf(panel_string, "%lf", val);\ xv_set(item, PANEL_VALUE, panel_string, 0);#define SET_PANEL_INT(item,val) sprintf(panel_string, "%d", val);\ xv_set(item, PANEL_VALUE, panel_string, 0);#define LIM_LOW(x,y) (x = (x < y) ? y : x)#define LIM_HIGH(x,y) (x = (x > y) ? y : x)#define SET_ABS(x) (x = (x > 0) ? x : -x)char *meth_set(ob, args) Objects *ob; char *args;{ char *panel_string = malloc(100);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -