[Note: this section of the manual pertains to the recent Beta Release of Minim and not to the version currently being distributed with Processing.]
Instruments
Up until now, we’ve basically discussed ways in which one can make sound continuously. When we add in the notion of an Instrument, we can then start to play notes which have a beginning and an end.
If you don’t already know object-oriented progamming, this paragraph is for you. If you do, then you can probably skip to the next. When one writes an instrument in Minim, one makes an Instrument Class. In Processing, this is stored in another tab of the sketch. A class is an encapsulation of data and functions that act on that data. Every class must have a constructor, so that Processing knows what to do when the program says to make me a new instrument.
Here’s an example instrument, modified a bit from our oscilExample.
[snip java]
class ToneInstrument implements Instrument
{
Oscil sineOsc;
Multiplier multiplyGate;
AudioOutput out;
ToneInstrument( float frequency, float amplitude, AudioOutput output )
{
sineOsc = new Oscil( frequency, amplitude );
multiplyGate = new Multiplier( 0 );
sineOsc.patch( multiplyGate ).patch( output );
}
void noteOn( float dur )
{
multiplyGate.setValue( 1.0 );
}
void noteOff()
{
multiplyGate.setValue( 0.0 );
}
}
[/snip]
Note On and Note Off
The thing that makes an Instrument a special class in Minim, is that it must have a noteOn and a noteOff method. These are called by an unseen note manager which is part of the Minim object that must be a part of every sketch that uses Minim. The noteOn method contains those statements which execute when the note starts, and the noteOff method contains statements which are executed when the note stops. noteOn is always passed a float which is the duration of the note in seconds. In order to enforce that noteOn and noteOff are in every instrument, your instrument must “implements Instrument” as seen in the last example.
Calling the Instrument
An instrument isn’t worth anything unless you play it with something. Here’s a simplified version of the main sketch tab in oscilExample.
[snip java]
import ddf.minim.*;
import ddf.minim.ugens.*;
Minim minim;
AudioOutput out;
void setup()
{
size( 512, 200, P2D );
minim = new Minim( this );
out = minim.getLineOut( Minim.MONO, 2048 );
ToneInstrument myNote = new ToneInstrument( 587.3f, 0.9, out );
out.playNote( 0.5, 2.6, myNote );
myNote = new ToneInstrument( 415.3f, 0.9, out );
out.playNote( 3.5, 2.6, myNote );
}
void draw()
{
background( 0 );
}
[/snip]
This will create two notes using the ToneInstrument in the first example of this section.
It turns out that because we don’t really need to do anything in this instance with the ToneInstrument references, we can actually just turn the last four lines of the setup() method into
[snip java]
out.playNote( 0.5, 2.6, new ToneInstrument( 587.3f, 0.9, out ) );
out.playNote( 3.5, 2.6, new ToneInstrument( 415.3f, 0.9, out ) );
[/snip]
which makes things a little easier to read.
Unpatching
Our computers are not all powerful. This means that we must deal with the real-world limitations of CPU powers. In order to minimize CPU usage, you can patch to the output in noteOn and unpatch from the output in noteOff. This prevents output from ever asking for sampleframes while the note isn’t making any sound. This would make the first example of this section look like this.
[snip java]
class ToneInstrument implements Instrument
{
Oscil sineOsc;
Multiplier multiplyGate;
AudioOutput out;
ToneInstrument( float frequency, float amplitude, AudioOutput output )
{
sineOsc = new Oscil( frequency, amplitude );
multiplyGate = new Multiplier( 0 );
sineOsc.patch( multiplyGate );
}
void noteOn( float dur )
{
multiplyGate.setValue( 1.0 );
multiplyGate.patch( out );
}
void noteOff()
{
multiplyGate.setValue( 0.0 );
multiplyGate.unpatch( out );
}
}
[/snip]
Examples to Look At
oscilExample
noiseExample
UGen Methods
As you can see in the last example, the methods of some of the UGens are used in the noteOn and noteOff methods of instruments. In the last example you can see the setValue( float ) method of Multiplier being used. There are many examples of these methods being used in our examples. Take a look at the methods available on the UGens in http://code.compartmental.net/minim-beta/javadoc/ddf/minim/ugens/package-summary.html.
Envelopes
Having noteOn and noteOff methods for an Instrument also allows the use of envelopes to change the sound of notes throughout their duration. Most of the envelope UGens require an activate() or noteOn() method call in the Instrument’s noteOn() method. Some of the envelope UGens, like the ADSR Ugen, for example, require a noteOff() method call in the instrument’s noteOff() method, to know when to start the release phase of the envelope.
Examples to Look At
ADSRExample
dampExample
lineExample