예제 #1
0
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();
}
예제 #2
0
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();
}
예제 #3
0
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();
}
예제 #4
0
파일: STEREO.cpp 프로젝트: RTcmix/RTcmix
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();
}
예제 #5
0
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();
}
예제 #6
0
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);
}
예제 #8
0
파일: HOLO.cpp 프로젝트: eriser/RTcmix
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();
}
예제 #10
0
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();
}
예제 #11
0
파일: DISTORT.cpp 프로젝트: RTcmix/RTcmix
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();
}
예제 #12
0
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();
}
예제 #13
0
파일: PANECHO.cpp 프로젝트: RTcmix/RTcmix
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();
}
예제 #14
0
파일: REV.cpp 프로젝트: RTcmix/RTcmix
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();
}
예제 #15
0
파일: COMBIT.cpp 프로젝트: jwmatthys/RTcmix
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();
}
예제 #16
0
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();
}
예제 #18
0
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();
}
예제 #19
0
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();
}
예제 #20
0
  /**
   * 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();
  }
예제 #21
0
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();
}
예제 #24
0
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();
}
예제 #25
0
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();
}
예제 #26
0
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();
}
예제 #27
0
/* ----------------------------------------------------------------- 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();
}
예제 #28
0
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();
}
예제 #30
0
int SPECTACLE_BASE :: init(double p[], int n_args)
{
   float outskip = p[0];
   float inskip = p[1];
   inputdur = p[2];
   amp = p[3];
   ringdur = p[4];
   fft_len = (int) p[5];
   window_len = (int) p[6];
   window_type = getWindowType(p[7]);
   float overlap = p[8];

   /* Make sure FFT length is a power of 2 <= MAXFFTLEN and <= RTBUFSAMPS. */
   bool valid = false;
   for (int x = 1; x <= MAXFFTLEN; x *= 2) {
      if (fft_len == x) {
         valid = true;
         break;
      }
   }
   if (!valid || fft_len > MAXFFTLEN)
      return die(instname(), "FFT length must be a power of two <= %d",
                                                                  MAXFFTLEN);

// FIXME: now this isn't a problem; instead, decimation can't be larger
// than RTBUFSAMPS.  But must couch errmsg in terms of overlap and fft length,
// not decimation...
#if 0
   if (fft_len > RTBUFSAMPS)
      return die(instname(),
                 "FFT length must be a power of two less than or equal\n"
                 "to the output buffer size set in rtsetparams (currently %d).",
                 RTBUFSAMPS);
#endif
   half_fft_len = fft_len / 2;
   fund_anal_freq = SR / (float) fft_len;

   /* Make sure window length is a power of 2 >= FFT length. */
   valid = false;
   for (int x = fft_len; x <= MAXWINDOWLEN; x *= 2) {
      if (window_len == x) {
         valid = true;
         break;
      }
   }
   if (!valid)
      return die(instname(),
                     "Window length must be a power of two >= FFT length\n"
                     "(currently %d) and <= %d.", fft_len, MAXWINDOWLEN);

   /* Make sure overlap is a power of 2 in our safety range. */
   valid = false;
//FIXME: need to adjust MINOVERLAP so that iterations is never 0 in run()
// This might depend upon window_len??
   for (float x = MINOVERLAP; x <= MAXOVERLAP; x *= 2.0) {
      if (overlap == x) {
         valid = true;
         break;
      }
   }
   if (!valid)
      return die(instname(),
                 "Overlap must be a power of two between %g and %g.",
                 MINOVERLAP, MAXOVERLAP);
   int_overlap = (int) overlap;

   /* derive decimation from overlap */
   decimation = (int) (fft_len / overlap);

   DPRINT2("fft_len=%d, decimation=%d\n", fft_len, decimation);

   if (pre_init(p, n_args) != 0)    /* can modify ringdur */
      return DONT_SCHEDULE;

   iamparray = floc(1);
   if (iamparray) {
      int lenamp = fsize(1);
      tableset(SR, inputdur, lenamp, iamptabs);
   }
   else
      rtcmix_advise(instname(), "Setting input amplitude curve to all 1's.");

   oamparray = floc(2);
   if (oamparray) {
      int lenamp = fsize(2);
      tableset(SR, inputdur + ringdur, lenamp, oamptabs);
   }
   else
      rtcmix_advise(instname(), "Setting output amplitude curve to all 1's.");

   if (rtsetinput(inskip, this) == -1)
      return DONT_SCHEDULE;
   if (inchan >= inputChannels())
      return die(instname(), "You asked for channel %d of a %d-channel file.",
                                                   inchan, inputChannels());

   /* <latency> is the delay before the FFT looks at actual input rather than
      zero-padding.  Need to let inst run long enough to compensate for this.
   */
   window_len_minus_decimation = window_len - decimation;
   latency = window_len + window_len_minus_decimation;
   float latency_dur = latency * (1.0 / SR);
   if (rtsetoutput(outskip, latency_dur + inputdur + ringdur, this) == -1)
      return DONT_SCHEDULE;
   total_insamps = (int)(inputdur * SR);    /* without latency_dur */
   input_end_frame = total_insamps + latency;
   DPRINT1("input_end_frame=%d\n", input_end_frame);

   input = new float [window_len];           /* input buffer */
   output = new float [window_len];          /* output buffer */
   anal_window = new float [window_len];     /* analysis window */
   synth_window = new float [window_len];    /* synthesis window */
   fft_buf = new float [fft_len];            /* FFT buffer */
   anal_chans = new float [fft_len + 2];     /* analysis channels */

   if (make_windows() != 0)
      return DONT_SCHEDULE;

   /* Delay dry output by window_len - decimation to sync with wet sig. */
   drybuf = new float [decimation];
   dry_delay = new DLineN(window_len);
   dry_delay->setDelay((float) window_len_minus_decimation);

   /* Init iamp and oamp to starting amplitudes. */
   iamp = (iamparray == NULL) ? 1.0 : iamparray[0];
   oamp = (oamparray == NULL) ? amp : oamparray[0];

   skip = (int) (SR / (float) resetval);

   if (post_init(p, n_args) != 0)
      return DONT_SCHEDULE;

   return nSamps();
}