( /* Josh McMullen and Juan Gonzalez, Music and Computers, Assignment 3 "Raindrops": Our patch is supposed to simulate falling rain, rainstorm atmospheric tones and thunderous lightning. We allow the user to control the frequency, amplitude, and tempo of: rain1: a wind like sound. increasing the tempo makes it sound like wind. with tempo of zero, it sounds like misting rain rain2: a low pitched raindrop. doesn't really sound like drops, but it generates a random beat at random amplitudes, and it sounds neat rain3: same as rain2, but higher frequency rain4: this sound is probably the most out of place, it is a low rumbling sound. we think it adds a strength to the overall sound rain5: this is the lightning. It happens randomly every .5 seconds. the higher the "tempo" slider, the more often it will happen (maximum of 2 per second). Our documentation should be clear as you go through the program, so without further ado... */ /************************************************************/ /* Variables */ /************************************************************/ // the GUI window var window; // variables for the sliders. // Slider 1: control amplitude and frequency ("pitch") of soft hiss rain var amp1, freq_p1, freq_t1, button1; // Slider 2: control amplitude, frequency ("pitch"), and frequency ("tempo") of normal rain var amp2, freq_p2, freq_t2, button2; // Slider 3: exactly the same as Slider 2 var amp3, freq_p3, freq_t3, button3; // Slider 4: control amplitude, frequency ("pitch") of low rolling rain var amp4, freq_p4, freq_t4, button4; // Slider 5: control amplitude and frequency ("pitch"), and frequency ("tempo") of lightning crash var amp5, freq_p5, freq_t5, button5; // Other variables var rain1, wind1; var rain2, trigger2, impulse2, wave2; var rain3, trigger3, impulse3, wave3; var rain4, modwave4, ampwave4; var rain5, wave5, envelope5, sound5, env5; /************************************************************/ /* GUI code */ /************************************************************/ // The window window = GUIWindow.new("Rain Drops are Falling on my Computer", Rect.newBy(98, 78, 801, 438)); window.backColor_(rgb(20,40,255)); // Labels at Top StringView.new(window, Rect.newBy(285, 19, 128, 20), "Amplitude"); StringView.new(window, Rect.newBy(447, 19, 128, 20), "Pitch"); StringView.new(window, Rect.newBy(610, 19, 128, 20), "Tempo"); // Hiss Rain Controls StringView.new(window, Rect.newBy(16, 58, 85, 22), "Wind"); button1 = ButtonView.new(window, Rect.newBy(128, 58, 76, 21), "Reset", 0, 0, 1, 0, 'linear').backColor_(rgb(0,0,0)); button1.backColor_(rgb(60,147,215)); button1.action = { amp1.value = 0; freq_p1.value = 300; freq_t1.value = 0 }; amp1 = SliderView.new(window, Rect.newBy(285, 58, 128, 20), "amp1", 0, 0, 0.1, 0, 'linear'); amp1.backColor_(rgb(0,0,0)).knobColor_(rgb(255,252,23)); freq_p1 = SliderView.new(window, Rect.newBy(448, 58, 128, 20), "freq_p1", 300, 300, 2000, 0, 'linear'); freq_p1.backColor_(rgb(0,0,0)).knobColor_(rgb(255,252,23)); freq_t1 = SliderView.new(window, Rect.newBy(603, 58, 128, 20), "freq_t1", 0, 0, 0.5, 0, 'linear'); freq_t1.backColor_(rgb(0,0,0)).knobColor_(rgb(255,252,23)); // Raindrops 1 Controls StringView.new(window, Rect.newBy(14, 108, 85, 22), "Low Rain"); button2 = ButtonView.new(window, Rect.newBy(123, 116, 76, 21), "Reset", 0, 0, 1, 0, 'linear'); button2.backColor_(rgb(60,147,215)); button2.action = { amp2.value = 0; freq_p2.value = 100; freq_t2.value = 0 }; amp2 = SliderView.new(window, Rect.newBy(285, 109, 128, 20), "amp2", 0, 0, 7, 0, 'linear'); amp2.backColor_(rgb(0,0,0)).knobColor_(rgb(255,252,23)); freq_p2 = SliderView.new(window, Rect.newBy(446, 109, 128, 20), "freq_p2", 100, 100, 200, 0, 'linear'); freq_p2.backColor_(rgb(0,0,0)).knobColor_(rgb(255,252,23)); freq_t2 = SliderView.new(window, Rect.newBy(603, 110, 128, 20), "freq_t2", 0, 0, 20, 0, 'linear'); freq_t2.backColor_(rgb(0,0,0)).knobColor_(rgb(255,252,23)); // Raindrops 2 Controls StringView.new(window, Rect.newBy(17, 157, 85, 22), "High Rain"); button3 = ButtonView.new(window, Rect.newBy(126, 160, 76, 21), "Reset", 0, 0, 1, 0, 'linear'); button3.backColor_(rgb(60,147,215)); button3.action = { amp3.value = 0; freq_p3.value = 210; freq_t3.value = 0 }; amp3 = SliderView.new(window, Rect.newBy(285, 162, 128, 20), "amp3", 0, 0, 7, 0, 'linear'); amp3.backColor_(rgb(0,0,0)).knobColor_(rgb(255,252,23)); freq_p3 = SliderView.new(window, Rect.newBy(447, 163, 128, 20), "freq_p3", 210, 210, 500, 0, 'linear'); freq_p3.backColor_(rgb(0,0,0)).knobColor_(rgb(255,252,23)); freq_t3 = SliderView.new(window, Rect.newBy(605, 163, 128, 20), "freq_t3", 0, 0, 20, 0, 'linear'); freq_t3.backColor_(rgb(0,0,0)).knobColor_(rgb(255,252,23)); // Rumbling Rain Controls StringView.new(window, Rect.newBy(16, 210, 85, 22), "Rumble"); button4 = ButtonView.new(window, Rect.newBy(126, 214, 76, 21), "Reset", 0, 0, 1, 0, 'linear'); button4.backColor_(rgb(60,147,215)); button4.action = { amp4.value = 0; freq_p4.value = 30; freq_t4.value = 0 }; amp4 = SliderView.new(window, Rect.newBy(285, 217, 128, 20), "amp4", 0, 0, 1, 0, 'linear'); amp4.backColor_(rgb(0,0,0)).knobColor_(rgb(255,252,23)); freq_p4 = SliderView.new(window, Rect.newBy(446, 216, 128, 20), "freq_p4", 30, 30, 60, 0, 'linear'); freq_p4.backColor_(rgb(0,0,0)).knobColor_(rgb(255,252,23)); freq_t4 = SliderView.new(window, Rect.newBy(605, 216, 128, 20), "freq_t4", 0, 0, 0.1, 0, 'linear'); freq_t4.backColor_(rgb(0,0,0)).knobColor_(rgb(255,252,23)); // Lightning Crash Controls StringView.new(window, Rect.newBy(18, 277, 85, 22), "Thunder"); button5 = ButtonView.new(window, Rect.newBy(127, 275, 76, 21), "Reset", 0, 0, 1, 0, 'linear'); button5.backColor_(rgb(60,147,215)); button5.action = { amp5.value = 0; freq_p5.value = 0; freq_t5.value = 0 }; amp5 = SliderView.new(window, Rect.newBy(286, 280, 128, 20), "amp5", 0, 0, 2.5, 0, 'linear'); amp5.backColor_(rgb(0,0,0)).knobColor_(rgb(255,252,23)); freq_p5 = SliderView.new(window, Rect.newBy(447, 278, 128, 20), "freq_p5", 0, 0, 4000, 0, 'linear'); freq_p5.backColor_(rgb(0,0,0)).knobColor_(rgb(255,252,23)); freq_t5 = SliderView.new(window, Rect.newBy(607, 278, 128, 20), "freq_t5", 0, 0, 1, 0, 'linear'); freq_t5.backColor_(rgb(0,0,0)).knobColor_(rgb(255,252,23)); /************************************************************/ /* Sound Generation */ /************************************************************/ Synth.play({ // Generating rain1 sound // wind1 modulates the other sine to sound like wind blowing // The pink noise adds the hiss. wind1 = SinOsc.ar(Plug.kr(freq_t1), 0, 1, 2); rain1 = PinkNoise.ar * SinOsc.ar(Plug.kr(freq_p1) * wind1, 0, Plug.kr(amp1)); // Generating rain2 sound // The "trigger" is not in the set of forbidden trigger functions for the assignment trigger2 = LFPulse.ar(Plug.kr(freq_t2)); // this is the trigger pulse for the following impulse generator // this impulse sequencer generates random-ish "beats" at different frequencies. the random choice is made by how fast trigger2 pulses impulse2 = ImpulseSequencer.ar({[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 0, 0, 0, 0, 0, 0, 0].choose}, trigger2); // the following is the sine wave that is played at each pulse wave2 = FSinOsc.ar(Plug.kr(freq_p2), Plug.kr(amp2)); // with the above, we can generate rain drop-ish sounds as a beat, using Decay2 to make the attacks and decays smoother rain2 = Decay2.ar(impulse2, 0.03, 0.01, wave2); // Generating rain3 sound...this is done exactly as above with a slight change to the randomness function trigger3 = LFPulse.ar(Plug.kr(freq_t3)); impulse3 = ImpulseSequencer.ar({[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 0, 0, 0].choose}, trigger3); wave3 = FSinOsc.ar(Plug.kr(freq_p3), Plug.kr(amp3)); rain3 = Decay2.ar(impulse3, 0.02, 0.01, wave3); // Generating rain4 sound // ampwave modulates the final sinewave's amplitude. modwave does it for frequency ampwave4 = SinOsc.ar(Plug.kr(freq_t4)); modwave4 = SinOsc.ar(35, 0, ampwave4, 0, 1); rain4 = SinOsc.ar(Plug.kr(freq_p4) * modwave4, 0, Plug.kr(amp4)); // Generating rain5 sound // The following is commented out b/c before we knew how to use Spawn.ar, we had them outside of the Spawn function. // The Ugens must be inside the Spawn function. we left this here so you could see how the entire result Ugen inside the // Spawn is constructed. we could have separated them inside the Spawn, but we thought this was clear enough. // As for how this works, we have an envelope that has a quick attack and then a slower decay, and it is // applied to a sawtooth multiplied with brown noise. even at low amplitudes, this clips, and this is the desired // effect (makes it better lightning). The sound is Spawned randomly depending on the tempo value, and the check // of the tempo value is made every .5 seconds (b/c it respawns this often). /*env5 = Env.new([0, 1, 0, 0], [0.1, 1, 5], [0, -4, 0]); envelope5 = EnvGen.ar(env5, 1); wave5 = Saw.ar(Plug.kr(freq_p5), 0, Plug.kr(amp5) * envelope5); sound5 = BrownNoise.ar * wave5;*/ rain5 = Spawn.ar({if(1.0.rand < freq_t5.value, {BrownNoise.ar * Saw.ar(Plug.kr(freq_p5), 0, Plug.kr(amp5) * EnvGen.ar(Env.new([0, 1, 0, 0], [0.1, 1, 1], [0, -4, 0]), 1))}, {nil})}, 1, 0.5); // adding the sounds together to make the final sound rain1 + rain2 + rain3 + rain4 + rain5 }); window.close; )