Submit
Browse
Anonymous
Login
RSS
SuperCollider Code
Fork Code: Env editor with knobs to edit individual points
name
code content
( ~windowize = { arg layout; var win; win = Window.new; win.layout = layout; win.front; }; ~env_controller = ( new: { arg self, env, spec; self = self.deepCopy; self.get_env = env; self.spec = spec ?? [3, \freq.asSpec]; spec = self.spec.value[1]; spec = spec ?? self.label.asSpec ?? \widefreq.asSpec; self.level_spec = spec; self.time_spec = ControlSpec(0.01,8,\exp,0,0.1); self.curve_spec = ControlSpec(-9,9,\lin,0,0); self; }, get_xy: { arg self; var x = List.new; var y = List.new; var env = self.get_env; env.levels.do { arg lvl, n; y.add(lvl); if(n == 0) { x.add(0); } { x.add(env.times[n-1]) } }; [x.integrate.asArray,y.asArray] }, time_scale: 1/2, get_norm_xy: { arg self, time_scale; var x = List.new; var y = List.new; var env = self.get_env; var times, levels; var res; time_scale = time_scale ?? self.time_scale; times = self.time_spec.unmap(env.times); levels = self.level_spec.unmap(env.levels); x = times; y = levels; x = x.insert(0, 0); res = [x.integrate.asArray * time_scale,y.asArray]; res }, set_norm_xy: { arg self, val, time_scale; var times, levels; time_scale = time_scale ?? self.time_scale; #times, levels = val; times = times.copy; times.removeAt(0); times = times / time_scale; times = times.differentiate; times = self.time_spec.map(times); levels = self.level_spec.map(levels); self.get_env.times = times; self.get_env.levels = levels; }, edit: { arg self; ~env_editor.new(self).make_window; }, label: \bla ); ~env_to_string = { arg env; var prec = 5; "Env(%, %, %)".format( env.levels.collect({ arg x; x.asFloat.asStringPrec(prec)}), env.times.collect({arg x; x.asFloat.asStringPrec(prec)}), env.curves ); }; ~env_editor = ( new: { arg self, controller; self = self.deepCopy; self.controller = controller; self; }, update_label: { arg self; self.env_label.string_( "%".format( ~env_to_string.(self.controller.get_env), ) ); }, update_env: { arg self; self.env_view.value_(self.controller.get_norm_xy); }, update_knobs: { arg self; var index = self.env_view.index; var levels = self.controller.get_env.levels; var times = self.controller.get_env.times; var level_spec = self.controller.level_spec; var time_spec = self.controller.time_spec; if(levels[index].notNil) { self.knob_level.value = level_spec.unmap(levels[index]); }; if(times[index].notNil) { self.knob_time.value = time_spec.unmap(times[index]); }; }, make_layout: { arg self; var node_name, name, spec; var win, val, slider, label, layout; var prec = 0.001; var knob_layout; var knob_size = 15; var level_spec, time_spec, curve_spec; name = self.controller.label; level_spec = self.controller.level_spec; time_spec = self.controller.time_spec; curve_spec = self.controller.curve_spec; label = StaticText.new; label.string = name.asString; label.minWidth = 160; val = StaticText.new; val.minWidth = 100; val.string = self.controller.get_val; slider = EnvelopeView.new(nil, Rect(0, 0, 230, 80)) .drawLines_(true) .selectionColor_(Color.red) .drawRects_(true) .step_(0) .thumbSize_(10) .keepHorizontalOrder_(true) .value_(self.controller.get_norm_xy); self.env_view = slider; self.env_view.selectIndex(1); self.env_view.action = { arg env; if(env.index == 0 and: { env.x > 0 }) { env.x = 0; }; self.controller.set_norm_xy(env.value); self.update_label; self.update_knobs; }; self.env_view.mouseDownAction = { arg view, x, y, mod; self.mouse_down_point = Point(x,y); self.mouse_down_index = view.index; self.mouse_down_time_scale = self.controller.time_scale; }; self.env_view.mouseUpAction = { arg view, x, y, mod; self.update_knobs; if(mod.isShift) { self.env_view.selectIndex(self.mouse_down_index) } }; self.env_view.mouseMoveAction = { arg view, x, y, mod; var val; if(mod.isShift) { val = x - self.mouse_down_point.x; self.controller.time_scale = self.mouse_down_time_scale + (val/500); self.update_env; } }; self.env_view.keyDownAction = { self.update_knobs; }; self.knob_level = Knob.new .mode_(\vert) .maxWidth_(knob_size); self.knob_time = Knob.new .mode_(\vert) .maxWidth_(knob_size); self.knob_curve = Knob.new .mode_(\vert) .maxWidth_(knob_size); self.knob_level.action = { arg knob; var index = self.env_view.index; var levels = self.controller.get_env.levels; if(levels[index].notNil) { levels[index] = level_spec.map(knob.value); self.controller.get_env.levels = levels; self.env_view.y = knob.value; self.update_label; }; }; self.knob_time.action = { arg knob; var index = self.env_view.index; var times = self.controller.get_env.times; if(times[index].notNil) { times[index] = time_spec.map(knob.value); self.controller.get_env.times = times; self.env_view.value_(self.controller.get_norm_xy); self.env_view.selectIndex(index); self.update_label; } }; self.knob_curve.action = { arg knob; self.controller.get_env.curves = curve_spec.map(knob.value); self.env_view.curves = curve_spec.map(knob.value); self.update_label; }; self.env_label = StaticText.new .font_(Font("Arial",10)) .string_("--"); knob_layout = HLayout.new( self.knob_level, self.knob_time, self.knob_curve, self.env_label ); self.update_label; self.update_knobs; layout = VLayout.new( label, slider, knob_layout ); self.layout = layout; layout; }, make_window: { arg self; ~windowize.(self.make_layout); }, ); ~ctrl = ~env_controller.new(Env([80,1500.1,90.51,300,400],[0.1,0.2,0.1,0.1]), [0, \freq.asSpec]); ) ( SynthDef(\ftest, { arg out=0, amp=0.1, gate=1, pan=0, spread=0.8, freq=200, doneAction=2; var sig, sig1, sig2, sig3; freq = freq + EnvGen.kr(\fenv.kr(Env([80,500.1,90.51,300,400],[0.1,0.2,0.1,0.1])), gate); sig = SinOsc.ar(freq); sig = sig * EnvGen.ar(\adsr.kr(Env.adsr(0.01,0.1,0.8,0.1)),gate,doneAction:doneAction); sig = Splay.ar(sig, spread, amp, pan); Out.ar(out, sig); }).add; ); ( Pdef(\plop, Pbind( \instrument, \ftest, \fenv, Pfunc ({ ~ctrl.get_env }), \freq, 200, \dur, 1, \amp, 0.1 )).play; ) ~ctrl.edit;
code description
I needed an Env editor with knobs to edit individual points. Maybe it can be useful to someone. You can zoom horizontally with shift+mouseDrag. Show also a way to write classes with events
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