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