int START::init(double p[], int n_args) { float outskip = p[0]; float dur = p[1]; float pitch = p[2]; float fdecay = p[3]; float nydecay = p[4]; float amp = p[5]; int squish = (int)p[6]; spread = p[7]; deleteflag = (int)p[8]; if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; strumq1 = new StrumQueue; strumq1->ref(); curstrumq[0] = strumq1; float freq = cpspch(pitch); sset(SR, freq, fdecay, nydecay, strumq1); randfill(amp, squish, strumq1); amptable = floc(1); if (amptable) { int amplen = fsize(1); tableset(SR, dur, amplen, amptabs); } else { rtcmix_advise("START", "Setting phrase curve to all 1's."); aamp = 1.0; } skip = (int)(SR / (float)resetval); return nSamps(); }
int MCLAR :: init(double p[], int n_args) { nargs = n_args; Stk::setSampleRate(SR); if (rtsetoutput(p[0], p[1], this) == -1) return DONT_SCHEDULE; amptable = floc(1); if (amptable) // the amp array has been created using makegen theEnv = new Ooscili(SR, 1.0/p[1], 1); theClar = new Clarinet(50.0); // 50 Hz is lowest freq for now noiseamp = p[4]; theClar->setNoise(p[4]); stiff = p[6]; theClar->setReedStiffness(p[6]); freq = p[3]; theClar->noteOn(p[3], p[5]); pctleft = n_args > 7 ? p[7] : 0.5; /* default is .5 */ return nSamps(); }
FiltType BUTTER :: getFiltType(bool trystring) { double index = (double) currentFrame() / nSamps(); const PField &field = getPField(4); // must try int first, since a valid code cast to char * will crash strncmp int code = field.intValue(index) - 1; // NB: user codes are 1-based if ((code < LowPass || code > BandReject) && trystring) { const char *str = field.stringValue(index); code = _string_to_filtcode(str); // -1 if no match if (code != -1) filttype_was_string = true; } FiltType filttype; switch (code) { case 0: filttype = LowPass; break; case 1: filttype = HighPass; break; case 2: filttype = BandPass; break; case 3: filttype = BandReject; break; default: filttype = FiltInvalid; break; } return filttype; }
int WAVY::init(double p[], int n_args) { if (n_args < 9) return usage(); _nargs = n_args; const float outskip = p[0]; const float dur = p[1]; if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; if (outputChannels() < 1 || outputChannels() > 2) return die("WAVY", "Must have mono or stereo output only."); int wavelenA; double *wavetabA = (double *) getPFieldTable(6, &wavelenA); if (wavetabA == NULL) return die("WAVY", "p6 must be wavetable (use maketable)"); int wavelenB; double *wavetabB = (double *) getPFieldTable(7, &wavelenB); if (wavetabB == NULL) { wavetabB = wavetabA; wavelenB = wavelenA; } _oscilA = new Ooscil(SR, 440.0, wavetabA, wavelenA); _oscilB = new Ooscil(SR, 440.0, wavetabB, wavelenB); if (setExpression() != 0) return DONT_SCHEDULE; assert(_fp != NULL || _combiner != NULL); return nSamps(); }
OeqType MULTEQ :: getEQType(bool trystring, int pfindex) { double index = (double) currentFrame() / nSamps(); const PField &field = getPField(pfindex); // must try int first, since a valid code cast to char * will crash strncmp int code = field.intValue(index); if (trystring && (code < 0 || code > 4)) { const char *str = field.stringValue(index); code = _string_to_eqcode(str); // -1 if no match } OeqType eqtype; switch (code) { case 0: eqtype = OeqLowPass; break; case 1: eqtype = OeqHighPass; break; case 2: eqtype = OeqLowShelf; break; case 3: eqtype = OeqHighShelf; break; case 4: eqtype = OeqPeaking; break; case 5: eqtype = OeqBandPassCSG; break; default: eqtype = OeqInvalid; break; } return eqtype; }
int TRANS::init(double p[], int n_args) { nargs = n_args; if (nargs < 5) return die("TRANS", "Usage: TRANS(start, inskip, dur, amp, trans[, inchan, pan])"); const float outskip = p[0]; const float inskip = p[1]; float dur = p[2]; if (dur < 0.0) dur = -dur - inskip; inchan = (nargs > 5) ? (int) p[5] : 0; pctleft = (nargs > 6) ? p[6] : 0.5; if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; if (inchan >= inputChannels()) { return die("TRANS", "You asked for channel %d of a %d-channel file.", inchan, inputChannels()); } // to trigger first read in run() inframe = RTBUFSAMPS; initamp(dur, p, 3, 1); oneover_cpsoct10 = 1.0 / cpsoct(10.0); if (fastUpdate) // no transp updates _increment = cpsoct(10.0 + octpch(p[4])) * oneover_cpsoct10; return nSamps(); }
// --------------------------------------------------------------------- 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(); }
// this is called when the instrument initializes and gets scheduled int LOCALIZE::init(double p[], int n_args) { float mult; int flipper; // set up input and output int returnval = rtsetoutput(p[0], p[2], this); if (returnval == -1) return DONT_SCHEDULE; returnval = rtsetinput(p[1], this); if (returnval == -1) return DONT_SCHEDULE; // get the p-field values we will use later _amp = p[3]; // angle + distance from source to destination dist = sqrt( pow((p[4]-p[7]), 2.0) + pow((p[5]-p[8]), 2.0) + pow((p[6]-p[9]), 2.0) ); theta = asin((p[5] - p[8])/dist); headdelay = (p[10]*p[11])/1000.0; // simple assumption, sound 1000 ft/sec // calculate the ear delays flipper = 0; if (theta > 0.0) { if (p[4] - p[7] > 0.0) { // upper right mult = 1.0 - theta/M_PI_2; } else { // upper left mult = 1.0 - theta/M_PI_2; // flip flipper = 1; } } else { if (p[4] - p[7] > 0.0) { // lower right mult = 1.0 - (-theta/M_PI_2); } else { // lower left mult = 1.0 - (-theta/M_PI_2); // flip flipper = 1; } } // simple head shadow (decrease amp by 0.6 when full R or L) if (flipper == 0) { _delayR = 0; _delayL = mult * headdelay * SR; _ampL = 1.0 - (mult * 0.6); } else { _delayR = mult * headdelay * SR; _delayL = 0; _ampR = 1.0 - (mult * 0.6); } // set up delay lines theDelayR = new Odelayi(0.1 * SR); theDelayL = new Odelayi(0.1 * SR); // set up our sample-reading theIn = new Ortgetin(this); // check and calculate behind head (head filter) // simple lowpass filter for now _dofilt = 0; if ((int)p[13] == 1) { float filt_cutoff = 0.0; if (theta < 0.0) // behind us filt_cutoff = -theta/M_PI_2; // from full to 500 Hz cutoff totally behind, tracking exponentially (3) headfilt = new Oonepole(44100.0, 500.0 + pow((1.0 - filt_cutoff), 3.0) * 21000.0); // cut the amplitude slightly _amp *= (1.0 - (filt_cutoff * 0.3)); // -theta/M_PI_2 already calculated _dofilt = 1; } // do amp/distance calculation _doampdist = 0; if ((int)p[14] == 1) { // linear float distcut; _mindistamp = p[15]; _totlindist = p[16]; if (dist < _totlindist) distcut = 1.0 - dist/_totlindist; else distcut = -1; if (distcut < _mindistamp) distcut = _mindistamp; _amp *= distcut; _doampdist = 1; } if ((int)p[14] == 2) { // inverse square float distcut; _mindistamp = p[15]; if (dist*p[11] >= 1.0) distcut = 1.0/(dist * p[11]); else distcut = 1.0; if (distcut < _mindistamp) distcut = _mindistamp; _amp *= distcut; _doampdist = 2; } _branch = 0; _inputchan = p[12]; return nSamps(); }
int LPCIN::run() { int n = 0; float out[2]; /* Space for only 2 output chans! */ const int inchans = inputChannels(); // Samples may have been left over from end of previous run's block if (_leftOver > 0) { int toAdd = min(_leftOver, framesToRun()); #ifdef debug printf("using %d leftover samps starting at offset %d\n", _leftOver, _savedOffset); #endif bmultf(&_alpvals[_savedOffset], _ampmlt, toAdd); // Scale signal rtbaddout(&_alpvals[_savedOffset], toAdd); increment(toAdd); n += toAdd; _leftOver -= toAdd; _savedOffset += toAdd; } /* framesToRun() returns the number of sample frames -- 1 sample for each channel -- that we have to write during this scheduler time slice. */ for (; n < framesToRun(); n += _counter) { double p[10]; update(p, LPCIN_bw + 1); _amp = p[LPCIN_amp]; _warpFactor = p[LPCIN_warp]; _reson_is_on = p[LPCIN_cf] ? true : false; _cf_fact = p[LPCIN_cf]; _bw_fact = p[LPCIN_bw]; int loc; _frameno = _frame1 + ((float)(currentFrame())/nSamps()) * _frames; #ifdef debug printf("\tgetting frame %g of %d (%d out of %d signal samps)\n", _frameno, (int)_frames, currentFrame(), nSamps()); #endif if (_dataSet->getFrame(_frameno,_coeffs) == -1) break; // If requested, stabilize this frame before using if (_autoCorrect) stabilize(_coeffs, _nPoles); _ampmlt = _amp * _coeffs[RESIDAMP] / 10000.0; // XXX normalize this! float newpch = (_coeffs[PITCH] > 0.0) ? _coeffs[PITCH] : 64.0; if (_coeffs[RMSAMP] < _cutoff) _ampmlt = 0; if (_reson_is_on) { /* Treat _cf_fact as absolute freq. If _bw_fact is greater than 20, treat as absolute freq. Else treat as factor (i.e., cf * factor == bw). */ float cf = _cf_fact; float bw = (_bw_fact < 20.0) ? cf * _bw_fact : _bw_fact; rszset(SR, cf, bw, 1., _rsnetc); /* printf("%f %f %f %f\n",_cf_fact*cps, _bw_fact*_cf_fact*cps,_cf_fact,_bw_fact,cps); */ } float *cpoint = _coeffs + 4; if (_warpFactor != 0.0) { float warp = (_warpFactor > 1.) ? .0001 : _warpFactor; _ampmlt *= _warpPole.set(warp, cpoint, _nPoles); } _counter = int(((float)SR/(newpch * /*_perperiod*/ 1.0) ) * .5); // _counter = (RTBUFSAMPS < MAXVALS) ? RTBUFSAMPS : MAXVALS; // _counter = (_counter > (nSamps() - currentFrame())) ? nSamps() - currentFrame() : _counter; _counter = min(_counter, framesToRun() - n); if (_counter <= 0) break; rtgetin(_inbuf, this, _counter); // Deinterleave input for (int from=_inChannel, to=0; to < _counter; from += inchans, ++to) _buzvals[to] = _inbuf[from]; #ifdef debug printf("\t _buzvals[0] = %g\n", _buzvals[0]); #endif if (_warpFactor) { // float warp = (_warpFactor > 1.) ? shift(_coeffs[PITCH],newpch,(float)SR) : _warpFactor; float warp = _warpFactor; #ifdef debug printf("\tpch: %f newpch: %f d: %f\n",_coeffs[PITCH], newpch, warp); #endif /************* warp = ABS(warp) > .2 ? SIGN(warp) * .15 : warp; ***************/ _warpPole.run(_buzvals, warp, cpoint, _alpvals, _counter); } else { ballpole(_buzvals,&_jcount,_nPoles,_past,cpoint,_alpvals,_counter); } #ifdef debug { int x; float maxamp=0; for (x=0;x<_counter;x++) { if (ABS(_alpvals[x]) > ABS(maxamp)) maxamp = _alpvals[x]; } printf("\t maxamp = %g\n", maxamp); } #endif if (_reson_is_on) bresonz(_alpvals,_rsnetc,_alpvals,_counter); int sampsToAdd = min(_counter, framesToRun() - n); // printf("\tscaling %d samples by %g\n", sampsToAdd, _ampmlt); bmultf(_alpvals, _ampmlt, sampsToAdd); // Scale signal /* Write this block to the output buffer. */ rtbaddout(_alpvals, sampsToAdd); /* Keep track of how many sample frames this instrument has generated. */ increment(sampsToAdd); } // Handle case where last synthesized block extended beyond framesToRun() if (n > framesToRun()) { _leftOver = n - framesToRun(); _savedOffset = _counter - _leftOver; #ifdef debug printf("saving %d samples left over at offset %d\n", _leftOver, _savedOffset); #endif } return framesToRun(); }
int STGRANR::init(double p[], int n_args) { /* p0=start_time * p1=input start time * now p2 was p1=duration * p3=amplitude * p4=rate, p5-8 ratevar * p9-12 duration * p13-16 location * p17-20 transposition * p21 granlayers (not in use) * p22 seed * makegen slot 1 is amp env, makegen slot 2 is grain env */ starttime = p[0]; inskip = p[1]; evdur = p[2]; if (evdur < 0.0) evdur = -evdur - inskip; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; // no input if (rtsetoutput(starttime, evdur, this) == -1) return DONT_SCHEDULE; if (outputChannels() > 2) return die("STGRANR", "Can't handle more than 2 output channels."); amp = p[3]; inframe = RTBUFSAMPS; amptable = floc(1); if (amptable) { alen = fsize(1); tableset(SR, evdur, alen, tabs); } else rtcmix_advise("STGRANR", "Setting phrase curve to all 1's."); grenvtable = floc(2); if (grenvtable) { grlen = fsize(2); } else rtcmix_advise("STGRANR", "Setting grain envelope to all 1's."); aamp = amp; skip = (int)(SR/(float)resetval); rate = p[4]; ratevarlo = (double)p[5]; ratevarmid = (double)p[6]; if (ratevarmid < ratevarlo ) ratevarmid = ratevarlo; ratevarhi = (double)p[7]; if (ratevarhi < ratevarmid ) ratevarhi = ratevarmid; ratevarti = (double)p[8]; durlo = (double)p[9]; durmid = (double)p[10]; if (durmid < durlo ) durmid = durlo; durhi = (double)p[11]; if (durhi < durmid ) durhi = durmid; if ( durhi > rate ) { die("STGRANR", "Grain durations %f sec. are larger than rate: %f seconds per grain.",durhi,rate); return(DONT_SCHEDULE); } durti = (double)p[12]; loclo = (double)p[13]; locmid = (double)p[14]; if (locmid < loclo ) locmid = loclo; lochi = (double)p[15]; if (lochi < locmid ) lochi = locmid; locti = (double)p[16]; transplo = (double)p[17]; transpmid = (double)p[18]; if (transpmid < transplo ) transpmid = transplo; transphi = (double)p[19]; if (transphi < transpmid ) transphi = transpmid; transpti = (double)p[20]; granlyrs = (int)p[21]; srrand((int)(p[22])); return nSamps(); }
int GVERB::init(double pfs[], int n_args) { if (rtsetoutput(pfs[0], pfs[2]+pfs[11], this) == -1) return DONT_SCHEDULE; if (outputChannels() != 2) return die("GVERB", "stereo output required"); if (rtsetinput(pfs[1], this) == -1) return DONT_SCHEDULE; // no input inputframes = pfs[2] * SR; inputchan = pfs[12]; amp = pfs[3]; float maxroomsize = 300.0f; float roomsize = 50.0f; float revtime = 7.0f; float damping = 0.5f; float spread = 15.0f; float inputbandwidth = 0.5f; float drylevel = 0.0f; //-1.9832f; float earlylevel = 0.0f; //-1.9832f; float taillevel = 0.0f; float ga,gb,gt; unsigned int i; int n; float r; float diffscale; int a,b,c,cc,d,dd,e; float spread1,spread2; // BGG max/msp heritage, params/etc. stored in this "p" struct (ty_gverb) p = &realp; // zero out the struct, to be careful bzero((void *)p, sizeof (ty_gverb)); p->rate = SR; p->fdndamping = damping; p->maxroomsize = maxroomsize; p->roomsize = CLIP(roomsize, 0.1f, maxroomsize); p->revtime = revtime; p->drylevel = drylevel; p->earlylevel = earlylevel; p->taillevel = taillevel; p->maxdelay = p->rate*p->maxroomsize/340.0; p->largestdelay = p->rate*p->roomsize/340.0; /* Input damper */ p->inputbandwidth = inputbandwidth; p->inputdamper = damper_make(1.0 - p->inputbandwidth); /* FDN section */ p->fdndels = (ty_fixeddelay **)malloc(FDNORDER*sizeof(ty_fixeddelay *)); if(!p->fdndels) return die("GVERB", "out of memory for fixeddelay ptrs"); for(i = 0; i < FDNORDER; i++) { p->fdndels[i] = fixeddelay_make((int)p->maxdelay+1000); if(!p->fdndels[i]) return die("GVERB", "out of memory for fixeddelays"); } p->fdngains = (float *)malloc(FDNORDER*sizeof(float)); p->fdnlens = (int *)malloc(FDNORDER*sizeof(int)); if(!p->fdngains || !p->fdnlens) return die("GVERB", "out of memory for delay gains and lengths"); p->fdndamps = (ty_damper **)malloc(FDNORDER*sizeof(ty_damper *)); if(!p->fdndamps) return die("GVERB", "out of memory for delay amps"); for(i = 0; i < FDNORDER; i++) { p->fdndamps[i] = damper_make(p->fdndamping); if(!p->fdndamps[i]) return die("GVERB", "out of memory for delay amps 2"); } ga = 60.0; gt = p->revtime; ga = pow(10.0,-ga/20.0); n = (int)(p->rate*gt); p->alpha = pow((double)ga,(double)1.0/(double)n); gb = 0.0; for(i = 0; i < FDNORDER; i++) { if (i == 0) gb = 1.000000*p->largestdelay; if (i == 1) gb = 0.816490*p->largestdelay; if (i == 2) gb = 0.707100*p->largestdelay; if (i == 3) gb = 0.632450*p->largestdelay; #if 0 p->fdnlens[i] = nearest_prime((int)gb, 0.5); #else p->fdnlens[i] = (int)gb; #endif // p->fdngains[i] = -pow(p->alpha,(double)p->fdnlens[i]); p->fdngains[i] = -powf((float)p->alpha,p->fdnlens[i]); } p->d = (float *)malloc(FDNORDER*sizeof(float)); p->u = (float *)malloc(FDNORDER*sizeof(float)); p->f = (float *)malloc(FDNORDER*sizeof(float)); if(!p->d || !p->u || !p->f) return die("GVERB", "out of memory for other delay stuff"); /* Diffuser section */ diffscale = (float)p->fdnlens[3]/(210+159+562+410); spread1 = spread; spread2 = 3.0*spread; b = 210; r = 0.125541f; a = (int)(spread1*r); c = 210+159+a; cc = c-b; r = 0.854046f; a = (int)(spread2*r); d = 210+159+562+a; dd = d-c; e = 1341-d; p->ldifs = (ty_diffuser **)malloc(4*sizeof(ty_diffuser *)); if(!p->ldifs) return die("GVERB", "out of memory for diffuser left structs"); p->ldifs[0] = diffuser_make((int)(diffscale*b),0.75); p->ldifs[1] = diffuser_make((int)(diffscale*cc),0.75); p->ldifs[2] = diffuser_make((int)(diffscale*dd),0.625); p->ldifs[3] = diffuser_make((int)(diffscale*e),0.625); if(!p->ldifs[0] || !p->ldifs[1] || !p->ldifs[2] || !p->ldifs[3]) return die("GVERB", "out of memory for diffuser left makes"); b = 210; r = -0.568366f; a = (int)(spread1*r); c = 210+159+a; cc = c-b; r = -0.126815f; a = (int)(spread2*r); d = 210+159+562+a; dd = d-c; e = 1341-d; p->rdifs = (ty_diffuser **)malloc(4*sizeof(ty_diffuser *)); if(!p->rdifs) return die("GVERB", "out of memory for diffuser right structs"); p->rdifs[0] = diffuser_make((int)(diffscale*b),0.75); p->rdifs[1] = diffuser_make((int)(diffscale*cc),0.75); p->rdifs[2] = diffuser_make((int)(diffscale*dd),0.625); p->rdifs[3] = diffuser_make((int)(diffscale*e),0.625); if(!p->rdifs[0] || !p->rdifs[1] || !p->rdifs[2] || !p->rdifs[3]) return die("GVERB", "out of memory for diffuser right makes"); /* Tapped delay section */ p->tapdelay = fixeddelay_make(44000); p->taps = (int *)malloc(FDNORDER*sizeof(int)); p->tapgains = (float *)malloc(FDNORDER*sizeof(float)); if(!p->tapdelay || !p->taps || !p->tapgains) return die("GVERB", "out of memory for taps"); p->taps[0] = (int)(5+0.410*p->largestdelay); p->taps[1] = (int)(5+0.300*p->largestdelay); p->taps[2] = (int)(5+0.155*p->largestdelay); p->taps[3] = (int)(5+0.000*p->largestdelay); for(i = 0; i < FDNORDER; i++) { p->tapgains[i] = pow(p->alpha,(double)p->taps[i]); } // these values get set after all the init stuff if (pfs[4] < 1.0 || pfs[4] > maxroomsize) return die("GVERB", "bogus roomsize: %f\n", pfs[4]); gverb_set_roomsize(p, pfs[4]); // sets p->roomsize if (pfs[5] < 0.1 || pfs[5] > 360.0) return die("GVERB", "bad revtime: %f\n", pfs[5]); gverb_set_revtime(p, pfs[5]); if (pfs[6] < 0.0 || pfs[6] > 1.0) return die("GVERB", "incorrect damping: %f\n", pfs[6]); gverb_set_damping(p, pfs[6]); if (pfs[7] < 0.0 || pfs[7] > 1.0) return die("GVERB", "input bandwith problem: %f\n", pfs[7]); gverb_set_inputbandwidth(p, pfs[7]); if (pfs[8] < -90.0 || pfs[8] > 0.0) return die("GVERB", "dry level wrong: %f\n", pfs[8]); gverb_set_drylevel(p, pfs[8]); if (pfs[9] < -90.0 || pfs[9] > 0.0) return die("GVERB", "problem with early reflection level: %f\n", pfs[9]); gverb_set_earlylevel(p, pfs[9]); if (pfs[10] < -90.0 || pfs[10] > 0.0) return die("GVERB", "bogus tail level: %f\n", pfs[10]); gverb_set_taillevel(p, pfs[10]); branch = 0; return nSamps(); }
int REVERBIT::init(double p[], int n_args) { float outskip = p[0]; float inskip = p[1]; float dur = p[2]; reverbtime = p[4]; reverbpct = p[5]; rtchan_delaytime = p[6]; cutoff = p[7]; dcblock = n_args > 8 ? (p[8] != 0.0) : true; // default is "yes" float ringdur = n_args > 9 ? p[9] : reverbtime + RVTSLOP; if (outputChannels() != 2) return die("REVERBIT", "Output must be stereo."); if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; if (inputChannels() > 2) return die("REVERBIT", "Can't have more than 2 input channels."); if (rtsetoutput(outskip, dur + ringdur, this) == -1) return DONT_SCHEDULE; insamps = (int) (dur * SR); if (reverbtime <= 0.0) return die("REVERBIT", "Reverb time must be greater than 0."); if (reverbpct < 0.0 || reverbpct > 1.0) return die("REVERBIT", "Reverb percent must be between 0 and 1 inclusive."); if (rtchan_delaytime <= 0.0) return die("REVERBIT", "Right chan delay time must be greater than 0."); if (cutoff < 0.0) return die("REVERBIT", "Cutoff frequency should be positive (or zero to " "disable filter)."); usefilt = (cutoff > 0.0); if (usefilt) toneset(SR, cutoff, 1, tonedata); else rtcmix_advise("REVERBIT", "Low-pass filter disabled."); float maxdeltime = rtchan_delaytime; // If delay time is very short, make delay line longer than necessary. if (rtchan_delaytime < MIN_DELAY) maxdeltime *= DELAY_FACTOR; int delsamps = (int) (maxdeltime * SR + 0.5); delarray = new float[delsamps]; delset(SR, delarray, deltabs, maxdeltime); // Array dimensions taken from lib/rvbset.c (+ 2 extra for caution). int rvbsamps = (int)((0.1583 * SR) + 18 + 2); rvbarray = new float[rvbsamps]; rvbset(SR, reverbtime, 0, rvbarray); amparray = floc(1); if (amparray) { int amplen = fsize(1); tableset(SR, dur, amplen, amptabs); } prev_in[0] = prev_out[0] = 0.0; // for DC-blocker prev_in[1] = prev_out[1] = 0.0; return nSamps(); }
int CONVOLVE1::init(double p[], int n_args) { const float outskip = p[0]; const float inskip = p[1]; const float indur = p[2]; const float impskip = p[5]; const float impdur = p[6]; if (impdur <= 0.0) return die("CONVOLVE1", "Impulse duration must be greater than zero."); _impgain = p[7]; _wetpct = p[9]; // NB: used before first call to doupdate if (_wetpct < 0.0 || _wetpct > 1.0) return die("CONVOLVE1", "Wet percent must be between 0 and 1."); _inchan = int(p[10]); // Read impulse response table, and set FFT size based on this. _imptab = (double *) getPFieldTable(4, &_imptablen); if (_imptab == NULL) return die("CONVOLVE1", "Must store impulse response in a table."); _impStartIndex = int(impskip * SR + 0.5); if (_impStartIndex >= _imptablen) return die("CONVOLVE1", "Impulse start time exceeds impulse duration."); int impend = _impStartIndex + int(impdur * SR + 0.5); // NOTE: <impend> may be past end of table; we handle that in prepareImpulse. DPRINT2("impend=%d, _imptablen=%d\n", impend, _imptablen); _impframes = impend - _impStartIndex; _halfFFTlen = kMinFFTsize / 2; for ( ; _halfFFTlen < kMaxImpulseFrames; _halfFFTlen *= 2) if (_halfFFTlen >= _impframes) break; _fftlen = 2 * _halfFFTlen; DPRINT2("_impframes=%d, _halfFFTlen=%d\n", _impframes, _halfFFTlen); rtcmix_advise("CONVOLVE1", "Using %d impulse response frames. FFT length is %d.", _impframes, _fftlen); if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; // no input if (_inchan >= inputChannels()) return die("CONVOLVE1", "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. const float latency = float(_impframes) / SR; const float ringdur = latency; if (rtsetoutput(outskip, latency + indur + ringdur, this) == -1) return DONT_SCHEDULE; if (outputChannels() > 2) return die("CONVOLVE1", "Must have mono or stereo output."); _inframes = int(indur * SR + 0.5); // not including latency int winlen; double *wintab = (double *) getPFieldTable(8, &winlen); if (wintab) { if (winlen > 32767) // limit for new fixed-point Ooscili return die("CONVOLVE1", "Window table size must be less than 32768."); const float freq = 1.0 / ((float) _impframes / SR); _winosc = new Ooscili(SR, freq, wintab, winlen); } return nSamps(); }
int BUTTER :: init(double p[], int n_args) { nargs = n_args; float outskip = p[0]; float inskip = p[1]; float dur = p[2]; amp = p[3]; nfilts = n_args > 5 ? (int) p[5] : 1; do_balance = n_args > 6 ? (bool) p[6] : true; inchan = n_args > 7 ? (int) p[7] : 0; // default is chan 0 if (rtsetinput(inskip, this) != 0) return DONT_SCHEDULE; if (inchan >= inputChannels()) return die("BUTTER", "You asked for channel %d of a %d-channel file.", inchan, inputChannels()); const float ringdur = 0.1; if (rtsetoutput(outskip, dur + ringdur, this) == -1) return DONT_SCHEDULE; insamps = (int) (dur * SR + 0.5); if (nfilts < 1 || nfilts > MAXFILTS) return die("BUTTER", "Steepness (p5) must be an integer between 1 and %d.", MAXFILTS); type = getFiltType(true); if (type == FiltInvalid) return die("BUTTER", "Type must be \"lowpass\", \"highpass\", " "\"bandpass\", or \"bandreject\"."); for (int i = 0; i < nfilts; i++) filt[i] = new Butter(SR); balancer = new Balance(SR); balancer->setWindowSize(BALANCE_WINDOW_SIZE); amparray = floc(1); if (amparray) { int lenamp = fsize(1); tableset(SR, dur, lenamp, amptabs); } if (n_args < 11) { // no p10 filter freq PField, must use gen table cfarray = floc(2); if (cfarray == NULL) return die("BUTTER", "Either use the filter frequency pfield (p10) " "or make an old-style gen function in slot 2."); int len = fsize(2); tableset(SR, dur, len, cftabs); } if (type == BandPass || type == BandReject) { if (n_args < 12) { // no p11 filter bandwidth PField, must use gen table bwarray = floc(3); if (bwarray == NULL) return die("BUTTER", "Either use the filter bandwidth pfield (p11) " "or make an old-style gen function in slot 3."); int len = fsize(3); tableset(SR, dur, len, bwtabs); } } skip = (int) (SR / (float) resetval); return nSamps(); }
int PFSCHED::run() { int i; if (firsttime == 1) { double tval = 0.0; // get rid of the compiler warning :-) if (pfbusses[pfbus].thepfield != NULL) tval = pfbusses[pfbus].val; pfbusses[pfbus].thepfield = PFSCHEDpfield; // this is the PField to read Arg targs[MAXDISPARGS]; int nargs, lenindex; // if DYNTABLETOKEN is the first value in the data, it means we need // to construct a new table, based on the current pfield value // and the construction data stored in the data[] array if ( (*(pfbusses[pfbus].thepfield)).doubleValue(0) == DYNTABLETOKEN) { nargs = (int)(*(pfbusses[pfbus].thepfield)).doubleValue(1) + 2; lenindex = 1; targs[0] = "line"; targs[1] = (*(pfbusses[pfbus].thepfield)).doubleValue(2); for (i = 2; i < nargs; i++) { // additional occurrences of DYNTABLETOKEN signal a 'curval', so // use the current pfield value if ( (*(pfbusses[pfbus].thepfield)).doubleValue(i+1) == DYNTABLETOKEN) { targs[i] = tval; } else { targs[i] = (*(pfbusses[pfbus].thepfield)).doubleValue(i+1); } } int len = targs[lenindex]; double *data = NULL; data = new double[len]; if (data == NULL) { die("maketable", "Out of memory."); return NULL; } if (_dispatch_table(targs, nargs, lenindex + 1, &data, &len) != 0) { delete [] data; return NULL; // error message already given } TablePField *table; table = new TablePField(data, len); // replace the pfield with the newly-constructed table pfbusses[pfbus].thepfield = table; } pfbusses[pfbus].percent = 0.0; pfbusses[pfbus].dqflag = 0; // note the subtraction; the PField will be read for the correct duration pfbusses[pfbus].theincr = (SR/(float)resetval)/(double)(nSamps()-(RTBUFSAMPS+1)); pfbusses[pfbus].drawflag = 1; // signal to start reading from the pfield if (set_dq_flag == 1) pfbusses[pfbus].dqflag = 1; firsttime = 0; } i = framesToRun(); increment(i); return i; }
int WAVESHAPE::init(double p[], int n_args) { nargs = n_args; float outskip = p[0]; float dur = p[1]; rawfreq = p[2]; doampnorm = n_args > 10 ? (bool) p[10] : true; if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; if (outputChannels() > 2) return die("WAVESHAPE", "Can't handle more than 2 output channels."); waveform = NULL; int tablelen = 0; if (n_args > 7) { // handle table coming in as optional p7 TablePField waveform = (double *) getPFieldTable(7, &tablelen); } if (waveform == NULL) { waveform = floc(WAVE_GEN_SLOT); if (waveform == NULL) return die("WAVESHAPE", "Either use the wavetable pfield (p7) or make " "an old-style gen function in slot %d.", WAVE_GEN_SLOT); tablelen = fsize(WAVE_GEN_SLOT); } float freq = rawfreq; if (rawfreq < 15.0) freq = cpspch(rawfreq); osc = new Ooscili(SR, freq, waveform, tablelen); xferfunc = NULL; lenxfer = 0; if (n_args > 8) { // handle table coming in as optional p8 TablePField xferfunc = (double *) getPFieldTable(8, &lenxfer); } if (xferfunc == NULL) { xferfunc = floc(XFER_GEN_SLOT); if (xferfunc == NULL) return die("WAVESHAPE", "Either use the transfer function pfield " "(p8) or make an old-style gen function in slot %d.", XFER_GEN_SLOT); lenxfer = fsize(XFER_GEN_SLOT); } indenv = NULL; if (n_args < 10) { // no p9 guide PField, so must use gen table indenv = floc(INDEX_GEN_SLOT); if (indenv == NULL) return die("WAVESHAPE", "Either use the index pfield (p9) or make " "an old-style gen function in slot %d.", INDEX_GEN_SLOT); lenind = fsize(INDEX_GEN_SLOT); tableset(SR, dur, lenind, indtabs); } ampenv = floc(AMP_GEN_SLOT); if (ampenv) { int lenamp = fsize(AMP_GEN_SLOT); tableset(SR, dur, lenamp, amptabs); } setDCBlocker(freq, true); // initialize dc blocking filter skip = (int) (SR / (float) resetval); return nSamps(); }
int MBASE::init(double p[], int n_args) { int flag, UseMikes; float outskip, inskip, abs_factor, dummy; double R, T, dist; outskip = p[0]; inskip = p[1]; m_dur = p[2]; if (m_dur < 0) /* "dur" represents timend */ m_dur = -m_dur - inskip; if (rtsetinput(inskip, this) == -1) { // no input return(DONT_SCHEDULE); } insamps = (int)(m_dur * SR); inamp = p[3]; if (inamp < 0) { m_paths = 1; // Dont process secondary paths inamp = -inamp; } /* Get results of Minc setup calls (space, mikes_on, mikes_off, matrix) */ if (get_setup_params(Dimensions, &m_attenParams, &dummy, &abs_factor, &UseMikes, &MikeAngle, &MikePatternFactor) == -1) { return die(name(), "You must call setup routine `space' first."); } // call inst-specific init code if (localInit(p, n_args) == DONT_SCHEDULE) return die(name(), "localInit failed."); if (m_inchan >= inputChannels()) return die(name(), "You asked for channel %d of a %d-channel input file.", m_inchan, inputChannels()); if (inputChannels() == 1) m_inchan = 0; if (outputChannels() != 4) return die(name(), "Output must be 4-channel (2 signal, 2 reverb feed)."); /* (perform some initialization that used to be in space.c) */ int meanLength = MFP_samps(SR, Dimensions); // mean delay length for reverb get_lengths(meanLength); /* sets up delay lengths */ set_gains(); /* sets gains for filters */ set_walls(abs_factor); /* sets wall filts for move routine */ /* flag for use of ear filters */ m_binaural = (!UseMikes && m_dist < 0.8 && m_dist != 0.0); amparray = floc(1); if (amparray) { int amplen = fsize(1); tableset(SR, m_dur, amplen, amptabs); /* controls input dur only */ } /* determine extra run time for this routine before calling rtsetoutput() */ double reflectionDur = 0.0; finishInit(&reflectionDur); m_branch = 0; if (rtsetoutput(outskip, m_dur + reflectionDur, this) == -1) return DONT_SCHEDULE; DBG1(printf("nsamps = %d\n", nSamps())); return nSamps(); }
int BASE::init(double p[], int n_args) { int UseMikes; float outskip, inskip, abs_factor, rvb_time; outskip = p[0]; inskip = p[1]; m_dur = p[2]; if (m_dur < 0) /* "dur" represents timend */ m_dur = -m_dur - inskip; if (rtsetinput(inskip, this) == -1) { // no input return(DONT_SCHEDULE); } insamps = (int)(m_dur * SR); inamp = p[3]; double Matrix[12][12]; /* Get results of Minc setup calls (space, mikes_on, mikes_off, matrix) */ if (get_setup_params(Dimensions, Matrix, &abs_factor, &rvb_time, &UseMikes, &MikeAngle, &MikePatternFactor) == -1) { return die(name(), "You must call setup routine `space' first."); } // call inst-specific init code if (localInit(p, n_args) == DONT_SCHEDULE) { return die(name(), "localInit failed."); } if (m_inchan >= inputChannels()) { return die(name(), "You asked for channel %d of a %d-channel input file.", m_inchan, inputChannels()); } if (inputChannels() == 1) m_inchan = 0; if (outputChannels() != 2) { return die(name(), "Output must be stereo."); } wire_matrix(Matrix); /* (perform some initialization that used to be in space.c) */ int meanLength = MFP_samps(SR, Dimensions); // mean delay length for reverb get_lengths(meanLength); /* sets up delay lengths */ set_gains(rvb_time); /* sets gains for filters */ set_walls(abs_factor); /* sets wall filts for move routine */ set_allpass(); set_random(); /* sets up random variation of delays */ /* flag for use of ear filters */ m_binaural = (!UseMikes && m_dist < 0.8 && m_dist != 0.0); amparray = floc(1); if (amparray) { int amplen = fsize(1); tableset(SR, m_dur, amplen, amptabs); /* controls input dur only */ } else rtcmix_advise(name(), "Setting phrase curve to all 1's."); /* determine extra run time for this routine before calling rtsetoutput() */ double ringdur = 0.0; finishInit(rvb_time, &ringdur); m_branch = 0; if (rtsetoutput(outskip, m_dur + ringdur, this) == -1) return DONT_SCHEDULE; DBG1(printf("nsamps = %d\n", nSamps())); return nSamps(); }
int JGRAN :: init(double p[], int n_args) { nargs = n_args; float outskip = p[0]; float dur = p[1]; int seed = (int) p[3]; osctype = (p[4] == 0.0) ? AS : FM; randomize_phase = n_args > 5 ? (bool) p[5] : true; // default: yes if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; if (outputChannels() > 2) return die("JGRAN", "Output must be mono or stereo."); amp_table = make_table(1, dur, SR); // get grain envelope table double *function = NULL; int tablelen = 0; if (n_args > 6) { // handle table coming in as optional p6 TablePField function = (double *) getPFieldTable(6, &tablelen); } if (function == NULL) { function = floc(2); if (function == NULL) return die("JGRAN", "Either use the grain envelope pfield (p6) " "or make an old-style gen function in slot 2."); tablelen = fsize(2); } grainenv_oscil = new OscilL(SR, 0.0, function, tablelen); // get grain waveform table and create oscillator(s) function = NULL; tablelen = 0; if (n_args > 7) { // handle table coming in as optional p7 TablePField function = (double *) getPFieldTable(7, &tablelen); } if (function == NULL) { function = floc(3); if (function == NULL) { tablelen = DEFAULT_WAVETABLE_SIZE; rtcmix_advise("JGRAN", "Using sine for grain waveform (no table 3)."); } else tablelen = fsize(3); } car_oscil = new OscilL(SR, 0.0, function, tablelen); if (osctype == FM) mod_oscil = new OscilL(SR, 0.0, function, tablelen); // create additional tables, if corresponding pfield is missing if (osctype == FM) { if (n_args <= 8) { modmult_table = make_table(4, dur, SR); if (modmult_table == NULL) return die("JGRAN", "Either use the modulation frequency " "multiplier pfield (p8) or make an old-style " "gen function in slot 4."); } if (n_args <= 9) { modindex_table = make_table(5, dur, SR); if (modindex_table == NULL) return die("JGRAN", "Either use the index envelope pfield (p9) " "or make an old-style gen function in slot 5."); } } if (n_args <= 10) { minfreq_table = make_table(6, dur, SR); if (minfreq_table == NULL) return die("JGRAN", "Either use the min. grain frequency pfield (p10) " "or make an old-style gen function in slot 6."); } if (n_args <= 11) { maxfreq_table = make_table(7, dur, SR); if (maxfreq_table == NULL) return die("JGRAN", "Either use the max. grain frequency pfield (p11) " "or make an old-style gen function in slot 7."); } if (n_args <= 12) { minspeed_table = make_table(8, dur, SR); if (minspeed_table == NULL) return die("JGRAN", "Either use the min. grain speed pfield (p12) " "or make an old-style gen function in slot 8."); } if (n_args <= 13) { maxspeed_table = make_table(9, dur, SR); if (maxspeed_table == NULL) return die("JGRAN", "Either use the max. grain speed pfield (p13) " "or make an old-style gen function in slot 9."); } if (n_args <= 14) { minintens_table = make_table(10, dur, SR); if (minintens_table == NULL) return die("JGRAN", "Either use the min. grain intensity pfield (p14) " "or make an old-style gen function in slot 10."); } if (n_args <= 15) { maxintens_table = make_table(11, dur, SR); if (maxintens_table == NULL) return die("JGRAN", "Either use the max. grain intensity pfield (p15) " "or make an old-style gen function in slot 11."); } if (n_args <= 16) { density_table = make_table(12, dur, SR); if (density_table == NULL) return die("JGRAN", "Either use the grain density pfield (p16) " "or make an old-style gen function in slot 12."); } if (outputChannels() == 2) { if (n_args <= 17) { pan_table = make_table(13, dur, SR); if (pan_table == NULL) return die("JGRAN", "Either use the pan pfield (p17) or make an " "old-style gen function in slot 13."); } if (n_args <= 18) { panvar_table = make_table(14, dur, SR); if (panvar_table == NULL) return die("JGRAN", "Either use the pan randomization pfield (p18) " "or make an old-style gen function in slot 14."); } } // seed multipliers straight from Piche/Bezkorowajny source durnoi = new JGNoise((unsigned int) seed * 243); freqnoi = new JGNoise((unsigned int) seed * 734); pannoi = new JGNoise((unsigned int) seed * 634); ampnoi = new JGNoise((unsigned int) seed * 824); if (randomize_phase) phasenoi = new JGNoise((unsigned int) seed * 951); krate = resetval; skip = (int) (SR / (float) krate); return nSamps(); }
int PVOC::init(double *p, int n_args) { if (!n_args || n_args < 9) { die("PVOC", "usage:\nPVOC(outskip, inskip, dur, amp, input_chan, fft_size, window_size, decim, interp, [ pitch_mult, npoles, osc threshold ])"); return(DONT_SCHEDULE); } if (outputchans != 1) { die("PVOC", "Output file must have 1 channel only"); return(DONT_SCHEDULE); } float outskip = p[0]; float inskip = p[1]; float dur = p[2]; _amp = p[3]; _inputchannel = (int) p[4]; if (_inputchannel >= inputChannels()) { die("PVOC", "Requesting channel %d of a %d-channel input file", _inputchannel, inputChannels()); return(DONT_SCHEDULE); } if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; // no input if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; // pick up arguments from command line // Note: all these are class vars R = (int)SR; /* sampling rate */ N = (int)p[5]; /* FFT length */ Nw = (int)p[6]; /* window size */ D = (int)p[7]; /* decimation factor */ I = (int)p[8]; /* interpolation factor */ P = p[9]; /* oscillator bank pitch factor */ Np = (int)p[10]; /* linear prediction order */ _oscThreshold = p[11]; /* synthesis threshhold */ /* freopen( "pv.out", "w", stderr ); */ #ifdef debug printf("pv parameters:\n" ); printf("R (samprate) = %d\n", R ); printf("N (fft len) = %d\n", N ); printf("Nw (windowlen) = %d\n", Nw ); printf("D (decimation) = %d\n", D ); printf("I (interpolation) = %d\n", I ); printf("P = %g\n", P ); printf("Np = %d\n", Np ); printf("thresh = %g\n", _oscThreshold ); #endif if (I > Nw) { die("PVOC", "Window size must be >= interpolation factor"); return(DONT_SCHEDULE); } TWOPI = 8.*atan(1.); obank = P != 0.; N2 = N>>1; Nw2 = Nw>>1; if (obank) initOscbank(N2, Np, R, Nw, I, P); // Factors for convert() and unconvert() _fundamental = (float) R / (N2 * 2); _convertFactor = R / (D * TWOPI); _unconvertFactor = TWOPI * I / R; _convertPhase = ::NewArray(N2 + 1); _unconvertPhase = ::NewArray(N2 + 1); // All buffer allocation done in configure() /* * initialize input and output time values (in samples) */ _in = -Nw; if ( D ) _on = (_in*I)/D; else _on = _in; #ifdef debug printf("_in: %d _on: %d\n", _in, _on); #endif // Get pv filter if present ::GetFilter(&_pvFilter); if (_pvFilter) _pvFilter->ref(); return nSamps(); }
/* ----------------------------------------------------------------- init --- */ int MROOM::init(double p[], int n_args) { float outskip = p[0]; float inskip = p[1]; float dur = p[2]; ovamp = p[3]; xdim = p[4]; ydim = p[5]; float rvbtime = p[6]; reflect = p[7]; innerwidth = p[8]; inchan = n_args > 9 ? (int)p[9] : AVERAGE_CHANS; int quant = n_args > 10 ? (int)p[10] : DEFAULT_QUANTIZATION; if (outputchans != 2) return die("MROOM", "Requires stereo output."); float ringdur = (rvbtime > MAX_DELAY) ? rvbtime : MAX_DELAY; if (rtsetoutput(outskip, dur + ringdur, this) == -1) return DONT_SCHEDULE; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; insamps = (int)(dur * SR + 0.5); if (inchan >= inputChannels()) return die("MROOM", "You asked for channel %d of a %d-channel input file.", inchan, inputChannels()); if (inputChannels() == 1) inchan = 0; // ***FIXME: input validation for trajectory points? int ntimes = get_timeset(timepts, xvals, yvals); if (ntimes == 0) return die("MROOM", "Must have at least two timeset calls before MROOM."); traject(ntimes); tableset(SR, dur, POS_ARRAY_SIZE, xpostabs); tableset(SR, dur, POS_ARRAY_SIZE, ypostabs); int delsamps = (int)(MAX_DELAY * SR + 0.5); delayline = new float[delsamps]; delset(SR, delayline, deltabs, MAX_DELAY); /* Array dimensions taken from lib/rvbset.c (+ 2 extra for caution). */ int rvbsamps = (int)((0.1583 * SR) + 18 + 2); rvbarrayl = new float[rvbsamps]; rvbarrayr = new float[rvbsamps]; rvbset(SR, rvbtime, 0, rvbarrayl); rvbset(SR, rvbtime, 0, rvbarrayr); amparray = floc(1); if (amparray) { int amplen = fsize(1); tableset(SR, dur, amplen, amptabs); } else rtcmix_advise("MROOM", "Setting phrase curve to all 1's."); aamp = ovamp; /* in case amparray == NULL */ skip = (int)(SR / (float)resetval); quantskip = (int)(SR / (float)quant); return nSamps(); }
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(); }
int TRANSBEND :: init(double p[], int n_args) { float outskip, inskip, dur, transp, interval = 0, total_indur, dur_to_read; float averageInc; int pgen; if (n_args < 5) { die("TRANSBEND", "Wrong number of args."); return(DONT_SCHEDULE); } outskip = p[0]; inskip = p[1]; dur = p[2]; amp = p[3]; pgen = (int) p[4]; inchan = (n_args > 5) ? (int) p[5] : 0; pctleft = (n_args > 6) ? p[6] : 0.5; if (dur < 0.0) dur = -dur - inskip; if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; if (inchan >= inputChannels()) { return die("TRANSBEND", "You asked for channel %d of a %d-channel file.", inchan, inputChannels()); } pitchtable = floc(pgen); if (pitchtable) { int plen = fsize(pgen); float isum = 0; for (int loc = 0; loc < plen; loc++) { float pch = pitchtable[loc]; isum += octpch(pch); } interval = isum / plen; #ifdef DEBUG printf("average interval: %g\n", interval); #endif tableset(SR, dur, plen, ptabs); } else { die("TRANSBEND", "Unable to load pitch curve (table %d)!", pgen); return(DONT_SCHEDULE); } averageInc = (double) cpsoct(10.0 + interval) / cpsoct(10.0); #ifdef NOTYET total_indur = (float) m_DUR(NULL, 0); dur_to_read = dur * averageInc; if (inskip + dur_to_read > total_indur) { warn("TRANSBEND", "This note will read off the end of the input file.\n" "You might not get the envelope decay you " "expect from setline.\nReduce output duration."); /* no exit() */ } #endif /* total number of frames to read during life of inst */ in_frames_left = (int) (nSamps() * averageInc + 0.5); /* to trigger first read in run() */ inframe = RTBUFSAMPS; amptable = floc(1); if (amptable) { int amplen = fsize(1); tableset(SR, dur, amplen, tabs); } else rtcmix_advise("TRANSBEND", "Setting phrase curve to all 1's."); skip = (int) (SR / (float) resetval); return nSamps(); }
int SHAPE :: init(double p[], int n_args) { nargs = n_args; float outskip = p[0]; float inskip = p[1]; float dur = p[2]; amp = p[3]; min_index = p[4]; max_index = p[5]; int ampnorm_genno = (int) p[6]; inchan = n_args > 7 ? (int) p[7] : 0; /* default is chan 0 */ if (n_args < 7) return die("SHAPE", "Needs at least 7 arguments."); if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; if (inchan >= inputChannels()) return die("SHAPE", "You asked for channel %d of a %d-channel file.", inchan, inputChannels()); if (max_index < min_index) return die("SHAPE", "Max. distortion index must not be less than min. index."); double *function = floc(1); if (function) { int len = fsize(1); amp_table = new TableL(SR, dur, function, len); } function = NULL; int tablelen = 0; if (n_args > 9) { // handle table coming in as optional p9 TablePField function = (double *) getPFieldTable(9, &tablelen); } if (function == NULL) { function = floc(2); if (function == NULL) return die("SHAPE", "Either use the transfer function pfield (p9) " "or make an old-style gen function in slot 2."); tablelen = fsize(2); } shaper = new WavShape(); shaper->setTransferFunc(function, tablelen); function = NULL; if (n_args < 11) { // no p10 guide PField, must use gen table function = floc(3); if (function) { int len = fsize(3); index_table = new TableL(SR, dur, function, len); } else rtcmix_advise("SHAPE", "Setting distortion index curve to all 1's."); } /* Construct the <ampnorm> WavShape object if (1) p6 is a TablePField, or (2) if p6 is non-zero, in which case use p6 as the gen slot for the amp norm function. If p6 is zero, then don't construct <ampnorm>. */ function = NULL; const PField &field = getPField(6); tablelen = field.values(); function = (double *) field; if (function == NULL) { // no table pfield if (ampnorm_genno > 0) { function = floc(ampnorm_genno); if (function == NULL) return die("SHAPE", "You specified table %d as the amplitude " "normalization function, but you didn't create the table.", ampnorm_genno); tablelen = fsize(ampnorm_genno); } } if (function) { ampnorm = new WavShape(); ampnorm->setTransferFunc(function, tablelen); } dcblocker = new DCBlock(); skip = (int) (SR / (float) resetval); return nSamps(); }
/* Called by the scheduler for every time slice in which this instrument should run. This is where the real work of the instrument is done. */ int LPCPLAY::run() { int n = 0; float out[2]; /* Space for only 2 output chans! */ #if 0 printf("\nLPCPLAY::run()\n"); #endif // Samples may have been left over from end of previous run's block if (_leftOver > 0) { int toAdd = min(_leftOver, framesToRun()); #ifdef debug printf("using %d leftover samps starting at offset %d\n", _leftOver, _savedOffset); #endif rtbaddout(&_alpvals[_savedOffset], toAdd); increment(toAdd); n += toAdd; _leftOver -= toAdd; _savedOffset += toAdd; } /* framesToRun() returns the number of sample frames -- 1 sample for each channel -- that we have to write during this scheduler time slice. */ for (; n < framesToRun(); n += _counter) { double p[12]; update(p, 12); _amp = p[2]; _pitch = p[3]; _transposition = ABS(_pitch); _warpFactor = p[6]; _reson_is_on = p[7] ? true : false; _cf_fact = p[7]; _bw_fact = p[8]; int loc; if ( _unvoiced_rate && !_voiced ) { ++_frameno; /* if unvoiced set to normal rate */ } else { _frameno = _frame1 + ((float)(currentFrame())/nSamps()) * _frames; } #if 0 printf("frame %g\n", _frameno); #endif if (_dataSet->getFrame(_frameno,_coeffs) == -1) break; // If requested, stabilize this frame before using if (_autoCorrect) stabilize(_coeffs, _nPoles); float buzamp = getVoicedAmp(_coeffs[THRESH]); _voiced = (buzamp > 0.1); /* voiced = 0 for 10:1 noise */ float noisamp = (1.0 - buzamp) * _randamp; /* for now */ _ampmlt = _amp * _coeffs[RESIDAMP]; if (_coeffs[RMSAMP] < _cutoff) _ampmlt = 0; float cps = tablei(currentFrame(),_pchvals,_tblvals); float newpch = cps; // If input pitch was specified as -X.YZ, use this as actual pitch if ((_pitch < 0) && (ABS(_pitch) >= 1)) newpch = _transposition; if (_reson_is_on) { /* If _cf_fact is greater than 20, treat as absolute freq. Else treat as factor. If _bw_fact is greater than 20, treat as absolute freq. Else treat as factor (i.e., cf * factor == bw). */ float cf = (_cf_fact < 20.0) ? _cf_fact*cps : _cf_fact; float bw = (_bw_fact < 20.0) ? cf * _bw_fact : _bw_fact; rszset(SR, cf, bw, 1., _rsnetc); #ifdef debug printf("cf %g bw %g cps %g\n", cf, bw,cps); #endif } float si = newpch * _magic; float *cpoint = _coeffs + 4; if (_warpFactor != 0.0) { float warp = (_warpFactor > 1.) ? .0001 : _warpFactor; _ampmlt *= _warpPole.set(warp, cpoint, _nPoles); } if (_hnfactor < 1.0) { buzamp *= _hnfactor; /* compensate for gain increase */ } float hn = (_hnfactor <= 1.0) ? (int)(_hnfactor*_srd2/newpch)-2 : _hnfactor; _counter = int(((float)SR/(newpch * _perperiod) ) * .5); _counter = (_counter > (nSamps() - currentFrame())) ? nSamps() - currentFrame() : _counter; #ifdef debug printf("fr: %g err: %g bzamp: %g noisamp: %g pch: %g ctr: %d\n", _frameno,_coeffs[THRESH],_ampmlt*buzamp,_ampmlt*noisamp,newpch,_counter); #endif if (_counter <= 0) break; // Catch bad pitches which generate array overruns else if (_counter > _arrayLen) { rtcmix_warn("LPCPLAY", "Counter exceeded array size -- limiting. Frame pitch: %f", newpch); _counter = _arrayLen; } bbuzz(_ampmlt*buzamp,si,hn,_sineFun,&_phs,_buzvals,_counter); #ifdef debug printf("\t _buzvals[0] = %g\n", _buzvals[0]); #endif l_brrand(_ampmlt*noisamp,_noisvals,_counter); /* TEMPORARY */ #ifdef debug printf("\t _noisvals[0] = %g\n", _noisvals[0]); #endif for (loc=0; loc<_counter; loc++) { _buzvals[loc] += _noisvals[loc]; /* add voiced and unvoiced */ } if (_warpFactor) { float warp = (_warpFactor > 1.) ? shift(_coeffs[PITCH],newpch,(float)SR) : _warpFactor; #ifdef debug printf("\tpch: %f newpch: %f d: %f\n",_coeffs[PITCH], newpch, warp); #endif /************* warp = ABS(warp) > .2 ? SIGN(warp) * .15 : warp; ***************/ _warpPole.run(_buzvals, warp, cpoint, _alpvals, _counter); } else { ballpole(_buzvals,&_jcount,_nPoles,_past,cpoint,_alpvals,_counter); } #ifdef debug { int x; float maxamp=0; for (x=0;x<_counter;x++) { if (ABS(_alpvals[x]) > ABS(maxamp)) maxamp = _alpvals[x]; } printf("\t maxamp = %g\n", maxamp); } #endif if (_reson_is_on) bresonz(_alpvals,_rsnetc,_alpvals,_counter); // Apply envelope last float envelope = evp(currentFrame(),_envFun,_envFun,_evals); bmultf(_alpvals, envelope, _counter); int sampsToAdd = min(_counter, framesToRun() - n); /* Write this block to the output buffer. */ rtbaddout(_alpvals, sampsToAdd); /* Keep track of how many sample frames this instrument has generated. */ increment(sampsToAdd); } // Handle case where last synthesized block extended beyond framesToRun() if (n > framesToRun()) { _leftOver = n - framesToRun(); _savedOffset = _counter - _leftOver; #ifdef debug printf("saving %d samples left over at offset %d\n", _leftOver, _savedOffset); #endif } return framesToRun(); }
int FREEVERB :: init(double p[], int n_args) { float outskip = p[0]; float inskip = p[1]; float dur = p[2]; roomsize = p[4]; predelay_time = p[5]; ringdur = p[6]; damp = p[7]; dry = p[8]; wet = p[9]; width = p[10]; // Keep reverb comb feedback <= 1.0 max_roomsize = (1.0 - offsetroom) / scaleroom; if (roomsize < 0.0) return die("FREEVERB", "Room size must be between 0 and %g.", max_roomsize); if (roomsize > max_roomsize) { roomsize = max_roomsize; rtcmix_advise("FREEVERB", "Room size cannot be greater than %g. Adjusting...", max_roomsize); } int predelay_samps = (int) ((predelay_time * SR) + 0.5); if (predelay_samps > max_predelay_samps) return die("FREEVERB", "Pre-delay must be between 0 and %g seconds.", (float) max_predelay_samps / SR); if (damp < 0.0 || damp > 100.0) return die("FREEVERB", "Damp must be between 0 and 100%%."); if (dry < 0.0 || dry > 100.0) return die("FREEVERB", "Dry signal level must be between 0 and 100%%."); if (wet < 0.0 || wet > 100.0) return die("FREEVERB", "Wet signal level must be between 0 and 100%%."); if (width < 0.0 || width > 100.0) return die("FREEVERB", "Width must be between 0 and 100%%."); if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; if (rtsetoutput(outskip, dur + ringdur, this) == -1) return DONT_SCHEDULE; insamps = (int) (dur * SR); if (inputChannels() > 2) return die("FREEVERB", "Can't have more than 2 input channels."); if (outputChannels() > 2) return die("FREEVERB", "Can't have more than 2 output channels."); rvb = new revmodel(); rvb->setroomsize(roomsize); rvb->setpredelay(predelay_samps); rvb->setdamp(damp * 0.01); rvb->setdry(dry * 0.01); rvb->setwet(wet * 0.01); rvb->setwidth(width * 0.01); amparray = floc(1); if (amparray) { int lenamp = fsize(1); tableset(SR, dur, lenamp, amptabs); } return nSamps(); }
int VOCODE3::init(double p[], int n_args) { _nargs = n_args; if (_nargs < 11) return usage(); const float outskip = p[0]; const float inskip = p[1]; const float dur = p[2]; if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; if (outputChannels() > 2) return die("VOCODE3", "Output must be either mono or stereo."); if (inputChannels() != 2) return die("VOCODE3", "Must use 2 input channels: 'left' for carrier; 'right' for modulator."); _modtable_src = (double *) getPFieldTable(4, &_numfilts); if (_modtable_src == NULL) return die("VOCODE3", "p4 must have the modulator center freq. table."); int len; _cartable_src = (double *) getPFieldTable(5, &len); if (_cartable_src == NULL) return die("VOCODE3", "p5 must have the carrier center freq. table."); if (len != _numfilts) return die("VOCODE3", "Modulator and carrier center freq. tables must " "be the same size."); _modtable_prev = new double [_numfilts]; // these two arrays inited below _cartable_prev = new double [_numfilts]; _maptable_src = (double *) getPFieldTable(6, &len); if (_maptable_src && (len != _numfilts)) return die("VOCODE3", "Center freq. mapping table (p6) must be the same " "size as the modulator and carrier tables."); _maptable = new int [_numfilts]; if (_maptable_src) { for (int i = 0; i < _numfilts; i++) _maptable[i] = int(_maptable_src[i]); } else { // no user mapping table; make linear mapping for (int i = 0; i < _numfilts; i++) _maptable[i] = i; } _scaletable = (double *) getPFieldTable(7, &len); if (_scaletable && (len != _numfilts)) return die("VOCODE3", "The carrier scaling table must be the same size " "(%d elements) as the carrier frequency table.", _numfilts); _modtransp = p[8]; _cartransp = p[9]; _modq = p[10]; _carq = p[11]; _lastmod = new float [_numfilts]; _modulator_filt = new Oequalizer * [_numfilts]; _carrier_filt = new Oequalizer * [_numfilts]; _balancer = new Obalance * [_numfilts]; #ifdef NOTYET const bool print_stats = Option::printStats(); #else const bool print_stats = true; #endif if (print_stats) { rtcmix_advise(NULL, "VOCODE3: mod. CF\tcar. CF [Hz, after transp]"); rtcmix_advise(NULL, " (Q=%2.1f)\t(Q=%2.1f)", _modq, _carq); rtcmix_advise(NULL, " -----------------------------------------"); } for (int i = 0; i < _numfilts; i++) { _modulator_filt[i] = new Oequalizer(SR, kBandPassType); _modtable_prev[i] = _modtable_src[i]; float mfreq = updateFreq(_modtable_src[i], _modtransp); _modulator_filt[i]->setparams(mfreq, _modq); _carrier_filt[i] = new Oequalizer(SR, kBandPassType); _cartable_prev[i] = _cartable_src[i]; float cfreq = updateFreq(_cartable_src[i], _cartransp); _carrier_filt[i]->setparams(cfreq, _carq); _balancer[i] = new Obalance(SR); _lastmod[i] = 0.0f; // not necessary if (print_stats) rtcmix_advise(NULL, " %7.1f\t%7.1f", mfreq, cfreq); } return nSamps(); }
int WIGGLE::init(double p[], int n_args) { const float outskip = p[0]; const float dur = p[1]; depth_type = (n_args > 4) ? getDepthType(p[4]) : NoModOsc; filter_type = (n_args > 5) ? getFiltType(p[5]) : NoFilter; float ringdur; if (filter_type == NoFilter) { nfilts = 0; ringdur = 0.0f; } else { if (filter_type != LowPass && filter_type != HighPass) return die("WIGGLE", "Filter type (p5) must be 0, 1, or 2."); nfilts = (n_args > 6) ? int(p[6]) : 1; if (nfilts < 1 || nfilts > MAXFILTS) return die("WIGGLE", "Steepness (p6) must be an integer between 1 and %d.", MAXFILTS); if (n_args > 7) do_balance = bool(p[7]); if (do_balance) { balancer = new Balance(SR); balancer->setWindowSize(BALANCE_WINDOW_SIZE); } ringdur = 0.1f; } if (rtsetoutput(outskip, dur + ringdur, this) == -1) return DONT_SCHEDULE; if (outputChannels() < 1 || outputChannels() > 2) return die("WIGGLE", "Output must be mono or stereo."); for (int i = 0; i < nfilts; i++) filt[i] = new Butter(SR); double *array = floc(AMP_FUNC); if (array) { int len = fsize(AMP_FUNC); amp_table = new TableL(SR, dur, array, len); } int len; if (n_args > 8) carwave_array = (double *) getPFieldTable(8, &len); if (carwave_array == NULL) { carwave_array = floc(CAR_WAVE_FUNC); if (carwave_array == NULL) return die("WIGGLE", "Either use the carrier wavetable pfield (p8), " "or make an old-style gen function in slot %d.", CAR_WAVE_FUNC); len = fsize(CAR_WAVE_FUNC); } carrier = new OscilL(SR, 0.0, carwave_array, len); array = floc(CAR_GLISS_FUNC); if (array) { len = fsize(CAR_GLISS_FUNC); cargliss_table = new TableN(SR, dur, array, len); } if (depth_type != NoModOsc) { if (n_args > 9) modwave_array = (double *) getPFieldTable(9, &len); if (modwave_array == NULL) { modwave_array = floc(MOD_WAVE_FUNC); if (modwave_array == NULL) return die("WIGGLE", "Either use the modulator wavetable pfield " "(p9), or make an old-style gen function " "in slot %d.", MOD_WAVE_FUNC); len = fsize(MOD_WAVE_FUNC); } modulator = new OscilL(SR, 0.0, modwave_array, len); array = floc(MOD_FREQ_FUNC); if (array) { len = fsize(MOD_FREQ_FUNC); modfreq_table = new TableL(SR, dur, array, len); } else if (n_args < 11) // no p10 mod freq return die("WIGGLE", "Either use the modulator frequency pfield " "(p10), or make an old-style gen function in " "slot %d.", MOD_FREQ_FUNC); array = floc(MOD_DEPTH_FUNC); if (array) { len = fsize(MOD_DEPTH_FUNC); moddepth_table = new TableL(SR, dur, array, len); } else if (n_args < 12) // no p11 mod depth return die("WIGGLE", "Either use the modulator depth pfield " "(p11), or make an old-style gen function in " "slot %d.", MOD_DEPTH_FUNC); } if (filter_type != NoFilter) { array = floc(FILTER_CF_FUNC); if (array) { len = fsize(FILTER_CF_FUNC); filtcf_table = new TableL(SR, dur, array, len); } else if (n_args < 13) // no p12 filter cf return die("WIGGLE", "Either use the filter cutoff frequency pfield " "(p12), or make an old-style gen function in " "slot %d.", FILTER_CF_FUNC); } if (outputChannels() == 2) { array = floc(PAN_FUNC); if (array) { len = fsize(PAN_FUNC); pan_table = new TableL(SR, dur, array, len); } else if (n_args < 14) // no p13 pan return die("WIGGLE", "Either use the pan pfield (p13), or make an " "old-style gen function in slot %d.", PAN_FUNC); } cpsoct10 = cpsoct(10.0); return nSamps(); }
int VSTART1::init(double p[], int n_args) { // p0 = start; p1 = dur; p2 = pitch (oct.pc); p3 = fundamental decay time // p4 = nyquist decay time; p5 = distortion gain; p6 = feedback gain // p7 = feedback pitch (oct.pc); p8 = clean signal level // p9 = distortion signal level; p10 = amp; p11 = squish // p12 = low vibrato freq range; p13 = hi vibrato freq range // p14 = vibrato freq depth (expressed in cps); p15 = random seed value // p16 = pitch update (default 200/sec) // p17 = stereo spread [optional] // p18 = flag for deleting pluck arrays (used by FRET, BEND, etc.) [optional] // assumes makegen 1 is the amplitude envelope, makegen 2 is the vibrato // function, and makegen 3 is the vibrato amplitude envelope if (rtsetoutput(p[0], p[1], this) == -1) return DONT_SCHEDULE; strumq1 = new StrumQueue; strumq1->ref(); curstrumq[0] = strumq1; freq = cpspch(p[2]); tf0 = p[3]; tfN = p[4]; sset(SR, freq, tf0, tfN, strumq1); randfill(1.0, (int)p[11], strumq1); dq = new DelayQueue; dq->ref(); curdelayq = dq; delayset(SR, cpspch(p[7]), dq); delayclean(dq); amp = p[10]; amptable = floc(1); if (amptable) { int amplen = fsize(1); tableset(SR, p[1], amplen, amptabs); } else { rtcmix_advise("VSTART1", "Setting phrase curve to all 1's."); aamp = amp; } vloc = floc(2); if (vloc == NULL) return die("VSTART1", "You need to store a vibrato function in gen num. 2."); vlen = fsize(2); vsibot = p[12] * (float)vlen/SR; vsidiff = vsibot - (p[13] * (float)vlen/SR); srrand((int)p[15]); vsi = ((rrand()+1.0)/2.0) * vsidiff; vsi += vsibot; vphase = 0.0; eloc = floc(3); if (eloc == NULL) return die("VSTART1", "You need to store a vibrato amp. envelope in gen num. 3."); int elen = fsize(3); tableset(SR, p[1], elen, tab); dgain = p[5]; fbgain = p[6]/dgain; cleanlevel = p[8]; distlevel = p[9]; vdepth = p[14]; reset = (int)p[16]; if (reset == 0) reset = 200; spread = p[17]; deleteflag = (int)p[18]; d = 0.0; return nSamps(); }