// Brian Jacobs & John Paul Reid // COCO 12, Spring 2000 // SuperCollider Project #1 // May 4, 2000 // // For our project, we decided to make a program that would play three different waves; a sine wave, // a sawtooth wave, and a pulse wave. The user can then manipulate these waves by means of frequency // and amplitude and can then run them each through a low pass and high pass filter. We made the GUI // start off by playing a random chord and we added the scope in with our GUI to make everything // viewable in one window. We also added checkboxes to turn the waves on an off, and we added a reset // button to the GUI. // Originally we planned on making this much simpler with just three different kinds of waves and // sliders for amplitude and frequency. However, the more we found out about SuperCollider, the more // we decided to add to our program. ( // Our GUI window variable. var w; // Frequency variables - sine wave, sawtooth wave, and pulse wave - for numerical views and sliders. var sinFreqNum, sinFreqSlid, sawFreqNum, sawFreqSlid, pulFreqNum, pulFreqSlid; // Amplitude variables - sine wave, sawtooth wave, and pulse wave - for numerical views and sliders. var sinAmpNum, sinAmpSlid, sawAmpNum, sawAmpSlid, pulAmpNum, pulAmpSlid; // Low Pass Filter variables - sine wave, sawtooth wave, and pulse wave - for numerical views and sliders. var sinLowNum, sinLowSlid, sawLowNum, sawLowSlid, pulLowNum, pulLowSlid; // High Pass Filter variables - sine wave, sawtooth wave, and pulse wave - for numerical views and sliders. var sinHighNum, sinHighSlid, sawHighNum, sawHighSlid, pulHighNum, pulHighSlid; // Checkbox variables and reset button. var sinBox, sawBox, pulBox, rst; // Wave names. var w1, w2, w3; // The starting value of rq, the bandwidth/cutoff frequency. var rq = 0.3; // A randow starting chord variable. var sCr; // Chosing a random start chord. sCr = 400.150.rand; // Our GUI window. w = GUIWindow.new("Three Wave Mix", Rect.newBy(10, 60, 780, 530)).backColor_(rgb(118,169,176)); ScopeView.new( w, Rect.newBy(415, 0, 365, 530), 4410, -1, 1).backColor_(rgb(176,176,176)); // Sine wave controls. sinBox = CheckBoxView.new( w, Rect.newBy(5, 5, 128, 20), "Sine Wave", 0, 0, 1, 0, 'linear'); sinFreqNum = NumericalView.new( w, Rect.newBy(5, 35, 60, 20), "Frequency", sCr * 3/2, 20, 1000, 1, 'exponential'); sinFreqSlid = SliderView.new( w, Rect.newBy(70, 35, 200, 20), "Frequency", sCr * 3/2, 20, 1000, 1, 'exponential') .backColor_(rgb(90,130,176)).knobColor_(rgb(17,20,176)); StringView.new( w, Rect.newBy(275, 35, 130, 20), "Frequency").backColor_(rgb(243,4,151)); sinAmpNum = NumericalView.new( w, Rect.newBy(5, 65, 60, 20), "Amplitude", 0.1, 0, 0.33, 0.01, 'linear'); sinAmpSlid = SliderView.new( w, Rect.newBy(70, 65, 200, 20), "Amplitude", 0.1, 0, 0.33, 0.01, 'linear') .backColor_(rgb(90,130,176)).knobColor_(rgb(17,20,176)); StringView.new( w, Rect.newBy(275, 65, 130, 20), "Amplitude").backColor_(rgb(243,4,151)); // Filters for the sine wave. sinLowNum = NumericalView.new( w, Rect.newBy(5, 95, 60, 20), "Low Pass Filter", 1000, 0, 1000, 1, 'linear'); sinLowSlid = SliderView.new( w, Rect.newBy(70, 95, 200, 20), "Low Pass Filter", 1000, 0, 1000, 1, 'linear') .backColor_(rgb(90,130,176)).knobColor_(rgb(17,20,176)); StringView.new( w, Rect.newBy(275, 95, 130, 20), "Low Pass Filter").backColor_(rgb(243,4,151)); sinHighNum = NumericalView.new( w, Rect.newBy(5, 125, 60, 20), "High Pass Filter", 0, 0, 1000, 1, 'linear'); sinHighSlid = SliderView.new( w, Rect.newBy(70, 125, 200, 20), "High Pass Filter", 0, 0, 1000, 1, 'linear') .backColor_(rgb(90,130,176)).knobColor_(rgb(17,20,176)); StringView.new( w, Rect.newBy(275, 125, 130, 20), "High Pass Filter").backColor_(rgb(243,4,151)); // Sawtooth wave controls. sawBox = CheckBoxView.new( w, Rect.newBy(5, 175, 128, 20), "Sawtooth Wave", 0, 0, 1, 0, 'linear'); sawFreqNum = NumericalView.new( w, Rect.newBy(5, 205, 60, 20), "Frequency", sCr * 5/4, 20, 1000, 1, 'exponential'); sawFreqSlid = SliderView.new( w, Rect.newBy(70, 205, 200, 20), "Frequency", sCr * 5/4, 20, 1000, 1, 'exponential') .backColor_(rgb(65,176,5)).knobColor_(rgb(40,122,0)); StringView.new( w, Rect.newBy(275, 205, 130, 20), "Frequency").backColor_(rgb(90,171,189)); sawAmpNum = NumericalView.new( w, Rect.newBy(5, 235, 60, 20), "Amplitude", 0.04, 0, 0.33, 0.01, 'linear'); sawAmpSlid = SliderView.new( w, Rect.newBy(70, 235, 200, 20), "Amplitude", 0.04, 0, 0.33, 0.01, 'linear') .backColor_(rgb(65,176,5)).knobColor_(rgb(40,122,0)); StringView.new( w, Rect.newBy(275, 235, 130, 20), "Amplitude").backColor_(rgb(90,171,189)); // Filters for the sawtooth wave. sawLowNum = NumericalView.new( w, Rect.newBy(5, 265, 60, 20), "Low Pass Filter", 1000, 0, 1000, 1, 'linear'); sawLowSlid = SliderView.new( w, Rect.newBy(70, 265, 200, 20), "Low Pass Filter", 1000, 0, 1000, 1, 'linear') .backColor_(rgb(65,176,5)).knobColor_(rgb(40,122,0)); StringView.new( w, Rect.newBy(275, 265, 130, 20), "Low Pass Filter").backColor_(rgb(90,171,189)); sawHighNum = NumericalView.new( w, Rect.newBy(5, 295, 60, 20), "High Pass Filter", 0, 0, 1000, 1, 'linear'); sawHighSlid = SliderView.new( w, Rect.newBy(70, 295, 200, 20), "High Pass Filter", 0, 0, 1000, 1, 'linear') .backColor_(rgb(65,176,5)).knobColor_(rgb(40,122,0)); StringView.new( w, Rect.newBy(275, 295, 130, 20), "High Pass Filter").backColor_(rgb(90,171,189)); // Pulse wave controls. pulBox = CheckBoxView.new( w, Rect.newBy(5, 345, 128, 20), "Pulse Wave", 0, 0, 1, 0, 'linear'); pulFreqNum = NumericalView.new( w, Rect.newBy(5, 375, 60, 20), "Frequency", sCr, 20, 1000, 1, 'exponential'); pulFreqSlid = SliderView.new( w, Rect.newBy(70, 375, 200, 20), "Frequency", sCr, 20, 1000, 1, 'exponential') .backColor_(rgb(220,8,15)).knobColor_(rgb(153,6,11)); StringView.new( w, Rect.newBy(275, 375, 130, 20), "Frequency").backColor_(rgb(225,225,9)); pulAmpNum = NumericalView.new( w, Rect.newBy(5, 405, 60, 20), "Amplitude", 0.1, 0, 0.33, 0.01, 'linear'); pulAmpSlid = SliderView.new( w, Rect.newBy(70, 405, 200, 20), "Amplitude", 0.1, 0, 0.33, 0.01, 'linear') .backColor_(rgb(220,8,15)).knobColor_(rgb(153,6,11)); StringView.new( w, Rect.newBy(275, 405, 130, 20), "Amplitude").backColor_(rgb(225,225,9)); // Filters for the pulse wave. pulLowNum = NumericalView.new( w, Rect.newBy(5, 435, 60, 20), "Low Pass Filter", 1000, 0, 1000, 1, 'linear'); pulLowSlid = SliderView.new( w, Rect.newBy(70, 435, 200, 20), "Low Pass Filter", 1000, 0, 1000, 1, 'linear') .backColor_(rgb(220,8,15)).knobColor_(rgb(153,6,11)); StringView.new( w, Rect.newBy(275, 435, 130, 20), "Low Pass Filter").backColor_(rgb(225,225,9)); pulHighNum = NumericalView.new( w, Rect.newBy(5, 465, 60, 20), "High Pass Filter", 0, 0, 1000, 1, 'linear'); pulHighSlid = SliderView.new( w, Rect.newBy(70, 465, 200, 20), "High Pass Filter", 0, 0, 1000, 1, 'linear') .backColor_(rgb(220,8,15)).knobColor_(rgb(153,6,11)); StringView.new( w, Rect.newBy(275, 465, 130, 20), "High Pass Filter").backColor_(rgb(225,225,9)); // Reset Button. rst = ButtonView.new( w, Rect.newBy(143, 505, 129, 20), "Reset", 0, 0, 1, 0, 'linear').backColor_(rgb(164,176,143)); // Linking all the sliders and numerical views for the sine controls. sinFreqNum.action = {sinFreqSlid.value = sinFreqNum.value}; sinFreqSlid.action = {sinFreqNum.value = sinFreqSlid.value}; sinAmpNum.action = {sinAmpSlid.value = sinAmpNum.value}; sinAmpSlid.action = {sinAmpNum.value = sinAmpSlid.value}; sinLowNum.action = {sinLowSlid.value = sinLowNum.value}; sinLowSlid.action = {sinLowNum.value = sinLowSlid.value}; sinHighNum.action = {sinHighSlid.value = sinHighNum.value}; sinHighSlid.action = {sinHighNum.value = sinHighSlid.value}; // Linking all the sliders and numerical views for the sawtooth controls. sawFreqNum.action = {sawFreqSlid.value = sawFreqNum.value}; sawFreqSlid.action = {sawFreqNum.value = sawFreqSlid.value}; sawAmpNum.action = {sawAmpSlid.value = sawAmpNum.value}; sawAmpSlid.action = {sawAmpNum.value = sawAmpSlid.value}; sawLowNum.action = {sawLowSlid.value = sawLowNum.value}; sawLowSlid.action = {sawLowNum.value = sawLowSlid.value}; sawHighNum.action = {sawHighSlid.value = sawHighNum.value}; sawHighSlid.action = {sawHighNum.value = sawHighSlid.value}; // Linking all the sliders and numerical views for the pulse controls. pulFreqNum.action = {pulFreqSlid.value = pulFreqNum.value}; pulFreqSlid.action = {pulFreqNum.value = pulFreqSlid.value}; pulAmpNum.action = {pulAmpSlid.value = pulAmpNum.value}; pulAmpSlid.action = {pulAmpNum.value = pulAmpSlid.value}; pulLowNum.action = {pulLowSlid.value = pulLowNum.value}; pulLowSlid.action = {pulLowNum.value = pulLowSlid.value}; pulHighNum.action = {pulHighSlid.value = pulHighNum.value}; pulHighSlid.action = {pulHighNum.value = pulHighSlid.value}; // Reset button controls, which resets the sliders and numeric values to their initial values as determined by sCr. rst.action = { sinFreqNum.value = sCr * 3/2; sinFreqSlid.value = sCr * 3/2; sinAmpNum.value = 0.1; sinAmpSlid.value = 0.1; sinLowNum.value = 1000; sinLowSlid.value = 1000; sinHighNum.value = 0; sinHighSlid.value = 0; sawFreqNum.value = sCr * 5/4; sawFreqSlid.value = sCr * 5/4; sawAmpNum.value = 0.04; sawAmpSlid.value = 0.04; sawLowNum.value = 1000; sawLowSlid.value = 1000; sawHighNum.value = 0; sawHighSlid.value = 0; pulFreqNum.value = sCr; pulFreqSlid.value = sCr; pulAmpNum.value = 0.1; pulAmpSlid.value = 0.1; pulLowNum.value = 1000; pulLowSlid.value = 1000; pulHighNum.value = 0; pulHighSlid.value = 0; }; // Our synth playing commands, which use the numeric values to control the frequencies, amplitudes, and filters. { w1 = RHPF.ar( RLPF.ar( SinOsc.ar(ControlIn.kr(sinFreqNum), 0, ControlIn.kr(sinAmpNum) * ControlIn.kr(sinBox)), ControlIn.kr(sinLowNum), ControlIn.kr(q)), ControlIn.kr(sinHighNum), ControlIn.kr(q)); w2 = RHPF.ar( RLPF.ar( Saw.ar(ControlIn.kr(sawFreqNum), ControlIn.kr(sawAmpNum) * ControlIn.kr(sawBox)), ControlIn.kr(sawLowNum), ControlIn.kr(q)), ControlIn.kr(sawHighNum), ControlIn.kr(q)); w3 = RHPF.ar( RLPF.ar( Pulse.ar(ControlIn.kr(pulFreqNum), 0.5, ControlIn.kr(pulAmpNum) * ControlIn.kr(pulBox)), ControlIn.kr(pulLowNum), ControlIn.kr(q)), ControlIn.kr(pulHighNum), ControlIn.kr(q)); (w1 + w2 + w3); // And a scope display directly in our GUI. Scope.ar(w.at(0), (w1 + w2 + w3)); }.play; // And the window closes itself. w.close; )