Submit
Browse
Anonymous
Login
RSS
SuperCollider Code
Fork Code: Additive Synthesis GUI Demo 3
name
code content
// ************************************ // Additive Synthesis Demo (GUI) // Patch 3 - Inharmonic Partials // Bruno Ruviaro, 2013-07-24 // ************************************ /* 2 button rows to play up to 16 inharmonic partials of a given fundamental frequency. Horizontal Sliders control ADSR envelope, Global Volume, and Fundamental Frequency. All partials have equal amplitude. How to start: select all (ctrl + A), then evaluate (ctrl + enter) (on a Mac, use command key instead of control key) */ s.waitForBoot({ var win, buttonArray, knobArray, notesArray, partialArray, attackSlider, decaySlider, sustainSlider, releaseSlider, volumeSlider, fundamentalSlider, slidersWidth, fundamentalBus, updateButtonDisplay, att = 0.01, dec = 0.3, sus = 0.5, rel = 1.0, masterOut = 0.1; notesArray = Array.newClear(16); partialArray = Array.newClear(16); slidersWidth = 375; fundamentalBus = Bus.control(s, 1); fundamentalBus.set(110); Window.closeAll; s.meter; win = Window.new("Additive Synthesis - Inharmonics", Rect(500, 100, 800, 550)).front; win.background = Color.grey; win.alpha = 0.95; win.onClose = {s.freeAll; "Done!".postln}; CmdPeriod.doOnce({win.close}); // Change the gaps and margins to see how they work win.view.decorator = FlowLayout(win.view.bounds, margin: 10@10, gap: 20@20 ); buttonArray = Array.fill(16, {Button(win.view, 80@80)}); knobArray = Array.fill(16, {Knob(win.view, 80@50)}); // Little function to update numbers displayed on buttons updateButtonDisplay = {arg button, index; var current = button.value; button.states = [ [(partialArray[index]).asString, Color.black], [(partialArray[index]).asString, Color.black, Color.green]]; button.value = current; }; knobArray.do({arg item, count; knobArray[count].centered = true; knobArray[count].value = rrand(0.4, 0.6).round(0.01); // de-centered positions (center=0.5) knobArray[count].action = {arg knob; // update array of partials partialArray[count] = knob.value.linlin(0, 1, -0.2, 0.2).round(0.01) + count + 1; // update button display updateButtonDisplay.value(buttonArray[count], count); // if this partial is currently playing, update its partial number: if(notesArray[count].isNil.not, {notesArray[count].set(\partial, partialArray[count])})}}); // Initialize array of partials with first knob values partialArray.do({arg item, count; partialArray[count] = knobArray[count].value.linlin(0, 1, -0.2, 0.2).round(0.01) + count + 1}); // in the line above, "+ 0.5" adjusts for knob center = 0.5 (becomes center = 1); // this deviation value then is multiplied by the partial number // Initialize Buttons with proper number display buttonArray.do({arg item, count; updateButtonDisplay.value(item, count)}); buttonArray.do({arg item, count; item.action = {arg state; case {state.value==1} {notesArray[count] = Synth("addsynth", [ \fundamental, fundamentalBus.asMap, \partial, partialArray[count], \amp, 0.1, \att, att, \dec, dec, \sus, sus, \rel, rel])} {state.value==0} {notesArray[count].release; notesArray[count] = nil} }}); attackSlider = EZSlider( parent: win, bounds: slidersWidth @ 30, label: "Attack", controlSpec: ControlSpec(0.01, 4.0, \lin, 0.01, 0.1, "sec"), action: {|ez| att = ez.value}, initVal: 0.01, unitWidth: 30) .setColors( stringColor: Color.black, sliderBackground: Color.grey(0.7), numNormalColor: Color.black); decaySlider = EZSlider( parent: win, bounds: slidersWidth @ 30, label: "Decay", controlSpec: ControlSpec(0.01, 1, \lin, 0.01, 0.1, "sec"), action: {|ez| dec = ez.value}, initVal: 0.3, unitWidth: 30) .setColors( stringColor: Color.black, sliderBackground: Color.grey(0.7), numNormalColor: Color.black); sustainSlider = EZSlider( parent: win, bounds: slidersWidth @ 30, label: "Sustain", controlSpec: ControlSpec(1, 100, \lin, 1, 75, "%"), action: {|ez| sus = ez.value/100.0}, initVal: 75, unitWidth: 30) .setColors( stringColor: Color.black, sliderBackground: Color.grey(0.7), numNormalColor: Color.black); releaseSlider = EZSlider( parent: win, bounds: slidersWidth @ 30, label: "Release", controlSpec: ControlSpec(0.3, 6, \lin, 0.1, 0.5, "sec"), action: {|ez| rel = ez.value}, initVal: 0.5, unitWidth: 30) .setColors( stringColor: Color.black, sliderBackground: Color.grey(0.7), numNormalColor: Color.black); volumeSlider = EZSlider( parent: win, bounds: slidersWidth*2.05 @ 30, label: "VOL", controlSpec: ControlSpec(1, 100, \lin, 1, 10, "%"), action: {|ez| masterOut.set(\amp, ez.value/100)}, initVal: 10, unitWidth: 30) .setColors( stringColor: Color.white, sliderBackground: Color.grey(0.9), numNormalColor: Color.grey); fundamentalSlider = EZSlider( parent: win, bounds: slidersWidth*2.05 @ 30, label: "FREQ", controlSpec: ControlSpec(50, 200, \lin, 1, 110, "Hz"), action: {|ez| fundamentalBus.set(ez.value)}, initVal: 110, unitWidth: 30) .setColors( stringColor: Color.white, sliderBackground: Color.grey(0.9), numNormalColor: Color.grey); // SynthDefs { SynthDef("addsynth", { arg fundamental = 110, partial = 2.1, amp = 0.1, gate = 1, att = 0.01, dec = 0.3, sus = 0.5, rel = 1; var snd, env, freq; freq = fundamental * partial; env = EnvGen.ar(Env.adsr(att, dec, sus, rel), gate, doneAction: 2); snd = SinOsc.ar(Lag.kr(freq, 1), 0, amp) * env; Out.ar(0, snd!2); }).add; SynthDef(\amp, {arg inbus=0, amp = 0.1; ReplaceOut.ar(inbus, In.ar(inbus, 2) * amp); }).add; // Wait for SynthDefs to be added... s.sync; // Now call the Master Out Synth: masterOut = Synth("amp", addAction: \addToTail); }.fork; "Additive Synthesis Demo 1".postln; "".postln; });
code description
2 button rows to play up to 16 inharmonic partials of a given fundamental frequency. Horizontal Sliders control ADSR envelope, Global Volume, and Fundamental Frequency. All partials have equal amplitude.
use markdown for formating
category tags
comma separated, i.g. "wild, siren" (do not enter default SC class names, please)
ancestor(s)
comma separated identificators, i.g. "1-C,1-1,1-4M,1-x"
Private?
the code will be accessible by direct url and not visible in public activity
signup to submit public code without captcha
comment of change