int FMINST::init(double p[], int n_args) { nargs = n_args; float outskip = p[0]; float dur = p[1]; if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; if (outputChannels() > 2) return die("FMINST", "Can't handle more than 2 output channels."); carfreqraw = p[3]; if (carfreqraw < 15.0) carfreq = cpspch(carfreqraw); else carfreq = carfreqraw; modfreqraw = p[4]; if (modfreqraw < 15.0) modfreq = cpspch(modfreqraw); else modfreq = modfreqraw; double *wavetable = NULL; int tablelen = 0; if (n_args > 8) { // handle table coming in as optional p8 TablePField wavetable = (double *) getPFieldTable(8, &tablelen); } if (wavetable == NULL) { wavetable = floc(WAVET_GEN_SLOT); if (wavetable == NULL) return die("FMINST", "Either use the wavetable pfield (p8) or make " "an old-style gen function in slot %d.", WAVET_GEN_SLOT); tablelen = fsize(WAVET_GEN_SLOT); } carosc = new Ooscili(SR, carfreq, wavetable, tablelen); modosc = new Ooscili(SR, modfreq, wavetable, tablelen); if (n_args < 10) { // no p9 guide PField, must use gen table indexenv = floc(INDEX_GEN_SLOT); if (indexenv == NULL) return die("FMINST", "Either use the index guide pfield (p9) or make " "an old-style gen function in slot %d.", INDEX_GEN_SLOT); int len = fsize(INDEX_GEN_SLOT); tableset(SR, dur, len, indtabs); } initamp(dur, p, 2, 1); if (fastUpdate) { minindex = p[5]; indexdiff = p[6] - minindex; pan = p[7]; } return nSamps(); }
int BEND1::init(double p[], int n_args) { // p0 = start; p1 = dur; p2 = pitch0 (oct.pc); p3 = pitch1 (oct.pc) // p4 = gliss function #; p5 = fundamental decay time // p6 = nyquist decay time; p7 = distortion gain; p8 = feedback gain // p9 = feedback pitch (oct.pc); p10 = clean signal level // p11 = distortion signal level; p12 = amp; p13 = update gliss nsamples // p14 = stereo spread [optional] float dur = p[1]; if (rtsetoutput(p[0], dur, this) == -1) return DONT_SCHEDULE; strumq1 = curstrumq[0]; freq0 = cpspch(p[2]); diff = cpspch(p[3]) - freq0; tf0 = p[5]; tfN = p[6]; sset(SR, freq0, tf0, tfN, strumq1); dq = curdelayq; delayset(SR, cpspch(p[9]), dq); amp = p[12]; amptable = floc(1); if (amptable) { int amplen = fsize(1); tableset(SR, dur, amplen, amptabs); } else { rtcmix_advise("BEND1", "Setting phrase curve to all 1's."); aamp = amp; } glissf = floc((int)p[4]); if (glissf) { int leng = fsize((int)p[4]); tableset(SR, p[1],leng,tags); } else return die("BEND1", "You haven't made the glissando function (table %d).", (int)p[4]); dgain = p[7]; fbgain = p[8]/dgain; cleanlevel = p[10]; distlevel = p[11]; reset = (int)p[13]; if (reset == 0) reset = 100; spread = p[14]; d = 0.0; return nSamps(); }
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 strumq; 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(); }
/* setup filters for IIR instruments p0 - center frequency if < 15, indicates oct.pc format instead of Hz if negative, abs. value is multiplier of first frequency given p1 - bandwidth (Hz) if negative, abs. value is percent (from 0 to 1) of frequency p2 - amplitude multiplier followed by additional triplets for a total of 64 filters. */ double IIR_setup(float p[], int n_args) { int i, j; float first = 1.0f; rtcmix_advise("IIR setup", "centerfreq bandwidth relative amp"); for (i = 0, j = 0; i < n_args; i += 3, j++) { float cf, bw, amp; if (j == MAXFILTER) return die("IIR setup", "Can't have more than %d filters.", MAXFILTER); if (p[i] < 0.0) cf = -p[i] * first; else cf = (p[i] < 15.0) ? cpspch(p[i]) : p[i]; if (i == 0) first = cf; bw = p[i + 1] < 0.0 ? -p[i + 1] * cf : p[i + 1]; amp = p[i + 2]; _filter_spec[j].cf = cf; _filter_spec[j].bw = bw; _filter_spec[j].amp = amp; rtcmix_advise(NULL, " %10.4f %10.4f %10.4f", cf, bw, amp); } _num_filters = j; return (double) _num_filters; }
int STRUM2::init(double p[], int n_args) { _nargs = n_args; const float outskip = p[0]; const float dur = p[1]; if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; if (outputChannels() > 2) return die("STRUM2", "Use mono or stereo output only."); _rawfreq = p[3]; float freq = (_rawfreq < 15.0) ? cpspch(_rawfreq) : _rawfreq; int squish = int(p[4]); float fundDecayTime = p[5]; if (fundDecayTime < kMinDecay) fundDecayTime = kMinDecay; float nyquistDecayTime = fundDecayTime * 0.1; _strum = new Ostrum(SR, freq, squish, fundDecayTime, nyquistDecayTime); return nSamps(); }
void FMINST::doupdate() { double p[10]; update(p, 10); amp = p[2]; if (amptable) amp *= tablei(currentFrame(), amptable, amptabs); if (p[3] != carfreqraw) { carfreqraw = p[3]; if (carfreqraw < 15.0) carfreq = cpspch(carfreqraw); else carfreq = carfreqraw; } if (p[4] != modfreqraw) { modfreqraw = p[4]; if (modfreqraw < 15.0) modfreq = cpspch(modfreqraw); else modfreq = modfreqraw; modosc->setfreq(modfreq); } minindex = p[5]; float maxindex = p[6]; if (minindex > maxindex) { // swap if wrong order float tmp = minindex; minindex = maxindex; maxindex = tmp; } float guide; if (nargs > 9) // guide pfield is present guide = p[9]; else // backward-compatible gen table guide = tablei(currentFrame(), indexenv, indtabs); float index = minindex + ((maxindex - minindex) * guide); peakdev = index * modfreq; pan = p[7]; }
int COMBFILT::init(double p[], int n_args) { // p0 = outsk; p1 = insk; p2 = input dur; p3 = amp mult // p4 = pitch; p5 = a (input mult); p6 = b (delay mult); // p7 = filter type (FIR/IIR) // p8 = wetdry; p9 = inchan [optional]; p10 = spread [optional] // p11 = rise // p12 = sustain // p13 = decay // assumes function table 1 is the amplitude envelope if (rtsetinput(p[1], this) != 0) return DONT_SCHEDULE; if (rtsetoutput(p[0], p[2], this) != 0) return DONT_SCHEDULE; insamps = (int)(p[2] * SR); if (p[4] < 15.0) combfreq = cpspch(p[4]); else combfreq = p[4]; // FIXME: need check here: combfreq < SR/2 delay = (int)rint(SR/combfreq); amptable = floc(1); if (amptable) { int amplen = fsize(1); tableset(SR, p[2], amplen, tabs); } else rtcmix_advise("COMBFILT", "Setting phrase curve to all 1's."); amp = p[3]; a = p[5]; b = p[6]; // FIXME: need check here: type < 2 type = (int)p[7]; skip = (int)(SR/(float)resetval); // how often to update amp curve inchan = (int)p[9]; if ((inchan+1) > inputChannels()) return die("COMBFILT", "You asked for channel %d of a %d-channel file.", inchan,inputChannels()); wetdry = p[8]; spread = p[10]; maxdelay = (int)rint(SR); runsamp = 0; return(this->mytag); }
void WAVY::doupdate() { double p[10]; update(p, 10, 1 << 2 | 1 << 3 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 9); _amp = p[2]; if (p[3] != _freqAraw) { _freqAraw = p[3]; _freqA = (_freqAraw < 15.0) ? cpspch(_freqAraw) : _freqAraw; _oscilA->setfreq(_freqA); if (p[4] == 0.0) { _freqB = _freqA; _oscilB->setfreq(_freqB); } } if (p[4] != 0.0 && p[4] != _freqBraw) { _freqBraw = p[4]; _freqB = (_freqBraw < 15.0) ? cpspch(_freqBraw) : _freqBraw; _oscilB->setfreq(_freqB); } if (p[5] != _phaseOffset) { _phaseOffset = p[5]; // Get current phase of oscilA; offset oscilB phase from this by // _phaseOffset, in units relative to wavetable lengths. We try to // handle the case where the two freqs are different. const int lenB = _oscilB->getlength(); const double phaseA = _oscilA->getphase() / _oscilA->getlength(); const double freqscale = _freqB / _freqA; double phase = (phaseA + (_phaseOffset * freqscale)) * lenB; while (phase >= double(lenB)) phase -= double(lenB); _oscilB->setphase(phase); } _pan = (_nargs > 9) ? p[9] : 0.5f; }
int main(int argc, char *argv[]) { int i; if(argc == 1) { printf("you must specify pitch in 8ve.pc form\n"); exit(0); } for(i=1; i< argc; i++) printf("%f = %f\n",atof(argv[i]),cpspch(atof(argv[i]))); return 0; }
void STRUM2::doupdate() { double p[7]; update(p, 7, 1 << 2 | 1 << 3 | 1 << 6); _amp = p[2]; if (p[3] != _rawfreq) { _rawfreq = p[3]; float freq = (_rawfreq < 15.0) ? cpspch(_rawfreq) : _rawfreq; _strum->setfreq(freq); } _pan = (_nargs > 6) ? p[6] : 0.5; // default is .5 }
void WAVETABLE::doupdate() { double p[5]; update(p, 5, 1 << 2 | 1 << 3 | 1 << 4); amp = p[2]; if (amptable) amp *= tablei(currentFrame(), amptable, amptabs); if (p[3] != freqraw) { freqraw = p[3]; float freq = (freqraw < 15.0) ? cpspch(freqraw) : freqraw; osc->setfreq(freq); } spread = p[4]; }
int WAVETABLE::init(double p[], int n_args) { float outskip = p[0]; float dur = p[1]; if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; if (outputChannels() > 2) return die("WAVETABLE", "Can't handle more than 2 output channels."); initamp(dur, p, 2, AMP_GEN_SLOT); freqraw = p[3]; float freq; if (freqraw < 15.0) freq = cpspch(freqraw); else freq = freqraw; spread = p[4]; wavetable = NULL; int tablelen = 0; if (n_args > 5) // handle table coming in as optional p5 TablePField wavetable = (double *) getPFieldTable(5, &tablelen); if (wavetable == NULL) { wavetable = floc(WAVET_GEN_SLOT); if (wavetable) tablelen = fsize(WAVET_GEN_SLOT); else { rtcmix_advise("WAVETABLE", "No wavetable specified, so using sine wave."); tablelen = 1024; wavetable = new double [tablelen]; ownWavetable = true; const double twopi = M_PI * 2.0; for (int i = 0; i < tablelen; i++) wavetable[i] = sin(twopi * ((double) i / tablelen)); } } if (tablelen > 32767) return die("WAVETABLE", "wavetable must have fewer than 32768 samples."); osc = new Ooscili(SR, freq, wavetable, tablelen); return nSamps(); }
void WAVESHAPE::doupdate() { double p[10]; update(p, 10, kFreq | kMinIndex | kMaxIndex | kAmp | kPan | kIndex); if (rawfreq != p[2]) { rawfreq = p[2]; float freq = rawfreq; if (rawfreq < 15.0) freq = cpspch(rawfreq); osc->setfreq(freq); setDCBlocker(freq, false); } float min_index = p[3]; float max_index = p[4]; if (max_index < min_index) max_index = min_index; float rawamp = p[5]; if (ampenv) rawamp *= tablei(currentFrame(), ampenv, amptabs); spread = p[6]; float rawindex; if (nargs > 9) rawindex = p[9]; else rawindex = tablei(currentFrame(), indenv, indtabs); index = min_index + ((max_index - min_index) * rawindex); if (doampnorm) amp = index ? rawamp / index : 0.0; else amp = rawamp; }
void WIGGLE::doupdate() { double p[14]; update(p, 14, 1 << 2 | 1 << 3 | 1 << 8 | 1 << 9 | 1 << 10 | 1 << 11 | 1 << 12 | 1 << 13); amp = p[2]; if (amp_table) amp *= amp_table->tick(currentFrame(), 1.0); if (p[3] != car_freq_raw) { car_freq_raw = p[3]; if (car_freq_raw < 15.0f) base_car_freq = cpspch(car_freq_raw); else base_car_freq = car_freq_raw; } // back-compat for gliss gen function if (cargliss_table) { float gliss = cargliss_table->tick(currentFrame(), 1.0); gliss = cpsoct(10.0 + gliss) / cpsoct10; car_freq = base_car_freq * gliss; } else car_freq = base_car_freq; if (depth_type != NoModOsc) { // guaranteed to have either the gen or the pfield mod_freq = modfreq_table ? modfreq_table->tick(currentFrame(), 1.0) : p[10]; if (mod_freq < 0.0f) // negative value acts as ratio flag mod_freq *= -car_freq; // guaranteed to have either the gen or the pfield mod_depth = moddepth_table ? moddepth_table->tick(currentFrame(), 1.0) : p[11]; if (depth_type == CarPercent) mod_depth *= 0.01f; } if (filter_type != NoFilter) { // guaranteed to have either the gen or the pfield float cf = filtcf_table ? filtcf_table->tick(currentFrame(), 1.0) : p[12]; if (cf != cf_raw) { if (cf <= 0.0f) cf = 1.0f; if (cf > nyquist) cf = nyquist; if (filter_type == LowPass) { for (int i = 0; i < nfilts; i++) filt[i]->setLowPass(cf); } else if (filter_type == HighPass) { for (int i = 0; i < nfilts; i++) filt[i]->setHighPass(cf); } cf_raw = cf; } } pan = pan_table ? pan = pan_table->tick(currentFrame(), 1.0) : p[13]; #ifdef DEBUG1 printf("amp=%f cfreq=%f mfreq=%f mdpth=%f pan=%f\n", amp, car_freq, mod_freq, mod_depth, pan); #endif }
double m_diapason(float p[], int n_args, double pp[]) { diap = (pp[0]<18.0) ? cpspch(pp[0]) : pp[0]; octaveOffset = (n_args>1) ? pp[1] : 8.0; return 0; }
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(); }
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 LPCPLAY::localInit(double p[], int n_args) { int i; if (!n_args || n_args < 6) return die("LPCPLAY", "p[0]=starting time, p[1]=duration, p[2]=amp, p[3]=pitch, p[4]=frame1, p[5]=frame2, [ p[6]=warp p7=resoncf, p8=resonbw [ p9--> pitchcurves ] ]\n"); /* Store pfields in variables, to allow for easy pfield renumbering. You should retain the RTcmix numbering convention for the first 4 pfields: outskip, inskip, dur, amp; or, for instruments that take no input: outskip, dur, amp. */ float outskip = p[0]; float ldur = p[1]; _amp = p[2]; _pitch = p[3]; int startFrame = (int) p[4]; int endFrame = (int) p[5]; int frameCount = endFrame - startFrame + 1; if (frameCount <= 0) return die("LPCPLAY", "Ending frame must be > starting frame."); _warpFactor = p[6]; // defaults to 0 // Duration can be calculated from frame count const float defaultFrameRate = 112.0; ldur = (ldur > 0.) ? ldur : (frameCount/defaultFrameRate); /* Tell scheduler when to start this inst. */ if (rtsetoutput(outskip, ldur, this) == -1) return DONT_SCHEDULE; _envFun = floc(ENV_SLOT); sbrrand(1); // Pull all the current configuration information out of the environment. GetLPCStuff(&_highthresh, &_lowthresh, &_thresh, &_randamp, &_unvoiced_rate, &_risetime, &_decaytime, &_cutoff); GetConfiguration(&_maxdev, &_perperiod, &_hnfactor, &_autoCorrect); // Pitch table _pchvals = new double[frameCount]; // Finish the initialization float *cpoint = _coeffs + 4; evset(SR, getdur(), _risetime, _decaytime, ENV_SLOT, _evals); _frames = frameCount; _frame1 = startFrame; for (i = startFrame; i <= endFrame; ++i) { float findex = i; if (_dataSet->getFrame(findex, _coeffs) < 0) break; _pchvals[i - startFrame] = (_coeffs[PITCH] ? _coeffs[PITCH] : 256.); /* just in case I am using datasets with no pitch value stored */ } float actualweight = weight(startFrame, endFrame, _thresh); if (!actualweight) actualweight = cpspch(_pitch); // Transpose relative amount using input with +-0.01 == +-1 semitone if (ABS(_pitch) < 1.0) _transposition = pow(2.0,(_pitch/.12)); // Transpose relative amount using input as new center in hz else if (_pitch > 20) _transposition = _pitch/actualweight; // Transpose using input as new center in octave pt p.c. else if (_pitch > 0) _transposition = cpspch(_pitch)/actualweight; else if (_pitch < -20) _transposition = -_pitch; /* flat pitch in hz */ else _transposition = cpspch(-_pitch); /* flat pitch in octave pt */ if (n_args <= _datafields && _pitch > 0) { rtcmix_advise("LPCPLAY", "Overall transp factor: %f, weighted av. pitch = %g Hz", _transposition, actualweight); if (_maxdev) readjust(_maxdev,_pchvals,startFrame,endFrame,_thresh,actualweight); for (i=startFrame; i<=endFrame; ++i) { _pchvals[i - startFrame] *= _transposition; } } else { int lastfr=_frame1; float transp, lasttr=_transposition; for (int nn = _datafields-1; nn < n_args; nn+=2) { if (ABS(p[nn+1]) < 1.) { transp = pow(2.0,(p[nn+1]/.12)); } else { transp = cpspch(ABS(p[nn+1])) / weight((float)lastfr,(p[nn]+1.),_thresh); } float tranincr=(transp-lasttr)/(p[nn]-lastfr); transp=lasttr; for (i=lastfr;i<(int)p[nn];i++) { _pchvals[i-_frame1]*=transp; transp+=tranincr; } lastfr = (int) p[nn]; lasttr = transp; } if (p[n_args-2] < (float) endFrame) { /* if last frame in couplets wasn't last frame in batch, use base value from there to the end */ transp = _transposition; for (i=lastfr; i<endFrame; ++i) _pchvals[i-startFrame] *= transp; } } tableset(SR, getdur(), frameCount, _tblvals); // actualweight = weight(startFrame,endFrame,_thresh); float actualcps = cpspch(ABS(_pitch)); /* note, dont use this feature unless pitch is specified in p[3]*/ _sineFun = floc(SINE_SLOT); _reson_is_on = p[7] ? true : false; _cf_fact = p[7]; _bw_fact = p[8]; _frameno = _frame1; /* in case first frame is unvoiced */ #ifdef MAXMSP // see note above CLASSBRADSSTUPIDUNVOICEDFLAG = BRADSSTUPIDUNVOICEDFLAG; #endif return 0; }