Created
October 11, 2014 05:30
-
-
Save Xpktro/4eba5069d97eec7b1dc0 to your computer and use it in GitHub Desktop.
One of my ChucK experiments
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Our sound chain is quite simple buy nice-sounding. | |
// The Rhodey instrument (even when not shown in lectures, is | |
// a STK instrument and meets the evaluation criteria) is a nice | |
// Rhodes-keyboard-like sound, I love it and now I can use it. | |
// (you should REALLY hear the ChucK website demo) | |
Rhodey rho[3]; | |
Pan2 rhoPan[3]; | |
Gain rhoGain => NRev rhoRev => dac; | |
// I'm using really low gain parameters to avoid distorsion | |
.14 => rhoRev.gain; | |
.2 => rhoRev.mix; | |
.2 => rhoGain.gain; | |
// Then assign each Rhodey to it's own pan (in a random position) | |
// and with a random gain to finally chuck them to their master gain. | |
for(0 => int i; i < rho.cap()-1; i++) { | |
rho[i] => rhoPan[i] => rhoGain; | |
Math.random2f(-1., 1.) => rhoPan[i].pan; | |
Math.random2f(8., 1.) => rho[i].gain; | |
} | |
// Our lead voice is... a voice! for the first time, and sound great also. | |
VoicForm voice => NRev voiceRev => dac; | |
.5 => voiceRev.gain; | |
.1 => voiceRev.mix; | |
0.05 => voice.vibratoGain; | |
// It must remain silent until we order it to sing. | |
0 => voice.noteOn; | |
// Our scale | |
[49, 50, 52, 54, 56, 57, 59, 61] @=> int notes[]; | |
// And an apparently meaningless variable (see below). | |
1 => int grade; | |
// Our timing system, not all variables are used but it's shown if it's | |
// useful for anyone. | |
.75::second => dur quarter; | |
quarter / 2 => dur eighth; | |
quarter * 2 => dur half; | |
half * 2 => dur whole; | |
// possiblyInverse would return a number of a note if it happens to shift | |
// octaves up (+12) or down (-12) using a random number as a decider. | |
fun int possiblyInverse(int note) { | |
Math.random2f(0., 1.) => float chance; | |
if(chance <= .1) { | |
note + 12 => note; | |
} else if(chance <= .2) { | |
note - 12 => note; | |
} | |
return note; | |
} | |
// This function would return a possibly inverted chord of | |
// the give grade for the given scale. Note that the scale | |
// must have 8 or 8*X notes to get this to work properly. | |
// (see below for information on what a grade is) | |
fun int[] getChord(int grade, int scale[]) { | |
// Grade: 1-7 | |
int base, third, fifth; | |
scale[grade - 1] => base; | |
if(grade + 2 >= notes.cap()) { | |
scale[(grade + 2 - notes.cap())] + 12 => third; | |
} else { | |
scale[(grade + 2) - 1] => third; | |
} | |
if(grade + 4 >= notes.cap()) { | |
scale[(grade + 4 - notes.cap())] + 12 => fifth; | |
} else { | |
scale[(grade + 4) - 1] => fifth; | |
} | |
// Inversions: | |
possiblyInverse(base) => base; | |
possiblyInverse(third) => third; | |
possiblyInverse(fifth) => fifth; | |
return [base, third, fifth]; | |
} | |
// This is the heart of the song. Let's talk a little about harmony. | |
// Chords are made of 3 notes basically: the base (say C), the third, | |
// which is the *third* note from the base (say E) and the fifht, which | |
// is the *fifth* note from the base (say G), moving positions would give us | |
// a series of chords which are numbered from 1 to 7 and are called 'grades'. | |
// In any *common* song, the notes, grouped by chords, follows some | |
// kinds of 'recipes', these chord recipes are called progressions. | |
// The one I'm using is got from http://www.musictheory.net/lessons/57 | |
fun int nextGrade(int prevGrade) { | |
if(prevGrade == 1) { | |
return Math.random2(1, 7); | |
} | |
if(prevGrade == 5 || prevGrade == 7) { | |
return 1; | |
} | |
if(prevGrade == 4) { | |
if(Math.random2(0, 1) == 0) { | |
return 7; | |
} else { | |
if(Math.random2(0, 1) == 0) { | |
return 5; | |
} else { | |
return 7; | |
} | |
} | |
} | |
if(prevGrade == 2) { | |
if(Math.random2(0, 1) == 0) { | |
return 5; | |
} else { | |
return 7; | |
} | |
} | |
if(prevGrade == 6) { | |
if(Math.random2(0, 1) == 0) { | |
return 2; | |
} else { | |
return 4; | |
} | |
} | |
if(prevGrade == 3) { | |
return 6; | |
} | |
if(prevGrade == 7) { | |
return 3; | |
} | |
} | |
// If you saw the forementioned link, you have found that the former function | |
// was to be used with minor scales, so this is the *major* version of the recipe: | |
/*fun int nextGrade(int prevGrade) { | |
// http://www.musictheory.net/lessons/57 | |
if(prevGrade == 1) { | |
return Math.random2(1, 7); | |
} | |
if(prevGrade == 5) { | |
return 1; | |
} | |
if(prevGrade == 7) { | |
if(Math.random2(0, 1) == 0) { | |
return 3; | |
} else { | |
return 1; | |
} | |
} | |
if(prevGrade == 2 || prevGrade == 4) { | |
if(Math.random2(0, 1) == 0) { | |
return 5; | |
} else { | |
return 7; | |
} | |
} | |
if(prevGrade == 6) { | |
if(Math.random2(0, 1) == 0) { | |
return 2; | |
} else { | |
return 4; | |
} | |
} | |
if(prevGrade == 3) { | |
return 6; | |
} | |
}*/ | |
// This function would make the voice sing each 2 eighths | |
// (a quarter). | |
fun void voiceSing(int beat, int chord[]) { | |
if(beat % 2 == 0) { | |
// We set the voice to sing an octave upper the give frequency. | |
Std.mtof(chord[Math.random2(0, 2)]) * 2 => voice.freq; | |
1 => voice.noteOn; | |
} | |
} | |
// We define our beat counter. | |
0 => int beat; | |
// Define the ending point of our song. | |
now + 27::second => time end; | |
// And repeat while we're not done yet: | |
while(now < end) { | |
// Get a new chord based on our current grade. | |
getChord(grade, notes) @=> int chord[]; | |
// See if the voice will sing. | |
voiceSing(beat, chord); | |
// And play our chords with the Rhodey | |
if(beat % 4 == 0) { | |
for(0 => int i; i<rho.cap()-1; i++) { | |
Std.mtof(chord[i]) => rho[i].freq; | |
1 => rho[i].noteOn; | |
} | |
// At the end, we get the next grade in our sequence | |
// and store it for the next beat. | |
nextGrade(grade) => grade; | |
} | |
// We increment our beat counter. | |
beat++; | |
// And let an eighth pass... | |
eighth => now; | |
} | |
// The sad (and very quick) ending of our song consists of | |
// the Rhodey and the voice playing the main chord. | |
getChord(1, notes) @=> int chord[]; | |
for(0 => int i; i<rho.cap()-1; i++) { | |
Std.mtof(chord[i]) => rho[i].freq; | |
1 => rho[i].noteOn; | |
} | |
voiceSing(0, chord); | |
3::second => now; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment