fltdelay - recirculating delay line with filter in feedback loop fltdelay out[b] d d d d d d d d d d d d d d d in[bvpn] pitch[bvpn] decay[bvpn] table[vpn] level[vpn] final[vpn] onset[vpn] place[vpn] filtr[vpn] noise[vpn] stiff[vpn]; in[bvpn] optional input block (for use as resonator) pitch[bvpn] desired fundamental freq (use Hz postop !!) decay[bvpn] duration factor (0 to 1: 1 = full duration) table[fvpn] function to initialize table (e.g. from gen6) level[vpn] amplitude of pluck (0 to 1: 1 = loudest) final[vpn] number of db down at p4 (0 to 100: 40 = norm) onset[vpn] attack time for pluck (0 to .1 sec: 0 = fast) place[vpn] pluck point on string (0 to .5: 0 = normal) filtr[vpn] lowpass prefilter cutoff freq (0 to .5 Srate) noise[vpn] time of initial noise burst (-1 to +0.1 sec) stiff[vpn] stiffness (0 to 10: 10 = stiffest/sharpest) This unit generator implements the Karplus-Strong plucked-string algorithm as improved by David Jaffe and Julius Smith (see CMJ Vol. 7 No. 2, pp. 56-69). In its simplest form, operation is as follows: gen6 is used to fill a table with random numbers. The first N random numbers (where N is approximately sample_rate / pitch) are fed into a delay line of length N. The output of the delay line is the output of the u.g.; but the output is also sent to a filter which computes a weighted average of the current output sample and the previous output sample. The output of this averaging filter is then stuffed back into the beginning of the delay line. The result is that every N samples, a given sample in the loop will be replaced by an average of that sample and the adjacent sample. Hence, the delay line begins with white noise in it and ends up with all zeros (or some small DC value) in it. As it happens, the resulting sound can be very similar to that of a plucked string. A simple plucked string instrument can be defined by: #define FLTDELAY(b) fltdelay b d d d d d d d d d d d d d d d ins 0 pluck; FLTDELAY(b1) 0 440Hz 1 1 1 40 .001 0 .5 0 0; out b1; end; GEN6(f1) ; (The #define statement is predefined for you on ). A great many options can also be explored: an input can be connected up so that the recirculating delay line acts as a resonator (but beware of overflow - the input should either be low amplitude or the value of "final" should be very large to produce rapid decay). The pitch can be allowed to vary (but don't let it drop below sample_rate / funclength). The decay can be made to vary (but note that the effect of the "decay" parameter depends upon the pitch - higher pitches are attenuated more rapidly for the same value of "decay"). The "final" parameter provides control of the decay independently of pitch (the decay is always exponential, and the duration is always p4; "final" specifies whether the note is to be 40 db down by p4 or perhaps 80 db down - in which case it will sound shorter). The "onset" parameter applies a linear ramp of duration "onset" seconds to the output of the fltdelay u.g.; this can used to soften the typical pluck attack. It is also possible to output a noise burst of duration "noise" seconds prior to starting up the recirculating delay line. Conversely, a negative value for "noise" causes the recirculating delay line to run for negative "noise" seconds prior to the start of the note. Lastly, a stiffer string can be simulated by specifying sharpened partials (but values of "stiff" less than 4 will probably be inaudible). The remaining options apply only to the numbers in the delay line just prior to the start of the note: A function other than gen6 can be used to fill the table. The initial amplitude can be set via "level". A comb prefilter can be applied to the numbers in the table to simulate plucking at a different "place" along the string (for example, setting "place" to .5 is like plucking the string in the middle in that all even harmonics are eliminated). A lowpass prefilter can be applied to the numbers in the table to decrease the brightness of the plucked sound (for example, setting "filtr" to .1 applies a lowpass prefilter with a cutoff frequency of .1 * sample_rate). Note: When prefiltering is NOT desired, the value of "filtr" should be .5. The compute time for the fltdelay u.g. is on the order of three oscs provided that the pitch does not change and that the pitch does not exceed sampling_rate / 8. Very high pitches and changing pitches take at least twice as long to compute. The fltdelay u.g. can also be used to implement more drumlike sounds by setting "decay" to -1 or letting it switch randomly between +1 and -1 (but don't set it to a value other than + or - 1 unless you want to affect the rate of decay as well). AUTHOR: Mark Dolson