Generating MIDI files

True - it might cause some other apps to try to read the garbage. I've switched to deleteFile.

As I wanted to output title and other text into MIDI files with JUCE, I created a helper class:

class MidiMessageHelper
{
public:
    static MidiMessage trackTitle(const String &title);
    static MidiMessage trackCopyright(const String &copyright);
private:
    static MidiMessage trackText(int type, const String &text);
};

MidiMessage MidiMessageHelper::trackText(int type, const String &text)
{
    char titleTrack[128];
    sprintf_s(titleTrack, 128, "%c%c%c%s", 0xff, type, text.length(), text.toRawUTF8());
    MidiMessage result(titleTrack, strlen(titleTrack));
    return result;
}

MidiMessage MidiMessageHelper::trackTitle(const String &title)
{
    return trackText(3, title);
}

MidiMessage MidiMessageHelper::trackCopyright(const String &copyright)
{
    return trackText(2, copyright);
}

Seems to be working well in my application so far (with unit tests).

1 Like

Like the copyright notice meta event (type = 2) or the track name meta event (type = 3) .

The functions I used are the only ones I could see in the documentation - there are others?

The functions I used are the only ones I could see in the documentation - there are others?

Juce might benefit from some more midimessage constructors. I misread your message on my smartphone.

your code will only work for smaller texts. The string length in midi text meta events is a variable length quantity and should be calculated as such:

MidiMessage MyMidiMessage::textMetaEvent(int type, String text)
{
    jassert(type > 0 && type < 16)

    //const int textLength = text.length();
    const int textLength = CharPointer_UTF8::getBytesRequiredFor (text.getCharPointer());

    HeapBlock<uint8> m (textLength + 2 + 4);    //allocate for text, 0xff, type and max 4 length bytes

    int n = 6;

    m[--n] = textLength & 0x7f;
    
    for (int lengthLeft = textLength; lengthLeft >>= 7;)
        m[--n] = lengthLeft & 0x7f | 0x80;

    m[--n] = (uint8)type;
    m[--n] = 0xff;

    memcpy(m + 6, text.getCharPointer(), textLength);

    return MidiMessage (m + n, 6 - n + textLength, 0);
}

While this is not entirely trivial, maybe Jules might even consider adding it to the MidiMessage class :)