Submit
Browse
Anonymous
Login
RSS
SuperCollider Code
Fork Code: Abusing Convolution2 to make pitch
name
code content
// fixed (unchanging) impulse response // cmd-. to stop ( s.waitForBoot { var c = Condition.new, cleanfunc = { CmdPeriod.remove(cleanfunc); b.free }; fork { b = Buffer.alloc(s, 2048, 1); CmdPeriod.add(cleanfunc); s.sync; a = { RecordBuf.ar(BrownNoise.ar * EnvGen.ar(Env(#[0, 1, 0], #[0.5, 0.5], \sin), timeScale: b.duration, doneAction: 2), b, loop: 0); 0 }.play; OSCpathResponder(s.addr, ['/n_end', a.nodeID], { |time, resp, msg| resp.remove; c.unhang; }).add; c.hang; a = { var freq = MouseX.kr(150, 450, warp: 1, lag: 0.1); LeakDC.ar(Convolution2.ar(Impulse.ar(freq), b, framesize: b.numFrames) * -35.dbamp) ! 2; }.play; }; }; ) // multiple impulse responses for timbre control ( s.waitForBoot { var c = Condition.new, cleanfunc = { CmdPeriod.remove(cleanfunc); b.free }; fork { b = Buffer.allocConsecutive(3, s, 2048, 1); CmdPeriod.add(cleanfunc); s.sync; a = { var sig = [BrownNoise.ar, PinkNoise.ar, WhiteNoise.ar]; sig.do { |chan, i| RecordBuf.ar(chan * EnvGen.ar(Env(#[0, 1, 0], #[0.5, 0.5], \sin), timeScale: b[i].duration, doneAction: 2), b[i], loop: 0); 0 }; }.play; OSCpathResponder(s.addr, ['/n_end', a.nodeID], { |time, resp, msg| resp.remove; c.unhang; }).add; c.hang; a = { var freq = MouseX.kr(150, 450, warp: 1, lag: 0.1), index = MouseY.kr(0, 1.99, lag: 0.1), iWhole = index.trunc(2), iFrac = index - iWhole, iAdjust = iFrac >= 1.0, trig = Impulse.ar(freq), convolvers = b.collect { |buf, i| LeakDC.ar(Convolution2.ar(trig, buf, framesize: buf.numFrames)) }; ( XFade2.ar( Select.ar(iWhole + (2 * iAdjust), convolvers), Select.ar(iWhole + 1, convolvers), iFrac.fold(0, 1) * 2 - 1 ) * -30.dbamp ) ! 2; }.play; }; }; )
code description
Inspired by Formlet, which does something like formant synthesis by outputting short sinusoidal grains in response to impulses, I thought, what if we replace the sine grains with an arbitrary impulse response? You could do that with TGrains, but as the pitch goes up, so does the number of overlapping grains and CPU use along with it. But, convolution of a chain of impulses should be the same as granular synthesis, if the grain contents are used as the convolution kernel (impulse response). The first example does this with a buffer containing BrownNoise (shaped by a Hanning envelope). The second example adds timbre control by crossfading between three different Convolution2 results. To avoid clicks in the output when crossing buffer boundaries, I had to ensure that even-numbered buffers always go into XFade2's leftmost input and odd ones into the second input. (Note, the second example could be made more efficient/scalable by using just two Convolution2 units, and providing a trigger to the third input whenever its calculated buffer number changes. Exercise for the reader...)
use markdown for formating
category tags
comma separated, i.g. "wild, siren" (do not enter default SC class names, please)
ancestor(s)
comma separated identificators, i.g. "1-C,1-1,1-4M,1-x"
Private?
the code will be accessible by direct url and not visible in public activity
signup to submit public code without captcha
comment of change