2 var listPat, indexPat, repeats;
3 *new { arg listPat, indexPat, repeats=1;
4 ^super.newCopyArgs(listPat, indexPat, repeats)
6 storeArgs { ^[listPat,indexPat,repeats] }
7 embedInStream { arg inval;
8 var indexStream, index, item, itemCount;
9 var listStream = listPat.asStream;
10 repeats.value(inval).do {
11 var list = listStream.next(inval);
12 if (list.isNil) { ^inval };
13 indexStream = indexPat.asStream;
16 index = indexStream.next(inval);
19 itemCount = itemCount + 1;
20 item = list.wrapAt(index);
21 inval = item.embedInStream(inval);
23 if(itemCount == 0) { ^inval }
29 ListPattern : Pattern {
30 var <>list, <>repeats=1;
32 *new { arg list, repeats=1;
34 ^super.new.list_(list).repeats_(repeats)
36 Error("ListPattern (" ++ this.name ++ ") requires a non-empty collection; received "
37 ++ list ++ ".").throw;
41 ^super.copy.list_(list.copy)
43 storeArgs { ^[ list, repeats ] }
48 *new { arg list, repeats=1, offset=0;
49 ^super.new(list, repeats).offset_(offset)
51 embedInStream { arg inval;
52 var item, offsetValue;
53 offsetValue = offset.value;
54 if (inval.eventAt('reverse') == true, {
55 repeats.value(inval).do({ arg j;
56 list.size.reverseDo({ arg i;
57 item = list.wrapAt(i + offsetValue);
58 inval = item.embedInStream(inval);
62 repeats.value(inval).do({ arg j;
64 item = list.wrapAt(i + offsetValue);
65 inval = item.embedInStream(inval);
71 storeArgs { ^[ list, repeats, offset ] }
75 embedInStream { arg inval;
77 var offsetValue = offset.value;
78 if (inval.eventAt('reverse') == true, {
79 repeats.value(inval).reverseDo({ arg i;
80 item = list.wrapAt(i + offsetValue);
81 inval = item.embedInStream(inval);
84 repeats.value(inval).do({ arg i;
85 item = list.wrapAt(i + offsetValue);
86 inval = item.embedInStream(inval);
94 embedInStream { arg inval;
96 var localList = list.copy.scramble;
98 repeats.value(inval).do({ arg j;
99 localList.size.do({ arg i;
100 item = localList.wrapAt(i);
101 inval = item.embedInStream(inval);
108 Prand : ListPattern {
109 embedInStream { arg inval;
112 repeats.value(inval).do({ arg i;
113 item = list.at(list.size.rand);
114 inval = item.embedInStream(inval);
120 Pxrand : ListPattern {
121 embedInStream { arg inval;
123 var index = list.size.rand;
124 repeats.value(inval).do({ arg i;
126 index = (index + (size - 1).rand + 1) % size;
127 item = list.at(index);
128 inval = item.embedInStream(inval);
134 Pwrand : ListPattern {
136 *new { arg list, weights, repeats=1;
137 ^super.new(list, repeats).weights_(weights)
139 embedInStream { arg inval;
141 var wStr = weights.asStream;
142 repeats.value(inval).do({ arg i;
143 wVal = wStr.next(inval);
144 if(wVal.isNil) { ^inval };
145 item = list.at(wVal.windex);
146 inval = item.embedInStream(inval);
150 storeArgs { ^[ list, weights, repeats ] }
155 embedInStream { arg inval;
157 var maxState = ((list.size - 1) div: 2) - 1;
158 repeats.value(inval).do({
161 index = list.at(index).choose.clip(0, maxState) * 2 + 2;
162 item = list.at(index - 1);
165 inval = item.embedInStream(inval);
172 Pdfsm : ListPattern {
174 *new { arg list, startState=0, repeats=1;
175 ^super.new( list, repeats ).startState_(startState)
178 embedInStream { arg inval;
179 var currState, sigStream;
180 var sig, state, stream;
181 var numStates = list.size - 1;
182 repeats.value(inval).do({
184 currState = startState;
185 sigStream = list[0].asStream;
188 sig = sigStream.next(inval);
189 state = list[currState + 1];
190 if( sig.isNil, { false }, {
191 if( state.includesKey(sig), {
192 #currState, stream = state[sig];
194 #currState, stream = state[\default];
196 currState.notNil and: {currState < numStates};
199 inval = stream.embedInStream(inval);
207 var <>list, <>which=0;
208 *new { arg list, which=0;
209 ^super.new.list_(list).which_(which)
211 embedInStream { arg inval;
214 var indexStream = which.asStream;
216 (index = indexStream.next(inval)).notNil;
218 inval = list.wrapAt(index.asInteger).embedInStream(inval);
222 storeArgs { ^[ list, which ] }
226 embedInStream { arg inval;
228 var streamList = list.collect({ arg pattern; pattern.asStream; });
229 var indexStream = which.asStream;
232 if ((index = indexStream.next(inval)).isNil) { ^inval };
233 outval = streamList.wrapAt(index.asInteger).next(inval);
234 if (outval.isNil) { ^inval };
235 inval = outval.yield;
240 Ptuple : ListPattern {
241 embedInStream { arg inval;
242 var item, streams, tuple, outval;
244 repeats.value(inval).do({ arg j;
246 streams = list.collect({ arg item; item.asStream });
249 tuple = Array.new(streams.size);
250 streams.do({ arg stream;
251 outval = stream.next(inval);
252 if (outval.isNil, { sawNil = true; });
257 inval = yield(tuple);
265 embedInStream { arg inval;
267 var offsetValue = offset.value;
269 if (inval.eventAt('reverse') == true, {
270 repeats.value(inval).do({ arg j;
271 list.size.reverseDo({ arg i;
272 item = list.wrapAt(i + offsetValue);
273 if (item.isSequenceableCollection, {
274 item = item.wrapAt(j);
276 inval = item.embedInStream(inval);
280 repeats.value(inval).do({ arg j;
281 list.size.do({ arg i;
282 item = list.wrapAt(i + offsetValue);
283 if (item.isSequenceableCollection, {
284 item = item.wrapAt(j);
286 inval = item.embedInStream(inval);
294 // similar to Place, but the list is an array of Patterns or Streams
296 embedInStream { |inval|
297 var consecutiveNils = 0, index, repeat, item;
298 var streamList = list.collect({ |item| item.asStream });
299 var offsetValue = offset.value;
300 var localRepeats = repeats.value(inval);
303 while { (repeat < localRepeats) and: { consecutiveNils < list.size } } {
304 if(inval.eventAt(\reverse) == true) {
305 item = streamList.wrapAt(offsetValue - index - 1);
307 item = streamList.wrapAt(offsetValue + index);
309 if((item = item.next(inval)).notNil) {
311 inval = item.embedInStream(inval);
313 consecutiveNils = consecutiveNils + 1;
315 if((index = index + 1) == list.size) {
324 Pslide : ListPattern {
325 // 'repeats' is the number of segments.
326 // 'len' is the length of each segment.
327 // 'step' is how far to step the start of each segment from previous.
328 // 'start' is what index to start at.
329 // indexing wraps around if goes past beginning or end.
330 // step can be negative.
332 var <>len, <>step, <>start, <>wrapAtEnd;
333 *new { arg list, repeats = 1, len = 3, step = 1, start = 0, wrapAtEnd = true;
334 ^super.new(list, repeats).len_(len).step_(step).start_(start)
335 .wrapAtEnd_(wrapAtEnd);
337 embedInStream { arg inval;
340 var stepStr = step.asStream, stepVal;
341 var lengthStr = len.asStream, lengthVal;
343 repeats.value(inval).do {
344 lengthVal = lengthStr.next(inval);
345 if(lengthVal.isNil) { ^inval };
348 item = list.wrapAt(pos + j);
349 inval = item.embedInStream(inval);
354 item = list.at(pos + j);
356 inval = item.embedInStream(inval);
362 stepVal = stepStr.next(inval);
363 if(stepVal.isNil) { ^inval };
371 Pwalk : ListPattern {
372 // random walk pattern - hjh - jamshark70@gmail.com
374 var <>startPos, // starting index
375 <>stepPattern, // pattern for steps
376 <>directionPattern; // pattern should return a stream of:
377 // 1 to move in direction of stepPattern
378 // -1 to reverse the direction of stepPattern
379 // a new direction will be chosen when the walker
380 // reaches a boundary
382 *new { arg list, stepPattern, directionPattern = 1, startPos = 0;
383 ^super.new(list).startPos_(startPos)
384 .stepPattern_(stepPattern ?? { Prand([-1, 1], inf) })
385 .directionPattern_(directionPattern ? 1);
388 storeArgs { ^[list, stepPattern, directionPattern, startPos] }
391 embedInStream { arg inval;
393 var index = startPos;
394 var stepStream = stepPattern.asStream;
395 var directionStream = directionPattern.asStream;
396 // 1 = use steps as is; -1 = reverse direction
397 var direction = directionStream.next(inval) ? 1; // start with first value
400 // get step, stop when nil
401 (step = stepStream.next(inval)).notNil
403 inval = list[index].embedInStream(inval); // get value/stream out
404 step = step * direction; // apply direction
405 // if next thing will be out of bounds
406 if(((index + step) < 0) or: { (index + step) >= list.size }, {
407 direction = directionStream.next(inval) ? 1; // next direction, or 1
408 step = step.abs * direction.sign; // apply to this step
410 index = (index + step) % list.size;