template<typename F> void subinit(F f,size_t i) { new(begin() + i) T(f(i)); if(i < Size-1) { try { subinit(f,i+1); } catch(...) { (*this)[i].~T(); throw; } } }
// --------------------------------------------------------------------- init -- int SPECTACLE2_BASE::init(double p[], int n_args) { _nargs = n_args; #ifdef NOTYET _print_stats = Option::printStats(); #else _print_stats = true; #endif if (getargs(p, n_args) < 0) // subclass gets args return DONT_SCHEDULE; // NB: subclass init will have already grabbed all pfields except these... const float outskip = p[0]; const float inskip = p[1]; _inputdur = p[2]; _oamp = p[3]; // 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) return die(instname(), "FFT length must be a power of two <= %d", kMaxFFTLen); _half_fftlen = _fftlen / 2; _fund_anal_freq = SR / float(_fftlen); // 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) return die(instname(), "Window length must be a power of two >= FFT length (%d)\n" "and <= %d.", _fftlen, kMaxWindowLen); // 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) return die(instname(), "Overlap must be a power of two between %d and %d.", kMinOverlap, kMaxOverlap); // derive decimation from overlap _decimation = int(_fftlen / _overlap); // create this now, because subinit will need it _bin_groups = new int [_half_fftlen + 1]; // subclass init -- must follow FFT and bin groups init; sets _ringdur if (subinit(p, n_args) < 0) return DONT_SCHEDULE; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; if (_inchan >= inputChannels()) return die(instname(), "You asked for channel %d of a %d-channel input.", _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, // as well as to span the user's requested ring-down duration. _window_len_minus_decimation = _window_len - _decimation; _latency = _window_len_minus_decimation; const float latency_dur = _latency / SR; if (rtsetoutput(outskip, latency_dur + _inputdur + _ringdur, this) == -1) return DONT_SCHEDULE; _input_frames = int(_inputdur * SR + 0.5); // without latency_dur _input_end_frame = _input_frames + _latency; DPRINT2("_fftlen=%d, _decimation=%d\n", _fftlen, _decimation); DPRINT3("_latency=%d, _input_frames=%d, ring frames = %d\n", _latency, _input_frames, int(_ringdur * SR + 0.5)); return nSamps(); }
template<typename F> init_array(size_t size,F f) { assert(size == Size); subinit(f,0); }