Reading
and modifying .jm files
jMusic has the ability to save scores in its own file format, by convention
written with the suffix '.jm'.
This format may not seem very useful, but in this tutorial we'll see how
to read in an existing jm file then make further changes to it.
A jm file keeps all jMusic data attributes ( a MIDI file does not) such
as the phrase structure, difference between rhythmic value and duration,
and so on. . . The reading of jm files also means than a composition can
use existing material from one section for further development in another
section.
There are three files in this tutorial. The first one generates a jm
score and saves it to disk.
The second reads back that file, modifies it, and resaves it to disk as
a second jm file.
The third file writes and reads each of the score, a part, and a phrase,
within the one file as an exercise.
Click here to view source of
JmGenerate.java
Click here to view source of JmMod.java
Click here to view source of JmGenerateTest.java
Lets have a closer look at the important bit only. By now you should
be well versed in the jMusic basics : ).
Write.jm(score, "generate.jm"); |
The generate class simply creates a score of two parts with one phrase each.
Each phrase has randomly distributed notes.
The above line of code above saves the score as a file to disk with the
name 'generate.jm'
The importing of the jm.util package is necessary to use the Read and Write
classes.
import jm.JMC; import jm.music.data.*; import jm.midi.*; import jm.music.tools.*; import jm.util.*;
public final class JmMod implements JMC{ public static void main(String[] args){ Score score = new Score("JMDemo - Modify a jm file"); Part inst = new Part("Flute", FLUTE, 0); Part inst2 = new Part("Piano", PIANO, 1); Phrase phr = new Phrase(0.0); Phrase phr2 = new Phrase(0.0); / Read.jm(score, "generate.jm"); / inst = score.getPart(0); inst2 = score.getPart(1); phr = inst.getPhrase(0); phr2 = inst2.getPhrase(0); / / phr2.setStartTime(phr.getEndTime()); / View.show(score); Write.jm(score, "generateMod.jm"); Write.midi(score, "generateMod.mid"); } } |
This code fragment is from the JmMod.java file. The first line reads in
the jm file created by the previous class. It then accesses the parts and
phrases within it using the getPart() and getPhrase() methods. These methods
take a number as an argument which is the nth element of that type.
The final line makes a modification to the
second phrase by changing its start time. It gets the length of the first
phrase and uses that as its start time. Thereby making the two phrases
follow one after the other in time.
import jm.JMC; import jm.music.data.*; import jm.midi.*; import jm.music.tools.*; import jm.util.*;
public final class JmGenerateTest implements JMC{ public static void main(String[] args){ Score score = new Score("JMDemo - jm Generate test"); Part part1 = new Part("part 1", 1, 0); Part part2 = new Part("part 2", 1, 1); Phrase phr = new Phrase(0.0); Phrase phr2 = new Phrase(0.0); double beat = Math.random() * 1.0; phr = note_density(beat); beat = Math.random() * 1.0; phr2 = note_density(beat); part1.addPhrase(phr); part2.addPhrase(phr2); score.addPart(part1); score.addPart(part2); / View.show(score);
/ Write.midi(score, "generateTest.mid"); Write.jm(score, "generateTest.jm"); Write.jm(part1, "generateTest.prt"); / Write.jm(phr, "generateTest.phr"); Score scoreCopy = new Score(); Read.jm(scoreCopy, "generateTest.jm"); scoreCopy.setTitle("Score Copy"); View.show(scoreCopy, 10, 10); part1.empty(); Read.jm(part1, "generateTest.prt"); View.show(part1, 20, 20); phr.empty(); Read.jm(phr, "generateTest.phr"); View.show(phr, 40, 40);
System.out.println("Done!"); }
private static Phrase note_density(double beat) { Phrase phrase = new Phrase(); int cnt; int dyn = 100; long dur = 350; int pitch; cnt = (int)(Math.random() * 100); System.out.println(cnt); for(short i=0;i<cnt;i++){ pitch = (int)(Math.random() * 127); Note note = new Note(pitch, beat, dyn, dur); phrase.addNote(note); } return phrase; } } |
This code fragment is from the third class of this example, the JmGenerateTest.java
class.
After generating the score in the same way as above, this class writes the
score, the first part, and the first phrase to disk.
Following this a new score object is declared and the jm file read into
it.
The part and phrase objects previously used are emptied in turn and the
appropriate files read into them.
Each of the old and new scores, part, and phrase is displayed in a pseudo
notation window so you can compare the outputs and see the results.
|