Last active
January 2, 2021 19:23
-
-
Save markwheeler/b88b4f7b0f2870567b55cbc36abbd5ea to your computer and use it in GitHub Desktop.
Poly synth SC engine template
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// CroneEngine_PolyTemplate | |
// | |
// v1.0.0 Mark Eats | |
Engine_PolyTemplate : CroneEngine { | |
classvar maxNumVoices = 3; | |
var voiceGroup; | |
var voiceList; | |
var pitchBendRatio = 1; | |
var channelPressure = 0; | |
var channelTimbre = 0; | |
*new { arg context, doneCallback; | |
^super.new(context, doneCallback); | |
} | |
alloc { | |
voiceGroup = Group.new(context.xg); | |
voiceList = List.new(); | |
// Synth voice | |
SynthDef(\simpleSine, { | |
arg out, freq = 440, pitchBendRatio = 1, gate = 0, killGate = 1, amp = 1; | |
var signal, envelope, killEnvelope; | |
killGate = killGate + Impulse.kr(0); // Make sure doneAction fires | |
envelope = EnvGen.ar(envelope: Env.adsr( 0.01, 0.3, 0.3, 3.0), gate: gate, doneAction: Done.freeSelf); | |
killEnvelope = EnvGen.ar(envelope: Env.asr( 0, 1, 0.01), gate: killGate, doneAction: Done.freeSelf); | |
signal = SinOsc.ar(freq: freq * pitchBendRatio) * envelope * killEnvelope; | |
Out.ar(out, signal.dup * 0.3 * amp); | |
}).add; | |
// Commands | |
// noteOn(id, freq, vel) | |
this.addCommand(\noteOn, "iff", { arg msg; | |
var id = msg[1], freq = msg[2], vel = msg[3]; | |
var voiceToRemove, newVoice; | |
// Remove voice if ID matches or there are too many | |
voiceToRemove = voiceList.detect{arg item; item.id == id}; | |
if(voiceToRemove.isNil && (voiceList.size >= maxNumVoices), { | |
voiceToRemove = voiceList.detect{arg v; v.gate == 0}; | |
if(voiceToRemove.isNil, { | |
voiceToRemove = voiceList.last; | |
}); | |
}); | |
if(voiceToRemove.notNil, { | |
voiceToRemove.theSynth.set(\killGate, 0); | |
voiceList.remove(voiceToRemove); | |
}); | |
// Add new voice | |
newVoice = (id: id, theSynth: Synth.new(defName: \simpleSine, args: [ | |
\out, context.out_b, | |
\freq, freq, | |
\pitchBendRatio, pitchBendRatio, | |
\gate, 1, | |
\amp, vel.linlin(0, 1, 0.5, 1) | |
], target: voiceGroup).onFree({ voiceList.remove(newVoice); }), gate: 1); | |
voiceList.addFirst(newVoice); | |
}); | |
// noteOff(id) | |
this.addCommand(\noteOff, "i", { arg msg; | |
var voice = voiceList.detect{arg v; v.id == msg[1]}; | |
if(voice.notNil, { | |
voice.theSynth.set(\gate, 0); | |
voice.gate = 0; | |
}); | |
}); | |
// noteOffAll() | |
this.addCommand(\noteOffAll, "", { arg msg; | |
voiceGroup.set(\gate, 0); | |
voiceList.do({ arg v; v.gate = 0; }); | |
}); | |
// noteKill(id) | |
this.addCommand(\noteKill, "i", { arg msg; | |
var voice = voiceList.detect{arg v; v.id == msg[1]}; | |
if(voice.notNil, { | |
voice.theSynth.set(\killGate, 0); | |
voiceList.remove(voice); | |
}); | |
}); | |
// noteKillAll() | |
this.addCommand(\noteKillAll, "", { arg msg; | |
voiceGroup.set(\killGate, 0); | |
voiceList.clear; | |
}); | |
// pitchBend(id, ratio) | |
this.addCommand(\pitchBend, "if", { arg msg; | |
var voice = voiceList.detect{arg v; v.id == msg[1]}; | |
if(voice.notNil, { | |
voice.theSynth.set(\pitchBendRatio, msg[2]); | |
}); | |
}); | |
// pitchBendAll(ratio) | |
this.addCommand(\pitchBendAll, "f", { arg msg; | |
pitchBendRatio = msg[1]; | |
voiceGroup.set(\pitchBendRatio, pitchBendRatio); | |
}); | |
// pressure(id, pressure) | |
this.addCommand(\pressure, "if", { arg msg; | |
var voice = voiceList.detect{arg v; v.id == msg[1]}; | |
if(voice.notNil, { | |
// voice.theSynth.set(\pressure, msg[2]); | |
}); | |
}); | |
// pressureAll(pressure) | |
this.addCommand(\pressureAll, "f", { arg msg; | |
channelPressure = msg[1]; | |
// voiceGroup.set(\pressure, channelPressure); | |
}); | |
// timbre(id, timbre) | |
this.addCommand(\timbre, "if", { arg msg; | |
var voice = voiceList.detect{arg v; v.id == msg[1]}; | |
if(voice.notNil, { | |
// voice.theSynth.set(\timbre, msg[2]); | |
}); | |
}); | |
// timbreAll(timbre) | |
this.addCommand(\timbreAll, "f", { arg msg; | |
channelTimbre = msg[1]; | |
// voiceGroup.set(\timbre, channelTimbre); | |
}); | |
} | |
free { | |
voiceGroup.free; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment