1class:: TGrains 2summary:: Buffer granulator. 3categories:: UGens>Buffer, UGens>Generators>Granular 4 5Description:: 6Triggers generate grains from a buffer. Each grain has a Hanning envelope 7code:: 8(sin2(x) for x from 0 to π) 9:: 10and can be panned over multichannel output. 11 12classmethods:: 13 14method::ar 15 16argument::numChannels 17The number of output channels. 18 19argument::trigger 20At each trigger, the following arguments are sampled and used as 21the arguments of a new grain. A trigger occurs when a signal 22changes from non-positive to a positive value. 23 24If the trigger is audio rate then the grains will start with 25sample accuracy. 26 27argument::bufnum 28The index of the buffer to use. It must be a one channel (mono) 29buffer. 30 31argument::rate 321.0 is normal, 2.0 is one octave up, 0.5 is one octave down -1.0 33is backward normal rate… etc. 34 35argument::centerPos 36The position in the buffer in seconds at which the grain envelope 37will reach maximum amplitude. 38 39argument::dur 40Duration of the grain in seconds. 41 42argument::pan 43determines where to pan the output. 44list:: 45## If numChannels = 1, the pan argument is ignored. 46## If numChannels = 2, panning is similar to Pan2. 47## If numChannels > 2, panning is the same as PanAz. 48:: 49 50argument::amp 51Amplitude of the grain. 52 53argument::interp 541, 2, or 4. Determines whether the grain uses (1) no 55interpolation, (2) linear interpolation, or (4) cubic 56interpolation. 57 58Examples:: 59 60code:: 61 62s.boot; 63b = Buffer.read(s, Platform.resourceDir +/+ "sounds/a11wlk01.wav"); 64 65( 66{ 67 var trate, dur, rate; 68 trate = MouseY.kr(2,200,1); 69 dur = 4 / trate; 70 rate = Dseq([10, 1, 1, 0.5, 0.5, 0.2, 0.1], inf); 71 TGrains.ar(2, Impulse.ar(trate), b, rate, MouseX.kr(0,BufDur.kr(b)), dur, Dseq([-1, 1], inf), 0.1, 2); 72}.scope(zoom: 4); 73) 74 75( 76{ 77 var trate, dur, clk, pos, pan; 78 trate = MouseY.kr(8,120,1); 79 dur = 12 / trate; 80 clk = Impulse.kr(trate); 81 pos = MouseX.kr(0,BufDur.kr(b)) + TRand.kr(0, 0.01, clk); 82 pan = WhiteNoise.kr(0.6); 83 TGrains.ar(2, clk, b, 1, pos, dur, pan, 0.1); 84}.scope(zoom: 4); 85) 86 87// 4 channels 88( 89{ 90 var trate, dur, clk, pos, pan; 91 trate = MouseY.kr(8,120,1); 92 dur = 12 / trate; 93 clk = Impulse.kr(trate); 94 pos = MouseX.kr(0,BufDur.kr(b)) + TRand.kr(0, 0.01, clk); 95 pan = WhiteNoise.kr(0.6); 96 TGrains.ar(4, clk, b, 1, pos, dur, pan, 0.1); 97}.scope(4, zoom: 4); 98) 99 100( 101{ 102 var trate, dur, clk, pos, pan; 103 trate = MouseY.kr(8,120,1); 104 dur = 4 / trate; 105 clk = Dust.kr(trate); 106 pos = MouseX.kr(0,BufDur.kr(b)) + TRand.kr(0, 0.01, clk); 107 pan = WhiteNoise.kr(0.6); 108 TGrains.ar(2, clk, b, 1, pos, dur, pan, 0.1); 109}.scope(zoom: 4); 110) 111 112( 113{ 114 var trate, dur, clk, pos, pan; 115 trate = LinExp.kr(LFTri.kr(MouseY.kr(0.1,2,1)),-1,1,8,120); 116 dur = 12 / trate; 117 clk = Impulse.ar(trate); 118 pos = MouseX.kr(0,BufDur.kr(b)); 119 pan = WhiteNoise.kr(0.6); 120 TGrains.ar(2, clk, b, 1, pos, dur, pan, 0.1); 121}.scope(zoom: 4); 122) 123 124( 125{ 126 var trate, dur, clk, pos, pan; 127 trate = 12; 128 dur = MouseY.kr(0.2,24,1) / trate; 129 clk = Impulse.kr(trate); 130 pos = MouseX.kr(0,BufDur.kr(b)) + TRand.kr(0, 0.01, clk); 131 pan = WhiteNoise.kr(0.6); 132 TGrains.ar(2, clk, b, 1, pos, dur, pan, 0.1); 133}.scope(zoom: 4); 134) 135 136( 137{ 138 var trate, dur, clk, pos, pan; 139 trate = 100; 140 dur = 8 / trate; 141 clk = Impulse.kr(trate); 142 pos = Integrator.kr(BrownNoise.kr(0.001)); 143 pan = WhiteNoise.kr(0.6); 144 TGrains.ar(2, clk, b, 1, pos, dur, pan, 0.1); 145}.scope(zoom: 4); 146) 147 148( 149{ 150 var trate, dur, clk, pos, pan; 151 trate = MouseY.kr(1,400,1); 152 dur = 8 / trate; 153 clk = Impulse.kr(trate); 154 pos = MouseX.kr(0,BufDur.kr(b)); 155 pan = WhiteNoise.kr(0.8); 156 TGrains.ar(2, clk, b, 2 ** WhiteNoise.kr(2), pos, dur, pan, 0.1); 157}.scope(zoom: 4); 158) 159 160( 161{ 162 var trate, dur; 163 trate = MouseY.kr(2,120,1); 164 dur = 1.2 / trate; 165 TGrains.ar(2, Impulse.ar(trate), b, (1.2 ** WhiteNoise.kr(3).round(1)), MouseX.kr(0,BufDur.kr(b)), dur, WhiteNoise.kr(0.6), 0.1); 166}.scope(zoom: 4); 167) 168 169// demand ugens as inputs 170( 171{ 172 var trate, dur, z, d; 173 trate = MouseX.kr(1, 100, 1); 174 d = { Dwhite(0.1, 0.2, 1) }; 175 z = { 176 Drand([Dgeom(0.1, 1 + d.value, Diwhite(20, 40)), Dgeom(1, 1 - d.value, Diwhite(20, 40))]) 177 }; 178 TGrains.ar(2, 179 Impulse.ar(trate), 180 bufnum: 10, 181 rate: Dseq([1, 1, z.value, 0.5, 0.5, 0.2, 0.1, 0.1, 0.1, 0.1], inf) * 2 + 1, 182 centerPos: Dseq(z.dup(8), inf), 183 dur: Dseq([1, d.value, 1, z.value, 0.5, 0.5, 0.1, z.value] * 2, inf) / trate, 184 pan: Dseq([1, 1, 1, 0.5, 0.2, 0.1, 0, 0, 0], inf) * 2 - 1, 185 amp: Dseq([1, 0, z.value, 0, 2, 1.0, 1, 0.1, 0.1], inf) 186 ); 187}.scope(zoom: 4); 188) 189 190b.free 191 192:: 193