Previous Next Package
Introduction to MIDICompose
Rootclass MIDIObject
We have got to know a lot of classes now:
'MIDIFile',
'MIDIContainer',
'Note',
'Rest',
'Ghost',
'ProgramChange' and
'GMSystem'.
All this classes have one thing in common. They are all subclasses of
'MIDIObject'. MIDIObject is the Rootclass of all
the other classes. So if we want to create our own MIDI-class, we have to make it a
subclass of MIDIObject. In this lesson we will create a new MIDIObject called
'TremoloNote'. At first we define tremoloNote a subclass of MIDIObject.
MyCompose.java (Version 11)
TremoloNote will be used the same way as 'Note' but it
will sound a little bit different. It will not play only the pitch it is set to, but also
the note with a pitch that is one octave higher. These two notes will not be played
together but one after the other (tremolo). TremoloNote will play the lower note for one
sixteenth and then the higher one for one sixteenth, and then the lower one, and then the
higher, the lower, ... We start defining a constructor. Our constructor will be similar to
that of 'Note'. A TremoloNote will be created by writing 'new TremoloNote(int length, int
pitch)'. But we will also offer a second constructor that will work this way: 'new
TremoloNote(int lenght, int pitch, int tremoloLength)'.
MyCompose.java (Version 12)
The constructor of 'MIDIObject' is called by
writing 'super(int deltaTime)'. Every MIDIObject has a deltaTime which can be read and set
by methods (deltaTime(), setDeltaTime(int)). deltaTime is not an absolute timestamp but a
relative one (eg. all notes in melody have different deltaTimes in melody. And melody has
a deltaTime in midi. If we append melody to midi at position WHOLE * 4, the deltaTime of
the notes doesn't change. Only the deltaTime of the copy of melody is set to WHOLE * 4).
Now we will create TremoloNote by appending 'Note's.
But we can't use the method 'append' because TremoloNote is not a 'MIDIContainer'. We will
use 'add(MIDIObject object)', a method that all MIDIObjects can use. After the last 'Note'
is added we will lock TremoloNote. If a MIDIObject is locked, no more adds can be done.
MyCompose.java (Version 13)
The last version was not compileable, because MIDIObject has an abstract method, that we
have to overwrite. The method is called 'copy()' and returns a 'MIDIObject' that is
equal to itself, but only exists of copies of its elements. We can create such a copy, by
creating a new equal TremoloNote and return it. For testing, we only append melody to
midi.
MyCompose.java (Version 14)
Sounds wrong! The TremoloNotes are interrupted by the following notes. To avoid this we
must declare TremoloNote to be a MIDIObject that has a length! We can do this by
implementing the interface 'Lengthable'. This
requires to write some methods. Most important is 'length()' that returns the lenght of
itself. 'turnRound()' will do nothing (how should a note be turned round?). To implement
the method 'setLenght(int length)' we need to shorten all notes and set their deltaTimes.
MyCompose.java (Version 15)
If we try to run 'MyCompose.java' with the turnedRound melody on channel two, we will only
hear TremoloNotes on channel one. We can change this by making TremoloNotes channelable.
We simply implement the interface 'Channelable'
and write the methods 'channel()' that returns the current channel and 'setChannel(int
channel)' that sets the channel. After we have done this, our MIDIObject 'TremoloNote' is
done, and we can use it like all the other MIDIObjects.
MyCompose.java (Version 16)
An easier way to create 'TremoloNote' is to make it a subclass of
'MIDIContainer'. We don't have to implement
any methods of 'Lengthable' or 'Channelable', because 'MIDIContainer' has implemented it
already. We can use 'append(MIDIObject)' instead of 'add(MIDIObject)', so we don't need
to set any deltaTimes. We don't even have to implement 'copy()', but we better do so,
because we want 'copy()' to return a 'TremoloNote' instead of a 'MIDIContainer'. A
'MIDIContainer' is usually able to 'turnRound()'. But if we set its type to LINKED, this
method will have no effect.
MyCompose.java (Version 17)
If you want to build more Objects, you should know the differences between 'MIDIObject'
and 'MIDIContainer'. 'MIDIObject' doesn't support a lot of methods, so only use it if you
want to build very simple or completely new structures. This was lesson three. In the
next lesson we will take a look at the class 'Ramp'.
Previous Next Package