HMP File Format
(Incomplete - Under Construction)

Document version 1
Written by Chris Ison

Last Edited 24 May 2014

Copyright (C) 2014 WildMidi Developers
This document is licensed under the
Creative Commons Attribution-ShareAlike 4.0 International License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-sa/4.0/


Introduction

This document describes the HMP format as used by the WildMIDI project.
It is not a complete description of the HMP file format and only those
parts that are relevant to the WildMidi project are described here.
Unfortunately we cannot answer questions about the format that are not
described within this document.  If you feel there is an error in this
document please feel free to report it as a bug at
https://github.com/Mindwerks/wildmidi/issues/

The HMP format comes in 2 versions. Apart from the file header there is
no difference between the 2 versions as far WildMIDI is concerned.


Description

// First version of hmp files
{
    char header[] = "HMIMIDIP";
    char no_idea_1[24]; // All zeros
}

// *** OR ***

// Second version of hmp files
{
    char header[] = "HMIMIDIP013195";
    char no_idea_1[18];        // All zeros
}

// The remaining header section of hmp files
{   char file_length[4];       // File size minus header[] stored as little-endian
    char no_idea_2[16];        // All zeros
    char number_of_chunks[4];  // Number of chunks stored as little-endian
    char no_idea_3[4];         // Unknown
    char beats_per_minute[4];  // beats per minute stored as little-endian
                                   // *** NOTE: Using a division of 60 ***
    char song_length_s[4];     // length of song in seconds as little-endian
}

// First version of hmp files
{
    char no_idea4[712];        // Unknown
    // chunks start here
}

// *** OR ***

// Second version of hmp files
{
    char no_idea4[840];        // Unknown
    // chunks start here
}

// Chunk information
{
    char chunk_number[4];      // Stored as little-endian
    char chunk_length[4];      // Size of entire chunk stored as little-endian
    char track_number[4];      // Track numbe stored as little endian

    {
        // Repeat until end of chunk
        char midi_delta[] = ???;   // See MIDI Delta
        char midi_event[] = ???;   // See MIDI Events
    }
}


MIDI Delta

This is a variable length value that determins how time (in MIDI ticks)
is to pass before the following MIDI event is to be processed. Opposite
to MIDI variable length values. In HMP files the variable length value
is stored in LSB with bit 7 set off for all except the last 7 bit value.
A value of 255 would be stored as 0x7f 0x81, or a value of 1 would be
stored as 0x81 in the HMP variable length format.

    Examples:
    Delta of 255: < midi event > 0x7f 0x81 < midi event>
    Delta of 127: < midi event > 0xff < midi event >
    Delta of 65537: < midi event > 0x7f 0x00 0x82 < midi event >


MIDI Events

The first byte of a midi events is split into 2 x 4bits. Bits 7-4 is the
command while bits 3-0 is the MIDI channel the command is to occur on.
For example 0x94 means do command 9 on channel 4. The only exception to
this is where bits 7-4 = F in hexidecimal as these are a special group
of commands.

The following commands are detailed in this document with the channel
information (bits 3 - 0) set to 0, example 0x80.  However the channel
information could have a value anywhere from 0x0 to 0xf.

For more detail about the folling MIDI command information please see
MidiFileFormat.txt within the WildMIDI project source code.

// Note Off
{
    char cmd = 0x80;
    char note = 27; // Could be a value of 0 - 127
    char velocity = 0; // Could be a value of 0 - 127. Ignored by WildMIDI
}

// Note On
{
    char cmd = 0x90;
    char note = 32; // Could be a value of 0 - 127
    char velocity = 100; // Could be a value of 0 - 127. 
                         // If this value is 0 then it is treated as a note of
}

// Aftertouch
{
    // Adjust the velocity of a note as if adjusting the preasure you
    //  are placing on the key of a preasure sensitive keyboard after
    //  you started playing it.

    char cmd = 0xa0;
    char note = 32; // Could be a value of 0 - 127
    char velocity = 100; // Could be a value of 0 - 127.
}

// Controller
{
    char cmd = 0xb0;
    char controller = 32; // Could be a value of 0 - 127
    char setting = 100; // Could be a value of 0 - 127

    /*
        In track 1 of HMP files controller 110 is set to 255 to
        mark the start of the looped events of tracks 2 & 3.
        Controller 111 in track 1 set to 128 to mark the end of
        the looped events of track 2 & 3.
     */
}

// Patch
{
    /*
        Change the patch (or sound) used to play notes on the channel
     */
    char cmd = 0xc0;
    char change_patch = 32; // Could be a value of 0 - 127
}

// Preasure
{
    /*
        Adjust the velocity of all active notes on the channel
        as if adjusting the preasure you are placing on the keys
        of a preasure sensitive keyboard after you started playing
        them.
     */
    char cmd = 0xd0;
    char velocity = 32; // Could be a value of 0 - 127
}

// Pitch
{
    /*
        Adjust the pitch of a channel just like a pitch bend wheel does.
     */
    char cmd = 0xe0;
    char data_1 = 32; // Could be a value of 0 - 127
    char data_2 = 100; // Could be a value of 0 - 127.
}

// Sysex
{
    ** It is uncertain if sysex events will apepar in a HMP file **
    ** but they have been included because it is possible        **

    char cmd = 0xf0;
    // *** OR ***
    char cmd = 0xf7;

    char sysex_size[] = < variable length in MIDI file format >;
    char sysex_data[sysex_size] = ...; // Ending with 0xf7
}

// Meta Events
{
    char cmd = 0xff;
    char instruction = 0x02; // Could be 0 - 127
    char data_size[] = < variable length in MIDI file format >;
    char data[data_size];
}

