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