Reading and Reusing MIDI file data

It can be useful to create musical material in other programs (such as sequencers) and bring it into jMusic. This class shows how parts from various MIDI files can be brought together in a jMusic score. This score can then itself be saved as a MIDI file - perhaps to find it's way back to a sequencer of other program.

Here is an example of the output from the class.

Click here to view the source file

Let's have a closer look.

import jm.JMC;
import jm.music.data.*;
import jm.music.tools.*;
import jm.util.*;

/**
* A class which reads in MIDI files and
* extracts aspects of them to create a new score
* @author Andrew Brown
*/

The jm classes are imported. Of particular interest is the jm.util package which contains the Read and Write classes we use for MIDI files.

public final class ReadMIDI implements JMC{
/**
* Main method where all good Java programs start
*/

public static void main(String[] args){
// Make the MIDI files to be read
// Usually you would have made them is a
// sequencer or other MIDI program.

makeFileOne();
makeFileTwo();
makeFileThree();

In order to have some MIDI data to read we first create three MIDI files by calling the MakeFileX methods. These methods are discussed below, but create a one part score and save it as a MIDI file.


             	Score theScore = new Score("Temporary score");
Score newScore = new Score("Combination Score");

// read the MIDI files made earlier as input

Read.midi(theScore, "ScoreOne.mid");

// get the part from it

Part tempPart = theScore.getPart(0);

// add it to the new score

newScore.addPart(tempPart.copy());

theScore.empty();

//do the same for the next MIDI file riff

Read.midi(theScore, "ScoreTwo.mid");
tempPart = theScore.getPart(0);
tempPart.setChannel(1);
// set a different channel
newScore.addPart(tempPart.copy());

theScore.empty();

// similarly for the third MIDI file
Read.midi(theScore, "ScoreThree.mid");
tempPart = theScore.getPart(0);
tempPart.setChannel(2);
Mod.transpose(tempPart, -12);

// make a modification to the data from the MIDI file
newScore.addPart(tempPart.copy());

// show it

View.show(newScore);

//now we can write the new score to a MIDI file

Write.midi(newScore, "ReadMIDI.mid");
}

We create a score to read into and a second score to act as the combined arrangement container. Each MIDI file is read in and the zeroith part extracted from it. To keep the parts separate when we resave the arrangement as a MIDI file each is allocated a different channel. Once the data is read into a score we can manipulate it in any of the familiar jMusic ways. A simple transposition is one example of such a transformation.

The above code is well commented and should be quite clear if you read through it carefully.

	public static void makeFileOne() {
Score score = new Score();
score.addPart(riffMaker(70));
Write.midi(score, "ScoreOne.mid");
}

public static void makeFileTwo() {
Score score = new Score();
score.addPart(riffMaker(50));
Write.midi(score, "ScoreTwo.mid");
}

public static void makeFileThree() {
Score score = new Score();
score.addPart(riffMaker(40));
Write.midi(score, "ScoreThree.mid");
}

public static Part riffMaker(int pitch) {
int tempPitch = pitch;
Part p = new Part("title",(int)(Math.random()*80), 0);
Phrase phr = new Phrase();
for (int i = 0; i < 16; i++) {
Note n = new Note(tempPitch += (int)(Math.random()*8 - 4), SQ);
phr.addNote(n);
}
p.addPhrase(phr);
return p;
}
}
These methods are used to create the original melodies and MIDI files. The riffMaker() method is used by each makeFileX method. The only specified difference between the riffs is the starting pitch - this puts them in different ranges so the combined arrangement allows each to be heard clearly.