// @title GCRev.ck // @author Regina Collecchia (colleccr@ccrma.stanford.edu) // @desc Spring reverb effect with configurable tremolo frequency (Hz), duration (ms), and gain. // // Final piece for MUS 220A. Timing not perfect...nor my playing. But shows off the spring reverb // effect. Future: make it into a Chugin! // // Note: spring reverb should ideally downsample and antialias before delaying, then upsample // and anti-image before tremolo class GCRev extends Chubgraph { inlet => DelayL delay => PoleZero spring => LPF low => Gain tremolo => outlet; low => Gain feedback => delay; 0.05::second => delay.max => delay.delay; 0.7 => feedback.gain; -0.35 => spring.a1 => spring.b0; 1 => spring.b1; 4000 => low.freq; 1 => int i; while(i < 60000) { Math.random2f(0.5,0.6)+Math.sin(6.28*2*i)*0.4 => tremolo.gain; i++; } // set feedback fun void setFeedback( float fb ) { if ( fb < 0 || fb > 1.0 ) { <<< "invalid arguments for setFeedback! val must be between 0 and 1." >>>; return; } else { fb => feedback.gain; } // compute T60 here } // set tremolo by specifying a tremolo frequency tr, duration in ms, and gain g for the tremolo fun void setTremolo(float tr, float dur, float g) { if ( tr < 0 || dur < 0 || g > 1.0 ) { <<< "invalid arguments for setTremolo" >>>; return; } else { for ( 0 => int j; j < (dur*44100/1000); ++j ) { Math.random2f(0.9-g,1.0-g)+Math.sin(6.28*(44100/tr)*j)*g => tremolo.gain; // tr::ms => now; } } } } // --------------- BEGIN COMPOSITION ----------------- // // load soundfiles // tried a few different things here to avoid making the VM hang. // no dice. ended up "File->Export..."ing my soundfile. SndBuf ocean => Gain goc => Envelope ocenv => dac; // 38.9 sec long me.sourceDir() + "/ocean.wav" => ocean.read; SndBuf chirps => Gain gchirps => GCRev gc1 => JCRev reverb2 => dac; me.sourceDir() + "/chirps.wav" => chirps.read; SndBuf electric_verse; me.sourceDir() + "/warped/electric_verse.wav" => electric_verse.read; SndBuf acoustic_verse; me.sourceDir() + "/warped/acoustic_verse.wav" => acoustic_verse.read; SndBuf slide; me.sourceDir() + "/slide.wav" => slide.read; SndBuf electric_bridge; me.sourceDir() + "/warped/electric_bridge.wav" => electric_bridge.read; SndBuf acoustic_bridge; me.sourceDir() + "/warped/acoustic_bridge.wav" => acoustic_bridge.read; 1::samp => now; ocean.samples() => ocean.pos; chirps.samples() => chirps.pos; // PART 1: sounds of the bay (taken from the wave organ on the pier near // the Palace of Fine Arts), overlayed with guitar "chirps" (palm mutes / strikes). 0 => ocean.pos; 1.5 => goc.gain; 1.0 => ocenv.target; 2 => ocenv.time; // start chirps after 12 seconds of just ocean (a 39-sec long sound file) 12::second => now; 0 => chirps.pos; 0.5 => gchirps.gain; 0.3 => reverb2.mix; gc1.setTremolo(10, 39000, 1.0); gc1.setFeedback(0.9); 5::second => now; gc1.setFeedback(0.6); 5::second => now; // PART 2: verse (these 2 files are a little off, hence the 80::ms) acoustic_verse => Gain again_verse => JCRev reverb4 => dac.left; // 1:55 long 80::ms => now; electric_verse => GCRev gc2 => JCRev reverb3 => dac.right; // 1:55 long gc2.setTremolo(100, 115000, 0.2); 11020::ms => now; // solo guitar slide => Gain glside => GCRev gc3 => JCRev reverb5 => dac; // 1:40 long 0.6 => glside.gain; 0.1 => reverb5.mix => reverb4.mix => reverb3.mix; gc3.setTremolo(100, 100000, 0.2); 101300::ms => now; // PART 3: bridge to take us out electric_bridge => GCRev gc4 => JCRev reverb6 => dac.right; // 1:00 long acoustic_bridge => Gain again_bridge => JCRev reverb7 => dac.left; 0.4 => reverb6.mix; gc4.setTremolo(220, 60000, 0.4); 0.4 => again_bridge.gain; 0.4 => reverb7.mix; 61::second => now; // let reverb die out