Modedular.ck

From CSWiki
Revision as of 02:42, 26 February 2008 by Kijjaz (talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

This is the code for the version 0.2 testing

// Modedular version 0.2 testing
// by Kijjasak Triyanond (kijjaz) kijjaz@yahoo.com 

// [note] this is still quite experimental, so some functions might have problems
// some more features will be added soon.
// [fixes]
// * now the note function's code had been cleaned up
//   and is greatly reduced (in size) and optimized (generalized); the output is the same.
// * i've decided that the normal rotation should not rotate the whole mode data,
//   but instead set the offset of the readhead while using note function
//   the rotation can by 'Applied' so that it really rotate the interval array.
// * now chord is fully functional, check the test code to see chord in action           

// licence: Attribution-Share Alike 3.0
// You are free:
//    * to Share — to copy, distribute and transmit the work
//    * to Remix — to adapt the work
// Under the following conditions:
//    * Attribution. You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work).
//    * Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under the same, similar or a compatible license.

class Modedular
{
    [0] @=> int intervals[]; // array of intervals in the mode
    0 => int octaveSize; // octave size in semitones
    0 => int rotationOffset; // for easy mode rotation
       
    fun int update()
    {
        // use this to octave Octave Size
        0 => octaveSize;
        for(int i; i < intervals.cap(); i++) intervals[i] +=> octaveSize;
        return octaveSize;
    }
    fun void set(int input[])
    {
        // use this to copy intervals from the input array
        new int[input.cap()] @=> intervals;
        for(int i; i < input.cap(); i++) input[i] => intervals[i];
        update();
    }
    fun void set(string input)
    {
        // use this to set the mode to a preset value by a string
        if (input == "lydian") set([2,2,2,1,2,2,1]);
        if (input == "ionian") set([2,2,1,2,2,2,1]);
        if (input == "mixolydian") set([2,2,1,2,2,1,2]);
        if (input == "dorian") set([2,1,2,2,2,1,2]);
        if (input == "aeolian") set([2,1,2,2,1,2,2]);
        if (input == "phrygian") set([1,2,2,2,1,2,2]);
        if (input == "locrian") set([1,2,2,1,2,2,2]);
       
        if (input == "harmonic minor") set([2,1,2,2,1,3,1]);
        if (input == "melodic minor") set([2,1,2,2,2,2,1]);
        update();
    }
    fun void get(int input[])
    {
        // use this to copy to an outside array
        new int[input.cap()] @=> input;
        for(int i; i < input.cap(); i++) intervals[i] => input[i];
    }
   
    fun int note(int pitch)
    {
        // use this to acquire note (calculated in semitones) from the mode
        // without octave input
        pitch--; // so user can start the first pitch from 1 instead of 0
        0 => int octave; // but we still have to use octave if pitch is negative
        
        // calculate pitch and octave for use the intervals array
        // by limiting pitch in rang 0..intervals.cap()-1 and adjust octave number
        if (pitch < 0) octave--;
        pitch / intervals.cap() +=> octave;
        (pitch - (pitch / intervals.cap() - 1) * intervals.cap()) % intervals.cap() => pitch;
       
        0 => int sum;
        // calculate semitones for the pitch
        // with rootPosition for easy mode rotation
        for(int i; i < pitch; i++) intervals[(i + rotationOffset) % intervals.cap()] +=> sum; 
        octave * octaveSize +=> sum; // select desired octave
        return sum; // and we'll have the result in semitone
    }
    fun int note(int pitch, int octave)
    {
        // note, with octave number also
        return note(pitch) + octave * octaveSize;
    }   
   
    fun void rotate(int x)
    {
        // rotate the mode x times        
        x +=> rotationOffset;
        (rotationOffset - (rotationOffset / intervals.cap() - 1) * intervals.cap()) % intervals.cap() => rotationOffset;
    }
    fun void setRotate(int x)
    {
        // reset rotation point to x
        x => rotationOffset;
        (rotationOffset - (rotationOffset / intervals.cap() - 1) * intervals.cap()) % intervals.cap() => rotationOffset;
    }
    fun void rotateApply()
    {
        // use current rotation offset to really rotate the interval array.
        // then reset the rotation offset.
        int dummy[intervals.cap()];
        for(int i; i < intervals.cap(); i++) intervals[(i + rotationOffset) % intervals.cap()] => dummy[i];
        for(int i; i < intervals.cap(); i++) dummy[i] => intervals[i];
        0 => rotationOffset;
    }
    fun void rotateApply(int x)
    {
        // use in supplied number as the rotation offset, then really rotate the interval array.
        // then reset the rotation offset, also.        
        setRotate(x);
        rotateApply();
    }
   
    fun void chord(int root, int positions[], int result[])
    {
        // make a chord from position list (chord degrees)
        for(int i; i < positions.cap() && i < result.cap(); i++)
        {
            note(root + positions[i] - 1) => result[i];
        }
    }
    fun void chord(int root, int octave, int positions[], int result[])
    {
        // make a chord from position list, with octave
        for(int i; i < positions.cap() && i < result.cap(); i++)
        {
            note(root + positions[i] - 1) + octave * octaveSize => result[i];
        }
    }   
}

User Manual: (draft)

  • Use .set to set a new mode. The mode's data is formed by a serie of intervals (in semitones).

For example, .set( [2, 2, 1, 2, 2, 2, 1] ) will create Ionian mode or Major Scale. Other kinds and length of a scale can be created also for example, .set( [2, 1] ) creates a Whole-Half diminished scale.

  • .set can be used to set the mode to a preset by passing a string with the mode's name.

For example, .set("harmonic minor") would make the mode a harmonic minor instantly. Current mode names are: lydian, ionian, mixolydian, dorian, aeolian, phrygian, locrian, harmonic minor, melodic minor