// Using a standard buffer for playback.

b = Buffer.read(s, "sounds/break");

// parameters for PlayBuf:
// PlayBuf.ar(numChannels,bufnum,rate,trigger,startPos,loop)
(
SynthDef("cage",{ arg out=0,bufnum=0;
	Out.ar(out,
		PlayBuf.ar(1,bufnum, BufRateScale.kr(bufnum),loop: 1.0)
	)
}).play(s,[\out, 0, \bufnum, b.bufnum]);
)

BBCutBuffer has no specific read parameter as it is a subclass of Buffer.  This means that the read method is inherited from Buffer.
Investigate these relationships using browse:

BBCutBuffer.browse;

Notice that BBCutBuffer's superclass is Buffer.

Click on *new in the methods, and you'll see that the three parameters below are listed underneath 'this', which simply refers to the class itself.  So these parameters will be generated by default whenever you ask for a new BBCutBuffer, including giving the value 8 to beatlength by default.

You can see the same with BBCut2, and so on.

// Now using BBCut in a very simple way.
// you can see all these parameters yourself using help...
// BBCutBuffer parameters: (filename, beatlength, eventlist)
// BBCutBufffer may also contain an array of soundfiles.
// BBCut2 parameters: ( cutgroups, proc, quantiser)
// CutBuf1 parameters: (bbcutbuf, offset)

(	//the same for a soundfile: you must allow time for the soundfile to load
var sf;
		
Routine.run({
// put a soundfile into a BBCutBuffer (called sf)
sf= BBCutBuffer("sounds/break",4);

s.sync; //this forces a wait for the Buffer to load

// BBCut2 (which actually does the cutting) uses a CutBuf1 (which includes reference to the soundfile sf)
// All these parameters use default values (except those specified).
BBCut2(CutBuf1(sf)).play; //will use TempoClock.default so depends what tempo that is at
});

)

// Change the clock rate:
TempoClock.default.tempo_(1)

// Play around with the 'beatlength' parameter of BBCutBuffer - it's proportional to the TempoClock value. Set the former to 8 and the latter to 2, then 16 and 4, then 32 and 8, etc.
// None of the classes can actually know what length the sample is, so it estimates, based on the idea that a typical sample will have 4 beats in one bar.

// As above but using another class to decide the cutting: BBCutProc11.
// When a class is called without arguments, it uses default values.

*new(sdiv, barlength, phrasebars, numrepeats, stutterchance, stutterspeed, stutterarea)   
Create a BBCutProc11 object with the given parameters.

sdiv - sub division.  A single measure is cut up into sdiv primitive units. So sdiv=8 over 4 beats gives
eighth note resolution cutting.
barlength - Normally set to 4.0 beats, for 4/4 bars, this can be altered to allow cuts over a different 
number of beats. So barlength= 3 gives cuts respecting 3/4. 
phrasebars - The length of the current phrase is barlength*phrasebars. 
numrepeats - Total number of repeats for normal cuts. So 2 corresponds to a particular size cut 
at one offset plus one exact repetition.
stutterchance - the tail of a phrase has this chance of becoming a repeating one unit cell stutter
(0.0 to 1.0)
stutterspeed - the stutter can be an integer multiple of the subdivision speed. For instance, if subdiv is
8 (quavers) and stutterspeed is 2, then the stutter is in semiquavers (subdiv 16).
stutterarea - a stutter is permissible within this proportion of the last bar of a phrase. Use values larger than
1 for stutters across multiple bars. The default is 0.5, for a half bar at 4/4.

//you would usually load soundfiles separately (perhaps before performing) before running cutters

//better practise, more explicit
(
var sf, clock;

clock= ExternalClock(TempoClock(2.5));	
		
clock.play;		
		
Routine.run({
			
sf= BBCutBuffer("sounds/break",8);

s.sync; //this forces a wait for the Buffer to load

BBCut2(CutBuf1(sf), BBCutProc11.new).play(clock);
});

)

// BBCutProc11 with some non-default behaviour.

//must have run this line before any of the examples
f= BBCutBuffer("sounds/break",8); 

//default cutups
BBCut2(CutBuf1(f),BBCutProc11.new).play(2.4);

// (sdiv, barlength, phrasebars, numrepeats, stutterchance, stutterspeed, stutterarea)  
// play around with the various parameters, refering to the help file or the details above.
BBCut2(CutBuf1(f),BBCutProc11.new(8,4.0,2,3,0.8,8,1.0)).play(2.4);

// use choose to determine the stutterspeed and stutterarea
BBCut2(CutBuf1(f),BBCutProc11.new(8,4.0,2,3,0.8,([2,3,4,5,6,7,8].choose),([0.2, 0.1, 0.6, 1.2].choose))).play(2.4);
// you could also use wchoose - weighted choose.
// see Randomness help file for more details...

(	//demonstrating tempo following from Server Clock control
var bbcut, pulse, clock;

clock= ServerClock.new.play(100);

bbcut= BBCut2(CutBuf1(f),BBCutProc11.new(8,4.0,2,3,0.5,3,1.0));

pulse= SynthDef(\pulse, {
var rate, impulse;

rate= MouseX.kr(2,3);

impulse= Impulse.kr(rate);

SendTrig.kr(impulse, 100, rate);

Out.ar(0,Decay.kr(impulse,0.1)*SinOsc.ar(440,0,0.5))

}).play;

bbcut.play(clock); 

)

//adding/removing cutsynths

//better practise, more explicit
(
var sf, clock;

clock= ExternalClock(TempoClock(2.5));	
		
clock.play;		
		
Routine.run({
			
sf= BBCutBuffer("sounds/break",8);

s.sync; //this forces a wait for the Buffer to load

g=CutGroup(CutBuf1(sf));

a=BBCut2(g, BBCutProc11.new).play(clock);
});

)

//run these one at a time
g.cutsynths.postln; //default CutMixer was added

// there's no helpfile for CutComb1, but you can see the parameters using the above browse method:
CutComb1.browse;
// and clicking on the *new method...
// you'll see the two values are deltime and dectime and their default values...

// see help for clip2: 
g.add(CutComb1({arg i; (i.clip2(10)*0.005)+0.01},0.8));

g.add(CutComb1(0.01,0.2));

g.cutsynths.postln;

g.removeAt(2); 	//remove comb

// you can add more and more combs if you want, and then remove them one by one!

g.removeAt(1);

g.cutsynths.postln;

a.end

// Some other classes...

(
var sf, clock;

clock= ExternalClock(TempoClock(2.1));	
		
clock.play;		
		
Routine.run({
			
sf= BBCutBuffer("sounds/break",8);

s.sync; //this forces a wait for the Buffer to load

//0.3.coin chance of random offset starting position for cut playback
BBCut2(CutBuf1(sf,0.3), BBCutProc11.new).play(clock);
});

)

//run one line at a time
//NB runs with haiku_cage!
f= BBCutBuffer("sounds/haiku_cage.aiff",8);
f= BBCutBuffer("sounds/break",8);

Post << [\length,f.length, \beatlength, f.beatlength, \events, f.eventstarts] << nl;

// Just play the buff with CutBuf1.  Look in help for ChooseCutProc for details...

(	
BBCut2(CutGroup([CutBuf1(f,{arg buffer; buffer.eventstarts.choose})]), ChooseCutProc(0.5,8,[0.24,0.53,0.23])).play(2)
)

(	
BBCut2(CutGroup([CutBuf1(f,{arg buffer; buffer.eventstarts.choose})]), ChooseCutProc(4,{[1,2,4].choose},[0.24,0.53,0.23], 2, 0.9, 0.5, 0.25)).play(1.5)
)

To understand ChooseCutProc, look at the help file, 

ChooseCutProc.browse

In any case, here are the arguments:

//(cutsizefunc, repeatfunc, rollfunc, phraselength, rollchance, rollallowed, bpsd)    
(	
BBCut2(CutGroup([CutBuf1(f,{arg buffer; buffer.eventstarts.choose})]), ChooseCutProc(4,[1,2,3,5].wchoose([0.3,0.4,0.2,0.1]),{arg blocksize;blocksize*[0.01,0.02,0.03]}, 2, 1, 0.5, 0.25)).play(2.4)
)

// choose the number of repeats
(	
BBCut2(CutGroup([CutBuf1(f,{arg buffer; buffer.eventstarts.choose})]), ChooseCutProc(0.5,{[1,2,3,4].choose},[0.24,0.53,0.23])).play(2)
)

//CutBuf1: choose when the events start, use Band Pass Filter, choose type of cutting...
(	
BBCut2(CutGroup([CutBuf1(f,{arg buffer; buffer.eventstarts.choose}), CutBPF1(600,drqfunc:0.5)]), ChooseCutProc(0.125,8)).play(3)
)

//change the event positions allowed (in samples) - (buffer.eventstarts.choose)
f.events_([17000, 18000, 19000, 20000, 21000, 22000, 23000, 24000]);
f.events_([50000,80000,100000]);
f.events_([0, 0]);
f.events_([100000, 120000, 130000, 140000, 150000, 160000, 170000, 180000, 190000]);
f.events_([20000, 22000, 23000, 24000, 25000, 26000, 27000, 28000, 29000]);
f.events_([30000, 32000, 33000, 34000, 35000, 36000, 37000, 38000, 39000]);

// soundfile names, breakpoints, choice of start points in samples
f= BBCutBuffer.array(["sounds/break","sounds/haiku_cage.aiff"],[8,4],[[0,0],[10000,20000,40000]]);

// post the information 
f.do({ arg val; Post << [\length,val.length, \beatlength, val.beatlength, \events, val.eventstarts] << nl;});

//will only select playback positions from the events list given above, using an offset choice function
(	
BBCut2(CutGroup([CutBuf1(f[1],{arg buffer; buffer.eventstarts.choose}), CutBPF1(100,drqfunc:0.5)]), ChooseCutProc(0.225,8)).play(2)
)

(	
BBCut2(CutGroup([CutBuf1(f[0],{arg buffer; buffer.eventstarts.choose}), CutBPF1(2000,drqfunc:0.5)]), ChooseCutProc(0.125,2)).play(2)
)

(	
var freq;
freq = 1000;
BBCut2(CutGroup([CutBuf1(f[0],{arg buffer; buffer.eventstarts.choose}), CutBPF1(freq,drqfunc:0.2)]), ChooseCutProc(0.225,1.2)).play(2)
)

(	
m = BBCut2(CutGroup([CutBuf1(f[0],{arg buffer; buffer.eventstarts.choose}), CutBPF1(300,drqfunc:0.1)]), ChooseCutProc(0.225,1.2)).play(2)
)

//change the event positions allowed (in samples)
f[0].events_([17000, 18000, 19000, 20000, 21000, 22000, 23000, 24000]);
f[1].events_([50000,80000,100000]);
f[0].events_([0, 0]);
f[1].events_([100000, 120000, 130000, 140000, 150000, 160000, 170000, 180000, 190000]);
f[1].events_([20000, 22000, 23000, 24000, 25000, 26000, 27000, 28000, 29000]);
f[1].events_([30000, 32000, 33000, 34000, 35000, 36000, 37000, 38000, 39000]);

//adding/removing cutsynths
//also look up the help for WarpCutProc1

(
var sf, clock;

clock= ExternalClock(TempoClock(2.5));	
		
clock.play;		
		
Routine.run({
			
sf= BBCutBuffer("sounds/break",8);

s.sync; //this forces a wait for the Buffer to load

g=CutGroup(CutBuf1(sf));

BBCut2(g, WarpCutProc1.new).play(clock);
});

)

//run these one at a time
g.cutsynths.postln; //default CutMixer was added

g.add(CutComb1({arg i; 0.025-(i.clip2(20)*0.001)},0.5));

g.cutsynths.postln;

g.add(CutBRF1({rrand(1000,5000)},{rrand(0.1,0.9)},{rrand(1.01,1.05)}));

g.cutsynths.postln;

g.removeAt(2); 	//remove comb

g.cutsynths.postln;

g.removeAt(0); 	//remove cutbuf

g.add(CutStream1.new) //add in a new source, audio in

g.cutsynths.postln;

// WarpCutProc1

*new(blocksizefunc, rollfunc, probs, phraselength, accel, bpsd)   
Create a WarpCutProc1 object with the given parameters.

blocksizefunc - A function (or something else responding to value) returning the next block size.  The function
will be passed the number of beatsleft in the current phrase, and the current phrase length in case judgement
is to depend on position within a phrase.
rollfunc - A function returning the number of cuts to subdivide a block in a roll. This function is passed the
current blocklength as argument in case you want a decision to take account of how much space you divide.
probs - An array of three probabilities (0.0 to 1.0). They are [prob of simple statement, prob of even roll, 
prob of accelerando rather than decelerando geometric series]. The algorithm cascades through one prob 
at a time. If a block is not simple, then it is a roll. If it isn't an even roll it is a geometric roll. 
phraselength - Next length of phrase in beats.
accel -a parameter to control the acceleration rate of the geometric series. Good values are 0.5 to 0.99.
Do not pass 0.0 or 1.0 without expecting a crash.
bpsd - beats per sub division. Sets a primitive cut size resolution for choose offset messages. 

Instance Methods

initWarpCutProc1 Called internally after a new.

(	//defaults
var sf;

Routine.run({	
	sf= BBCutBuffer("sounds/a11wlk01.wav",4);
	
	s.sync;
	
	//144 bpm
	BBCut2(CutBuf1(sf),WarpCutProc1.new).play(2.4);
});

)

// CutStream1 is the input.  The default input (as here) is the first bus input (in most cases audio in)
(	//oddness on AudioIn 
BBCut2(CutStream1.new,WarpCutProc1({[1,2,4].wchoose([0.7,0.2,0.1])},{[9,19,29].choose},[0.0,0.5,0.5],100.0,{0.8+(0.15.rand)})).play(2.2); 
)

Buffer

(
var buf, clock;

clock= ExternalClock(TempoClock(2.1));	
		
clock.play;		
		
Routine.run({
			
// buf= BBCutBuffer.alloc(s,44100,1); // allocate a 1 second (44100 sample), mono buffer...
// buf= BBCutBuffer.read(s, "sounds/a11wlk01.wav");
buf= BBCutBuffer.read(s, "sounds/haiku_cage.aiff");

s.sync; //this forces a wait for the Buffer to be allocated

BBCut2(CutStream1(s.options.numOutputBusChannels, buf, 0.5, 0.001, 0.5, -4), WarpCutProc1.new).play(clock);
});

)

// Example with complex WarpCut

(
var buf, clock;

clock= ExternalClock(TempoClock(2.1));	
		
clock.play;		
		
Routine.run({
			
// buf= BBCutBuffer.alloc(s,44100,1); // allocate a 1 second (44100 sample), mono buffer...
// buf= BBCutBuffer.read(s, "sounds/a11wlk01.wav");
buf= BBCutBuffer.read(s, "sounds/haiku_cage.aiff");

s.sync; //this forces a wait for the Buffer to be allocated

// BBCut2(CutStream1(s.options.numOutputBusChannels, buf, 0.5, 0.001, 0.5, -4), WarpCutProc1({[2,3,8].wchoose([0.7,0.2,0.1])},{[2,3,4].choose},[0.8,0.1,0.1],100.0,{0.7+(0.15.rand)})).play(clock);

BBCut2(CutStream1(0, buf, 0.5, 0.001, 0.5, -4), WarpCutProc1({[1, 2, 3, 4].wchoose([0.6,0.2,0.1,0.1])},{[1,19,29,39].choose},[0.0,0.5,0.5],100.0,{0.8+(0.15.rand)})).play(clock);
});

)

Server.browse;

// *new(blocksizefunc, rollfunc, probs, phraselength, accel, bpsd)   
// weighted choose: the chances of each of 1, 2 and 4 being chosen are .7, .2 and .1 respectively...
s.options.numOutputBusChannels

[1,2,4].wchoose([0.7,0.2,0.1])

// choose from 9, 19 and 29
[9,19,29].choose

// an array
[0.0,0.5,0.5]

// random of .15 with an offset of .8
0.8+(0.15.rand)

// For more on randomness, look at Randomness help