Engine_organ
| // CroneEngine_organ | |
| // | |
| // Based on Engine_polytemplate v1.0.0 Mark Eats | |
| // https://gist.github.com/markwheeler/b88b4f7b0f2870567b55cbc36abbd5ea | |
| Engine_organX : CroneEngine { | |
| classvar maxNumVoices = 8; | |
| var voiceGroup; | |
| var voiceList; | |
| var pitchBendRatio = 1; | |
| var channelPressure = 0; | |
| var channelTimbre = 0; | |
| var vrate = 3; | |
| var amp = 0.7; | |
| var bass = 1; | |
| var quint = 1; | |
| var fundamental = 1; | |
| var oct = 1; | |
| var nazard = 1; | |
| var blockFlute = 1; | |
| var tierce = 1; | |
| var larigot = 1; | |
| var sifflute = 1; | |
| *new { arg context, doneCallback; | |
| ^super.new(context, doneCallback); | |
| } | |
| alloc { | |
| voiceGroup = Group.new(context.xg); | |
| voiceList = List.new(); | |
| // Synth voice | |
| // based on Tonewheel1 from SynthDEFaults - A Collection of Tradicional SynthDefs- //under GNU GPL 3 as per SuperCollider license //Organized by Zé Craum | |
| // http://sccode.org/1-5aD | |
| SynthDef(\organ_tonewheel1, { | |
| arg out, freq = 440, pitchBendRatio = 1, gate = 0, killGate = 1, amp = amp, atk = 0.001, dec = 0.1, sus = 0.2, rel = 0.01, pan = 0, | |
| bass, quint, fundamental, oct, nazard, blockFlute, tierce, larigot, sifflute, //organ voices (drawbars) amplitudes | |
| vrate, vdepth = 0.008, vdelay = 0.1, vonset = 0, vrateVariation = 0.1, vdepthVariation = 0.1; //vibrato arguments; | |
| var signal, envelope, vibrato, killEnvelope; | |
| killGate = killGate + Impulse.kr(0); // Make sure doneAction fires | |
| envelope = EnvGen.ar(envelope: Env.adsr( atk, dec, sus, rel), gate: gate, doneAction: Done.freeSelf); | |
| vibrato = Vibrato.kr(DC.kr(freq), DC.kr(vrate), DC.kr(vdepth), DC.kr(vdelay), DC.kr(vonset), DC.kr(vrateVariation), DC.kr(vdepthVariation)); | |
| killEnvelope = EnvGen.ar(envelope: Env.asr( 0, 1, 0.01), gate: killGate, doneAction: Done.freeSelf); | |
| signal = DynKlang.ar(`[[-12, 7, 0, 12, 19, 24, 28, 31, 36].midiratio, ([DC.ar(bass) , DC.ar(quint), DC.ar(fundamental), DC.ar(oct), DC.ar(nazard), DC.ar(blockFlute), DC.ar(tierce), DC.ar(larigot), DC.ar(sifflute)].normalizeSum), nil], vibrato) * envelope * killEnvelope; | |
| Out.ar(0, Pan2.ar(signal, pan, 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: \organ_tonewheel1, args: [ | |
| \out, context.out_b, | |
| \freq, freq, | |
| \pitchBendRatio, pitchBendRatio, | |
| \bass, bass, | |
| \quint, quint, | |
| \fundamental, fundamental, | |
| \oct, oct, | |
| \nazard, nazard, | |
| \blockFlute, blockFlute, | |
| \tierce, tierce, | |
| \larigot, larigot, | |
| \sifflute, sifflute, | |
| \vrate, vrate, | |
| \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); | |
| }); | |
| this.addCommand(\vrate, "f", { arg msg; | |
| vrate = msg[1]; | |
| voiceGroup.set(\vrate, vrate); | |
| }); | |
| this.addCommand(\amp, "f", { arg msg; | |
| amp = msg[1]; | |
| voiceGroup.set(\amp, amp); | |
| }); | |
| this.addCommand(\bass, "f", { arg msg; | |
| bass = msg[1]; | |
| voiceGroup.set(\bass, bass); | |
| }); | |
| this.addCommand(\quint, "f", { arg msg; | |
| quint = msg[1]; | |
| voiceGroup.set(\quint, quint); | |
| }); | |
| this.addCommand(\fundamental, "f", { arg msg; | |
| fundamental = msg[1]; | |
| voiceGroup.set(\fundamental, fundamental); | |
| }); | |
| this.addCommand(\oct, "f", { arg msg; | |
| oct = msg[1]; | |
| voiceGroup.set(\oct, oct); | |
| }); | |
| this.addCommand(\nazard, "f", { arg msg; | |
| nazard = msg[1]; | |
| voiceGroup.set(\nazard, nazard); | |
| }); | |
| this.addCommand(\blockFlute, "f", { arg msg; | |
| blockFlute = msg[1]; | |
| voiceGroup.set(\blockFlute, blockFlute); | |
| }); | |
| this.addCommand(\tierce, "f", { arg msg; | |
| tierce = msg[1]; | |
| voiceGroup.set(\tierce, tierce); | |
| }); | |
| this.addCommand(\larigot, "f", { arg msg; | |
| larigot = msg[1]; | |
| voiceGroup.set(\larigot, larigot); | |
| }); | |
| this.addCommand(\sifflute, "f", { arg msg; | |
| sifflute = msg[1]; | |
| voiceGroup.set(\sifflute, sifflute); | |
| }); | |
| } | |
| free { | |
| voiceGroup.free; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment