( name: 'granular_sampler', func: { | freq, gate | var buf = \buf.kr; var trigger = gate; var bufFrames = BufFrames.kr(buf); var grainTriggerFreq = \grainTriggerFreq.kr(20); var positionRamp = Phasor.ar( trigger, rate: BufRateScale.kr(buf) * \rate.kr(1), start: \sampleStart.kr(0), end: \sampleEnd.kr(1), ) * \direction.kr(1); var envelope = EnvGen.kr( Env([0, 1, 1, 0], [0, BufDur.kr(buf) - 0.01, 0]), trigger ); GrainBuf.ar( numChannels: 2, trigger: Impulse.ar(grainTriggerFreq), dur: \density.kr(2) / grainTriggerFreq, sndbuf: buf, rate: \grainRate.kr(1), pos: positionRamp / bufFrames, interp: 0, pan: \pan.kr(0), envbufnum: -1, ) * envelope; }, specs:( density: [0.1, 10.0, \lin ,0.1, 2], direction: [-1, 1, \lin, 1, 1], grainRate: [0.1, 2, \lin, 0.1, 1], grainTriggerFreq: [0.1, 200, \lin, 0.1, 20], pan: [-1.0, 1.0, \lin, 0.1, 0], rate: [0.1, 2, \lin, 0.01, 1], ), useEnv: true, defaults:( attack: 0.01, release: 0.1, curve: 1 ), )