Difference between revisions of "StereoChordEGG.ck"

From CSWiki
Jump to: navigation, search
 
Line 1: Line 1:
 +
    // In the late '60s or early 70's Paia electronics came out with a circuit kit called the
 +
    // Stereo Chord EGG (Electronic Gratification Generator).  It was a top-octave generator
 +
    // along with a resistor network to mix up the I,IV and V chords into the left and right channels.
 +
    //
 +
    //  This little chuck proggy is an attempt to re-create "the wisdom of the ancients"  and let you
 +
    // hear what this little guy sounded like -- as best as my 35 year old, admittedly alcohol
 +
    // addled memories will permit.
  
// In the late '60s or early 70's Paia electronics came out with a circuit kit called the
 
// Stereo Chord EGG (Electronic Gratification Generator).  It was a top-octave generator
 
// along with a resistor network to mix up the I,IV and V chords into the left and right channels.
 
//
 
//  This little chuck proggy is an attempt to re-create "the wisdom of the ancients"  and let you
 
// hear what this little guy sounded like -- as best as my 35 year old, admittedly alcohol
 
// addled memories will permit.
 
  
 +
    class Chord
 +
    {
 +
        string myName;  // a name for us to show the user during debug prints.  BTW: what's with <<<>>> ??!?!
  
class Chord
 
{
 
string myName;  // a name for us to show the user during debug prints.  BTW: what's with <<<>>> ??!?!
 
  
 +
        //Paia's circuit used a top-octave generator to make a square wave train that they somehow filtered.
 +
        // I can't remember how that happened so I used banded wave guides, since it sounded right.
  
//Paia's circuit used a top-octave generator to make a square wave train that they somehow filtered.
+
        // Paia used three note chords, so that's good enough for us.
// I can't remember how that happened so I used banded wave guides, since it sounded right.
+
        BandedWG tonic => gain g;
 +
        BandedWG two => g;
 +
        BandedWG third => g;
  
// Paia used three note chords, so that's good enough for us.
+
        // the banded wave guides will be playing all the time, so the only control is that
BandedWG tonic => gain g;
+
        // we will be ramping the gain of the mixer from current vol to wanted vol.
BandedWG two => g;
+
        float currvol;
BandedWG third => g;
+
        float wantedvol;
 +
        g => dac;
  
// the banded wave guides will be playing all the time, so the only control is that
+
        // set some defaults for the banded wave guide generators.  I don't know or care too much
// we will be ramping the gain of the mixer from current vol to wanted vol.
+
        //  what these all mean.  It is enough that someone out in internet land knows.
float currvol;
+
        // "The internet is the ultimate irreferance":  Jim Hinds. and you can quote me on that.
float wantedvol;
+
        public void  setBand ( BandedWG b, float loudness, int note ) {
g => dac;
+
            loudness=> b.gain;
 +
            1=> b.preset;
  
// set some defaults for the banded wave guide generators. I don't know or care too much
+
            // comp-XXX salesman: "hey Arnie! He doesn't know what std.mtof does!". Spock: "read the source, luke".
//  what these all mean. It is enough that someone out in internet land knows.
+
            std.mtof(21+note) => b.freq;
//  "The internet is the ultimate irreferance":  Jim Hinds. and you can quote me on that.
 
public void  setBand ( BandedWG b, float loudness, int note ) {
 
loudness=> b.gain;
 
1=> b.preset;
 
  
// comp-XXX salesman: "hey Arnie! He doesn't know what std.mtof does!". Spock: "read the source, luke".
+
            // we love rand functions to set important parameters so that the wool is firmly over our eyes.
std.mtof(21+note) => b.freq;
+
            //  As the Church of the Subgenius sez: "Praise Bob!"
 +
            std.rand2f( 0.1, 0.9 ) => b.bowRate;
 +
            std.rand2f( 0.2, 0.35 ) => b.bowPressure;
 +
            std.rand2f( 0.6, 0.8 ) => b.startBowing;
 +
        }
  
// we love rand functions to set important parameters so that the wool is firmly over our eyes.
 
//  As the Church of the Subgenius sez: "Praise Bob!"
 
std.rand2f( 0.1, 0.9 ) => b.bowRate;
 
std.rand2f( 0.2, 0.35 ) => b.bowPressure;
 
std.rand2f( 0.6, 0.8 ) => b.startBowing;
 
}
 
  
 +
        // adjust the gain up or down as needed without going passed the desired limit
 +
        // note that the direction of the adjustment MUST be in agreement with the desired
 +
        // direction.  This method doesnt know about that.  That's one reason it is private.
 +
        private void gainTo ( float v, float wanted ) {
 +
            currvol + v => float adjust;
 +
            if ( wanted > currvol && adjust > wanted ) wanted => adjust;
 +
            if ( wanted < currvol && adjust < wanted ) wanted => adjust;
 +
            adjust=>currvol;
 +
            adjust=>g.gain;
 +
        }
  
// adjust the gain up or down as needed without going passed the desired limit
+
        // set some reasonable values for this object.  Normally we would do this in a constructor. (where
// note that the direction of the adjustment MUST be in agreement with the desired
+
        // are the constructors?  I must have missed something...
// direction.  This method doesnt know about that.  That's one reason it is private.
+
        //
private void gainTo ( float v, float wanted ) {
+
        public void setChord ( int tonicValue, int twoValue, int thirdValue,string n) {
currvol + v => float adjust;
+
            n => myName;
if ( wanted > currvol && adjust > wanted ) wanted => adjust;
+
            setBand (tonic, .80, tonicValue);
if ( wanted < currvol && adjust < wanted ) wanted => adjust;
+
            setBand (two, .85, twoValue);
adjust=>currvol;
+
            setBand (third, .9, thirdValue);
adjust=>g.gain;
+
            0 => wantedvol;
}
+
            0 => currvol;
 +
            0=> g.gain;
 +
        }
  
// set some reasonable values for this object.  Normally we would do this in a constructor. (where
+
        //ramp the volume on this object incrementally till we hit the wanted volume
// are the constructors?  I must have missed something...
+
        public void rampgain ( ) {
//
+
            float adjust;
public void setChord ( int tonicValue, int twoValue, int thirdValue,string n) {
+
            while ( 1 ) {
n => myName;
+
                175::ms => now;
setBand (tonic, .80, tonicValue);
+
                if ( currvol > wantedvol ) {
setBand (two, .85, twoValue);
+
                    gainTo(-.2, wantedvol);
setBand (third, .9, thirdValue);
+
                }
0 => wantedvol;
+
                if ( currvol < wantedvol ) {
0 => currvol;
+
                    gainTo(.1, wantedvol);
0=> g.gain;
+
                }
}
+
                // <<<myName, currvol,wantedvol>>>;
 +
            }
 +
        }
  
//ramp the volume on this object incrementally till we hit the wanted volume
+
    }
public void rampgain ( ) {
 
float adjust;
 
while ( 1 ) {
 
175::ms => now;
 
if ( currvol > wantedvol ) {
 
gainTo(-.2, wantedvol);
 
}
 
if ( currvol < wantedvol ) {
 
gainTo(.1, wantedvol);
 
}
 
// <<<myName, currvol,wantedvol>>>;
 
}
 
}
 
  
}
+
    //  a function for "syntactic cod-liver-oil" since we can't spork c.rampgain directly
 +
    fun void runChord (Chord c) {
 +
        c.rampgain();
 +
    }
  
// a function for "syntactic cod-liver-oil" since we can't spork c.rampgain directly
+
    //set up the I, IV and V chords and start them sounding at amplitude zero
fun void runChord (Chord c) {
+
    Chord I;
c.rampgain();
+
    I.setChord ( 1,3,5,"I");
}
+
    spork ~ runChord(I);
 +
    Chord IV;
 +
    IV.setChord ( 4,6,1,"IV");
 +
    spork ~ runChord(IV);
 +
    Chord V;
 +
    V.setChord ( 5,7,2,"V");
 +
    spork ~ runChord(V);
  
//set up the I, IV and V chords and start them sounding at amplitude zero
+
    //since machines like to use numbers to access the chords, rather than names like I,IV,V
Chord I;
+
    //we put the chord object (references) into an array
I.setChord ( 1,3,5,"I");
+
    [I,IV,V] @=> Chord @ s[ ] ;
spork ~ runChord(I);
 
Chord IV;
 
IV.setChord ( 4,6,1,"IV");
 
spork ~ runChord(IV);
 
Chord V;
 
V.setChord ( 5,7,2,"V");
 
spork ~ runChord(V);
 
  
//since machines like to use numbers to access the chords, rather than names like I,IV,V
+
    //changeto will bring up the volume on one of the chords and leave it like for a specified duration
//we put the chord object (references) into an array
+
    fun void changeto (float amplitude,int index,dur t )
[I,IV,V] @=> Chord @ s[ ] ;
+
    {
 +
        for ( 0 =>int i; i <3 ; i++ ) {
 +
            0 => float v;
 +
            if (i == index ) amplitude => v;
 +
            v=> s [i].wantedvol;
 +
        }
 +
        t => now ;
 +
    }
  
//changeto will bring up the volume on one of the chords and leave it like for a specified duration
+
    //select a chord at random, bring it up to a random level and hold for some reasonable time
fun void changeto (float amplitude,int index,dur t )
+
    while (1) {
{
+
        changeto (std.rand2f(.5,.9),  std.rand2(0,2), std.rand2f(1.5,4)::second );
for ( 0 =>int i; i <3 ; i++ ) {
+
    }
0 => float v;
 
if (i == index ) amplitude => v;
 
v=> s [i].wantedvol;
 
}
 
t => now ;
 
}
 
 
 
//select a chord at random, bring it up to a random level and hold for some reasonable time
 
while (1) {
 
changeto (std.rand2f(.5,.9),  std.rand2(0,2), std.rand2f(1.5,4)::second );
 
}
 

Revision as of 17:34, 21 February 2006

   // In the late '60s or early 70's Paia electronics came out with a circuit kit called the
   // Stereo Chord EGG (Electronic Gratification Generator).  It was a top-octave generator
   // along with a resistor network to mix up the I,IV and V chords into the left and right channels.
   // 
   //  This little chuck proggy is an attempt to re-create "the wisdom of the ancients"  and let you
   // hear what this little guy sounded like -- as best as my 35 year old, admittedly alcohol
   // addled memories will permit.


   class Chord 
   {
       string myName;  // a name for us to show the user during debug prints.  BTW: what's with <<<>>> ??!?!


       //Paia's circuit used a top-octave generator to make a square wave train that they somehow filtered.
       // I can't remember how that happened so I used banded wave guides, since it sounded right.
       // Paia used three note chords, so that's good enough for us.
       BandedWG tonic => gain g;
       BandedWG two => g;
       BandedWG third => g;
       // the banded wave guides will be playing all the time, so the only control is that
       // we will be ramping the gain of the mixer from current vol to wanted vol.
       float currvol;
       float wantedvol;
       g => dac;
       // set some defaults for the banded wave guide generators.  I don't know or care too much
       //  what these all mean.  It is enough that someone out in internet land knows.
       //  "The internet is the ultimate irreferance":  Jim Hinds. and you can quote me on that.
       public void  setBand ( BandedWG b, float loudness, int note ) {
           loudness=> b.gain;
           1=> b.preset;
           // comp-XXX salesman: "hey Arnie!  He doesn't know what std.mtof does!". Spock: "read the source, luke".
           std.mtof(21+note) => b.freq;
           // we love rand functions to set important parameters so that the wool is firmly over our eyes.
           //  As the Church of the Subgenius sez: "Praise Bob!"
           std.rand2f( 0.1, 0.9 ) => b.bowRate;
           std.rand2f( 0.2, 0.35 ) => b.bowPressure;
           std.rand2f( 0.6, 0.8 ) => b.startBowing;
       }


       // adjust the gain up or down as needed without going passed the desired limit
       // note that the direction of the adjustment MUST be in agreement with the desired
       // direction.  This method doesnt know about that.  That's one reason it is private.
       private void gainTo ( float v, float wanted ) {
           currvol + v => float adjust;
           if ( wanted > currvol && adjust > wanted ) wanted => adjust;
           if ( wanted < currvol && adjust < wanted ) wanted => adjust;
           adjust=>currvol;
           adjust=>g.gain;
       }
       // set some reasonable values for this object.  Normally we would do this in a constructor. (where
       // are the constructors?  I must have missed something...
       //
       public void  setChord ( int tonicValue, int twoValue, int thirdValue,string n) {
           n => myName;
           setBand (tonic, .80, tonicValue);
           setBand (two, .85, twoValue);
           setBand (third, .9, thirdValue);
           0 => wantedvol;
           0 => currvol;
           0=> g.gain;
       }
       //ramp the volume on this object incrementally till we hit the wanted volume
       public void rampgain ( ) {
           float adjust;
           while ( 1 ) {
               175::ms => now;
               if ( currvol > wantedvol ) {
                   gainTo(-.2, wantedvol);
               }
               if ( currvol < wantedvol ) {
                   gainTo(.1, wantedvol);
               }
               //	<<<myName, currvol,wantedvol>>>;
           }
       }
   }
   //  a function for "syntactic cod-liver-oil" since we can't spork c.rampgain directly
   fun void runChord (Chord c) {
       c.rampgain();
   }
   //set up the I, IV and V chords and start them sounding at amplitude zero
   Chord I;
   I.setChord ( 1,3,5,"I");
   spork ~ runChord(I);
   Chord IV;
   IV.setChord ( 4,6,1,"IV");
   spork ~ runChord(IV);
   Chord V;
   V.setChord ( 5,7,2,"V");
   spork ~ runChord(V);
   //since machines like to use numbers to access the chords, rather than names like I,IV,V
   //we put the chord object (references) into an array
   [I,IV,V] @=> Chord @ s[ ] ;
   //changeto will bring up the volume on one of the chords and leave it like for a specified duration
   fun void changeto (float amplitude,int index,dur t )
   {
       for ( 0 =>int i; i <3 ; i++ ) {
           0 => float v;
           if (i == index ) amplitude => v;
           v=> s [i].wantedvol;
       }
       t => now ;
   }
   //select a chord at random, bring it up to a random level and hold for some reasonable time
   while (1) {
       changeto (std.rand2f(.5,.9),  std.rand2(0,2), std.rand2f(1.5,4)::second );
   }