In this guide, we will learn how to create and manipulate chords and chord progressions, how to use
allChordsAs()methods of the
ChordProgression class, and how to play different patterns simultaneously by using voices in JFugue.
This is the second part of the three-part tutorial series, in which we are trying to re-create the intro of the jazz version of Sunday Morning by Maroon 5. But the steps provided in the articles, are easily applicable to any other song creation process as well.
In the previous part of the series, we covered the fundamentals of the JFugue library, learning how to use notes, octaves, durations, tempo, instruments, and patterns. At the end of the first article, we created the intro vocals without any chords. By the end of this tutorial, our song will have the chords ready to play along with the vocals.
In the final part of our tutorial series, we will learn about Rhythms in JFugue. This will allow us to build and play the rhythms on top of the previous parts. We will also take a look at how to save our music to a MIDI file using the JFugue as well as to read music from a MIDI file using the JFugue library.
If you want to check out other parts of the series, here are the links:
- JFugue Beginners Guide Part I: Notes, Durations, Patterns
- JFugue Beginners Guide Part II: Chords and Chord Progressions (here)
- JFugue Beginners Guide Part III: Rhythms, Reading and Writing to MIDI
Chords and Chord Progressions in JFugue
When it comes to chords, JFugue offers multiple ways to create them. First, let's take a look at how to create our very own chords by combining the notes one by one.
We will create the D-Minor7 chord, which also happens to be the first chord of our song. This chord consists of four (4) notes that we can combine and play simultaneously:
That works well for now but it can become a very tedious job to create every single chord note by note. In this song, we have three (3) chords (Dm, G, C) with 3 (DMin9, GMaj13, CMaj9) inversions.
We don't necessarily have to create all chords manually. You can create your chords using
ChordProgression if you're familiar with music theory. To do so, we'll import and instantiate the
ChordProgression class with the chord progressions of our chords:
import org.jfugue.theory.ChordProgression; ChordProgression cp = new ChordProgression("ii V I");
We can also set the key of the chord progression by chaining
setKey() method to it:
ChordProgression cp = new ChordProgression("ii V I") .setKey("C");
We can play chord progressions just as same we did with patterns:
PatternProducer, which, as the name suggests, produces patterns. And when we pass
ChordProgression into the
Player.play() method, the method asks for the pattern from
ChordProgression and plays it just as same it does with the patterns.
Another effective method of the
distribute(). This method allows us to distribute a musical feature along with the chords inside of a
At the moment our chords in
cp are Dm, G, and C.
Let's change all chords to 7th using
ChordProgression cp = new ChordProgression("ii V I") .setKey("C") .distribute("7"); player.play(cp);
Another essential change would be to set the duration of each chord and to add some 'Rest' in between the chords. Using
allChordsAs() method, we can select each chord in
cp by typing
$ with an index number of the chord:
ChordProgression cp = new ChordProgression("ii V I") .setKey("C") .distribute("7") .allChordsAs("$0hqit Ri $1hqi Ri $2wh Rht");
We can think of
$2 as placeholders that refer to the
I respectively. Any modifications that we apply to them are applied to the chords in
cp. Go ahead and play to see the difference.
Free eBook: Git Essentials
Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!
Another cool thing about
ChordProgression is that we can easily convert it to the
Pattern and use Pattern specific methods to modify it even further:
Pattern cpPattern = cp.getPattern(); System.out.print(cpPattern); player.play(cpPattern.setTempo(180).setInstrument("DRAWBAR_ORGAN").repeat(4));
getPattern() method, we convert the
cp to a
Pattern instance, then we print the current chords in the
cp so that we can see the chords being filled in. Finally, we set the tempo, the instrument, and the repeat value.
The chords that JFugue plays look like:
D4MIN7hqit Ri G4MAJ7hqi Ri C4MAJ7wh Rht
ChordProgression provides a range of possibilities, but as mentioned before, it requires some knowledge of musical theory. If don't know much about music theory but have basic knowledge of chords, then you can conveniently use chords inside the patterns.
To get the full potential of the Staccato, which is proud to be human-readable, we will write our chords directly into the pattern:
Pattern mainChords = new Pattern("T180 D4Min9hqit Ri G4Maj13hqi Ri C4Maj9wh Rht");
D4Min9hqit down. "D" is the name of the chord, followed by the "4" which is the number that represents the octave, followed by "Min9" which stands for "Minor 9th", and followed by "hqit" which are the duration measurements.
We can take advantage of the
Pattern class and add some more chords to the pattern by chaining the
mainChords.add("D4Minhqit Ri 4Majhqi Ri C4Majwh Rht");
Notice that we didn't specify the tempo in the second part of the pattern, since setting the tempo once is enough to apply it for all of the following musical events.
In the real world, not every instrument in a song plays in sequential order. Now that we have our chords playing properly, we would like to add some other patterns to play along with it, not to append directly to it, like we did with
JFugue provides a special token called 'Voice'. Most of the songs are made of layers of patterns. For instance, the piano keeps playing chords while the drumbeat goes on and vocals sing along them. In JFugue, the 'Voice' token represents each of these individual players/singers, allowing them to play together, play at the same time.
We can use up to 16 different voices, which is the sum of the standard MIDI channels. Voice numbers can range from
V15. We can populate voices with any instruments we'd like. Except for the 10th channel or
V9. This special voice layer is reserved for the percussion by default and can have different sets of percussion instruments and layers at V9 (more on that later).
Let's try to recreate the intro of the 'Sunday Morning' (Jazz version) by adding new voices to our current
Pattern mainChords = new Pattern("T180 V0 D4Min9hqit Ri G3Maj13hqi Ri C4Maj9wh Rh"); mainChords.add("D4Minhqit Ri G4Majhqi Ri C4Majwh Rht"); Pattern pianoTouch = new Pattern("T180 V1 Rw | Rw | Rhi | G4qi G3s A3is CMajis ri"); pianoTouch.add("Rw | Rw | Rhi | G4s C5wa100d0"); player.play(mainChords, pianoTouch);
mainChords pattern is the same as it was before. We've added a new pattern
pianoTouch and set it to the second voice channel
V1. Since these notes occurred at the end of each chord loop, we had to hold them using
Rw to play right at the correct time. You may have noticed that the final note of the
pianoTouch pattern has this weird token
a100d0 glued to the whole note of C. That token represents the attack velocity and the decay velocity of the note.
We have set the attack value to 100, making our note sound a bit louder than the others, and have set the decay value to 0, which caused our note volume to decrease to zero very quickly. You can set either of them and none of them on your preference to any value between 0 to 127.
The part that we composed at
pianoTouch plays only once in the original song. So, we want to make sure that while the
mainChords plays on repeat, the
pianoTouch doesn't repeat.
We can create a new pattern
introOnce to group our other patterns. This way we can arrange what to play once and what to play on repeat. Replace the line that calls
play() with these two lines:
Pattern introOnce = new Pattern(mainChords, pianoTouch); player.play(introOnce, mainChords.repeat(2));
This should play the
pianoTouch once, and repeat the
mainChords 2 more times afterward.
Our song is coming along great! Now it's time to help the dancers, we will use the
Rhythm class to guide them in the next part of the series!
In this tutorial, we learned how to use chords and chord progressions in the JFugue library. We also covered
allChordsAs() methods of the
ChordProgression class, how to play different patterns simultaneously by using voices, and how to apply attack/decay properties to notes or chords.
In the next and final part of the article series, we will learn how to create and use the rhythms in JFugue. By doing so, we will be able to finalize our song. We will also cover how to save our song into a MIDI file format using JFugue, as well as how to import a MIDI file and read content into the Staccato format.
You can continue to read the next part: JFugue Beginners Guide Part III: Rhythms, Reading and Writing to MIDI.
Or if you need more details about the fundamentals of JFugue, you can check out the first article to refresh your knowledge: JFugue Beginners Guide Part I: Notes, Durations, Patterns.