Differences in JFugue 5.0

Things to Know when Migrating from JFugue 4.x

Motivation: Why JFugue 5.0 is Different

JFugue 5.0 is a from-scratch revision of JFugue. One day, after JFugue had been around for over 10 years, I thought, "What would JFugue look like if I created it today?" given everything I had learned in the past decade about developing clean and maintainable code, music theory, and people's experiences with JFugue. Within one weekend, I had the foundation of the new JFugue in place. I literally started with File > New Class and started writing all-new code, referring back to the JFugue 4.0.3 code on very few occasions.

The "Intervals" class was the first class I created, giving JFugue a new foundation on music theory. Then came "Note" and "Chord", and soon, "ChordProgression". I created an entirely new mechanism for parsing the music strings, and I believe the music strings themselves are really a general music specification which I now call "Staccato" (for which JFugue is the reference implementation). The focus of Staccato is on writing and reading human-readable music code.

Given all of this, JFugue 5.0 is not a drop-in replacement for previous versions of JFugue. When giving version numbers to an API, I believe that it's fair for a change in the major version number can be associated with significant changes to the API.

Without further ado, here are some of the differences you'll find in this version. This article just focuses on differences; you may also be interested in What's New in JFugue 5.0.

The Differences

This section also appears in "The Complete Guide to JFugue"

Many of the original concepts of JFugue persist in JFugue 5 and many classes maintain the same names (e.g., Player, Pattern, ParserListener, Note, Rhythm), but the methods of these classes are different, and the classes have been reorganized into a new package structure. If you are using an integrated development environment (IDE) such as Eclipse or NetBeans, simply "organizing imports" in your existing code should resolve the correct package names for the basic classes like Player and Pattern.

Some classes from previous versions of JFugue has been renamed in this version; for example, the former DeviceThatWillReceiveMidi is now simply MidiReceiver. Expect same-named classes, like Note and Rhythm, to have substantial differences in the methods they provide. There is also a lot of new and exciting functionality in JFugue 5, particularly around music theory, so please explore this guide and the API documentation to learn more!

Terminology Change: From JFugue MusicString to Staccato. What had been called the JFugue MusicString in the past is now gaining its own traction and has a new name: Staccato. The intention is that, while Staccato had its origin as JFugue's MusicString, it has earned its own wings and is a music format that can be used on projects outside of JFugue. And now, JFugue 5 is a reference implementation for parsing Staccato music.

Adjustment of Octave Range and Default Octaves. In the past, the MusicString allowed octaves in a range from -1 to 9; for example, C-1 would be a C-note in the lowest octave. The octaves have changed: the allowable range is now 0 through 10, meaning that the lowest note in Staccato is C0 and the highest note is G10. This is now consistent with MIDI note numbers.

This has the effect of making music sound an octave higher. If you previously composed a song with C5, you'll notice that C5 in JFugue 5 sounds one octave higher than C5 in JFugue 4. The new version is more consistent with the rest of the musical world; in particular, it ensures that A5, the A about Middle-C is the same as 440Hz, which is verified by this simple program (also in the code as A440Test.java):

player.play("A5 m440"); // Make sure that A5 sounds like 440Hz

Eliminating the -1 octave also removes a parsing ambiguity when determining whether a note was in the -1 octave (e.g., C-1) or was the end of a tie (e.g., C-w).

The default octave - which allows one to say C and assume they would hear Middle-C - is 5. The default octave for a chord, such as Cmaj, had been 3 in past versions of JFugue but is now 4, since that is the typical octave for notes in the bass clef (just below Middle-C).

Despite the changes you may have to make to your MusicStrings (now Staccato strings), hopefully your headache will be eased with the understanding that the new octave settings are more correct than the previous ones.

Elimination of Brackets around Note Numbers. If you have programmed music using note numbers, such as [74]w, please remove the brackets from the note numbers, giving 74w. Brackets should be used in cases where the contents of the brackets is a string representation of a value that needs to be looked up (e.g., I[Piano], T[Allegro]). This includes percussive instruments in the 10th MIDI channel, so if you have V9 [Bass_Drum]w, that is a legitimate use of the bracket notation and those brackets must remain.

Change in Expressing MIDI Commands in Music Strings. In previous versions of JFugue, MIDI commands such as Pitch Wheel or Controller Events were specified by starting a token with a special character, such as & or ^. Those characters were hard to remember and did not provide for readability of the music string; in addition, there are only so many special characters that one may type, so they self-limited the number of "meta-musical expressions" (instructions about the music) that could be specified in a Music String. In JFugue 5, MIDI commands are invoked through the Function system. JFugue 5's Functions allow an end-user to name a function that accepts a set of parameters in parentheses. JFugue pre-defines functions for Pitch Wheel, Controller Events, and other MIDI functionality. Now, these look like :PitchWheel(x,y) or :PW(x,y), or :Controller(x,y) or :CON(x,y). The MIDI commands are still interpreted by the Parser and come through a ParserListener in specific methods, such as onPitchWheelParsed and onControllerEventParsed.

Elimination of Music Classes that Wrapped Basic Values. Previous versions of JFugue had classed like Instrument and Tempo that did little more than wrap a value representing an instrument or a tempo. Many of these classes do not exist in JFugue 5; it is sufficient to share information about an instrument by simply passing along a byte value representing an instrument, since the Instrument class provided little else. This also impacts the methods in ParserListener, as you will see in the next section. For constants representing instrument names (e.g, PIANO = 0), see MidiDictionary.

More and Different Methods in ParserListener. ParserListener is probably the most commonly-used interface in JFugue. In JFugue 5, the methods in ParserListener are significantly different from previous versions. First, most of the methods start with the word 'on' (e.g., onTempoChanged, onNoteParsed). Parameters for methods like onInstrumentParsed on onControllerEventParsed are now the byte values representing the changed or parsed values rather than classes that wrap these values, as discussed in the previous section. New methods have been added to support new functionality (e.g., onLyricParsed, onMarkerParsed). Two new workflow methods, beforeParsingStarts and afterParsingFinished, let your implementation of a ParserListener know when to do important set-up and tear-down activities.