«Simple pattern-based beat slicer» by david_morgan

on 24 Jan'16 22:00 in beat slicer

Revised: Made some improvements from previous submission.

I hadn't really come across a simple self-contained example to use with patterns.

You can download a free drum loop from: https://freesound.org/people/pushtobreak/sounds/5647/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/**********************************
You can download a free drum loop from:
https://freesound.org/people/pushtobreak/sounds/5647/
***********************************/
(
SynthDef(\smplr_m3, {arg startPos = 0, buf, rate = 1, loop = 1,
	atk = 0.005, rel = 0.005, curve = 0, dur = 0.1,
	amp = 0.5, out = 0, pan = 0;

	var env, sig;
	env= Env([0,1,1,0], [atk, dur-atk-rel, rel], curve).ar(doneAction:2);
	sig = PlayBuf.ar(numChannels: 1, bufnum: buf, rate: BufRateScale.kr(buf) * rate, startPos: startPos, loop: loop);
	sig = sig * env * amp;
	OffsetOut.ar(out, Pan2.ar(sig, pan));
}).add;
)

(
// Logic for providing slices to the queue
~sliceProducer = {arg count, slices, beats, queue;

	var pos = count % beats;
	var delta = (slices/beats).reciprocal;
	var slice = (count/delta % slices);
	var event = (delta:delta, slice:slice);
	var rem = (beats - pos);

	if (0.2.coin && (rem <= 1) ) {

		var div = delta/2;
		var event = (delta:div, slice:slice);
		2.do({
			queue.add(event);
		});
	} {
		if (pos == 0) {
			event[\slice] = 0;
			queue.add(event);
		} {
			event[\slice] = (0..slices-1).choose;
			queue.add(event);
		}
	};
};

// main interface
~slcr = {arg buf, beats = 8, beatDiv = 2, sliceProducer, amp = 0.1, clock = TempoClock.default;

	// buffer info
	var numFrames = buf.numFrames;
	var sampleRate = buf.sampleRate;

	// length in seconds of sample
	var len = numFrames/sampleRate;

	// beats per second
	var bps = beats/len;

	// number of slices
	var slices = beats * beatDiv;

	// frames per slice
	var fps = numFrames/slices;

	// yields slice data to the pattern
	var rtn = Routine({

		var queue = LinkedList.new;
		var count = 0;

		inf.do({arg i;

			var event;

			if (queue.isEmpty) {
				sliceProducer.value(count, slices, beats, queue);
			};

			event = queue.popFirst;
			count = count + event[\delta];
			[event[\delta], event[\slice] * fps].yield;
		});
	});

	// return the pattern
	Pbind(\instrument, \smplr_m3,
		[\delta, \startPos], rtn,
		\buf, buf,
		\rate, Pfunc({ clock.tempo }) / bps,
		\amp, amp,
		\dur, Pfunc({ clock.beatDur }) * Pkey(\delta)
	);
};
)

(
TempoClock.default.tempo_(2);
~buf = Buffer.read(s, "/path/to/mono/soundfile");
)

(
Ndef(\out).clear;
Ndef(\out).play;
Ndef(\out)[0] = ~slcr.(buf: ~buf, beats: 4, beatDiv: 2, sliceProducer: ~sliceProducer, amp: 0.5);
Ndef(\out)[10] = \filter -> {arg in; FreeVerb.ar(in, 0.3, 0.5); };
)
raw 2487 chars (focus & ctrl+a+c to copy)
reception
comments