diff --git a/fm pulsar wave terrain.scd b/fm pulsar wave terrain.scd new file mode 100644 index 0000000..9d5e5aa --- /dev/null +++ b/fm pulsar wave terrain.scd @@ -0,0 +1,117 @@ +( +// Generate a terrain table +~terrain = Buffer.alloc(s, 1024, 1); +~terrain.sine1([1, 0.5, 0.3, 0.2, 0.1], true); // You can sculpt this more chaotically + +SynthDef("fm_pulsar_terrain", { + arg a, e, f, d; + var t, overlap, carfreq, modfreq, mInd, vel, vel_, tblPos, sig; + + f = \freq.kr(100); + + vel = \kel.kr(0.5); + vel_ = vel.clip(0,1.0).linlin( 0, 1, 2, 0.7); + + e = EnvGen.kr( + Env.adsr( + \att.kr(0.025) * vel_, + \dec.kr(0.02) * vel_, + \susl.kr(0.7), + \rel.kr(4), + curve: \curve.kr(-4) + ), + gate: \gate.kr(1), + doneAction:2 + ) * vel; + + carfreq = f * \cf.kr(2) + LFNoise1.kr(3).range(0,50); + modfreq = carfreq * \mf.kr(2) + LFNoise1.kr(3).range(0,100); + + t = Impulse.ar(f); + + mInd = e.pow(3.3); // use envelope shape to shift table pos + overlap = 1.1 - e.pow(0.5); + d = overlap / f; + + // convert modfreq to index between 0 and 1 for VOsc + tblPos = modfreq.linlin(0, 8000, 0, 1).wrap(0, 1); // safer than clip for edge cases + + a = Mix([ + SinOsc.ar(f), + GrainBuf.ar(1, t, d, ~terrain, tblPos, carfreq, 0, 2) + ]); + + a = LeakDC.ar(a * e); + Out.ar(\outBus.kr(0), a.dup * \gain.kr(0.1)); + +}).add; +) + +Synth(\fm_pulsar_terrain); + + + +( +// MIDI +// EMF: one major issue here is that ~notes is never actually initialized as an array, so it's nil. when you try to store a Synth at index nn, SC throws an error, because you can't put an item into nil. So, we first initialize ~notes as an array of size 128. After I add this line, your polyphonic MIDI code seems to work fine (no stuck notes) + +~notes = Array.newClear(128); + +MIDIdef.noteOn(\noteOnTest, { + arg vel, nn, chan, src; + [vel, nn].postln; + + if (chan == 0, { + ~notes[nn] = Synth.new( + \fm_pulsar_terrain, + [ + \freq, nn.midicps, + \amp, vel.linexp(1,127,0.01,0.3), + // \gate, 1, + + ] + ); + }); +}); + +MIDIdef.noteOff(\noteOffTest, { + arg vel, nn, chan; + [vel, nn].postln; + + if (chan == 0, { + ~notes[nn].set(\gate, 0); + ~notes[nn] = nil; + }); +}); + +[ + [\freq, 0, 50, 4000], + [\amp, 1, 0.0, 1.5], + [\cf, 2, 0.1, 4.0], + [\mf, 3, 0.1, 4.0], + [\tblIndex, 4, 0.0, 1.0], + [\gain, 5, 0.01, 1.0], + [\att, 6, 0.001, 0.2], + [\dec, 7, 0.001, 0.2], + [\rel, 8, 0.1, 8.0], + [\susl, 9, 0.0, 1.0], + [\curve, 10, -8.0, 8.0], + [\kel, 11, 0.0, 1.0] +].do { |spec| + var param, cc, min, max; + #param, cc, min, max = spec; + + MIDIdef.cc(param.asSymbol, { |val, num, chan, src| + if (chan == 2) { + var mapped = val.linlin(0, 127, min, max); + ~pulsar.set(param, mapped); + } + }, cc); +}; +) + + +( +MIDIClient.init; +MIDIIn.connectAll; +) \ No newline at end of file