Basically, each FFT bin gets fitted with its own recirculating delay line, and the delay times and feedbacks are controlled by makegens. For example, if you randomize the delay times, you get wild repetitive, spectrally splintered patterns.
p-fields:
/* SPECTACLE - FFT-based delay processor p0 = output start time p1 = input start time p2 = input duration p3 = amplitude multiplier p4 = ring-down duration p5 = FFT length (power of 2, usually 1024) p6 = window length (power of 2, usually FFT length * 2) p7 = window type (0: Hamming; see below for others) p8 = overlap - how much FFT windows overlap (any power of 2) 1: no overlap, 2: hopsize=FFTlen/2, 4: hopsize=FFTlen/4, etc. 2 or 4 is usually fine; 1 is fluttery; the higher the more CPU time p9 = wet/dry mix (0: dry -> 1: wet) [optional, default is 1] p10 = input channel [optional, default is 0] p11 = percent to left channel [optional, default is .5] The following function tables control amplitude. Function table 1 is the input amplitude, spanning just the input duration. Function table 2 is the output amplitude, spanning the entire note, including ring-down duration. The following function tables control EQ, delay time, and delay feedback for all the frequency bands of the FFT. Think of them as curves on a graph with frequency on the x axis and amplitude, delay time or feedback on the y axis. Function table 3 is the EQ table (i.e., amplitude scaling of each band), in dB (0 dB means no change, + dB boost, - dB cut). Function table 4 is the delay time table. Function table 5 is the delay feedback table. Values > 1 are dangerous! NOTES: p7 - window type: 0: Hamming, 1: Hanning, 2: Rectangle, 3: Triangle, 4: Blackman, 5: Kaiser When in doubt, use Hamming. p8 - overlap: 1: no overlap, 2: hopsize=FFTlen/2, 4: hopsize=FFTlen/4, etc. 2 or 4 is usually fine; 1 is fluttery; higher overlaps use more CPU. Also possible to use negative powers of 2, e.g., .5, .25, .125, etc. This leaves a gap between successive FFTs, creating ugly robotic effects -- beware of clipping. p9 - wet/dry mix: This is pre-EQ. */Sample scorefile:
rtsetparams(44100, 2) load("SPECTACLE") /* ftp://presto.music.virginia.edu/pub/rtcmix/snd/ah.snd */ rtinput("/Users/johgibso/snd/ah.snd") inchan = 0 inskip = .2 indur = 2 ringdur = 15 /* play after indur elapses, while delay lines flush */ amp = 12 wetdry = 1 /* 100% wet */ fftlen = 1024 /* yielding 512 frequency bands */ winlen = fftlen * 2 /* the standard window length is twice FFT size */ overlap = 2 /* 2 hops per fftlen (4 per window) */ wintype = 0 /* use Hamming window */ /* input envelope (covering) */ makegen(1, 18, 1000, 0,0, 1,1, 19,1, 20,0) /* output envelope (covering + ) */ makegen(2, 4, 1000, 0,1,0, 1,1,-1, 2,0) /* EQ curve: -90 dB at 0 Hz, ramping up to 0 dB at 300 Hz, etc. */ makegen(3, 18, 1000, 0,-90, 100,-90, 300,0, 8000,0, 22050,-90) /* fixed delay times between .4 and 3, randomly spread across spectrum */ min = .4; max = 3 seed = 1 makegen(4, 20, 1000, 0, seed, min, max) /* constant feedback of 80% for all freq. bands */ fb = .8 makegen(5, 18, 1000, 0,fb, 1,fb) /* do it for the left chan! */ start = 0 SPECTACLE(start, inskip, indur, amp, ringdur, fftlen, winlen, wintype, overlap, wetdry, inchan, pctleft=1) /* shift delay table to make right channel sound different */ shiftgen(4, 500) /* do it for the right chan! */ SPECTACLE(start, inskip, indur, amp, ringdur, fftlen, winlen, wintype, overlap, wetdry, inchan, pctleft=0)