JMSL Tutorial: Instruments and Interpreters

MusicJob has a setInstrument() method, so it can maintain a reference to an JMSL Instrument. MusicShape, which is a subclass of MusicJob, is the first subclass to automatically use this Instrument.  When launched. it runs through each of its elements in sequence, handing them one at a time to its Instrument. It calls the Instrument's play() method with this element. The Instrument interprets the data in some way, and returns the time it took to do so (say, a half second if the element were interpreted as a quarter note at 120 bpm). The MusicShape waits for the amount of time returned by Instrument.play(), and proceeds to its next element.

Whether the element is interpreted as a Midi note, a set of synthesis parameters, or RGB colors, is entirely up to the Instrument.

Instrument is an interface.  JMSL provides a convenient InstrumentAdapter class which already implements Instrument. You can extend InstrumentAdapter and override its various method to provide custom behavior.

For example, we could just print the element by declaring our own subclass of InstrumentAdapter and override play() like so:
 

/** A simple Instrument subclass that just prints out the data it is handed, interprets element[0] as duration */
public class PrintingInstrument extends InstrumentAdapter {
    
     /** Overridden for custom interpretation */
     public double play(double playTime, double timeStretch, double dar[])
     {
             JMSL.out.println("Instrument.play() is handed the following array of doubles:");
             JMSL.printDoubleArray(dar);
             JMSL.out.println();
             double duration=dar[0]; // usually interpret dar[0] as duration
             return playTime + duration * timeStretch;  
     }
}
It is your responsibility to return the correctly updated time. Note that the method above interprets the first member of dar[] as duration, It scales duration by multiplying it with timeStretch and adds it to the original playTime. Duration units is in seconds, and timeStretch defaults to 1 so a duration of 1.0 with timeStretch 1 is one second. A timeStretch of 0.5 would play everything twice as fast. Among other things, timeStretch can be used to implement tempo.

Next we will revisit the MusicShape created in an earlier tutorial, and interpret it with the play() method above.


  (C) Phil Burk and Nick Didkovsky, All Rights Reserved
  JMSL is based upon HMSL (C) Phil Burk, Larry Polansky and David Rosenboom.