Skip to content

Instantly share code, notes, and snippets.

@madskjeldgaard
Last active May 16, 2023 15:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save madskjeldgaard/9283261f90d7b3ece15b4b72c4bdac79 to your computer and use it in GitHub Desktop.
Save madskjeldgaard/9283261f90d7b3ece15b4b72c4bdac79 to your computer and use it in GitHub Desktop.
My SuperCollider Buffer player synth
/*
This is the buffer player synth to end all buffer player synths
b = Buffer.read(s, "/Users/mads/test-sounds/Ellen-piano-001.wav")
Synth(\playbuf2, [\buffer, b, \dur, 2.5, \loop, 1, \playrate, 2, \pitchEnvAmount, 0.5, \pitchModAmount, 0.0, \modFreq, 0.1, \modEnvAmount, 0.2, \panModAmount, 1.0, \pan, 0.5, \lowPassFreq, 550, \filterModAmount, 0.9, \filterEnvAmount, 1, \filterEnvScale, 1, \lowPassRes, 0.5, \fmAmount, 0.9, \fmEnvAmount, 1])
TODO:
- Seperate filter envelope?
- Seperate pitch envelope?
*/
(
(1..2).do{|numChannels|
[
\adsr,
\perc,
\gate,
].do{|envName|
SynthDef("playbuf%_%".format(numChannels,envName).postln.asSymbol, {|buffer=0, out=0, gate=1, dur=1|
// Envelope
var doneAction = \doneAction.kr(2);
var sampleDoneAction = \sampleDoneAction.kr(0);
var envCurve = \envCurve.kr(1.0, spec: [-10.0,10.0,\lin]);
// var envType = Env.perc(attackTime, releaseTime, envCurve);
var envType = case
{envName == \adsr} {
var attackTime = \attackTime.kr(0.01, spec: [0.0,1.0,\lin]);
var releaseTime = \releaseTime.kr(0.125, spec: [0.0,1.0,\lin]);
var decayTime = \decayTime.kr(0.3, spec: [0.0,1.0,\lin]);
var sustainLevel = \sustainLevel.kr(0.5, spec: [0.0,1.0,\lin]);
Env.adsr(attackTime, decayTime, sustainLevel, releaseTime, curve: envCurve);
}
{envName == \perc} {
var attackTime = \attackTime.kr(0.01, spec: [0.0,1.0,\lin]);
var releaseTime = \releaseTime.kr(0.99, spec: [0.0,1.0,\lin]);
Env.perc(attackTime, releaseTime, curve: envCurve);
}
{envName == \gate} {
Env.step(levels:[0, 1, 0], times:[0.0, 1.0, 0.0])
}
;
var env = EnvGen.ar(envType, gate: gate, timeScale: dur, doneAction: doneAction);
// PlayBuf
var pitchEnvAmount = \pitchEnvAmount.kr(0.0, spec: [0.0,1.0,\lin]);
var playrate = \playrate.ar(1, spec: [-10.0,10.0,\lin]) * BufRateScale.kr(buffer);
var direction = \direction.kr(0, spec: [0,1,\lin,1]);
var loop = \loop.ar(0, spec: [0,1,\lin,1]);
var startPos = \startPos.ar(0.0, spec: [0.0,1.0,\lin]) * BufFrames.kr(buffer);
var amp = \amp.ar(1.0, spec: [0.0,1.0,\lin]);
// Filters
var filterFreq = \cutoff.kr(20000.0, spec: [10.0,20000.0,\exp]);
var filterRes = \resonance.kr(0.0, spec: [0.0,1.0,\lin]);
var filterType = \filterType.kr(0.0, spec: [0.0,1.0,\lin, 1]);
var filterModAmount = \filterModAmount.kr(0.0, spec: [0.0,1.0,\lin]);
var filterEnvAmount = \filterEnvAmount.kr(0.0, spec: [0.0,1.0,\lin]);
var filterEnvScale = \filterEnvScale.kr(1.0, spec: [1.0,100.0,\lin]);
// FM
var fmAmount = \fmAmount.kr(0.0, spec: [0.0,1.0,\lin]);
var fmFreq = \fmFreq.kr(102.3931, spec: [0.001,10000.0,\exp]);
var fmEnvAmount = \fmEnvAmount.kr(0.0, spec: [0.0,1.0,\lin]);
var fmEnvLag = \fmEnvLag.kr(0.5, spec: [0.0,1.0,\lin]);
// Modulation
var pitchModAmount = \pitchModAmount.kr(0.0, spec: [0.0,1.0,\lin]);
var modEnvAmount = \modEnvAmount.kr(0.0, spec: [0.0,1.0,\lin]);
var modFreq = \modFreq.kr(1.0, spec: [0.0,1000.0,\exp]);
var modulator, fmModulator, sig;
//------------------------------------------------------------------//
// Modulation //
//------------------------------------------------------------------//
// Apply envelope to FM modulator freq
fmFreq = (1.0 - fmEnvAmount) * fmFreq + (fmFreq * fmEnvAmount * env.lag(fmEnvLag));
fmModulator = SinOsc.ar(fmFreq);
// Apply envelope to modFreq
modFreq = (1.0 - modEnvAmount) * modFreq + (modFreq * modEnvAmount * env);
// The pitch modulator
modulator = LFTri.ar(modFreq);
// Apply pitch envelope to playrate
playrate = (1.0 - pitchEnvAmount) * playrate + (playrate * pitchEnvAmount * env);
// Apply modulator
playrate = (1.0 - pitchModAmount) * playrate + (playrate * pitchModAmount * modulator);
// Apply FM modulator to playrate
playrate = (1.0 - fmAmount) * playrate + (playrate * fmAmount * fmModulator);
playrate = playrate * Select.kr(direction, [1.0, (-1.0)]);
// Apply filter modulation
filterFreq = (1.0 - filterModAmount) * filterFreq + (filterFreq * filterModAmount * modulator);
// Apply envelope to filter freqs
filterFreq = (1.0 - filterEnvAmount) * filterFreq + (filterFreq * filterEnvAmount * env * filterEnvScale);
//------------------------------------------------------------------//
// The buffer player //
//------------------------------------------------------------------//
sig = PlayBuf.ar(numChannels, buffer, playrate, startPos: startPos, loop: loop, doneAction: 0);
//------------------------------------------------------------------//
// Filtering //
//------------------------------------------------------------------//
sig = DFM1.ar(sig, filterFreq.clip(20.0, 20000.0), filterRes, type: filterType, noiselevel:0);
//------------------------------------------------------------------//
// Panning and output stuff //
//------------------------------------------------------------------//
if(numChannels == 1, {
var pan = \pan.ar(0.0, spec: [-1.0,1.0,\lin]);
var panModAmount = \panModAmount.kr(0.0, spec: [0.0,1.0,\lin]);
// Apply modulation to pan
pan = (1.0 - panModAmount) * pan + (pan * panModAmount * modulator);
sig = Pan2.ar(sig, pan);
});
if(numChannels == 2, {
var pan = \pan.ar(0.0, spec: [-1.0,1.0,\lin]);
var panModAmount = \panModAmount.kr(0.0, spec: [0.0,1.0,\lin]);
pan = (1.0 - panModAmount) * pan + (pan * panModAmount * modulator);
sig = Balance2.ar(sig[0], sig[1], pan)
});
Out.ar(out, sig * amp * env);
}).add
};
}
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment