Struggling at building a midi file


#1

*edit : replaced my large piece of code by a minimal complete issue

Hello, I need some help to build a midi file, here is what I want to do :

  • Read a music (monophonic) file - OK
  • Detect pitches and offsets - rougthly OK
  • Translate to midi note number - OK
  • Put note events in a midi file - KO

The final purpose is to create a "whistle to midi" app.

Here is a test code for midi writing (sorry for duplication and length), it compile and run but the midifile is unreadable by sequencers or synthetisers (vlc) :

        MidiMessageSequence midiMessageSequence;
        midiMessageSequence.addEvent(MidiMessage::noteOn(1,69,1.0f), 1000.0f);
        midiMessageSequence.addEvent(MidiMessage::noteOff(1,69,1.0f), 4000.0f);
        midiMessageSequence.sort();
        
        MidiFile midiFile;
        midiFile.setSmpteTimeFormat (25, 40);
        midiFile.addTrack(midiMessageSequence);
        
        File outputFile(commandParser.getOutputFileName());
        FileOutputStream outputStream(outputFile);
        midiFile.writeTo(outputStream);
        outputStream.flush();

After searching for a long time I seems to fail at knowing how to put the events in the file and what events are necessary.

I also struggle dealing with timestamps.

I also want to know how to assign instruments to channels.

Can you help me please?

Thank you.

ps : OSX yosemite | Xcode 5 | introjucer

pps: sorry if bad english I'm french.


#2

I am doing a meticulous search on the forum, and I just find one interesting ressource, here is the link for those who are interested: http://www.juce.com/forum/topic/midi-file-smpte-time-format-bug

I'll post here all other related topics I find:

http://www.juce.com/forum/topic/generating-midi-files

http://www.juce.com/forum/topic/midi-timecode

http://www.juce.com/forum/topic/midimessagesequence-double-timestamps

http://www.juce.com/forum/topic/midimessagesequence-and-updatematchedpairs

http://www.juce.com/forum/topic/recording-memory

http://www.juce.com/forum/topic/saving-midifile

http://www.juce.com/forum/topic/converttickstoseconds-correct

 

problem still unsolved.


#3

To assign instruments, use MidiMessage::programChange

I'd recommend http://www.skytopia.com/project/articles/midi.html for an explanation of the midi file format.
From there you can also download a minimalistic piece of music to compare your midi file with: 
http://www.skytopia.com/project/articles/midi/cde2.mid

 


#4

Ok thank you for your links, it is well explained, I will analyse and compare midi files ouputs and I will reply to give the solution.


#5

Okay I I looked into all the hexadeciaml code produced by this simplified version :
 

       MidiMessageSequence midiMessageSequence;
        midiMessageSequence.addEvent(MidiMessage::noteOn(1,69,1.0f), 0.0f);
        midiMessageSequence.addEvent(MidiMessage::allNotesOff(1), 4000.0f);
        //midiMessageSequence.sort();
        
        MidiFile midiFile;
        midiFile.setTicksPerQuarterNote(127);
        midiFile.addTrack(midiMessageSequence);
        
        File outputFile(commandParser.getOutputFileName());
        FileOutputStream outputStream(outputFile);
        midiFile.writeTo(outputStream);
        outputStream.flush();

And the result was OK but repeated multiple times, that was due to how I use the file as a stream, resulting in adding to previous results, making the file corrupted.
 

The last thing I need to figure out is how to manipulate the juce version of timestamps.


#6

To override any previous midi file, just put :

outputFile.deleteFile();

(check the result) before :

FileOutputStream outputStream(outputFile);

#7

One last thing, adding the folowing event at the beginning of the sequence can help : 

midiMessageSequence.addEvent(MidiMessage::tempoMetaEvent(microsecondsPerQuarterNote));