📄 xspect.c
字号:
if (sp->nfft <= 512) { sp->nfft *= 2; if (sp->yinterp >= 2) /* Keep vertical size constant, if possible. */ sp->yinterp /= 2; } else { i = 1024; /* biggest FFT available on DSP board */ sp->yinterp = 1; /* assumes vertical display size <= 900 * pixels */ sprintf (notice_msg, "Specified window size too big; window limited to %fms.", (1000.0 * i) / freq); show_notice (0, notice_msg); break; } } sp->window_size = ((double) i) / freq; return (TRUE);}/*************************************************************************/Signal *spectrogram (sig, type, start, end, output) Signal *sig; double start, end; char *type, *output;{ Xv_Cursor cursor; Canvas canvas; Spectrogram *spect; short *p; int wasopen; double dtmp; Signal *ss, *spgm_32 (), *spgm_32C (), *e_spect (), *e_spgm (); View *view; int is_p_shorts, esps_ok; if (!sig) return (NULL); if (!strcmp (type, "narrowband")) spect_params = nb_spect_params; else spect_params = wb_spect_params; if (!(spect = new_spectrogram (sig))) { show_notice (1, "xwaves couldn't create spectrogram signal."); return (NULL); } if (end > (dtmp = sig->start_time + ((double) sig->file_size) / sig->freq)) end = dtmp; if (start < sig->start_time) start = sig->start_time; /* don't create absurdly short (spatially speaking) spectrograms */ if ((end - start) / spect->window_step < 8.0) goto free_bailout; spect->start_time = start; spect->end_time = end; spect->outname = savestring (output); is_p_shorts = sig->type & (VECTOR_SIGNALS | APERIODIC_SIGNALS | VAR_REC_SIGNALS); esps_ok = sig->header && sig->header->magic == ESPS_MAGIC && sig->file == SIG_CLOSED; if ((!use_dsp32 && esps_ok) || (esps_ok && !sig->header->e_scrsd)) ss = e_spect (spect); /* No board; up-to-date ESPS file */ /* * or any old ESPS file (including FEA_SD not read as scrsd) (might work) */ else if (!is_p_shorts || (is_p_shorts && sig->dim != 1)) { show_notice (1, "Data type not supported in spectrogram()."); return (NULL); } else if ((use_dsp32 && ((dsp_type == DSP32_FAB2) || (dsp_type == DSP32C_VME))) && ((start < BUF_START_TIME (sig)) || (end > BUF_END_TIME (sig)))) { wasopen = (sig->file >= 0); if (!sig->utils->read_data (sig, start, end - start)) { sprintf (notice_msg, "Can't read specified data segment (%f %f) in spectrogram().", start, end - start); show_notice (1, notice_msg); goto free_bailout; } if (dsp_type == DSP32_FAB2) ss = spgm_32 (spect); else if (dsp_type == DSP32C_VME) ss = spgm_32C (spect); if (sig->views) { /* restore displayed segment, if any */ start = sig->views->start_time; end = ET (sig->views) - start; /* i.e. not end, but duration */ get_view_segment (sig->views, &start, &end); } if (!wasopen) close_sig_file (sig); } else { /* use segment already in memory */ if (use_dsp32 && dsp_type == DSP32_FAB2) ss = spgm_32 (spect); else if (use_dsp32 && dsp_type == DSP32C_VME) ss = spgm_32C (spect); else ss = e_spgm (spect); } link_new_signal ((Object *) sig->obj, ss); /* put at head of signal list */ if (!(view = new_spect_display (ss))) { free_signal (ss); goto free_bailout; } return (ss);free_bailout: if (spect) free_spectrogram (spect); return (NULL);}/*************************************************************************/View *new_spect_display (ss) Signal *ss;{ View *view; if (!(view = new_spect_view (ss, FIXED_SCALE, NULL))) return (NULL); if (!new_spect_window (ss)) return (NULL); update_window_titles (ss); return (view);}#define RETURN(x) {DSP_UNLOCK; return (x);}/*************************************************************************/Signal *spgm_32 (sp) Spectrogram *sp;{#if defined(DS3100) || defined(APOLLO_68K) || defined(STARDENT_3000) || defined(hpux) || defined(SONY) || defined(M5600) || defined(IBM_RS6000) || defined(SG) || defined(OS5) || defined(DEC_ALPHA) || defined(LINUX) return;#else int size, step, nfrm, nsamps, nx, ny, x, init = 1; register int i, cnt; register short *p, *q, *data; static float fwind[1024]; struct mem_dpr { short nfft, win, step, ni; float pre, qc[5], qbw[5]; short fnx, fny, fni, fnh; float fh[100]; float window[512]; } dp; char **dpp; Signal *ss; struct header *hdr; double sf; char comment[300]; char name[200], *cp, *full_path (); static short bitmap[2048]; Signal *sig; void spblit (); static int INBUF_CHARS = INBUF_CHARS_32; static int INBUF_SHORTS = INBUF_SHORTS_32; char *dsp_bin = NULL; if (!sp || !(sig = sp->sig)) { show_notice (1, "Bad argument to spgm_32."); return NULL; } switch (DSP_LOCK (dsp32_wait)) { case LCKFIL_OK: break; case LCKFIL_INUSE: show_notice (1, "DSP board in use."); return NULL; break; default: case LCKFIL_ERR: show_notice (1, "Error in trying to secure exclusive access to DSP board."); return NULL; break; } if (use_spect_prog && spect_prog) dsp_bin = FIND_FAB2_BIN (NULL, spect_prog); if (!(use_spect_prog && setup_dsp (dsp_bin, ALWAYS_LOAD) || setup_dsp ((cp = FIND_FAB2_BIN (NULL, "dspgm")), ALWAYS_LOAD))) { sprintf (notice_msg, "Couldn't load dsp32 program %s or default %s.", spect_prog, cp); show_notice (1, notice_msg); RETURN (NULL) } if (dsp_bin) free (dsp_bin); if (cp) free (cp); dsprg (0, C_RUN, 0xffff001b); /* start prog. (it will wait for param load) */ dp.nfft = sp->nfft; /* stuff spectrogram parameters to board */ dp.win = size = (0.5 + (sig->freq * sp->window_size)); if (size > INBUF_SHORTS / 2) { sprintf (notice_msg, "%s (%d)\n%s (%d).", "Requested window size for spectrogram", size, "exceeds available buffer size", INBUF_SHORTS); show_notice (1, notice_msg); RETURN (NULL) } dp.step = step = (0.5 + (sig->freq * sp->window_step)); if ((size < 4) || !step) { sprintf (notice_msg, "Unreasonable step (%d) or window (%d) size in spgm_32.", step, size); show_notice (1, notice_msg); RETURN (NULL) } dp.ni = sp->yinterp; dp.qc[0] = sp->q_thresh; dp.qc[1] = sp->agc_ratio; dp.qc[2] = sp->q_step; dp.qc[3] = sp->var_ratio; dp.qbw[0] = sp->q_thresh + 60; dp.qbw[1] = sp->agc_ratio; dp.qbw[2] = sp->q_step * 15; dp.qbw[3] = sp->var_ratio; dp.pre = sp->preemp; dp.fnx = sp->xdith; dp.fny = sp->ydith; if (!do_color) dp.fni = sp->yinterp; /* Also used as a flag to skip dithering */ else dp.fni = 0; /* when computing color/grayscale * spectrograms. */ dp.fnh = sp->xdith * sp->ydith; for (i = 0; i < dp.fnh; i++) dp.fh[i] = sp->dimp[i]; if (!get_float_window (fwind, size, sp->window_type)) { show_notice (1, "Can't get_float_window() in spgm_32."); RETURN (NULL) } for (i = 0, cnt = (size + 1) / 2; i < cnt; i++) dp.window[i] = fwind[i]; /* * Now blast the structure to the dsp32 board as a short array. This is * necessary to assure that the actual transfers are shorts, since the * 680xx and SPARC architectures differ and the assemblers do different * things. */ for (i = sizeof (struct mem_dpr) / 2, p = (short *) &dp, q = (short *) sh_mem; i-- > 0;) *q++ = *p++; dsprg (0, C_PIR); /* notify dsp32 that params are loaded */ /* nsamps is total number of samples to be processed */ nsamps = (0.5 + ((sp->end_time - sp->start_time) * sig->freq)); ny = (sp->yinterp * sp->nfft) / 2; /* number of pixels per spectrum */ /* number of time-axis pixels forced to be modulo sizeof(int) */ nx = ((int) (1 + ((nsamps - size) / step)) / sizeof (int)) * sizeof (int); if (nx <= 0) { show_notice (1, "Spectrogram too short to be computed in spgm_32."); RETURN (NULL) } for (i = 0; i < 1000; i++) /* wait for params acknowledge */ if (dsprg (0, C_PCR) & PCR_PIF) break; if (i >= 1000) { show_notice (1, "DSP32 board/program not responding in spgm_32."); RETURN (NULL) /* dead board? */ } /* * get input data address. Note that this assumes all input data in * memory! */ if (!sig->data || !(data = ((short **) sig->data)[0])) { show_notice (1, "NULL signal data in spgm_32."); RETURN (NULL) } else data += time_to_index (sig, sp->start_time); /* nfrm will be the number of frames computed with each call to the dsp32 */ /* Need space for dithered version? (need 1 short/row for returned bitmap) */ nfrm = 2 * (INBUF_CHARS - ((do_color) ? 0 : ny)) / ny; /* Limit by output buf * size */ nfrm &= ~1; /* force an even number */ if ((step * nfrm) > (INBUF_SHORTS - size)) /* or is it limited by input * buf? */ nfrm = ((INBUF_SHORTS - size) / step) & ~1; /* force even number */ if (!nfrm) { show_notice (1, "Specified spectrogram parameters exceed available dsp32 buffer space."); RETURN (NULL) } if (!do_color && (nfrm > 16)) nfrm = 16; /* output limited by shortint size */ /* Now prepare the output signal structure. */ if (sp->outname && *sp->outname) strcpy (name, sp->outname); else sprintf (name, "%s.spgm", sp->signame); /* this SHOULD be made unique */ if (!(ss = new_signal (name, SIG_NEW, dup_header (sig->header), NULL, nx, 1.0 / sp->window_step, ny))) { show_notice (1, "Can't make new_signal() in spgm_32."); RETURN (NULL) } if (ss->header && ss->header->magic == ESPS_MAGIC && ss->header->esps_hdr) { hdr = new_header (FT_FEA); sf = sp->sigfreq; init_feaspec_hd (hdr, FALSE, SPFMT_SYM_EDGE, SPTYP_DB, TRUE, (long) ny, SPFRM_FIXED, (float *) NULL, sf, (long) ROUND (sp->window_size * sf), BYTE); set_pvd (hdr); sprintf (comment, "xwaves spectrogram: start_time %g end_time %g signal %s\n", sp->start_time, sp->end_time, sig->name); add_comment (hdr, comment); ss->header->esps_hdr = hdr; } ss->band = sp->sigfreq / 2.0; ss->band_low = 0.0; ss->params = (caddr_t) sp; if (!(dpp = (char **) malloc (sizeof (char *) * ny))) { show_notice (1, "Can't malloc pointer array in spgm_32."); RETURN (NULL) } for (i = 0; i < ny; i++) { if (!(dpp[i] = malloc (nx))) { show_notice (1, "Can't malloc row in spgm_32."); } } ss->data = (caddr_t) dpp; /* output signal: the spectrogram */ p = (short *) sh_mem; /* point to shared dsp32 memory */ *p++ = cnt = size + 1; /* one extra sample for preemphasis on board */ *p++ = 0; /* 1st call to board just buffers data */#ifdef SPGM_CENTER_ON_START for (i = size / 2; i--;) *p++ = 0; /* Center initial window on data start */ cnt -= size / 2; /* by padding with zeros. */#endif do { *p++ = *data++; } while (--cnt); dsprg (0, C_PIR); /* let dsp know that data has been sent */ if (!do_color) { /* create a bitmap array for dithered image */ sp->bitmap = XV_NULL; /* ! *//* Can't handle dithered bitmaps done on the board. */ /* * if((sp->bitmap = (Server_image) xv_create(XV_NULL, SERVER_IMAGE, * XV_WIDTH, nx, XV_HEIGHT, ny, SERVER_IMAGE_DEPTH, * 1, 0)) == XV_NULL) show_notice(1, "Can't create a server image in * spgm_32."); */ } for (i = 0; i < 10000; i++) /* Wait for dsp32 acknowledge. */ if (dsprg (0, C_PCR) & PCR_PIF) break;/**************************************************************************/ for (x = 0; x < nx; x += nfrm) { /* main loop running dsp32 */ /* now give him data */ if (nx - x < nfrm) nfrm = nx - x; /* This MUST be even! */ p = (short *) sh_mem; *p++ = cnt = nfrm * step; *p++ = nfrm; if (nsamps) { /* out of data? */ if ((nsamps -= cnt) < 0) cnt += nsamps; do { *p++ = *data++; } while (--cnt); if (nsamps < 0) cnt = -nsamps; } if (cnt) do { *p++ = 0; } while (--cnt); dsprg (0, C_PIR); /* let dsp know that data has been sent */ if (sp->bitmap && x) { /* blit the dithered image into a server * image */ spblit ((Server_image) sp->bitmap, bitmap, ny, nfrm, init); /* (from previous batch) */ init = 0; } for (i = 0; i < 100000; i++) /* wait for computations to finish. */ if (dsprg (0, C_PCR) & PCR_PIF) break; /* upload results */ { register short *q = (short *) sh_mem; int nk = nfrm / sizeof (short); for (i = 0; i < ny; i++) { p = (short *) (dpp[i] + x); cnt = nk; if (cnt > 0) do { *p++ = *q++; } while (--cnt); } if (sp->bitmap) /* copy the dithered image into a safe place */ for (p = bitmap + ny, i = ny; i-- > 0;) *--p = *q++; } } if (sp->bitmap) /* blit the final dithered image into a * server image */ spblit ((Server_image) sp->bitmap, bitmap, ny, nfrm, -1); ss->type = P_CHARS | SIG_SPECTROGRAM; ss->file_size = ss->buff_size = nx;#ifdef SPGM_CENTER_ON_START ss->start_time = sp->start_time;#else ss->start_time = sp->start_time + (sp->window_size / 2.0);#endif ss->freq = sig->freq / step; ss->end_time = sp->start_time + ((double) nx) / ss->freq; ss->version += 1; head_printf (ss->header, "version", &(ss->version)); head_printf (ss->header, "type_code", &(ss->type));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -