javajfugue

JFugue ParserListenerAdapter onChordParsed method not invoked


I am trying to read a midi file that contains only a guitar track. The track is made of both single notes and chords. While i can successfully read all notes through onNoteParsed method, i cannot read chords. In fact the onChordParsed method is never invoked.

import java.util.ArrayList;
import java.util.List;
import org.jfugue.parser.ParserListenerAdapter;
import org.jfugue.theory.Chord;
import org.jfugue.theory.Note;

public class MusicStringParserListener extends ParserListenerAdapter {

    private List<String> tokenList = new ArrayList<>();

    @Override
    public void onNoteParsed(Note note) {
        tokenList.add(note.getToneString() + note.getOctave() + note.getDuration());
    }

    @Override
    public void onChordParsed(Chord chord) {
        System.out.println("onChordParsed entered");
    }
    
    public List<String> getTokenList() {
        return tokenList;
    }
}

I tried to change the midi file to insert different kinds of chords, like major, minor or power chords, but still that method is not fired.

Am i missing something here?


Solution

  • You're right, onChordParsed isn't called - and should probably be removed from the API - and onNoteParsed is used instead.

    Parsing chords from a Staccato string

    When JFugue processes a chord, it breaks the chord into individual notes - which is necessary to support cases where some of the notes might change in melody during what would otherwise be a chord. As far as JFugue is concerned, "Cmaj" looks just like "C+E+G", but the latter provides more resolution, allowing things like "Cw+Eh_Ebh+Gw".

    You can still do what you want, though. When you get an onNoteParsed event, the Note will tell you whether it's the first note in a sequence, a next note in a sequence, or another note in melody during a sequence.

    For each note coming in, use the note's isFirstNote(), isHarmonicNote(), and isMelodicNote() methods to determine whether a note is in a chord. I believe what you'd see for Cw+Eh_Ebh+Gw is:

    I think that a single note that is not part of a chord will have isFirstNote() = false, but I'd need to double-check that.

    Parsing chords from MIDI

    Although MIDI data contains timestamps for each Note On and Note Off event, processing chords from MIDI data gets complicated quickly and is beyond what I have been able to implement in JFugue

    Here are some of the reasons why chord processing from MIDI is difficult.

    1. If the MIDI is a recording of live play, the times may be slightly off.
    2. There may be notes that are all played together that are not part of a single chord, or that are part of two chords, or some notes are chord and some are melody.
    3. There could be a chord that is played arpeggiated.
    4. There are chord inversions to think about.
    5. In MIDI, a Note On or Note Off event can appear anywhere in the MIDI stream! Usually, they're in the right temporal order, but this is not necessarily the case. So we couldn't determine a chord until the full MIDI is parsed.
    6. Notes that take place at the same time but in different channels should not be chords - but that's an assumption that may not always be true.

    I realize there are music notation tools that can read MIDI and resolve chords, but I imagine those come with some assumptions about the music and have undergone a lot of trial and error in their development. As JFugue currently stands, it just reads all MIDI notes as notes. Every note read from MIDI will appear as isFirstNote() with no recognition about whether the note is in harmony or melody.