int FILTSWEEP :: init(double p[], int n_args) { nargs = n_args; float outskip = p[0]; float inskip = p[1]; float dur = p[2]; float ringdur = p[4]; 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) == -1) return DONT_SCHEDULE; if (inchan >= inputChannels()) return die("FILTSWEEP", "You asked for channel %d of a %d-channel file.", inchan, inputChannels()); if (rtsetoutput(outskip, dur + ringdur, this) == -1) return DONT_SCHEDULE; insamps = (int) (dur * SR + 0.5); if (nfilts < 1 || nfilts > MAXFILTS) return die("FILTSWEEP", "Steepness (p5) must be an integer between 1 and %d.", MAXFILTS); for (int i = 0; i < nfilts; i++) filt[i] = new JGBiQuad(SR); if (do_balance) { balancer = new Balance(SR); balancer->setWindowSize(BALANCE_WINDOW_SIZE); scale = 1.0; } else scale = 1.0 / pow((double) nfilts, 1.8); // just a guess; needs work amparray = floc(1); if (amparray) { int lenamp = fsize(1); tableset(SR, dur, lenamp, amptabs); } if (n_args < 11) { // no p10 center freq PField, must use gen table cfarray = floc(2); if (cfarray == NULL) return die("FILTSWEEP", "Either use the center frequency pfield (p10) " "or make an old-style gen function in slot 2."); int len = fsize(2); tableset(SR, dur, len, cftabs); } if (n_args < 12) { // no p11 bandwidth PField, must use gen table bwarray = floc(3); if (bwarray == NULL) return die("FILTSWEEP", "Either use the bandwidth pfield (p11) " "or make an old-style gen function in slot 3."); int len = fsize(3); tableset(SR, dur, len, bwtabs); } return nSamps(); }
int AM::init(double p[], int n_args) { float outskip = p[0]; float inskip = p[1]; float dur = p[2]; inchan = (int) p[5]; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; // no input if (inchan >= inputChannels()) return die("AM", "You asked for channel %d of a %d-channel file.", inchan, inputChannels()); if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; if (outputChannels() > 2) return die("AM", "Can't handle more than 2 output channels."); amptable = floc(1); if (amptable) { int amplen = fsize(1); tableset(SR, dur, amplen, amptabs); } int tablelen = 0; if (n_args > 7) { // handle table coming in as optional p7 TablePField wavetable = (double *) getPFieldTable(7, &tablelen); } if (wavetable == NULL) { // use old gen slot wavetable = floc(2); if (wavetable) tablelen = fsize(2); else { // use default sine wave rtcmix_advise("AM", "No modulator 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)); } } modfreq = p[4]; modosc = new Ooscili(SR, modfreq, wavetable, tablelen); if (modfreq == 0.0) { freqtable = floc(3); if (freqtable) { int len = fsize(3); tableset(SR, dur, len, freqtabs); } else return die("AM", "If p4 is zero, old-style gen table 3 must " "contain modulator frequency curve."); } skip = (int) (SR / (float) resetval); return nSamps(); }
int MIX::init(double p[], int n_args) { const float outskip = p[0]; const float inskip = p[1]; float dur = p[2]; if (dur < 0.0) dur = -dur - inskip; if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; // no input for (int i = 0; i < inputChannels(); i++) { outchan[i] = (int) p[i + 4]; if (outchan[i] + 1 > outputChannels()) return die("MIX", "You wanted output channel %d, but have only specified " "%d output channels", outchan[i], outputChannels()); } initamp(dur, p, 3, 1); return nSamps(); }
int STEREO::init(double p[], int n_args) { nargs = n_args; outslots = n_args - MATRIX_PFIELD_OFFSET; const float outskip = p[0]; const float inskip = p[1]; float dur = p[2]; if (dur < 0.0) dur = -dur - inskip; if (n_args <= MATRIX_PFIELD_OFFSET) return die("STEREO", "You need at least one channel assignment."); if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; // no input if (outputChannels() != 2) return die("STEREO", "Output must be stereo."); initamp(dur, p, 3, 1); if (fastUpdate) updatePans(p); return nSamps(); }
int MULTEQ :: init(double p[], int n_args) { nargs = n_args; const float ringdur = 0.1; float outskip = p[0]; float inskip = p[1]; float dur = p[2]; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; insamps = (int) (dur * SR + 0.5); if (rtsetoutput(outskip, dur + ringdur, this) == -1) return DONT_SCHEDULE; if (inputChannels() > MAXCHAN) return die("MULTEQ", "Input and output must have no more than %d channels.", MAXCHAN); if (outputChannels() != inputChannels()) return die("MULTEQ", "Input and output must have same number of " "channels, no more than %d.", MAXCHAN); if ((nargs - FIRST_BAND_PF) % BAND_PFS) return die("MULTEQ", "For each band, need type, freq, Q, gain and bypass."); numbands = 0; int band = 0; for (int i = FIRST_BAND_PF; i < nargs; i += BAND_PFS, band += MAXCHAN) { if (numbands == MAXBAND) { warn("MULTEQ", "You can only have %d EQ bands.", MAXBAND); break; } OeqType type = getEQType(true, i); if (type == OeqInvalid) return die("MULTEQ", "Invalid EQ type string or code."); float freq = p[i + 1]; float Q = p[i + 2]; float gain = p[i + 3]; bool bypass = (bool) p[i + 4]; for (int c = 0; c < inputChannels(); c++) { eq[band + c] = new EQBand(SR, type, freq, Q, gain, bypass); if (eq[band + c] == NULL) return die("MULTEQ", "Can't allocate EQ band."); } numbands++; } skip = (int) (SR / (float) resetval); return nSamps(); }
int MYINST::init(double p[], int n_args) { _nargs = n_args; // store this for use in doupdate() // 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. const float outskip = p[0]; const float inskip = p[1]; const float dur = p[2]; // Here's how to handle an optional pfield. _inchan = (n_args > 4) ? int(p[4]) : 0; // default is chan 0 // no need to retrieve amp or pan here, because these will be set // before their first use inside of doupdate(). // Tell scheduler when to start this inst. If rtsetoutput returns -1 to // indicate an error, then return DONT_SCHEDULE. if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; // Test whether the requested number of output channels is right for your // instrument. The die function reports the error; the system decides // whether this should exit the program or keep going. if (outputChannels() > 2) return die("MYINST", "Use mono or stereo output only."); // Set file pointer on audio input. If the input source is real-time or // an aux bus, then <inskip> must be zero. The system will return an // an error in this case, which we must pass along. if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; // Make sure requested input channel number is valid for this input source. // inputChannels() gives the total number of input channels, initialized // in rtsetinput. if (_inchan >= inputChannels()) return die("MYINST", "You asked for channel %d of a %d-channel input.", _inchan, inputChannels()); // Return the number of sample frames that we'll write to output, which // the base class has already computed in response to our rtsetoutput call // above. nSamps() equals the duration passed to rtsetoutput multiplied // by the sampling rate and then rounded to the nearest integer. return nSamps(); }
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); }
int HOLO::init(double p[], int n_args) { /* HOLO: stereo FIR filter to perform crosstalk cancellation * * p0 = outsk * p1 = insk * p2 = dur * p3 = amp * p4 = xtalk amp mult * */ int i, rvin; if (inputChannels() != 2) { return die("HOLO", "Input must be stereo."); } if (outputChannels() != 2) { return die("HOLO", "Output must be stereo."); } rvin = rtsetinput(p[1], this); if (rvin == -1) { // no input return(DONT_SCHEDULE); } rvin = rtsetoutput(p[0], p[2], this); if (rvin == -1) { // no output return(DONT_SCHEDULE); } ncoefs = nCoeffs; for (int n = 0; n < 2; n++) { pastsamps[n] = new float[ncoefs + 1]; pastsamps2[n] = new float[ncoefs + 1]; for (i = 0; i < ncoefs; i++) { pastsamps[n][i] = 0.0; pastsamps2[n][i] = 0.0; } } amp = p[3]; xtalkAmp = (p[4] != 0.0) ? p[4] : 1.0; intap = 0; skip = (int)(SR / (float) resetval); return 0; }
int ROOM::init(double p[], int n_args) { float outskip = p[0]; float inskip = p[1]; float dur = p[2]; amp = p[3]; inchan = n_args > 4 ? (int)p[4] : AVERAGE_CHANS; if (outputchans != 2) return die("ROOM", "Output must be stereo."); if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; insamps = (int) (dur * SR + 0.5); if (inchan >= inputChannels()) return die("ROOM", "You asked for channel %d of a %d-channel input file.", inchan, inputChannels()); if (inputChannels() == 1) inchan = 0; nmax = get_room(ipoint, lamp, ramp, SR); if (nmax == 0) return die("ROOM", "You need to call roomset before ROOM."); echo = new float[nmax]; for (int i = 0; i < nmax; i++) echo[i] = 0.0; jpoint = 0; #ifdef DEBUG printf("maximum delay = %d samples.\n", nmax); #endif float ringdur = (float) nmax / SR; if (rtsetoutput(outskip, dur + ringdur, this) == -1) return DONT_SCHEDULE; amparray = floc(1); if (amparray) { int amplen = fsize(1); tableset(SR, dur + ringdur, amplen, amptabs); } else rtcmix_advise("ROOM", "Setting phrase curve to all 1's."); aamp = amp; /* in case amparray == NULL */ skip = (int)(SR / (float)resetval); return nSamps(); }
int JFIR :: init(double p[], int n_args) { nargs = n_args; float outskip = p[0]; float inskip = p[1]; float dur = p[2]; int order = (int) p[4]; inchan = (int) p[5]; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; insamps = (int) (dur * SR + 0.5); if (inchan >= inputChannels()) return die("JFIR", "You asked for channel %d of a %d-channel file.", inchan, inputChannels()); float ringdur = (float) order / SR; if (rtsetoutput(outskip, dur + ringdur, this) == -1) return DONT_SCHEDULE; double *response_table = NULL; int tablelen = 0; if (n_args > 8) { // handle table coming in as optional p8 TablePField response_table = (double *) getPFieldTable(8, &tablelen); } if (response_table == NULL) { response_table = floc(2); if (response_table == NULL) return die("JFIR", "Either use the frequency response pfield (p8) " "or make an old-style gen function in slot 2."); tablelen = fsize(2); } if (order < 1) return die("JFIR", "Order must be greater than 0."); filt = new NZero(SR, order); filt->designFromFunctionTable(response_table, tablelen, 0, 0); #ifdef PRINT_RESPONSE print_freq_response(); #endif amparray = floc(1); if (amparray) { int lenamp = fsize(1); tableset(SR, dur, lenamp, amptabs); } return nSamps(); }
int DISTORT::init(double p[], int n_args) { nargs = n_args; float outskip = p[0]; float inskip = p[1]; float dur = p[2]; type = p[4]; cutoff = n_args > 6 ? p[6] : 0.0; // filter disabled inchan = n_args > 7 ? (int) p[7] : 0; // default is chan 0 if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; if (inchan >= inputChannels()) return die("DISTORT", "You asked for channel %d of a %d-channel file.", inchan, inputChannels()); if (type == 1) distort = new Odistort(Odistort::SoftClip); else if (type == 2) distort = new Odistort(Odistort::SimpleTube); else if (type == 3) distort = new Odistort(Odistort::VariableClip); else if (type == 4) distort = new Odistort(Odistort::WaveShape); else return die("DISTORT", "Distortion type must be 1-4."); usefilt = (cutoff > 0.0); if (usefilt) { filt = new Butter(SR); filt->setLowPass(cutoff); } // legacy support for makegen amp double *function = floc(1); if (function) { int len = fsize(1); amptable = new TableL(SR, dur, function, len); } return nSamps(); }
int RVB::init(double p[], int n_args) { float outskip, inskip, 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); m_amp = p[3]; if (inputChannels() != 2) return die(name(), "Input must be stereo."); if (outputChannels() != 2) return die(name(), "Output must be stereo."); double Matrix[12][12]; /* Get results of Minc setup calls (space, mikes_on, mikes_off, matrix) */ if (get_rvb_setup_params(Dimensions, Matrix, &rvb_time) == -1) return die(name(), "You must call setup routine `space' first."); /* (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_random(); /* sets up random variation of delays */ set_allpass(); wire_matrix(Matrix); _skip = (int) (SR / (float) resetval); if (rtsetoutput(outskip, m_dur + rvb_time, this) == -1) return DONT_SCHEDULE; DBG1(printf("nsamps = %d\n", nSamps())); return nSamps(); }
int PANECHO::init(double p[], int n_args) { float outskip = p[0]; float inskip = p[1]; float dur = p[2]; float deltime0 = p[4]; float deltime1 = p[5]; float ringdur = p[7]; inchan = n_args > 8 ? (int) p[8] : 0; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; if (inchan >= inputChannels()) return die("PANECHO", "You asked for channel %d of a %d-channel file.", inchan, inputChannels()); if (rtsetoutput(outskip, dur + ringdur, this) == -1) return DONT_SCHEDULE; insamps = (int) (dur * SR + 0.5); if (outputChannels() != 2) return die("PANECHO", "Output must be stereo."); if (deltime0 <= 0.0 || deltime1 <= 0.0) return die("PANECHO", "Illegal delay times"); long delsamps = (long) (deltime0 * SR + 0.5); delay0 = new Odelayi(delsamps); delsamps = (long) (deltime1 * SR + 0.5); delay1 = new Odelayi(delsamps); if (delay0->length() == 0 || delay1->length() == 0) return die("PANECHO", "Can't allocate delay line memory."); prevdeltime0 = prevdeltime1 = -999999999.9; // force first update amptable = floc(1); if (amptable) { int amplen = fsize(1); tableset(SR, dur, amplen, amptabs); } return nSamps(); }
int REV :: init(double p[], int n_args) { float outskip = p[0]; float inskip = p[1]; float dur = p[2]; amp = p[3]; int rvbtype = (int) p[4]; float rvbtime = p[5]; inchan = (int) p[7]; if (rtsetoutput(outskip, dur + rvbtime, this) == -1) return DONT_SCHEDULE; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; insamps = (int) (dur * SR + 0.5); if (inchan >= inputChannels()) return die("REV", "You asked for channel %d of a %d-channel file", inchan, inputChannels()); switch (rvbtype) { case 1: reverb = new PRCRev(SR, rvbtime); break; case 2: reverb = new JCRev(SR, rvbtime); break; case 3: reverb = new NRev(SR, rvbtime); break; default: return die("REV", "Unknown reverb type %d.", rvbtype); } amparray = floc(1); if (amparray) { int lenamp = fsize(1); tableset(SR, dur, lenamp, amptabs); } return nSamps(); }
int COMBIT::init(double p[], int n_args) { float start = p[0]; float inskip = p[1]; float dur = p[2]; frequency = p[4]; rvbtime = p[5]; inchan = n_args > 6 ? (int) p[6] : 0; pctleft = n_args > 7 ? p[7] : 0.0; float ringdur = n_args > 8 ? p[8] : rvbtime; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; // no input if (inchan >= inputChannels()) return die("COMBIT", "You asked for channel %d of a %d-channel file.", inchan, inputChannels()); if (rtsetoutput(start, dur + ringdur, this) == -1) return DONT_SCHEDULE; insamps = (int) (dur * SR + 0.5); if (frequency <= 0.0) return die("COMBIT", "Invalid frequency value!"); float loopt = 1.0 / frequency; comb = new Ocombi(SR, loopt, loopt, rvbtime); if (comb->frequency() == 0.0) return die("COMBIT", "Failed to allocate comb memory!"); frequency = -1.0; // force update in run() amptable = floc(1); if (amptable) { int amplen = fsize(1); tableset(SR, dur + rvbtime, amplen, tabs); } skip = (int) (SR / (float) resetval); return nSamps(); }
int DEL1::init(double p[], int n_args) { float outskip = p[0]; float inskip = p[1]; float dur = p[2]; float deltime = p[4]; inchan = n_args > 6 ? (int) p[6] : 0; float ringdur = n_args > 7 ? p[7] : deltime; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; if (inchan >= inputChannels()) return die("DEL1", "You asked for channel %d of a %d-channel file.", inchan, inputChannels()); if (rtsetoutput(outskip, dur + ringdur, this) == -1) return DONT_SCHEDULE; insamps = (int) (dur * SR + 0.5); if (outputChannels() != 2) return die("DEL1", "Output must be stereo."); if (deltime <= 0.0) return die("DEL1", "Illegal delay time (%g).", deltime); long delsamps = (long) (deltime * SR + 0.5); delay = new Odelayi(delsamps); if (delay->length() == 0) return die("DEL1", "Can't allocate delay line memory."); amptable = floc(1); if (amptable) { int amplen = fsize(1); tableset(SR, dur, amplen, amptabs); } skip = (int) (SR / (float) resetval); return nSamps(); }
int DCBLOCK::init(double p[], int n_args) { 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() != inputChannels()) return die("DCBLOCK", "The number of input channels must be the same " "as the number of output channels."); _chans = inputChannels(); _blocker = new Odcblock * [_chans]; for (int i = 0; i < _chans; i++) _blocker[i] = new Odcblock(); return nSamps(); }
int PAN :: init(double p[], int n_args) { nargs = n_args; float outskip = p[0]; float inskip = p[1]; float dur = p[2]; inchan = n_args > 4 ? (int) p[4] : 0; // default is chan 0 if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; if (outputChannels() != 2) return die("PAN", "Output must be stereo."); if (inchan >= inputChannels()) return die("PAN", "You asked for channel %d of a %d-channel file.", inchan, inputChannels()); amparray = floc(1); if (amparray) { int lenamp = fsize(1); tableset(SR, dur, lenamp, amptabs); } if (n_args < 7) { // no p6 pan PField, must use gen table panarray = floc(2); if (panarray == NULL) return die("PAN", "Either use the pan pfield (p6) " "or make an old-style gen function in slot 2."); int len = fsize(2); tableset(SR, dur, len, pantabs); } skip = (int) (SR / (float) resetval); return nSamps(); }
int LOOP::init(double p[], int n_args) { if (n_args < 7) return die("LOOP", "Usage: LOOP(start, inskip, dur, amp, trans, loopstart, looplen[, inchan, pan])"); const float outskip = p[0]; const float inskip = p[1]; float dur = p[2]; if (dur < 0.0) dur = -dur - inskip; _incr = getIncrement(p[4]); _inchan = (n_args > 7) ? (int) p[7] : 0; _usesPan = (n_args > 8); _pan = _usesPan ? p[8] : 0.5; if (calculateLoop(p) == -1) return DONT_SCHEDULE; if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; if (outputChannels() > 2) return die("LOOP", "Use mono or stereo output only."); if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; if (_inchan >= inputChannels()) return die("LOOP", "You asked for channel %d of a %d-channel input.", _inchan, inputChannels()); _position = inskip * SR; // Actual starting position in the input file _inOffset = 0; // Offset of first sample in _in array compared to _position. return nSamps(); }
/** * These pfields are standard for LUAINST instruments: * p0 = Lua instrument name (string, all others are doubles). * p1 = Output start time (outskip). * p2 = Input start time (inskip, must be zero if there is no input). * p3 = Duration. * p4 = Amplitude. * pN = User-defined optional parameters. */ virtual int init(double *parameters, int parameterCount) { state.name = strdup(DOUBLE_TO_STRING(parameters[0])); state.parameters = new double[parameterCount]; state.parameterCount = parameterCount; for (int parameterI = 0; parameterI < parameterCount; ++parameterI) { state.parameters[parameterI] = parameters[parameterI]; } if (rtsetoutput((float) parameters[1], (float) parameters[3], this) == -1) { return DONT_SCHEDULE; } if (parameters[2] != 0.0) { if (rtsetinput(parameters[1], this) == -1) { return DONT_SCHEDULE; } state.inputChannelCount = inputChannels(); } state.outputChannelCount = outputChannels(); return nSamps(); }
int DELAY::init(double p[], int n_args) { float outskip = p[0]; float inskip = p[1]; float dur = p[2]; float deltime = p[4]; float ringdur = p[6]; inchan = n_args > 7 ? (int) p[7] : 0; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; // no input if (inchan >= inputChannels()) return die("DELAY", "You asked for channel %d of a %d-channel file.", inchan, inputChannels()); if (rtsetoutput(outskip, dur + ringdur, this) == -1) return DONT_SCHEDULE; insamps = (int) (dur * SR + 0.5); if (deltime <= 0.0) return die("DELAY", "Invalid delay time (%g)", deltime); long defaultDelay = MAX(100L, long(deltime * SR + 0.5)); delay = new Odelayi(defaultDelay); // This is how we check for memory failure. if (delay->length() == 0) return die("DELAY", "Can't allocate delay line memory."); amptable = floc(1); if (amptable) { int amplen = fsize(1); tableset(SR, dur, amplen, amptabs); } return nSamps(); }
int REVMIX::init(double p[], int n_args) { nargs = n_args; float outskip = p[0]; float inskip = p[1]; float dur = p[2]; inchan = n_args > 4 ? (int) p[4] : 0; // default is chan 0 if (inskip == 0) return die("REVMIX", "Input start time must be greater than zero."); if (dur > inskip) { rtcmix_warn("REVMIX", "Duration must be greater than input start time. " "Adjusting..."); dur = inskip; } if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; // no input if (inchan >= inputChannels()) return die("REVMIX", "You asked for channel %d of a %d-channel file.", inchan, inputChannels()); amparray = floc(1); if (amparray) { int amplen = fsize(1); tableset(SR, dur, amplen, amptabs); } skip = (int) (SR / (float) resetval); return nSamps(); }
int TRANS3 :: init(double p[], int n_args) { nargs = n_args; if (nargs < 5) return die("TRANS3", "Usage: TRANS3(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; if (rtsetoutput(outskip, dur, this) == -1) return DONT_SCHEDULE; if (rtsetinput(inskip, this) == -1) return DONT_SCHEDULE; if (inchan >= inputChannels()) { return die("TRANS3", "You asked for channel %d of a %d-channel file.", inchan, inputChannels()); } // to trigger first read in run() inframe = RTBUFSAMPS; oneover_cpsoct10 = 1.0 / cpsoct(10.0); amptable = floc(1); if (amptable) { int amplen = fsize(1); tableset(SR, dur, amplen, amptabs); } return nSamps(); }
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(); }
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 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(); }
/* ----------------------------------------------------------------- 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 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(); }
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 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(); }