PR(\defPerc)
A drum machine process that produces sound based on user-defined synthdefs.
Most of the parameters are identical to bufPerc; refer to its help file for details.
Specifying synthdefs
In PR(\defPerc), the ~bufPaths and ~bufCoords parameters are ignored. Instead, the parameter ~objects lists the objects to treat as synthdefs within this process. The parameter may take an array directly, or if the synthdefs will depend on resources that you load in ~postMCCreation, you can provide a function that returns the array. The function will be evaluated after the postMCCreation resources are prepared.
The following objects are supported:
"string" or \symbol: The name of a synthdef that you have already saved in the library using .store or .memStore.
SynthDef(...): The synthdef will be .memStore'd in the library for you.
Function { ... }: Will be converted into a synthdef and .memStore'd.
Patch: Will be converted into a synthdef and .memStore'd. Do not use nested patches.
Specifying synth arguments
The only synth argument automatically sent is \amp. All others must be given in the ~argPairs array, which takes the form [argName0: pattern0, argName1: pattern1 ... ]. The arguments are treated as extra streams for Pbind.
The same ~argPairs array is used for all synthdefs, which assumes that the arguments are more or less compatible across all of them. It is recommended to keep the sounds for a single process relatively similar. The drum machine processes are not polyphonic; you should not expect to layer several sounds within the same process.
Examples
// Synthdefs do not depend on additional resources.
s.boot;
TempoClock.default.tempo = 84/60;
(
PR(\defPerc).chuck(BP(\ex1), parms: (
objects: [
{ |amp = 1, decayscale = 1|
var sig = PinkNoise.ar(amp) * Decay2.kr(Impulse.kr(0), 0.01, 0.05);
sig = Klank.ar(`[
{ rrand(500.0, 1200.0) } ! 5,
{ rrand(0.5, 1.0) } ! 5,
{ rrand(0.4, 0.8) } ! 5
], sig, decayscale: decayscale);
DetectSilence.ar(sig, doneAction: 2);
sig * 0.1 // this synth can be kind of loud
}
],
amps: 0,
ampbase: #[1, 0.6, 0.3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
argPairs: [decayscale: BPStream(\dscale)],
dscale: Pwhite(0.8, 1.7, inf),
pbindPreAction: {
var pool = (4..15).scramble;
~amps = ~ampbase.copy;
rrand(3, 7).do({ |i|
~amps[pool[i]] = rrand(0.2, 0.7);
});
}
));
)
BP(\ex1).play;
BP(\ex1).stop;
BP(\ex1).free;
// Synthdefs DO depend on additional resources.
// This one loads part of a soundfile and plays it with different kinds of processing.
// Could also be done with \bufPerc if you write custom synthdefs.
(
PR(\defPerc).chuck(BP(\ex2), parms: (
inChannels: 2,
// load special resources here
postMCCreation: { |chan|
~buf = Buffer.readAndQuery(s, "sounds/a11wlk01-44_1.aiff", 4785, 12900);
},
objects: { [
// this shows that the buffer loading (in postMCCreation)
// takes place before synthdef creation
// thus, ~buf is populated by this point
"\nCreating synthdefs.".postln;
// forward with ringmod
{ |amp = 1, rate = 1, pan|
var dur = BufDur.ir(~buf),
sig = PlayBuf.ar(1, ~buf, rate * BufRateScale.ir(~buf)),
sig2 = SinOsc.ar(XLine.kr(ExpRand(300, 900), ExpRand(300, 900), dur));
FreeSelfWhenDone.kr(sig);
Pan2.ar(sig * sig2, pan, amp)
},
// backward with comb filter
{ |amp = 1, rate = 1, pan|
var sig = PlayBuf.ar(1, ~buf, rate.neg * BufRateScale.ir(~buf),
startPos: BufFrames.ir(~buf) - 1),
combDelay = ExpRand(100, 650).reciprocal;
// without LeakDC, DetectSilence never detects silence!
sig = LeakDC.ar(CombL.ar(sig, combDelay, combDelay, Rand(0.1, 0.4)));
DetectSilence.ar(sig, doneAction: 2);
Pan2.ar(sig, pan, amp)
}
] },
ampbase: #[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
amps: 0,
defbase: 0 ! 16,
argPairs: [rate: Pwhite(0.8, 1.25), pan: Pwhite(-1.0, 1.0, inf)],
usedKeys: #[defs],
pbindPreAction: {
var pool = (2..15).scramble;
~amps = ~ampbase.copy;
~defs = ~defbase.copy;
rrand(5, 10).do({ |i|
~amps[pool[i]] = rrand(0.1, 0.5);
// 0 == use forward synthdef; 1 == use backward
~defs[pool[i]] = 0.7.coin.binaryValue;
});
Func(\shrinkKeys).value;
},
// I made the buffer; I have to clean it up
free: { ~buf.free }
));
)
BP(\ex2).play;
BP(\ex2).stop;
BP(\ex2).free;