One for All: Difference between revisions

Xenjacob (talk | contribs)
No edit summary
BudjarnLambeth (talk | contribs)
m Categorised this uncategorised page
 
(4 intermediate revisions by one other user not shown)
Line 1: Line 1:
Rough multitrack recording by Jacob Barton, http://oneforall.ytmnd.com
Score in sagittal: [[File:SS01_One_for_All.pdf]]


Code tutorial (with assignment for xenharmonic campers) in ChucK (save as a .ck file to use in ChucK):
Premiere recording at Xenharmonic Praxis Summer Camp 2011, Hillsboro, WV: http://micro.soonlabel.com/0-praxis/audio/July/july_group_5a_one_for_all2.mp3
<nowiki>/* Sagittal Songbook 01
One for All
by Ryan Stickney


A four-part round in just intonation, in 11/4 time
Second recording at XPSC 2011: https://youtu.be/S62yVU1pspQ?t=1257
Coded by xenjacob Jan. 2020


The implementation is basic, and shared in this way both to introduce
Performance recording at Xenharmonic Praxis Summer Camp 2013, Salem, NH: https://jacobbarton.bandcamp.com/track/one-for-all
some basics of ChucK and to illustrate the
degree of 'grunt work' which may (not must) accompany any work of art.


ASSIGNMENT FOR XENCAMPERS:
Multitrack recording by Jacob Barton, http://oneforall.ytmnd.com
1. Get this code to work on your setup! Save this text as a .ck file.
If you are running miniAudicle, all you have to do then is
'Start Virtual Machine' and then 'Add Shred'.
2. Try modifying 1/1 pitch and/or tempo (read thru the comments below for how)
3. Learn the song!
4. Make a rough recording of yourself singing along to patch. (Change anything, have phun with it)
5. (Optional) Think up a single alteration that would make this patch
'more musical', and send it to xenjacob. No need to know how to code it yourself.


The melody line is first encoded as a 2D array corresponding
Code tutorial (with assignment for xenharmonic campers) in [http://chuck.cs.princeton.edu the ChucK environment] (copy and save the below text as a .ck file to use in ChucK):
to pitch and rhythm values
<nowiki>/* Sagittal Songbook 01
[[ pitch, rhythm ], ...]
    One for All
 
    by Ryan Stickney
This kind of score entry is labor-intensive, but a rather good match to the
 
Sagittal Songbook project due to the brevity of most of the songs.
  A four-part round in just intonation, in 11/4 time
 
  Coded by xenjacob Jan. 2020
Pitches are in JI intervals in relation to the defined 1/1 (notated C)
 
A decimal point in the fraction forces ChucK to do non-integer
  The implementation is basic, and shared in this way both to introduce
arithmetic to create a floating-point value (otherwise it will e.g. compute
  some basics of ChucK and to illustrate the
4/3 as 1 remainder 1 and discard the remainder)
  degree of 'grunt work' which may (not must) accompany any work of art.
 
 
Rhythms are declared in relation to the value of a quarter note,
  ASSIGNMENT FOR XENCAMPERS:
assigned here to the value 1 (half note = 2, dotted half = 3, etc.)
  1. Get this code to work on your setup! Save this text as a .ck file.
*/
  If you are running miniAudicle, all you have to do then is
 
  'Start Virtual Machine' and then 'Add Shred'.
[
  2. Try modifying 1/1 pitch and/or tempo (read thru the comments below for how)
[ 1/1., 2 ], // All
  3. Learn the song!
[ 3/2., 2 ], // things
  4. Make a rough recording of yourself singing along to patch. (Change anything, have phun with it)
[ 2/1., 1 ], // wing-
  5. (Optional) Think up a single alteration that would make this patch
[ 7/4., 1], // -ed
  'more musical', and send it to xenjacob. No need to know how to code it yourself.
[ 3/2., 1 ], // are
 
[ 4/3., 2 ], // made
  The melody line is first encoded as a 2D array corresponding
[ 5/4., 2 ], // for
  to pitch and rhythm values
[ 3/2., 2 ], // jump-
  [[ pitch, rhythm ], ...]
[ 2/1., 2 ], // -ing
 
[ 5/2., 1 ], // in-
  This kind of score entry is labor-intensive, but a rather good match to the
[ 9/4., 1 ], // -to
  Sagittal Songbook project due to the brevity of most of the songs.
[ 2/1., 1 ], // the
 
[ 7/4., 1 ], // sky__
  Pitches are in JI intervals in relation to the defined 1/1 (notated C)
[ 7/4., 2 ], // (bend)
  A decimal point in the fraction forces ChucK to do non-integer
[ 2/1., 5/3. ], // ____.
  arithmetic to create a floating-point value (otherwise it will e.g. compute
// implementing a rhythmic breath or 'hiccup' at the end of each phrase
  4/3 as 1 remainder 1 and discard the remainder)
// equal to two-thirds of a beat.
 
 
  Rhythms are declared in relation to the value of a quarter note,
[ 5/4., 2 ], // Fall-
  assigned here to the value 1 (half note = 2, dotted half = 3, etc.)
[ 5/4., 2 ], // -ing
  */
[ 4/3., 1 ], // brings
 
[ 9/8., 1 ], // no
  [
[ 5/4., 1 ], // di-
  [ 1/1., 2 ], // All
[ 2/1., 2 ], // -sas-
  [ 3/2., 2 ], // things
[ 7/4., 2 ], // -ter
  [ 2/1., 1 ], // wing-
[ 15/8., 2 ], // when
  [ 7/4., 1], // -ed
[ 5/4., 2 ], // you
  [ 3/2., 1 ], // are
[ 3/2., 3 ], // can
  [ 4/3., 2 ], // made
[ 4/3., 1 ], // fly_
  [ 5/4., 2 ], // for
[ 4/3., 2 ], // (bend)
  [ 3/2., 2 ], // jump-
[ 5/4., 5/3. ], // __.
  [ 2/1., 2 ], // -ing
 
  [ 5/2., 1 ], // in-
[ 3/2., 2 ], // Calls
  [ 9/4., 1 ], // -to
[ 2/1., 2 ], // sing
  [ 2/1., 1 ], // the
[ 3/2., 3 ], // birds
  [ 7/4., 1 ], // sky__
[ 9/8., 2 ], // to
  [ 7/4., 2 ], // (bend)
[ 1/1., 2 ], // each
  [ 2/1., 5/3. ], // ____.
[ 9/8., 1 ], // o-
  // implementing a rhythmic breath or 'hiccup' at the end of each phrase
[ 5/4., 1 ], // -ther
  // equal to two-thirds of a beat.
[ 11/8., 1 ], // but
 
[ 3/2., 1], // who
  [ 5/4., 2 ], // Fall-
[ 2/1., 3 ], // knows
  [ 5/4., 2 ], // -ing
[ 9/4., 1 ], // why?__
  [ 4/3., 1 ], // brings
[ 9/4., 2 ], // __(bend)
  [ 9/8., 1 ], // no
[ 2/1., 5/3.], // ___
  [ 5/4., 1 ], // di-
 
  [ 2/1., 2 ], // -sas-
[ 2/1., 4], // Fly-
  [ 7/4., 2 ], // -ter
[ 7/4., 3 ], // -ing
  [ 15/8., 2 ], // when
[ 4/3., 2 ], // looks
  [ 5/4., 2 ], // you
[ 3/2., 2 ], // fun;
  [ 3/2., 3 ], // can
[ 3/2., 4 ], // I'm
  [ 4/3., 1 ], // fly_
[ 1/1., 1 ], // will-
  [ 4/3., 2 ], // (bend)
[ 9/8., 1 ], // -ing
  [ 5/4., 5/3. ], // __.
[ 5/4., 1 ], // to
 
[ 1/1., 4.+2/3. ] // try.
  [ 3/2., 2 ], // Calls
 
  [ 2/1., 2 ], // sing
] @=> float score[][]; // "@=>" is the assignment operator for arrays.
  [ 3/2., 3 ], // birds
 
  [ 9/8., 2 ], // to
// Since there are only a few glissandi in the score,
  [ 1/1., 2 ], // each
// let's collect the index #'s of the notes which gliss
  [ 9/8., 1 ], // o-
// into an array "bends":
  [ 5/4., 1 ], // -ther
 
  [ 11/8., 1 ], // but
[ 13, 26, 39 ] @=> int bends[];
  [ 3/2., 1], // who
 
  [ 2/1., 3 ], // knows
// one_one will define the 1/1 frequency in Hz
  [ 9/4., 1 ], // why?__
// **CHANGE THIS** to try in different keys!
  [ 9/4., 2 ], // __(bend)
221 => float one_one;
  [ 2/1., 5/3.], // ___
// 261.6 is approximately concert C pitch
 
// 240 tunes to electrical hum (in the Americas and Asia anyway)
  [ 2/1., 4], // Fly-
// B flat (233) has also been traditionally used in this round.
  [ 7/4., 3 ], // -ing
 
  [ 4/3., 2 ], // looks
// 'pulse' wil define the time duration of a quarter note
  [ 3/2., 2 ], // fun;
// **CHANGE THIS** to try different tempi!
  [ 3/2., 4 ], // I'm
556::ms => dur pulse;
  [ 1/1., 1 ], // will-
// the :: must separate the numerical value and the duration unit
  [ 9/8., 1 ], // -ing
// (which can be samp, ms, second, minute, hour, day, or week)
  [ 5/4., 1 ], // to
 
  [ 1/1., 4.+2/3. ] // try.
// PlayScore is a function which will read the score (any score specified
 
// in the same manner, actually), note by note, into
  ] @=> float score[][]; // "@=>" is the assignment operator for arrays.
// a dedicated triangle wave oscillator.
 
 
  // Since there are only a few glissandi in the score,
// But Wait!
  // let's collect the index #'s of the notes which gliss
// Musicality Mod 1 (suggested by Thomas): the ability to play in other registers.
  // into an array "bends":
// PlayScore will take an additional argument, specifying the number of  
 
// octaves offset (-1 for octave down, 0 for at pitch, 1 for octave up, etc.
  [ 13, 26, 39 ] @=> int bends[];
fun void PlayScore( float play[][], int octave_shift )
 
{
  // one_one will define the 1/1 frequency in Hz
    TriOsc t => dac; // direct link to the digital audio converter (soundcard)
  // **CHANGE THIS** to try in different keys!
    0.25 => t.gain; // range [0,1] - let's leave room for 4 voices here
  221 => float one_one;
    // (digital distortion otherwise...which actually makes some really neat effects, try it!
  // 261.6 is approximately concert C pitch
   
  // 240 tunes to electrical hum (in the Americas and Asia anyway)
    // loop iterates thru the play array, one note entry at a time
  // B flat (233) has also been traditionally used in this round.
    for( 0 => int i; i < play.cap(); i++)
 
    {
  // 'pulse' wil define the time duration of a quarter note
        // read the array, change the frequency
  // **CHANGE THIS** to try different tempi!
        play[i][0] * one_one * Math.pow(2, octave_shift) => t.freq;
  556::ms => dur pulse;
       
  // the :: must separate the numerical value and the duration unit
        // glissando code
  // (which can be samp, ms, second, minute, hour, day, or week)
        // hard-coded to 3 total glisses, because ChucK doesn't
 
        // seem to have any built-in array searching
  // PlayScore is a function which will read the score (any score specified
        if( bends[0] == i || bends[1] == i || bends[2] == i )
  // in the same manner, actually), note by note, into
        {
  // a dedicated triangle wave oscillator.
            // divides the length of the rhythm of that note
 
            // into 366 parts, because, hey, leap year!
  // But Wait!
            366 => float rhdiv;
  // Musicality Mod 1 (suggested by Thomas): the ability to play in other registers.
            for( 0 => int j; j <= rhdiv; j++)
  // PlayScore will take an additional argument, specifying the number of
            {
  // octaves offset (-1 for octave down, 0 for at pitch, 1 for octave up, etc.
                // one_one * play[i][0] *
  fun void PlayScore( float play[][], int octave_shift )
                //  Math.pow( (play[i+1][0]/play[i][0]) , j/rhdiv ) => t.freq;
  {
                // Above code divides the glissando down by equal (logarithmic) steps,
      TriOsc t => dac; // direct link to the digital audio converter (soundcard)
                // Doesn't sound 'natural' to me,
      0.25 => t.gain; // range [0,1] - let's leave room for 4 voices here
                // Let's try equal-frequency steps:
      // (digital distortion otherwise...which actually makes some really neat effects, try it!
                ((play[i+1][0] - play[i][0])*one_one/rhdiv*j + play[i][0]*one_one) * Math.pow(2, octave_shift) => t.freq;
     
                 pulse*play[i][1]/rhdiv => now;
      // loop iterates thru the play array, one note entry at a time
                // I still wasn't happy with it,
      for( 0 => int i; i < play.cap(); i++)
                // but hey, "Publish or die." -- Rob Scott
      {
            }
          // read the array, change the frequency
        }
          play[i][0] * one_one * Math.pow(2, octave_shift) => t.freq;
        // this code is executed in non-glissando case
         
        else {
          // glissando code
            // chucking a duration to now advances time
          // hard-coded to 3 total glisses, because ChucK doesn't
            // by that amount within the shred
          // seem to have any built-in array searching
            pulse*play[i][1] => now;
          if( bends[0] == i || bends[1] == i || bends[2] == i )
        }
          {
    }
              // divides the length of the rhythm of that note
}
              // into 366 parts, because, hey, leap year!
 
              366 => float rhdiv;
PlayScore( score, 0); // Calling the function once will play thru the melody once.
              for( 0 => int j; j <= rhdiv; j++)
// See if you can add multiple shreds of this at just the right time to play in round!
              {
// Try alternating lower and higher octaves!
                  // one_one * play[i][0] *
/*
                  //  Math.pow( (play[i+1][0]/play[i][0]) , j/rhdiv ) => t.freq;
// remove lines 169 and 205, AND comment/remove line 165, to unlock...
                  // Above code divides the glissando down by equal (logarithmic) steps,
// CHAPTER TWO - Programmed Polyphony
                  // Doesn't sound 'natural' to me,
// a function to hang out between successive entries
                  // Let's try equal-frequency steps:
fun void waitLine() {
                  ((play[i+1][0] - play[i][0])*one_one/rhdiv*j + play[i][0]*one_one) * Math.pow(2, octave_shift) => t.freq;
    (22.+2/3.)*pulse => now;
                  pulse*play[i][1]/rhdiv => now;
}
                  // I still wasn't happy with it,
// to execute functions 'in series', simply call them, as  
                  // but hey, "Publish or die." -- Rob Scott
// to execute 'in parallel', use 'spork~' to create breakoff shreds.
                 }
// 'spork a shred' > 'fork a thread', good one Ge Wang...
          }
 
          // this code is executed in non-glissando case
// the below code initiates five separate shreds
          else {
// to simulate five round entries
              // chucking a duration to now advances time
 
              // by that amount within the shred
spork~ PlayScore ( score, 0 ); // first entry
              pulse*play[i][1] => now;
waitLine();
          }
spork~ PlayScore ( score, 1 );
      }
waitLine();
  }
spork~ PlayScore ( score, 0 );
 
waitLine();
  PlayScore( score, 0); // Calling the function once will play thru the melody once.
spork~ PlayScore ( score, 1 );
  // See if you can add multiple shreds of this at just the right time to play in round!
waitLine();
  // Try alternating lower and higher octaves!
// now check this out
  /*
// for the last entry, we gonna do a 'Meno Mosso' (slower tempo)
  // remove lines 169 and 205, AND comment/remove line 165, to unlock...
// we change ONE VARIABLE, and all four lines follow!
  // CHAPTER TWO - Programmed Polyphony
// if we had passed the pulse as an argument to each function instead of
  // a function to hang out between successive entries
// using this sort of global variable, this wouldn't work.
  fun void waitLine() {
1.1 *=> pulse; // multiply value of pulse by 1.1 and re-assign
      (22.+2/3.)*pulse => now;
spork~ PlayScore ( score, 0 ); // final entry
  }
// now, let the round play out;
  // to execute functions 'in series', simply call them, as  
// if the main shred of this script terminated early,
  // to execute 'in parallel', use 'spork~' to create breakoff shreds.
// it would automatically terminate any child shreds still running
  // 'spork a shred' > 'fork a thread', good one Ge Wang...
waitLine();
 
waitLine();
  // the below code initiates five separate shreds
waitLine();
  // to simulate five round entries
waitLine();
 
/*</nowiki>
  spork~ PlayScore ( score, 0 ); // first entry
  waitLine();
  spork~ PlayScore ( score, 1 );
  waitLine();
  spork~ PlayScore ( score, 0 );
  waitLine();
  spork~ PlayScore ( score, 1 );
  waitLine();
  // now check this out
  // for the last entry, we gonna do a 'Meno Mosso' (slower tempo)
  // we change ONE VARIABLE, and all four lines follow!
  // if we had passed the pulse as an argument to each function instead of
  // using this sort of global variable, this wouldn't work.
  1.1 *=> pulse; // multiply value of pulse by 1.1 and re-assign
  spork~ PlayScore ( score, 0 ); // final entry
  // now, let the round play out;
  // if the main shred of this script terminated early,
  // it would automatically terminate any child shreds still running
  waitLine();
  waitLine();
  waitLine();
  waitLine();
  /*</nowiki>
[[Category:Composition]]
[[Category:Sagittal notation]]
[[Category:Scores]]
[[Category:Listen]]