// =================================================== // SuperCollider: GrainFM Examples and Use Cases // =================================================== // Load this file into SuperCollider and evaluate each section as needed // --------------------------------------------------- // 1. Tonal Ambient Pad (Stable Pitch, Gentle Movement) // --------------------------------------------------- ( SynthDef(\grainFMPadClean, { |out=0, freq=440, amp=0.3, dur=10| var trig = Impulse.kr(15); // grains per second var snd; snd = GrainFM.ar( numChannels: 2, trigger: trig, dur: 0.2, carfreq: freq, modfreq: freq * 2, // simple ratio index: 1.5, pan: LFNoise1.kr(0.2), envbufnum: -1 ); snd = snd * EnvGen.kr(Env.linen(1, dur-2, 1), doneAction: 2) * amp; Out.ar(out, snd); }).add; ) // Example usage: Synth(\grainFMPadClean, [\freq, 330, \dur, 12]); // --------------------------------------------------- // 2. Cloudy Texture (Randomized Frequencies) // --------------------------------------------------- ( SynthDef(\grainFMCloud, { |out=0, amp=0.2, dur=8| var trig = Dust.kr(25); var freq = TExpRand.kr(200, 800, trig); var snd; snd = GrainFM.ar( numChannels: 2, trigger: trig, dur: 0.1, carfreq: freq, modfreq: freq * 1.5, index: TRand.kr(1, 10, trig), pan: TRand.kr(-1, 1, trig), envbufnum: -1 ); snd = snd * EnvGen.kr(Env.linen(1, dur-2, 1), doneAction: 2) * amp; Out.ar(out, snd); }).add; ) Synth(\grainFMCloud); // --------------------------------------------------- // 3. Evolving Drone (Slow Modulation of Grain Rate & Pitch) // --------------------------------------------------- ( SynthDef(\grainFMEvolvingDrone, { |out=0, baseFreq=100, amp=0.3, dur=20| var trig = Impulse.kr(LFNoise1.kr(0.1).range(5, 30)); var freq = LFNoise1.kr(0.05).range(baseFreq, baseFreq * 4); var modfreq = freq * LFNoise1.kr(0.02).range(0.5, 2); var snd; snd = GrainFM.ar( numChannels: 2, trigger: trig, dur: 0.15, carfreq: freq, modfreq: modfreq, index: 3, pan: LFNoise1.kr(0.3), envbufnum: -1 ); snd = snd * EnvGen.kr(Env.linen(2, dur-4, 2), doneAction: 2) * amp; Out.ar(out, snd); }).add; ) Synth(\grainFMEvolvingDrone); // --------------------------------------------------- // 4. Percussive Metallic Hits // --------------------------------------------------- ( SynthDef(\grainFMHit, { |out=0, freq=400, amp=0.4| var trig = Impulse.kr(1); var snd; snd = GrainFM.ar( numChannels: 2, trigger: trig, dur: 0.05, carfreq: freq, modfreq: freq * 3, index: 12, pan: 0, envbufnum: -1 ); snd = snd * EnvGen.kr(Env.perc(0.01, 0.3), doneAction: 2) * amp; Out.ar(out, snd); }).add; ) Synth(\grainFMHit); // --------------------------------------------------- // 5. Blending with a Pure Tone (Stable Pitch) // --------------------------------------------------- ( SynthDef(\grainFMWithTone, { |out=0, freq=440, amp=0.3, dur=10| var trig = Impulse.kr(20); var grain = GrainFM.ar(2, trig, 0.15, freq, freq * 2, 2, LFNoise1.kr(0.2), -1); var tone = SinOsc.ar(freq) * 0.1; var sig = Mix([grain, tone]); sig = sig * EnvGen.kr(Env.linen(1, dur-2, 1), doneAction: 2) * amp; Out.ar(out, sig); }).add; ) Synth(\grainFMWithTone); // --------------------------------------------------- // 6. MIDI-Controlled GrainFM Synth (For Sequencing) // --------------------------------------------------- ( SynthDef(\grainFMMidi, { |out=0, freq=440, amp=0.3, gate=1| var trig = Impulse.kr(10); var snd; snd = GrainFM.ar( numChannels: 2, trigger: trig, dur: 0.2, carfreq: freq, modfreq: freq * 2, index: 2, pan: LFNoise1.kr(0.2), envbufnum: -1 ); snd = snd * EnvGen.kr(Env.asr(0.01, 1, 1), gate, doneAction: 2) * amp; Out.ar(out, snd); }).add; ) ( MIDIIn.connectAll; ~grainFMResponder = NoteOnResponder({ |src, chan, num, vel| var freq = num.midicps; Synth(\grainFMMidi, [\freq, freq, \amp, vel/127]); }); ) // --------------------------------------------------- // You can now play GrainFM like an instrument from a MIDI controller! // ---------------------------------------------------