ChordPro auto-accompaniment: Implementation notes

I’m prep’ing my ChordPro to Yamaha accompaniment program (cp2mid) for distribution. Please check out the demo. In the meantime, here are a few comments about the implementation.

Command line interface

cp2mid doesn’t have a fancy graphical user interface (GUI). A GUI is too much for a simple tool that translates an extended ChordPro file into a Standard MIDI File (Type 0).

I’m distributing both Java source code and a JAR file. The JAR file contains the compiled Java — the Java executable, if you will. “JAR” is an acronym for “Java Archive” and is produced by the Java archive program (jar), which is part of the Java development environment (JDK). JAR is a way to package up a compiled Java program, hiding all of the interior classes, etc. An end user doesn’t really need to know about JAR.

Given the JAR file, enter the following command line to run cp2mid:

    java -jar cp2mid.jar AFile.cho

“AFile.cho” is the name of an extended ChordPro file to be translated. You can hide the cp2mid.jar file within a Windows BAT file or shell file. Here is cp2mid.bat:

    java -jar cp2mid.jar %1

Nothing complicated, here.

cp2mid recognizes the “.cho” file name extension. It does not recognize any other extensions. If you snag a ChordPro file from the Web, you may need to change its extension to “.cho”. cp2mid replaces “.cho” with “.mid” in order to make the MIDI file name. Thus, “AFile.cho” is translated to “AFile.mid”.

During development and testing, you can run cp2mid starting with the compiled classes, e.g., cp2mid.class. Enter the command line:

    java cp2mid AFile.cho

to run cp2mid. The Java interpreter will look for “cp2mid.class” and the rest of the compiled classes needed by cp2mid. These compiled classes must be available in the same directory as cp2mid.class. “cp2mid”, by the way, is the main class in the application. You’ll need to specify the main class when creating a JAR file. Again, these steps are relevant only to developers.

Java classes

cp2mid has five Java classes:

  • cp2mid (cp2mid.java) Main class and driver
  • SongElement (SongElement.java) Basic element (parts) of a Song
  • Song (Song.java) Represents a ChordPro song in terms of SongElements
  • Song2mid (Song2mid.java) Translates the internal song representation to MIDI
  • MidiFile (MidiFile.java) Represents and manipulates a standard MIDI File (SMF)

The MidiFile class was used in an earlier prototype and still contains a bit of unused legacy code. This may change in future versions. The MidiFile class exploits the standard Java MIDI packages and classes. It creates a MIDI file and inserts MIDI messages (meta, SysEx and otherwise) into a MIDI file.

cp2mid is the boss. It calls on the other classes to do their jobs. Processing is broken into five phases:

  1. Check and manipulate file names.
  2. Read the ChordPro file into a String array, one line per array element.
  3. Translate each line into one or more SongElements.
  4. Translate the SongElements into MIDI.
  5. Write the internal MIDI representation to a Type 0 SMF.

The translation phases do the heavy lifting.

Song and song elements

A Song is a list of SongElements. A SongElement represents one of several ChordPro song constituents:

  • Directive
  • Chord
  • Lyric
  • Line
  • Annotation
  • Comment
  • Tab

All SongElements have the same data members. Each SongElement has a tag which identifies its type. The type determines the validity and interpretation of the other data members.

The Song class translates extended ChordPro to a list of SongElements. This is, effectively, the intermediate, internal representation of a ChordPro song.

ChordPro directives begin with ‘{‘ and end with ‘}’. Usually ChordPro directives control song formating. Extended ChordPro uses key, tempo, time signature, style code, start accompaniment and stop accompaniment directives to issue MIDI messages that will control the accompaniment engine when the MIDI file is played back.

ChordPro chords and lyrics are what it’s all about. Chords begin with ‘[‘ and end with ‘]’. Chords are extended by an optional beat count which specifies how long the chord is held. A lyric is text and may be multiple syllables long (i.e., anything up to the next chord, annotation, or end of line.)

A line element is a marker for important end-of-lines. Line elements affect lyric formating.

Normally, a ChordPro annotation is text added to a song when it is displayed. Annotations begin with ‘*[‘ and end with ‘]’. Certain predefined annotations, e.g., [*MA], [*FA], etc. change the accompaniment section during play-back.

Comments are just that. cp2mid saves the text, but doesn’t do anything with it.

A ChordPro song may contain guitar tablature (tab). Right now, cp2mid ignores tablature. This has not been tested. I’m not sure how to handle or translate tablature as yet.

Song to MIDI

The Song2mid class translates the internal intermediate song representation to MIDI messages and adds the MIDI messages to a MIDI sequence. The MidiFile class helper functions create specific types of messages. Base MIDI message and sequence classes belong to the standard Java MIDI package.

The Song2mid class walks the SongElement list from front to back. Based on element type, it dispatches to an element type-specific handler. The handler adds one or more MIDI messages to the sequence.

A separate blog post describes the MIDI messages.

I tried to encapsulate most of the “Yamaha-ness” in the Song2mid and MidiFile classes. ChordPro is very loose and forgiving when it comes to chord syntax. Song2mid recognizes only the 33 or so Yamaha chord types as defined in the Genos Data List PDF. If Song2mid doesn’t recognize a chord, it issues either a major or minor triad.

Example songs

I will distribute 15 example songs in extended ChordPro and MIDI format. Even if you don’t run cp2mid (or look at its implementation), please take a look at the extended ChordPro songs and try the MIDI files on your arranger. All sorts of fun and crazy things happen in real music (key changes, time signature changes, anticipation) and the examples demonstrate how to handle many exceptional situations. I chose certain songs as examples for testing because they are weird. 🙂

I tested the MIDI files on Genos and I’m curious about their behavior on other arranger keyboards. The MIDI files are similar to those generated by Yamaha ChordTracker. If your arranger plays ChordTracker MIDI files, it should play cp2mid MIDI files.

I don’t want to lead you on — it takes a fair bit of effort to take an Internet ChordPro file and whip it into shape. ChordPro as a formating tool is very lenient and forgiving. Accompaniment requires tighter semantics and precision like most “executable” computer stuff. It’s fun to whip a song into shape, but it requires work.

Copyright © 2022 Paul J. Drongowski