// ---------------------------------------------------------------- configure -- int SPECTACLE2_BASE::configure() { _inbuf = new float [RTBUFSAMPS * inputChannels()]; _input = new float [_window_len]; // interior input buffer _output = new float [_window_len]; // interior output buffer _anal_bins = new float [_fftlen + 2]; // analysis bins if (_inbuf == NULL || _input == NULL || _output == NULL || _anal_bins == NULL) return -1; for (int i = 0; i < _window_len; i++) _input[i] = _output[i] = 0.0f; // Delay dry output by latency to sync with wet sig. _dry_delay = new Odelay(_window_len); _dry_delay->setdelay(_latency); // Read index chases write index by _decimation; add 2 extra locations to // keep read point from stepping on write point. Verify with asserts in // increment_out_*_index(). _outframes = _decimation + 2; _out_read_index = _outframes - _decimation; _out_write_index = 0; _outbuf = new float [_outframes]; if (_outbuf == NULL) return -1; for (int i = 0; i < _outframes; i++) _outbuf[i] = 0.0f; DPRINT1("_outframes: %d\n", _outframes); _bucket = new Obucket(_decimation, process_wrapper, (void *) this); _fft = new Offt(_fftlen); _fft_buf = _fft->getbuf(); _anal_window = new float [_window_len]; _synth_window = new float [_window_len]; if (_anal_window == NULL || _synth_window == NULL) return -1; int len; double *window = (double *) getPFieldTable(_window_pfield_index, &len); if (make_windows(window, len) != 0) return DONT_SCHEDULE; if (subconfigure() != 0) return -1; return 0; }
int SPECTACLE_BASE :: init(double p[], int n_args) { float outskip = p[0]; float inskip = p[1]; inputdur = p[2]; amp = p[3]; ringdur = p[4]; fft_len = (int) p[5]; window_len = (int) p[6]; window_type = getWindowType(p[7]); float overlap = p[8]; /* Make sure FFT length is a power of 2 <= MAXFFTLEN and <= RTBUFSAMPS. */ bool valid = false; for (int x = 1; x <= MAXFFTLEN; x *= 2) { if (fft_len == x) { valid = true; break; } } if (!valid || fft_len > MAXFFTLEN) return die(instname(), "FFT length must be a power of two <= %d", MAXFFTLEN); // FIXME: now this isn't a problem; instead, decimation can't be larger // than RTBUFSAMPS. But must couch errmsg in terms of overlap and fft length, // not decimation... #if 0 if (fft_len > RTBUFSAMPS) return die(instname(), "FFT length must be a power of two less than or equal\n" "to the output buffer size set in rtsetparams (currently %d).", RTBUFSAMPS); #endif half_fft_len = fft_len / 2; fund_anal_freq = SR / (float) fft_len; /* Make sure window length is a power of 2 >= FFT length. */ valid = false; for (int x = fft_len; x <= MAXWINDOWLEN; x *= 2) { if (window_len == x) { valid = true; break; } } if (!valid) return die(instname(), "Window length must be a power of two >= FFT length\n" "(currently %d) and <= %d.", fft_len, MAXWINDOWLEN); /* Make sure overlap is a power of 2 in our safety range. */ valid = false; //FIXME: need to adjust MINOVERLAP so that iterations is never 0 in run() // This might depend upon window_len?? for (float x = MINOVERLAP; x <= MAXOVERLAP; x *= 2.0) { if (overlap == x) { valid = true; break; } } if (!valid) return die(instname(), "Overlap must be a power of two between %g and %g.", MINOVERLAP, MAXOVERLAP); int_overlap = (int) overlap; /* derive decimation from overlap */ decimation = (int) (fft_len / overlap); DPRINT2("fft_len=%d, decimation=%d\n", fft_len, decimation); if (pre_init(p, n_args) != 0) /* can modify ringdur */ return DONT_SCHEDULE; iamparray = floc(1); if (iamparray) { int lenamp = fsize(1); tableset(SR, inputdur, lenamp, iamptabs); } else rtcmix_advise(instname(), "Setting input amplitude curve to all 1's."); oamparray = floc(2); if (oamparray) { int lenamp = fsize(2); tableset(SR, inputdur + ringdur, lenamp, oamptabs); } else rtcmix_advise(instname(), "Setting output amplitude curve to all 1's."); if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; if (inchan >= inputChannels()) return die(instname(), "You asked for channel %d of a %d-channel file.", inchan, inputChannels()); /* <latency> is the delay before the FFT looks at actual input rather than zero-padding. Need to let inst run long enough to compensate for this. */ window_len_minus_decimation = window_len - decimation; latency = window_len + window_len_minus_decimation; float latency_dur = latency * (1.0 / SR); if (rtsetoutput(outskip, latency_dur + inputdur + ringdur, this) == -1) return DONT_SCHEDULE; total_insamps = (int)(inputdur * SR); /* without latency_dur */ input_end_frame = total_insamps + latency; DPRINT1("input_end_frame=%d\n", input_end_frame); input = new float [window_len]; /* input buffer */ output = new float [window_len]; /* output buffer */ anal_window = new float [window_len]; /* analysis window */ synth_window = new float [window_len]; /* synthesis window */ fft_buf = new float [fft_len]; /* FFT buffer */ anal_chans = new float [fft_len + 2]; /* analysis channels */ if (make_windows() != 0) return DONT_SCHEDULE; /* Delay dry output by window_len - decimation to sync with wet sig. */ drybuf = new float [decimation]; dry_delay = new DLineN(window_len); dry_delay->setDelay((float) window_len_minus_decimation); /* Init iamp and oamp to starting amplitudes. */ iamp = (iamparray == NULL) ? 1.0 : iamparray[0]; oamp = (oamparray == NULL) ? amp : oamparray[0]; skip = (int) (SR / (float) resetval); if (post_init(p, n_args) != 0) return DONT_SCHEDULE; return nSamps(); }
/*-----------------------------------------------------------------------------------*/ PROCESS_THREAD(program_handler_process, ev, data) { #ifdef WITH_LOADER_ARCH unsigned char err; struct dsc *dsc; #endif /* WITH_LOADER_ARCH */ unsigned char i; struct dsc **dscp; PROCESS_BEGIN(); /* Create the menus */ ctk_menu_add(&contikimenu); #if WITH_LOADER_ARCH runmenuitem = ctk_menuitem_add(&contikimenu, "Run program..."); make_windows(); #endif /* WITH_LOADER_ARCH */ #if QUIT_MENU quitmenuitem = ctk_menuitem_add(&contikimenu, "Quit"); #endif /* QUIT_MENU */ displayname = NULL; #if CTK_CONF_SCREENSAVER program_handler_screensaver[0] = 0; #endif /* CTK_CONF_SCREENSAVER */ while(1) { PROCESS_WAIT_EVENT(); if(ev == ctk_signal_button_activate) { #ifdef WITH_LOADER_ARCH if(data == (process_data_t)&loadbutton) { ctk_window_close(&runwindow); program_handler_load(name, NULL); } else if(data == (process_data_t)&errorokbutton) { ctk_dialog_close(); } #endif /* WITH_LOADER_ARCH */ #if QUIT_MENU if(data == (process_data_t)&quityesbutton) { ctk_draw_init(); exit(EXIT_SUCCESS); } else if(data == (process_data_t)&quitnobutton) { ctk_dialog_close(); } #endif /* QUIT_MENU */ dscp = &contikidsc[0]; for(i = 0; i < CTK_MAXMENUITEMS; ++i) { if(*dscp != NULL #if CTK_CONF_ICONS && data == (process_data_t)(*dscp)->icon #endif /* CTK_CONF_ICONS */ ) { RUN((*dscp)->prgname, (*dscp)->process, NULL); break; } ++dscp; } } else if(ev == ctk_signal_menu_activate) { if((struct ctk_menu *)data == &contikimenu) { #if WITH_LOADER_ARCH dsc = contikidsc[contikimenu.active]; if(dsc != NULL) { RUN(dsc->prgname, dsc->process, NULL); } else if(contikimenu.active == runmenuitem) { make_windows(); ctk_window_close(&runwindow); ctk_window_open(&runwindow); CTK_WIDGET_FOCUS(&runwindow, &nameentry); } #else /* WITH_LOADER_ARCH */ if(contikidsc[contikimenu.active] != NULL) { RUN(contikidsc[contikimenu.active]->prgname, contikidsc[contikimenu.active]->process, NULL); } #endif /* WITH_LOADER_ARCH */ #if QUIT_MENU if(contikimenu.active == quitmenuitem) { ctk_dialog_new(&quitdialog, 24, 5); CTK_WIDGET_ADD(&quitdialog, &quitdialoglabel); CTK_WIDGET_ADD(&quitdialog, &quityesbutton); CTK_WIDGET_ADD(&quitdialog, &quitnobutton); CTK_WIDGET_FOCUS(&quitdialog, &quitnobutton); ctk_dialog_open(&quitdialog); } #endif /* QUIT_MENU */ } #if CTK_CONF_SCREENSAVER } else if(ev == ctk_signal_screensaver_start) { #if WITH_LOADER_ARCH if(program_handler_screensaver[0] != 0) { program_handler_load(program_handler_screensaver, NULL); } #endif /* WITH_LOADER_ARCH */ #endif /* CTK_CONF_SCREENSAVER */ } else if(ev == LOADER_EVENT_DISPLAY_NAME) { #if WITH_LOADER_ARCH if(displayname == NULL) { make_windows(); ctk_label_set_text(&loadingname, ((struct pnarg *)data)->name); ctk_dialog_open(&loadingdialog); process_post(&program_handler_process, LOADER_EVENT_LOAD, data); displayname = data; } else { /* Try again. */ process_post(&program_handler_process, LOADER_EVENT_DISPLAY_NAME, data); } #endif /* WITH_LOADER_ARCH */ } else if(ev == LOADER_EVENT_LOAD) { #if WITH_LOADER_ARCH if(displayname == data) { ctk_dialog_close(); displayname = NULL; log_message("Loading ", ((struct pnarg *)data)->name); err = LOADER_LOAD(((struct pnarg *)data)->name, ((struct pnarg *)data)->arg); if(err != LOADER_OK) { make_windows(); errorfilename[0] = '"'; strncpy(errorfilename + 1, ((struct pnarg *)data)->name, sizeof(errorfilename) - 2); errorfilename[1 + strlen(((struct pnarg *)data)->name)] = '"'; ctk_label_set_text(&errortype, (char *)errormsgs[err]); ctk_dialog_open(&errordialog); log_message((char *)errormsgs[err], errorfilename); } pnarg_free(data); } else { /* Try again. */ process_post(&program_handler_process, LOADER_EVENT_DISPLAY_NAME, data); } #endif /* WITH_LOADEER_ARCH */ } } PROCESS_END(); }
// --------------------------------------------------------------------- init -- int SpectacleBase::init(int fftlen, int windowlen, int overlap, float srate) { _fftlen = fftlen; _window_len = windowlen; _overlap = overlap; // Make sure FFT length is a power of 2 <= kMaxFFTLen. bool valid = false; for (int x = 1; x <= kMaxFFTLen; x *= 2) { if (_fftlen == x) { valid = true; break; } } if (!valid) { post("%s: FFT length must be a power of two <= %d. Setting to 1024...", instname(), kMaxFFTLen); _fftlen = 1024; } _half_fftlen = _fftlen / 2; // Make sure window length is a power of 2 >= FFT length. valid = false; for (int x = _fftlen; x <= kMaxWindowLen; x *= 2) { if (_window_len == x) { valid = true; break; } } if (!valid) { post("%s: Window length must be a power of two >= FFT length (%d)\n" "and <= %d. Setting to 2048...", instname(), _fftlen, kMaxWindowLen); _window_len = _fftlen * 2; } // Make sure _overlap is a power of 2 in allowed range. valid = false; for (int x = kMinOverlap; x <= kMaxOverlap; x *= 2) { if (_overlap == x) { valid = true; break; } } if (!valid) { post("%s: Overlap must be a power of two between %d and %d. " "Setting to 2...", instname(), kMinOverlap, kMaxOverlap); _overlap = 2; } _bin_groups = new int [_half_fftlen]; set_srate(srate); set_freqrange(0.0f, 0.0f); // derive decimation from overlap _decimation = int(_fftlen / _overlap); _window_len_minus_decimation = _window_len - _decimation; DPRINT2("_fftlen=%d, _decimation=%d", _fftlen, _decimation); _input = new float [_window_len]; // interior input buffer _output = new float [_window_len]; // interior output buffer if (_input == NULL || _output == NULL) return -1; for (int i = 0; i < _window_len; i++) _input[i] = _output[i] = 0.0f; // Read index chases write index by _decimation; add 2 extra locations to // keep read point from stepping on write point. Verify with asserts in // increment_out_*_index(). _outframes = _decimation + 2; _out_read_index = _outframes - _decimation; _out_write_index = 0; _outbuf = new float [_outframes]; if (_outbuf == NULL) return -1; for (int i = 0; i < _outframes; i++) _outbuf[i] = 0.0f; DPRINT1("_outframes: %d", _outframes); _anal_window = new float [_window_len]; _synth_window = new float [_window_len]; if (_anal_window == NULL || _synth_window == NULL) return -1; if (make_windows() != 0) return -1; _bucket = new Obucket(_decimation, process_wrapper, (void *) this); _fft = new Offt(_fftlen); _fft_buf = _fft->getbuf(); return 0; }