Installing
BBCut2 is a nifty library for doing break beat cutting. To use it, you must first install it. It is not available as a quark, alas. To get the library, download it from http://www.cogs.susx.ac.uk/users/nc81/bbcut2.html. Then unzip it. Inside, you will find several directories.
- Move the "bbcut2 classes" directory to ~/Library/Application\ Support/SuperCollider/Extensions . That tilda represents your home directory, so if your user name is nicole, you would put the file in /Users/nicole/Library/Application\ Support/SuperCollider/Extensions . If the Extensions directory does not exist on your system, then create it.
- Put the "bbcut2 help" directory inside the classes directory that you just moved.
- Put the "bbcut2 ugens" directory in ~/Library/Application\ Support/SuperCollider/Extensions/sc3-plugins . If this directory does not exist, then create it.
- Take the contents of the "bbcut2 sounds" directory and put them in the sounds folder with your SuperCollider application. so if you have SuperCollider in /Applications, you would put the contents of "bbcut2 sounds" in /Applications/SuperCollider/sounds
Then, re-start SuperCollider. Depending on what version of SC you have, you may have duplicate classes. If you do, there will be errors in the post window. If you see that this is a problem for you, go find the files in the BBCut classes and delete them, making sure to keep the other copy. The error message will tell you where to find the files and which ones they are.
The Clock
BBCut relies on a clock. When I'm coding, I usually base the clock off the default clock:
TempoClock.default.tempo_(180/60); clock = ExternalClock(TempoClock.default); clock.play;
The tempo is defined as beats per second. That's beats per minute, divided by 60 seconds. In the above example, the clock rate is 180 bpm, which is then divided by 60 to set the tempo. If you wanted a clock that was 60 bpm, you would set tempo_(60/60), or for 103 bpm, it would be tempo_(103/60)
BBCut uses an ExternalClock, which uses a TempoClock, so in the above example, I give it the default TempoClock. I don't have to use the default one, but could declare a new one if I wanted: clock = ExternalClock(TempoClock(182/60));
The next step is to the clock to play. If you forget this step (which I often do), nothing happens later on. Telling the clock to play is important. BBCut relies on this clock.
Working with Buffers
There is a special sort of buffer used by BBCut, called a BBCutBuffer. The constructor for this takes two arguments. The first is a string which should contain the path and file name of the file. The second argument is the number of beats in the file. For example, we could open one of the sound files that came with BBCut:
sf= BBCutBuffer("sounds/break",8);
We need to wait for the Buffer to load before we can start using it. One way to do that is to put the code that relies on the Buffer into a Routine. And then, we can tell the Routine to wait until the server is ready to carry on.
sf= BBCutBuffer("sounds/break",8); Routine.run({ s.sync; // this tells the task to wait // below here, we know all out Buffers are loaded . . . })
Now we can tell BBCut that we want to cut up a buffer and get it to start doing that.
cut = BBCut2(CutBuf3(sf)).play(clock);
BBCut2 is the class that runs everything, so we make a new one of these. Inside, we pass a CutBuf, which is a class that handles Buffer cutting. We tell the BBCut2 object to play, using the clock. This starts something going.
Cutting is much more interesting if it can jump around in the buffer a bit:
cut = BBCut2(CutBuf3(sf, 0.4)).play(clock);
We can specify the chances of a random cut. 0.0 means a 0% chance and 1.0 is a 100% chance. We can set the chances at any numbers between and including 0.0 to 1.0. If we want a 40% chance of a random jump, we would use 0.4.
Cut Procedures
We can tell BBCut to use one of several cut procedures. The original one is called BBCutProc11.
cut = BBCut2(CutBuf3(sf, 0.4), BBCutProc11.new).play(clock);
It can take several arguments, which are: sdiv, barlength, phrasebars, numrepeats, stutterchance, stutterspeed, stutterarea
- sdiv - is subdivision. 8 subdivsions gives quaver (eighthnote) resolution.
- barlength - is normally set to 4 for 4/4 bars. If you give it 3, you get 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)
For more on this, see the helpfile. In general, the cut procedures are very well documented. Here's an example of passing some arguments to BBCutProc11:
cut = BBCut2(CutBuf3(sf, 0.4), BBCutProc11(8, 4, 2, 2, 0.2).play(clock)
We can tell the cutter to stop playing, or free it
cut.stop; cut.free;
Putting all of what we have so far together, we get:
( var clock, sf, cut; TempoClock.default.tempo_(180/60); clock = ExternalClock(TempoClock.default); clock.play; sf= BBCutBuffer("sounds/break",8); Routine.run({ s.sync; // this tells the task to wait cut = BBCut2(CutBuf3(sf, 0.4), BBCutProc11(8, 4, 2, 2, 0.2)).play(clock); 30.wait; // // let things run for 30 seconds cut.stop; cut.free; }) )
There are several other cut procedures, like WarpCutProc1 or SQPusher1 or SQPusher2. If you go look at the main helpfile, you can find which ones are available. This file is called BBCut2Wiki (and is found at ~/Library/Application\ Support/SuperCollider/Extensions/bbcut2\ classes/bbcut2\ help/BBCut2Wiki.help.rtf or by selecting the text BBCut2Wiki and typing apple-d )
Polyphony
The clock keeps things in sync, so you can run two different cut procedures at the same time and have things line up in time.
cut1 = BBCut2(CutBuf3(sf, 0.4), BBCutProc11(8, 4, 2, 2, 0.2)).play(clock); cut2 = BBCut2(CutBuf3(sf, 0.2), WarpCutProc1.new).play(clock);
You can even mix and match sound files:
( var clock, sf1, sf2, cut1, cut2, group; TempoClock.default.tempo_(180/60); clock = ExternalClock(TempoClock.default); clock.play; sf1= BBCutBuffer("sounds/break",8); sf2= BBCutBuffer("sounds/break2",4); Routine.run({ s.sync; // this tells the task to wait cut1 = BBCut2(CutBuf3(sf1, 0.4), BBCutProc11(8, 4, 2, 2, 0.2)).play(clock); cut2 = BBCut2(CutBuf3(sf2, 0.2), WarpCutProc1.new).play(clock); 15.wait; cut1.stop; cut2.stop; }) )
If you want to also sync up a Pbind, you can use BBcut's clock via the playExt method:
Pbind.new(/* . . . */ ).playExt(clock);
Or, if you want to play an Event, you can use the tempo clock associated with the external clock
Event.new.play(clock.tempoclock);
Groups and FX
If we want to add fx to the chain, and take them back out, we can use a thing called a CutGroup:
// make a group with a Buffer group = CutGroup(CutBuf3(sf1, 0.4)); // then send it to get cut up cut1 = BBCut2(group, BBCutProc11(8, 4, 2, 2, 0.2)).play(clock); // then put some FX in the chain group.add(CutMod1.new);
The CutGroup acts like an array, which holds our CutBuf and also the fx. To get an idea of how this works, try running the following code, adapted from CutGroup's help file:
( 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.new); g.cutsynths.postln; g.add(CutBRF1.new); g.cutsynths.postln; g.removeAt(2); //remove comb g.cutsynths.postln;
Note that the fx that you add on start with index 2.
And also notice that you may get some errors in the post window when you remove fx: FAILURE /n_set Node not found. These are not usually a problem.
Tying it all Together
Here's an example using everything covered so far:
( var clock, sf1, sf2, cut1, cut2, group; TempoClock.default.tempo_(180/60); clock = ExternalClock(TempoClock.default); clock.play; sf1= BBCutBuffer("sounds/break",8); sf2= BBCutBuffer("sounds/break2",4); Routine.run({ s.sync; // this tells the task to wait group = CutGroup(CutBuf3(sf1, 0.2)); // make a group with a Buffer cut1 = BBCut2(group, BBCutProc11(8, 4, 2, 2, 0.2)).play(clock); // then cut it up 5.wait; cut2 = BBCut2(CutBuf3(sf2, 0.2), BBCutProc11(8, 4, 4, 2, 0.2)).play(clock); // start more drums from the other sound file 5.wait; group.add(CutComb1.new); // put some FX on the drums in cut1 15.wait; group.removeAt(2); // take the fx back off 1.wait; cut2.pause; 4.wait; cut1.stop; }) )
Summary
- You must download BBCut2 from a website and install it by moving folders around.
- The main BBCut helpfile is BBCut2Wiki
- BBCut uses it's own clock, called ExternalClock, which relies on TempoClocks.
- You must remember to start the clock
- BBCut uses it's own buffer class called BBCutBuffer. The constructor takes two arguments: a string with the path and filename, and the number of beats in the sound file. If you get the number of beats wrong, your results may sound weird.
- There are several cut procedures, one of which is called BBCutProc11. To use it, (or any other cut procedure in it's place), you use the construction BBcut2(CutBuf1(sf), BBCutProc11.new).play(clock)
- The cut procedures all have good help files.
- Due to the magic of clocks, you can start two BBCuts going at the same time and if they have the same clock, they will line up.
- It is possible to add FX or remove FX from your chain by using CutGroup.
Problems
- Get some of your own drum loops or rhythmic samples and try this out. You can find many loops at http://www.freesound.org/. Also, try some files with sustained tones.
- Experiment with the arguments to BBCutProc11. Try your files with several different values.
- Try out the different cut procedures. Look at their help files to find their arguments.
- The FX are not as well documented, but they're located in ~/Library/Application\ Support/SuperCollider/Extensions/bbcut2\ classes/cutsynths/fx . Try several of them out.