Playing a MIDI file


#1

I need some help for playing MIDI files. I have problems with the MidiFile Class, and I would like someone post some simple code to play a MIDI file, with the opening of each ports etc.

Someone can helps me ? I have finished the GUI after nearly 1 weew and now I’m blocking again on something else, with pointers etc. It’s boring :frowning:

For now, I’m here :

[code]portMIDI = MidiOutput::openDevice(0);

File* fileHard;
FileInputStream* fileInputStream;
MidiFile fileMIDI;

fileHard = new File (T(“C:\Projets\Devcpp\file.mid”)); // (1)
fileInputStream = fileHard->createInputStream();
fileMIDI->readFrom(fileHard->createInputStream()); // (2)[/code]

The line with the (1) gives me a warning :

[quote][Warning] unknown escape sequence ‘\P’
[Warning] unknown escape sequence ‘\D’
[Warning] unknown escape sequence ‘\G’
[Warning] unknown escape sequence ‘\M’[/quote]

And I have problems with the (2) about pointers, i need a InputStream& in parameter, and I only have InputStream*…

There is a thing I don’t understand, the function for reading audio data from an InputStream is :

And for MIDI data that’s :

Why a “&” here and a “*” on the other ?


Playing a MIDI file (revisited)
#2

For the first warning, I have understood, the path must be written with some “/” and not “” :lol:

But I haven’t found a solution for the MidiFile class…

Nobody can help me ?


#3

You should just be able to pass in the contents of your InputStream pointer to the MidiFile::readFrom() method. i.e.

[code]portMIDI = MidiOutput::openDevice(0);

File* fileHard;
FileInputStream* fileInputStream;
MidiFile fileMIDI;

fileHard = new File (T(“C:\Projets\Devcpp\file.mid”));
fileInputStream = fileHard->createInputStream();
fileMIDI->readFrom(*fileInputStream); // note the *[/code]

An & for a function parameter means you’re passing the variable in by reference. Basically when you pass a variable in to a function (e.g. function(int variable); ), a copy of the variable is made for the function to operate on. Passing in a variable by reference (e.g. function(int& variable); ) means a copy is not made - instead the function acts on the actual variable you passed in. Essentially it’s like passing in a pointer to a variable, but you don’t use pointer notation (e.g. you’d have stream.readByte() inside the function instead of stream->readByte()).

  • Niall.

#4

Yeah that works ! And thanks for the explanation :wink:


#5

No Problem :slight_smile:

  • Niall.

#6

I have another question, I just need some explanation…

Apparently, to play a MIDI file, I must use the method createControllerUpdatesForTime() to get the MidiMessage objects and the sendMessageNow of my MIDI output.

So, I must use a loop which will get the time corresponding to each Event (from 0 to getNumEvents() ), use a Timer to know if I am at the right Time to send all the messages one by one… and maybe I need the Thread class because I don’t want the program to be freezed while the file is played…

Am I right ? Someone can enlight me on this ?


#7

So ? Someone has an idea ? And apparently, I can’t use the Timer class to do this, I must use the Thread class to perform the time tests…


#8

Nobody uses MIDI commands here ? I haven’t found any example in the libraries, and I really need an answer, I’m on it for nearly 1 week and I don’t how to do… I’m working on a Drum Loop manager project, and I just need some minor MIDI capabilities, after I will be able to show you my work…


#9

Okay, I haven’t done any MIDI stuff with JUCE, but I’ll give it a shot…

With your midiMessageSequence, do you not just loop through it, dispatching/operating on the messages however you want? e.g.

[code]int i;
MidiMessage *tempMessage;
MidiMessageSequence *seq;
MidiFile phil();

seq = phil->getTrack(0); //or whatever track you want…
for(i=0;igetNumEvents();i++)
tempMessage = &(seq->getEventPointer()->message);
[/code]
Then use tempMessage to do whatever it is you’re wanting to do.

  • Niall.

#10

Thanks for the tip, I had a problem to get the MidiMessage one by one… I will have a try :wink: Then, the problem will be to send them to the midi port at the right time…


#11

With your help, now I have got some sound ! ! ! Yeah ! :lol:

But the synchronization is the problem now… I have created a thread, and used the wait instruction to… wait for the next event, at the right time, and with a maximum priority, the play of midi file is, you can imagine, not slow at all, but the drummer has lost 20 years of practice :lol: Now I’m looking for a way to do the synchronization faster…


#12

That works perfectly ! Yeaaaaaaaaaaah ! Thanks for your help NialM :wink: I will post the source code if somebody is interested… Because it’s not so easy to make the file be played well… I had to do a sort of each event before the loop in my Thread to accelerate the process…


#13

Yeah- would be great to see your concotion. Thanks!


#14

OK, I have posted a part of my code, the files cannot be compiled alone, but you will find all of the code I have done to play a MIDI file, and a class to use a SimpleListBox that allows to choose the MIDI output you want :wink:

It’s here : PlayingMidiFile.zip

The code is not optimizated at maximum, I have some bugs when I try to play with the port MidiYoke to use Kontakt and NSKIT7 in Tracktion, with more than 30% of CPU used, so I have still some work… (for example, the uint64 method of the Time class is useless, I don’t need too much precision…)


#15

Hello.
Link to MididFile.zip isn’t valid.
I don’t know format of midi file.
And trying to play MIDI by the touch.
So could someone help me with MIDI file playing.


#16

Is there an alternative link to an example that plays a MIDI file?


#17