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.
|