(
//********************ADAM SCOTT NEAL***********************\\
//**************UNTITLED SUPERCOLLIDER PROJECT*************\\
//***************************12/14/10***************************\\
//*************************************************************\\
//************************ SYNTHDEFS *************************\\
//*************************************************************\\
// ADDITIVE SYNTH 'HIGH BELLS'
var instrument, out;
SynthDef( "highbell", {arg dur=2.0, fundamental, partialOne,
partialTwo, partialThree, db=0, pan=0 ;
a = Env.new([ 0.0001, 1.0, 0.0001 ],[0.001, 0.999 ],'linear' ) ;
b = EnvGen.kr( a, doneAction: 2 ) ;
c = Mix(SinOsc.ar( [fundamental, partialOne, partialTwo, partialThree], 0.0, db.dbamp*[0.5, 0.4, 0.3, 0.2, 0.1]) );
out = Pan2.ar( c * b, pan);
Out.ar( 0, out ) ;
}).send(s);
// ADDITIVE SYNTH 'LARGE BELLS'
SynthDef( "lowbell", {arg dur=5.0, fundamental, partialOne,
partialTwo, partialThree, partialFour, partialFive, partialSix, partialSeven,
partialEight, db=0, pan=0 ;
a = Env.new([ 0.0001, 1.0, 0.75, 0.0001 ],[dur*0.001, dur*0.009, dur*0.99 ],'exponential' ) ;
b = EnvGen.kr( a, doneAction: 2 ) ;
c = Mix(SinOsc.ar([fundamental, partialOne, partialTwo, partialThree,
partialFour, partialFive, partialSix, partialSeven, partialEight],0,
db.dbamp*[0.5,1,0.8,0.5,0.9,0.
out = Pan2.ar( c * b, pan);
Out.ar( 0, out ) ;
}).send(s);
// FILTERED NOISE 'ORGAN'
SynthDef( "organ", {arg dur=5.0, fundamental, partialOne,
partialTwo, partialThree, partialFour, partialFive, partialSix, db=0,
pan=0 ;
a = Env.new([ 0.0001, 1.0, 0.75, 0.5, 0.0001 ],[dur*0.001, dur*0.009, dur*0.1, dur*0.89 ],'exponential' ) ;
b = EnvGen.kr( a, doneAction: 2 ) ;
c = Mix(Resonz.ar(PinkNoise.ar, [fundamental, partialOne, partialTwo,
partialThree, partialFour, partialFive, partialSix],0.0003, db.dbamp*[10,8,7,6,5,5,4,3,2])
out = Pan2.ar( (c*10) * b, pan);
Out.ar( 0, out ) ;
}).send(s);
// BANDPASS FILTER 'TRICKLING'
SynthDef("trickle", { arg dur, db = 0.0, crackleParam=1.0,
pan, cf, rq, sourcedB, reverbdB ;
var env, source, out ;
env = Env.new([ 0.00001, 1.0, 0.00001 ],[ 0.1, 0.9], 'exponential' );
source = EnvGen.kr( env, timeScale:
dur, doneAction: 2) * Crackle.ar(crackleParam, db.dbamp ) ;
// FILTER
out = BPF.ar(source, cf, rq
) ;
// SEND TO REVERB BUS
Out.ar(2, out * reverbdB.dbamp ) ;
out = Pan2.ar( out * sourcedB.dbamp, pan ) ;
Out.ar(0, out ) ;
}).send(s);
// RESONATING FILTER 'GHOSTS'
SynthDef("ghosts", {arg dur=2.0, centerFreq, db=0, pan=0
;
a = Env.new([ 0.0001, 1.0, 0.0001 ],[0.001, 0.999 ],'linear' ) ;
b = EnvGen.kr( a, doneAction: 2 ) ;
c = Resonz.ar(PinkNoise.ar, centerFreq, 0.001, db.dbamp);
out = Pan2.ar( (c*10) * b, pan);
Out.ar( 0, out ) ;
}).send(s);
// KARPLUS-STRONG 'DRUM'
SynthDef("drum", {arg pitch, db=0, pan=0;
a = Env.new([ 0.0001, 1.0, 0.0001 ],[0.001, 0.999 ],'linear' ) ;
b = EnvGen.kr( a, doneAction: 2 ) ;
c = Pluck.ar(WhiteNoise.ar(0.1), Impulse.kr(2), pitch.reciprocal, pitch.reciprocal, 2, 0.9, db.dbamp ) ;
out = Pan2.ar(c * b, pan);
Out.ar( 0, out);
}).send(s);
// REVERB
SynthDef("fxexamplereverb", {arg delaytime=0.01, decaytime=1;
var input;
var numc,numa,temp;
input=In.ar(0,2); //get two channels of input starting (and ending) on bus 0
numc = 4; // number of comb delays
numa = 6; // number of allpass delays
// reverb predelay time :
temp = DelayN.ar(input, 0.048,0.048);
temp=Mix.fill(numc,{
// chain of 4 allpass delays on each of two channels (8 total) :
numa.do({ temp = AllpassN.ar(temp, 0.051, [rrand(0.01, 0.05),rrand(0.01, 0.05)], 1) });
// add original sound to reverb and play it :
Out.ar(0,(0.1*temp));
}).send(s);
//****************************
//********************** SCORE/ROUTINE ***********************\\
//****************************
r = Routine({
//VARIABLES
var numberofnotes, waittimesarray,
indexnumber=0, upperindexnumber=0, lowerwaittime, upperwaittime, bellvolume,
waitspeed=1 ;
var superSet, currentSet, lowerBound=8, upperBound=16, lastLowerBound, boundaryShift, nextNote, nextNoteIndex, partialOne, partialTwo, partialThree,
partialFour, partialFive, partialSix,
partialSeven, partialEight;
var highBellNextNote, highBellNextNoteIndex,
highBellPartialOne, highBellPartialTwo, highBellPartialThree;
var trickleStartIndex, trickleNextIndex,
firstCf, nextCf, tricklewaittimesarray, trickleindexnumber=0 ;
var firstPan, panArray, panArrayweights
;
//"SUPER SET" - Frequencies based on synthesized bell timbres starting on 100, 200, 400, 800, 1600, and 3200 Hz
//all fundamental pitches and most partials (except the Karplus-Strong "drum") are based on this set
superSet = [100, 119, 156, 200, 238, 251, 301, 312, 400, 476, 502, 532, 602, 624, 800,
820, 952, 1004, 1064, 1204, 1248, 1600, 1640, 1904, 2008, 2128, 2408, 2496, 3200,
3280, 4016, 4256, 4816, 6400, 6560];
//ARRAY OF PAN POSITIONS, TO BE SELECTED BELOW
panArray = [-1, -0.8, -0.6, -0.4,
-0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1];
//START THE REVERB
Synth("fxexamplereverb")
;
1.0.wait; // small wait to keep routine from hiccupping at the beginning
// MAIN LOOP
4.do({
//CHOOSE THE NUMBER OF LARGE BELLS IN THE LOOP
numberofnotes = rrand(5,9) ;
("Number of Notes = "
++ numberofnotes).postln ;
//MAKE AN ARRAY FOR THE MAIN RHYTHM
waittimesarray = Array.fill(numberofnotes, {rrand(1,4)}) ;
("Wait Times = " ++
waittimesarray).postln ;
//"Wait speed" - should get faster as tonic goes higher
waitspeed = 1/(superSet[lowerBound]/400);
waitspeed.postln;
("Wait speed = " ++
waitspeed).postln;
//BELLS WILL BE CHOSEN FROM THIS SUBSET OF THE "SUPER SET"
currentSet = superSet.copyRange(lowerBound, upperBound);
("Current Set = " ++
currentSet).postln;
// FILTERED NOISE "ORGAN" WILL PLAY AT THE BEGINNING OF EACH LOOP
Synth( "organ", [ \dur, rrand(24, 36),
\fundamental, (superSet[lowerBound])*0.25,
\partialOne, (superSet[lowerBound+2])*0.25,
\partialTwo, (superSet[lowerBound+4])*0.25,
\partialThree, (superSet[lowerBound+6])*0.25,
\partialFour, (superSet[lowerBound+8])*0.25,
\partialFive, (superSet[lowerBound+10])*0.
\partialSix, (superSet[lowerBound+12])*0.
\db, -12, \pan, rrand(-0.1, 0.1) ] ) ;
indexnumber=0;
while({indexnumber < numberofnotes},
{
//LARGE BELLS CHOSEN RANDOMLY
THE CURRENT SUBSET - WAIT TIMES BASED ON RHYTHM ARRAY
nextNote = currentSet.choose.postln;
nextNoteIndex = superSet.indexOf(nextNote).
("Next Note = " ++ nextNote).postln;
("Wait this long: "
++ waittimesarray[indexnumber]).
Synth( "lowbell", [ \dur, rrand(5, 8),
\fundamental, nextNote,
\partialOne, superSet[nextNoteIndex + 2],
\partialTwo, superSet[nextNoteIndex + 4],
\partialThree, superSet[nextNoteIndex + 6],
\partialFour, superSet[nextNoteIndex + 8],
\partialFive, superSet[nextNoteIndex + 10],
\partialSix, superSet[nextNoteIndex + 12],
\partialSeven, superSet[nextNoteIndex + 14],
\partialEight, superSet[nextNoteIndex + 16],
\db, ((waittimesarray[indexnumber]*
// "TRIGGERED" INSTRUMENTS
//if the lowest pitch of the subset is played, play HIGH BELLS
if(nextNoteIndex == lowerBound, {
//MAKE A PANNING ARRAY, AND A WEIGHTS ARRAY - PANNING WILL BE
//WEIGHTED AROUND ONE PAN POSITION
firstPan = panArray.choose;
panArrayweights = Array.fill(11, 0);
panArrayweights.put(panArray.
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights = panArrayweights.normalizeSum;
"Small bells".postln ;
("How many notes do I play? : " ++ numberofnotes).postln;
upperindexnumber = 0 ;
numberofnotes.do({
bellvolume = waittimesarray[
upperwaittime = (bellvolume*waitspeed)*0.25;
highBellNextNoteIndex = ([12, 14, 16].choose)+lowerBound;
Synth( "highbell", [ \dur, rrand(2, 3),
\fundamental, superSet[
\partialOne, superSet[highBellNextNoteIndex + 4],
\partialTwo, superSet[nextNoteIndex + 8],
\partialThree, superSet[nextNoteIndex + 12],
\db, (bellvolume*3)-39, \pan, panArray.wchoose(
upperwaittime.wait;
("Wait time = " ++ upperwaittime).postln;
upperindexnumber = upperindexnumber + 1 ;
("Upper index number = " ++ upperindexnumber).postln ;
});
0.2.wait;
}); // end of HIGH BELLS
//if the fourth note of the subset is played, HIGH BELLS (with different pitches)
if(nextNoteIndex == (lowerBound+3), {
firstPan = panArray.choose;
panArrayweights = Array.fill(11, 0);
panArrayweights.put(panArray.
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights = panArrayweights.normalizeSum;
"Small bells".postln ;
("How many notes do I play? : " ++ numberofnotes).postln;
upperindexnumber = 0 ;
numberofnotes.do({
bellvolume = waittimesarray[
upperwaittime = (bellvolume*waitspeed)*0.25;
highBellNextNoteIndex = ([16, 18, 20].choose)+lowerBound;
Synth( "highbell", [ \dur, rrand(2, 3),
\fundamental, superSet[
\partialOne, superSet[highBellNextNoteIndex + 3],
\partialTwo, superSet[nextNoteIndex + 6],
\partialThree, superSet[nextNoteIndex + 9],
\db, (bellvolume*3)-39, \pan, panArray.wchoose(
upperwaittime.wait;
("Wait time = " ++ upperwaittime).postln;
upperindexnumber = upperindexnumber + 1 ;
("Upper index number = " ++ upperindexnumber).postln ;
});
0.2.wait;
}); // end of second HIGH BELLS
//if the highest note of the subset is played, play TRICKLE
if(nextNoteIndex == (upperBound), {
//FIRST CENTER FREQUENCY IS VERY HIGH IN THE SUPERSET -
//ALL SUBSEQUENT GRAINS WILL DESCEND THROUGH THE SUPERSET FREQUENCIES
"Trickling".postln ;
trickleStartIndex=25;
trickleNextIndex=
firstCf = superSet.clipAt(lowerBound+
("First Center Frequency: " ++ firstCf).postln ;
nextCf = firstCf;
firstPan = panArray.choose;
panArrayweights = Array.fill(11, 0);
panArrayweights.put(panArray.
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights = panArrayweights.normalizeSum;
rrand(5, 8).do({
//Make a rhythm array
("Number of Notes = " ++ numberofnotes).postln ;
tricklewaittimesarray = waittimesarray.copy;
("Wait Times = " ++ tricklewaittimesarray).postln ;
trickleindexnumber=0;
while({trickleindexnumber < numberofnotes}, {
("Wait this long: " ++ (tricklewaittimesarray[
//nextCf = nextCf-rrand(30, 100);
nextCf = superSet[lowerBound+
//if(nextCf < superSet[lowerBound], {nextCf = superSet[lowerBound]}, {nextCf = nextCf});
("Next Center Frequency: " ++ nextCf).postln;
Synth("trickle", [\dur, rrand(0.5, 1.0), \db, -9, \pan, panArray.wchoose(
(tricklewaittimesarray[
trickleindexnumber = trickleindexnumber + 1 ;
if(trickleNextIndex > 1, {trickleNextIndex = (trickleNextIndex - 1)}, {trickleNextIndex = 0});
}); // end of trickle do loop
0.2.wait;
}); // end of trickle
// if the sixth pitch of the subset is played, play "GHOSTS"
if(nextNoteIndex == (lowerBound+5), {
firstPan = panArray.choose;
panArrayweights = Array.fill(11, 0);
panArrayweights.put(panArray.
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights = panArrayweights.normalizeSum;
"Ghosts!".postln ;
("How many notes do I play? : " ++ numberofnotes).postln;
upperindexnumber = 0 ;
numberofnotes.do({
bellvolume = waittimesarray[
upperwaittime = (bellvolume*waitspeed)*0.1;
Synth( "ghosts", [ \dur, rrand(2, 3),
\centerFreq, [superSet[lowerBound+6], superSet[lowerBound+7], superSet[lowerBound+8],
superSet[lowerBound+9], superSet[lowerBound+10]].
\db, -3, \pan, panArray.wchoose(
upperwaittime.wait;
("Wait time = " ++ upperwaittime).postln;
upperindexnumber = upperindexnumber + 1 ;
("Upper index number = " ++ upperindexnumber).postln ;
});
0.2.wait;
}); // end of Ghosts
// if third pitch of the subset is played, play DRUM
if(nextNoteIndex == (lowerBound+2), {
firstPan = panArray.choose;
panArrayweights = Array.fill(11, 0);
panArrayweights.put(panArray.
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights.clipPut((
panArrayweights = panArrayweights.normalizeSum;
"Low drums".postln ;
("How many notes do I play? : " ++ numberofnotes).postln;
upperindexnumber = 0 ;
numberofnotes.do({
bellvolume = waittimesarray[
upperwaittime = (bellvolume*waitspeed)*0.1;
Synth( "drum", [ \pitch, (superSet[lowerBound])*0.5, \db,
-9, \pan, panArray.wchoose(
upperwaittime.wait;
("Wait time = " ++ upperwaittime).postln;
upperindexnumber = upperindexnumber + 1 ;
("Upper index number = " ++ upperindexnumber).postln ;
});
0.2.wait;
}); // end of DRUM
waittimesarray[
indexnumber = indexnumber + 1
;
}); // end of main while loop
//ON THE NEXT LOOP, THE SUBSET WILL SHIFT
lastLowerBound = lowerBound.copy;
boundaryShift = [-3, -2, 2, 3].choose;
lowerBound = lowerBound+boundaryShift;
upperBound = upperBound+boundaryShift;
}); // end of main do loop
// FINAL NOTE (THE LOWEST NOTE OF THE LAST SUBSET)
Synth( "organ", [ \dur, rrand(24, 36),
\fundamental, (superSet[lastLowerBound])*0.
\partialOne, (superSet[lastLowerBound+2])*
\partialTwo, (superSet[lastLowerBound+4])*
\partialThree, (superSet[lastLowerBound+6])*
\partialFour, (superSet[lastLowerBound+8])*
\partialFive, (superSet[lastLowerBound+10])*
\partialSix, (superSet[lastLowerBound+12])*
\db, -9, \pan, rrand(-0.1, 0.1) ] ) ;
Synth( "lowbell", [ \dur, rrand(5, 8),
\fundamental, superSet[lastLowerBound],
\partialOne, superSet[lastLowerBound + 2],
\partialTwo, superSet[lastLowerBound + 4],
\partialThree, superSet[lastLowerBound + 6],
\partialFour, superSet[lastLowerBound + 8],
\partialFive, superSet[lastLowerBound + 10],
\partialSix, superSet[lastLowerBound + 12],
\partialSeven, superSet[lastLowerBound + 14],
\partialEight, superSet[lastLowerBound + 16],
\db, -36, \pan, rrand(-0.6, 0.6) ] ) ;
"The End".postln;
});
SystemClock.play(r);
)