JFugue Examples

See what JFugue can do!

Each of the examples below is a complete program that you can copy, paste, and run. Have fun!

"Hello, World" in JFugue

Create music with only a few lines of code!


import org.jfugue.player.Player;

public class HelloWorld {
  public static void main(String[] args) {
    Player player = new Player();
    player.play("C D E F G A B");
  }
}

Playing multiple voices, multiple instruments, rests, chords, and durations

This example uses the Staccato 'V' command for specifing voices, 'I' for specifying instruments (text within brackets is looked up in a dictionary and maps to MIDI instrument numbers), '|' (pipe) for indicating measures (optional), durations including 'q' for quarter duration, 'qqq' for three quarter notes (multiple durations can be listed together), and 'h' for half, 'w' for whole, and '.' for a dotted duration; 'R' for rest, and the chords G-Major and C-Major. Whitespace is not significant and can be used for visually pleasing or helpful spacing.


import org.jfugue.player.Player;

public class HelloWorld2 {
  public static void main(String[] args) {
    Player player = new Player();
    player.play("V0 I[Piano] Eq Ch. | Eq Ch. | Dq Eq Dq Cq   V1 I[Flute] Rw | Rw | GmajQQQ CmajQ");
  }
}

Introduction to Patterns

Patterns are one of the fundamental units of music in JFugue. They can be manipulated in musically interesting ways.


import org.jfugue.pattern.Pattern;
import org.jfugue.player.Player;

public class IntroToPatterns {
  public static void main(String[] args) {
    Pattern p1 = new Pattern("V0 I[Piano] Eq Ch. | Eq Ch. | Dq Eq Dq Cq");
    Pattern p2 = new Pattern("V1 I[Flute] Rw     | Rw     | GmajQQQ  CmajQ");
    Player player = new Player();
    player.play(p1, p2);
  }
}

Introduction to Patterns, Part 2

Voice and instruments for a pattern can also be set through the API. In JFugue, methods that would normally return 'void' instead return the object itself, which allows you do chain commands together, as seen in this example.


import org.jfugue.pattern.Pattern;
import org.jfugue.player.Player;

public class IntroToPatterns2 {
  public static void main(String[] args) {
    Pattern p1 = new Pattern("Eq Ch. | Eq Ch. | Dq Eq Dq Cq").setVoice(0).setInstrument("Piano");
    Pattern p2 = new Pattern("Rw     | Rw     | GmajQQQ  CmajQ").setVoice(1).setInstrument("Flute");
    Player player = new Player();
    player.play(p1, p2);
  }
}

Introduction to Chord Progressions

It's easy to create a Chord Progression in JFugue. You can then play it, or you can see the notes that comprise the any of the chords in the progression.


import org.jfugue.player.Player;
import org.jfugue.theory.Chord;
import org.jfugue.theory.ChordProgression;
import org.jfugue.theory.Note;

public class IntroToChordProgressions {
  public static void main(String[] args) {
    ChordProgression cp = new ChordProgression("I IV V");

    Chord[] chords = cp.setKey("C").getChords();
    for (Chord chord : chords) {
      System.out.print("Chord "+chord+" has these notes: ");
      Note[] notes = chord.getNotes();
      for (Note note : notes) {
        System.out.print(note+" ");
      }
      System.out.println();
    }

    Player player = new Player();
    player.play(cp);
  }
}

Advanced Chord Progressions

You can do some pretty cool things with chord progressions. The methods below use $ to indicate an index into either the chord progression (in which case, the index points to the nth chord), or a specific chord (in which case the index points to the nth note of the chord). Underscore means "the whole thing". If you change the indexes, make sure you don't introduce an ArrayOutOfBoundsException (for example, a major chord has only three notes, so trying to get the 4th index, $3 (remember that this is zero-based), would cause an error).


import org.jfugue.player.Player;
import org.jfugue.theory.ChordProgression;

public class AdvancedChordProgressions {
  public static void main(String[] args) {
    ChordProgression cp = new ChordProgression("I IV V");

    Player player = new Player();
    player.play(cp.eachChordAs("$0q $1q $2q Rq"));

    player.play(cp.allChordsAs("$0q $0q $0q $0q $1q $1q $2q $0q"));

    player.play(cp.allChordsAs("$0 $0 $0 $0 $1 $1 $2 $0").eachChordAs("V0 $0s $1s $2s Rs V1 $_q"));
  }
}

Twelve-Bar Blues in Two Lines of Code

Twelve-bar blues uses a I-IV-V chord progression. But really, it's the Major 7ths that you'd like to hear... and if you want to play each chord in arpeggio, you need a 6th in there as well. But creating a I7%6-IV7%6-V7%6 chord progression is messy. So, this code creates a I-IV-V progression, then distributes a 7%6 across each chord, then creates the twelve bars, and then each chord is played as an arpeggio with note dynamics (note on velocity - how hard you hit the note). Finally, the pattern is played with an Acoustic_Bass instrument at 110 BPM. With all of the method chaining, that is kinda done in one line of code.


import org.jfugue.pattern.Pattern;
import org.jfugue.player.Player;
import org.jfugue.theory.ChordProgression;

public class TwelveBarBlues {
    public static void main(String[] args) throws IOException {
        Pattern pattern = new ChordProgression("I IV V")
                .distribute("7%6")
                .allChordsAs("$0 $0 $0 $0 $1 $1 $0 $0 $2 $1 $0 $0")
                .eachChordAs("$0ia100 $1ia80 $2ia80 $3ia80 $4ia100 $3ia80 $2ia80 $1ia80")
                .getPattern()
                .setInstrument("Acoustic_Bass")
                .setTempo(100);
        new Player().play(pattern);
    }
}

Introduction to Rhythms

One of my favorite parts of the JFugue API is the ability to create rhythms in a fun and easily understandable way. The letters are mapped to percussive instrument sounds, like "Acoustic Snare" and "Closed Hi Hat". JFugue comes with a default "rhythm set", which is a Map<Character, String> with entries like this: put('O', "[BASS_DRUM]i").


import org.jfugue.player.Player;
import org.jfugue.rhythm.Rhythm;

public class IntroToRhythms {
    public static void main(String[] args) {
        Rhythm rhythm = new Rhythm()
        .addLayer("O..oO...O..oOO..")
        .addLayer("..S...S...S...S.")
        .addLayer("````````````````")
        .addLayer("...............+");
    new Player().play(rhythm.getPattern().repeat(2));
    }
}

Advanced Rhythms

Through the Rhythm API, you can specify a variety of alternate layers that occur once or recur regularly. You can even create your own "RhythmAltLayerProvider" if you'd like to create a new behavior that does not already exist in the Rhythm API.


import org.jfugue.player.Player;
import org.jfugue.rhythm.Rhythm;

public class AdvancedRhythms {
    public static void main(String[] args) {
        Rhythm rhythm = new Rhythm()
          .addLayer("O..oO...O..oOO..") // This is Layer 0
          .addLayer("..S...S...S...S.")
          .addLayer("````````````````")
          .addLayer("...............+") // This is Layer 3
          .addOneTimeAltLayer(3, 3, "...+...+...+...+") // Replace Layer 3 with this string on the 4th (count from 0) measure
          .setLength(4); // Set the length of the rhythm to 4 measures
        new Player().play(rhythm.getPattern().repeat(2)); // Play 2 instances of the 4-measure-long rhythm
    }
}

All That, in One Line of Code?

Try this. The main line of code even fits within the 140-character limit of a tweet.


import org.jfugue.player.Player;
import org.jfugue.rhythm.Rhythm;
import org.jfugue.theory.ChordProgression;

public class TryThis {
    public static void main(String[] args) {
        new Player().play(new ChordProgression("I IV vi V").eachChordAs("$_i $_i Ri $_i"), new Rhythm().addLayer("..X...X...X...XO"));
    }
}

See the Contents of a MIDI File in Human-Readable and Machine-Parseable Staccato Format

Want to see the music in your MIDI file? Of course, you could load it in a sheet music tool. Here's how you can load it with JFugue. You'll get a Pattern of your music, which you can then pick apart in interesting ways (for example, count how many "C" notes there are... that's coming up in a few examples)


import java.io.File;
import java.io.IOException;
import javax.sound.midi.InvalidMidiDataException;
import org.jfugue.midi.MidiFileManager;

public class SeeMidi {
    public static void main(String[] args) throws IOException, InvalidMidiDataException {
        Pattern pattern = MidiFileManager.loadPatternFromMidi(new File(PUT YOUR MIDI FILENAME HERE));
        System.out.println(pattern);
    }
}

Connecting Any Parser to Any ParserListener

You can use JFugue to convert between music formats. Most commonly, JFugue is used to turn Staccato music into MIDI sound. Alternatively, you can play with the MIDI, MusicXML, and LilyPond parsers and listeners. Or, you can easily create your own parser or listener, and it will instantly interoperate with the other existing formats. (And if you convert to Staccato, you can then play the Staccato music... and edit it!)


import java.io.File;
import java.io.IOException;

import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiSystem;

import org.jfugue.midi.MidiParser;
import org.jfugue.pattern.Pattern;
import org.jfugue.player.Player;
import org.staccato.StaccatoParserListener;

public class ParserDemo {
    public static void main(String[] args) throws InvalidMidiDataException, IOException {
        MidiParser parser = new MidiParser();
        StaccatoParserListener listener = new StaccatoParserListener();
        parser.addParserListener(listener);
        parser.parse(MidiSystem.getSequence(new File(PUT A MIDI FILE HERE)));
        Pattern staccatoPattern = listener.getPattern();
        System.out.println(staccatoPattern);

        Player player = new Player();
        player.play(staccatoPattern);
    }
}

Create a Listener to Find Out About Music

You can create a ParserListener to listen for any musical event that any parser is parsing. Here, we'll create a simple tool that counts how many "C" notes (of any octave) are played in any song.


import java.io.File;
import java.io.IOException;

import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiSystem;

import org.jfugue.midi.MidiParser;
import org.jfugue.parser.ParserListenerAdapter;
import org.jfugue.theory.Note;

public class ParserDemo {
    public static void main(String[] args) throws InvalidMidiDataException, IOException {
        MidiParser parser = new MidiParser(); // Remember, you can use any Parser!
        MyParserListener listener = new MyParserListener();
        parser.addParserListener(listener);
        parser.parse(MidiSystem.getSequence(new File(PUT A MIDI FILE HERE)));
        System.out.println("There are " + listener.counter + " 'C' notes in this music.");
    }
}

class MyParserListener extends ParserListenerAdapter {
    public int counter;

    @Override
    public void onNoteParsed(Note note) {
        // A "C" note is in the 0th position of an octave
        if (note.getPositionInOctave() == 0) {
            counter++;
        }
    }
}

Play Music in Realtime

Create interactive musical programs using the RealtimePlayer.


import java.util.Scanner;

import javax.sound.midi.MidiUnavailableException;

import org.jfugue.pattern.Pattern;
import org.jfugue.realtime.RealtimePlayer;
import org.jfugue.theory.Note;

public class RealtimeExample {
    public static void main(String[] args) throws MidiUnavailableException {
        RealtimePlayer player = new RealtimePlayer();
        Random random = new Random();
        Scanner scanner = new Scanner(System.in);
        boolean quit = false;
        while (quit == false) {
            System.out.print("Enter a '+C' to start a note, "+
              "'-C' to stop a note, 'i' for a random instrument, " +
              "'p' for a pattern, or 'q' to quit: ");
            String entry = scanner.next();
            if (entry.startsWith("+")) {
               player.startNote(new Note(entry.substring(1)));
            }
            else if (entry.startsWith("-")) {
                player.stopNote(new Note(entry.substring(1)));
            }
            else if (entry.equalsIgnoreCase("i")) {
                player.changeInstrument(random.nextInt(128));
            }
            else if (entry.equalsIgnoreCase("p")) {
                player.play(PATTERNS[random.nextInt(PATTERNS.length)]);
            }
            else if (entry.equalsIgnoreCase("q")) {
                quit = true;
            }
        }
        scanner.close();
        player.close();
    }

    private static Pattern[] PATTERNS = new Pattern[] {
            new Pattern("Cmajq Dmajq Emajq"),
            new Pattern("V0 Ei Gi Di Ci  V1 Gi Ci Fi Ei"),
            new Pattern("V0 Cmajq V1 Gmajq")
    };
}

Anticipate Musical Events Before They Occur

You might imagine creating new types of ParserListeners, like an AnimationParserListener, that depend on knowing about the musical events before they happen. For example, perhaps your animation is of a robot playing a drum or strumming a guitar. Before the note makes a sound, the animation needs to get its virtual hands in the right place, so you might want a notice 500ms earlier that a musical event is about to happen. To bend time with JFugue, use a combination of the TemporalPLP class and Player.delayPlay(). delayPlay() creates a new thread that first waits the specified amount of time before playing. If you do this, make sure to call delayPlay() before plp.parse().


import org.jfugue.player.Player;
import org.jfugue.temporal.TemporalPLP;
import org.staccato.StaccatoParser;

public class TemporalExample {
    private static final String MUSIC = "C D E F G A B";
    private static final long TEMPORAL_DELAY = 500;

    public static void main(String[] args) {
        // Part 1. Parse the original music
        StaccatoParser parser = new StaccatoParser();
        TemporalPLP plp = new TemporalPLP();
        parser.addParserListener(plp);
        parser.parse(MUSIC);

        // Part 2. Send the events from Part 1, and play the original music with a delay
        DiagnosticParserListener dpl = new DiagnosticParserListener(); // Or your AnimationParserListener!
        plp.addParserListener(dpl);
        new Player().delayPlay(TEMPORAL_DELAY, MUSIC);
        plp.parse();
    }
}

Use "Replacement Maps" to Create Carnatic Music

JFugue's ReplacementMap capability lets you use your own symbols in a music string. JFugue comes with a CarnaticReplacementMap that maps Carnatic notes to microtone frequencies.


import org.jfugue.player.Player;
import org.staccato.maps.CarnaticReplacementMap;

public class CarnaticReplacementMapDemo {
  public static void main(String[] args) {
    ReplacementMapPreprocessor.getInstance().setReplacementMap(new CarnaticReplacementMap());

    Player player = new Player();
    player.play("<S> <R1> <R2> <R3> <R4>");
  }
}

Use "Replacement Maps" to Play Solfege

JFugue comes with a SolfegeReplacementMap, which means you can program music using "Do Re Me Fa So La Ti Do." The ReplacementMapParser converts those solfege tones to C D E F G A B. Using Replacement Maps, which are simply Map<String, String>, you can create any kind of music in a pattern that will be converted to musical notes (or whatever you put in the values of your Map).


import org.jfugue.pattern.Pattern;
import org.jfugue.player.Player;
import org.staccato.ReplacementMapPreprocessor;

public class SolfegeReplacementMapDemo {
	public static void main(String[] args) {
		ReplacementMapPreprocessor rmp = ReplacementMapPreprocessor.getInstance();
		rmp.setReplacementMap(new SolfegeReplacementMap()).setRequireAngleBrackets(false);
		Player player = new Player();
		player.play(new Pattern("do re mi fa so la ti do")); // This will play "C D E F G A B"

		// This next example brings back the brackets so durations can be added
		rmp.setRequireAngleBrackets(true);
		player.play(new Pattern("<Do>q <Re>q <Mi>h | <Mi>q <Fa>q <So>h | <So>q <Fa>q <Mi>h | <Mi>q <Re>q <Do>h"));
	}
}

Use "Replacement Maps" to Generate Fractal Music

A Lindenmayer system is a string rewriting system that can be used to create fractal shapes. You can use JFugue's ReplacementMap capability to create music based on string rewrite rules! (File this one under, "I didn't intentionally create a fractal music tool, it just kinda happened. Oops.")


import org.jfugue.pattern.Pattern;
import org.jfugue.player.Player;

public class LSystemMusic {
  public static void main(String[] args) {

    // Specify the transformation rules for this Lindenmayer system
    Map rules = new HashMap() {{
          put("Cmajw", "Cmajw Fmajw");
          put("Fmajw", "Rw Bbmajw");
          put("Bbmajw", "Rw Fmajw");
          put("C5q", "C5q G5q E6q C6q");
          put("E6q", "G6q D6q F6i C6i D6q");
          put("G6i+D6i", "Rq Rq G6i+D6i G6i+D6i Rq");
          put("axiom", "axiom V0 I[Flute] Rq C5q V1 I[Tubular_Bells] Rq Rq Rq G6i+D6i V2 I[Piano] Cmajw E6q " +
            "V3 I[Warm] E6q G6i+D6i V4 I[Voice] C5q E6q");
    }};

    // Set up the ReplacementMapPreprocessor to iterate 3 times
    // and not require brackets around replacements
    ReplacementMapPreprocessor rmp = ReplacementMapPreprocessor.getInstance();
    rmp.setReplacementMap(rules);
    rmp.setIterations(4);
    rmp.setRequireAngleBrackets(false);

    // Create a Pattern that contains the L-System axiom
    Pattern axiom = new Pattern("T120 " + "V0 I[Flute] Rq C5q "
                + "V1 I[Tubular_Bells] Rq Rq Rq G6i+D6i "
                + "V2 I[Piano] Cmajw E6q "
                + "V3 I[Warm] E6q G6i+D6i "
                + "V4 I[Voice] C5q E6q");

    Player player = new Player();
    System.out.println(rmp.preprocess(axiom.toString(), null));
    player.play(axiom);
  }
}

Come back to this page later for more examples!