// title: Simple Harmonic Motion // author: rukano // description: // Was just trying to reproduce the simple harmonic motion videos i've been watching. I think this is a compact and yet flexible way where you are able to change the scale, octave, frequency, etc very easily. // code: ( Server.default.waitForBoot({ SynthDef(\SimpleHarmonicPing, { |out, freq, amp, sustain, pan| var snd = BLowPass4.ar(Saw.ar(freq), freq*Line.kr(2, 1, sustain/4), 1); snd = snd * EnvGen.ar(Env.perc(0.01, sustain), doneAction:2); OffsetOut.ar(out, Pan2.ar(snd, pan, amp)) }).add; }); ~scale = Scale.chinese; ~octave = 4; ~sustain = 1.25; ~root = 0; ~mtranspose = 0; ~ctranspose = 0; ) ( var n = 7*2; var w = 1024, h = 600; var win = Window("", Rect(100, 100, w, h)).front; var uv = UserView(win, win.view.bounds); var sinFunc = { |i, periode=2pi| sin((i/n)*periode) }; var lastValues = { 0 }.dup(n); uv.background = Color.black; uv.animate = true; uv.frameRate = 120; uv.drawFunc = { |uv| var values = Array.fill(n, { |i| sinFunc.((i-1) + (uv.frame/100), uv.frame.linexp(1,60*(60*12), pi, 24pi)) }); // for 2 min QPen.strokeColor = Color.white; QPen.line( Point(0, h/2), Point(w, h/2) ); QPen.stroke; QPen.fillColor = Color.red; QPen.use{ QPen.translate(w/n/2,0); values.do{ |value, i| var lastValue = lastValues[i]; var center = Point( (i/n) * w, (h/2) + (value * (h/3))); QPen.fillOval(Rect.aboutPoint( center, 3, 3 )); if( ((lastValue < 0) and: { value > 0 }) or: { (lastValue > 0) and: { value < 0 } } ) { QPen.strokeColor = Color.white; QPen.strokeOval(Rect.aboutPoint( center, 5, 5) ); QPen.strokeOval(Rect.aboutPoint( center, 10, 10) ); ( scale: ~scale, instrument: \SimpleHarmonicPing, octave: ~octave, degree:i, amp:0.1, mtranspose: ~mtranspose, ctranspose: ~ctranspose, root: ~root, sustain: ~sustain, pan:i.linlin(0,n,-1, 1), detune:2.0.rand2, ).play; "trig %".format(i).postln; }; }; }; lastValues = values; }; )