PR(\break)


Breakbeat slicer, based on bufPerc.


The handling of the rhythm arrays is fundamentally the same as in bufPerc. What is different in break is the handling of the starting playback position in the buffer. bufPerc assumes that you will start at the beginning of the buffer for every note; if you want to start elsewhere, you can specify the frame number in ~argPairs = [start: 12000] (or use a pattern to change the starting position).


For breakbeats, it's easier to load the entire drum loop into one buffer and memorize the frame indices for interesting events in the loop that you will want to address. (Since in most cases the drum hits have to stay in sync with the beat, you probably won't start at arbitrary positions.) This calls for one additional parameter at initialization, and one new rhythm array.


Initialization


In addition to the bufPerc parameters:


segStart: A two dimensional array containing, for each loaded buffer, the frame indices of useful places to start playing in the drum loop.


[

// starting points for buffer 0

[0, 12000, 18000, ... ],

// starting points for buffer 1

[0, 22000, 35000, ... ]

]



Rhythm arrays


~start: For each note, which one of the segStart entries to use (by array index). The ~bufs the arrays specifies which buffer to use, so the starting point lookup is ~segStart.wrapAt(bufferIndex).wrapAt(startIndex).



Algorithmic considerations


You can add whatever variables you need into the Proto to keep track of what each starting index means (kick, snare, cymbals). It's up to you to write your own pbindPreAction and create data structures to support them. One suggestion is in the example.



Example


This process depends on a drum loop which you can download from http://www.dewdrop-world.net/sc3/Help/096_theory-groove.aif.zip -- put the file anywhere you like in your filesystem and fill in the path below.


s.boot;

TempoClock.default.tempo = 96/60;


(

PR(\break).chuck(BP(\x), parms: (

postMCCreation: { |chan|

chan.level = -8.dbamp; // maybe soften it

},

// put the path here

bufPaths: #["insert/path/here/096_theory-groove.aif"],

segStart: [[0, 13416, 20554, 27348, 40592, 47816, 61404, 69144, 75766, 82474]],

// this is part of the algorithm to generate the rhythm

// it is not required - it's up to you to organize the clips as you see fit

segments: (

kick: [0, 2, 5, 7, 8],

snare: [3],

hat: [1, 4, 6],

crash: [9]

),

amps: 0,

ampbase: (0 ! 16).put(0, 1),

startbase: 0 ! 16,

usedKeys: [\start],

pbindPreAction: {

var pool = (4..15), i;

~amps = ~ampbase.copy;

~start = ~startbase.copy;

// place a couple of snare hits on beat or 8th note

rrand(2, 4).do({

i = pool.select(_.even).choose;

pool.remove(i);

~amps[i] = 1;

~start[i] = ~segments[#[\snare, \crash].choose].choose;

});

// throw some other kix and hats in

rrand(2, 5).do({

i = pool.takeAt(pool.size.rand);

~amps[i] = rrand(0.3, 0.7);

~start[i] = ~segments[#[\kick, \hat].choose].choose;

});

Func(\shrinkKeys).value;

}

));

)


BP(\x).play;

BP(\x).stop;


// crank up the tempo using rates array

TempoClock.default.tempo = 132/60;

BP(\x).rates = [132/96]; // new tempo / original sample tempo


BP(\x).play;

BP(\x).stop;


BP(\x).free;