// This patch uses waveshaping with Chebyshev polynomials // on FM sounds of strings and piano- may crash computer // -Jeannie H. Lee // uses FM for creating randomly pitched piano and string like sounds ( // GUI for Brasslike, Woodwindlike, and Percussionlike tones var chebyTable, cAmpSlider, modIndexSlider, outputAmpSlider; var w, h, piano2, strings2 ; var majorscale, chebyButton, h2, h3, h4; var harm1,harm2; w = GUIWindow.new("chebystuff with Piano and Strings", Rect.newBy( 148, 64, 500, 275 )) .backColor = Color.new(128 + 128.rand, 128 + 128.rand, 128 + 128.rand); // w.at(0), etc CheckBoxView.new( w, Rect.newBy( 25, 35,105, 25 ), "Piano2", 0, 0, 1, 0, 'linear') .backColor = Color.new(128 + 128.rand, 128 + 128.rand, 128 + 128.rand); CheckBoxView.new( w, Rect.newBy( 25, 75,105, 25 ), "Strings2", 0, 0, 1, 0, 'linear') .backColor = Color.new(128 + 128.rand, 128 + 128.rand, 128 + 128.rand); StringView.new( w, Rect.newBy(25, 115, 105, 25), "carrier Amp slider"); cAmpSlider = SliderView.new( w, Rect.newBy(25, 145, 105, 25), "carrier amp slider", 0.5, 0, 12, 0.01, 'linear'); StringView.new( w, Rect.newBy(25, 175, 105, 25), "output Amp slider"); outputAmpSlider = SliderView.new( w, Rect.newBy(25, 205, 105, 25), "output Amp slider", 0.1, 0, 1.5, 0, 'linear'); chebyButton = ButtonView.new( w, Rect.newBy( 25, 240, 105, 25 ), "New Cheby set", 0, 0, 1, 0, 'linear'); chebyTable = Wavetable.chebyFill(512, [1]); WavetableView.new( w, Rect.newBy(178, 8, 280, 200), chebyTable, -1, 1).hElastic.vElastic; majorscale = #[1, 1.12, 1.26, 1.334, 1.498, 1.5, 1.68, 1.89, 2]; piano2 = { arg checkbox; var changeParams; var scaleMult; var dur; changeParams = { scaleMult = majorscale.choose; }; changeParams.value; // init scale multiplier Spawn.ar({ arg spawn, i, synth; // carrier sin wav, cWav, with freq, cFreq var cWav, cFreq, cWavOut; // carrier amplitude envelope, cAmp var cAmp; // modulating mWav1, mWav2 with freq1 and freq2, and index 1 and 2 var mWav1, mWav2, fm1, fm2 , i1, i2; // mod wav 1 envelope and mod 2 wav envelope 2 amplitude var m1Amp, m2Amp; // change scale multiplier changeParams.value; cFreq = 200; fm1 = 200; fm2 = 800; i1 = 2.73; i2 = 0.68; // amplitude envelope for carrier sin osc wav cAmp = Env.new([0.7,0.5,0.3,0.15,0.07,0],[0.05,0.05,0.15,0.25,0.55],'linear'); // amplitude envelope for modulating sin osc wav m1Amp = Env.new([1,0.6,0.3,0.15,0.07,0],[0.05,0.05,0.15,0.25,0.45],'linear'); m2Amp = Env.new([1,0.6,0.3,0.15,0.07,0],[0.05,0.05,0.15,0.25,0.45],'linear'); if (checkbox.value != 0.0 and: { 0.8.coin }, { // build fm patch mWav1 = SinOsc.ar(scaleMult*fm1, 0, i1*fm1); mWav2 = SinOsc.ar(scaleMult*fm2, 0, i2*fm2); cWav = SinOsc.ar(scaleMult*cFreq + mWav1 + mWav2, 0, Plug.kr(cAmpSlider) ); cWav = EnvGen.ar(cAmp, cWav, 0,1,0,1); cWavOut = Shaper.ar(chebyTable, cWav); Plug.kr( outputAmpSlider)*Pan2.ar(cWavOut, 1.0.rand2); }); }, 2,1); }; strings2 = { arg checkbox; Spawn.ar({ arg spawn, i, synth; // carrier sin wav, cWav, with freq, cFreq var cWav, cFreq, cWavOut; // carrier amplitude envelope, cAmp var cAmp; // modulating wavs var mWav1, mWav2, mWav3; var fm1, fm2, fm3; var vibratoWav; var attackNoiseWav; var chiff; var scaleMult, dur, changeParams; // add envelope to each mod wav var f1Env; var h1, h2, h3, h4, h5, h6,h7,h8,h9,h10,h11,h12,h13,h14, h15,h16,h17,h18; // modulating wav indices var i1, i2, i3; changeParams = { scaleMult = majorscale.choose; }; // change scale multiplier changeParams.value; chebyButton.action = { h1 = #[0,1].choose; h2 = #[0,1].choose; h3 = #[0,1].choose; h4 = #[0,1].choose; h5 = #[0,1].choose; h6 = #[0,1].choose; h7 = #[0,1].choose; h8 = #[0,1].choose; h9 = #[0,1].choose; h10 = #[0,1].choose; h11 = #[0,1].choose; h12 = #[0,1].choose; h13 = #[0,1].choose; h14 = #[0,1].choose; h15 = #[0,1].choose; h16 = #[0,1].choose; h17 = #[0,1].choose; h18 = #[0,1].choose; chebyTable = Wavetable.chebyFill(512, [h1,h2,h3, h4, h5, h6, h7,h8,h9,h10,h11,h12,h13, h14,h15,h16,h17,h18]); WavetableView.new( w, Rect.newBy(178, 8, 280, 200), chebyTable, -1, 1).hElastic.vElastic; h = HarmonicsDialog.new(chebyTable); }; cFreq = 200; fm1 = 200; fm2 =600; fm3 = 800; i1 = 1.415; i2 = 1.06; i3 = 0.088; // amplitude envelope for carrier sin osc wav cAmp = Env.new([0.1,1,0.75,0.65,0],[0.1,0.1,2.3,0.2],'linear'); // attack env chiff = Env.perc(0.0001, 0.2, 1, -4); vibratoWav = SinOsc.ar(5.5, 0, 0.02); attackNoiseWav = EnvGen.ar(chiff, BPF.ar( BrownNoise.ar(0.8), 2000, 0.02), 0, 1, 0, 1); f1Env =Env.new([0.1,1,0.75,0.65,0],[0.1,0.1,0.3,0.1],'linear'); if (checkbox.value != 0.0 and: { 0.8.coin }, { // build fm patch mWav1 = SinOsc.ar(scaleMult*fm1, 0, i1 * fm1); mWav2 = SinOsc.ar(scaleMult*fm2, 0, i2 * fm2); mWav3 = SinOsc.ar(scaleMult*fm3, 0, i3 * fm3); cWav = SinOsc.ar((vibratoWav+1)* (scaleMult*cFreq + mWav1 + mWav2+ mWav3), 0, Plug.kr(cAmpSlider)); cWavOut = Shaper.ar(chebyTable, cWav); Plug.kr( outputAmpSlider)* Pan2.ar(EnvGen.ar(cAmp, Mix.ar([ attackNoiseWav, cWavOut]),0, 1, 0,1), 1.0.rand2); }); }, 2, 2.5); }; // Play instruments Synth.scope({ Mix.ar([ // piano and strings play! piano2.value(w.at(0)), strings2.value(w.at(1)) ]); }); w.close; )