First steps with MidiOutput. What's wrong with this?


#1

Hi,

I am taking my first steps with Juce and outputting some midi. I’m using a midi monitor app and the output is not what I expected. I am trying to send note on/off but the app shows 2 byte sysex data (F0 F7). Am I missing something obvious here?

midiBuffer_.addEvent(MidiMessage::noteOn(1, 60, 127.f), 0); midiBuffer_.addEvent(MidiMessage::noteOff(1, 60), 44100); midiOutput_->sendBlockOfMessages(midiBuffer_, 0, 44100);

Also I have a ComboBox taking the StringArray straight from getDevices(); When the ComboBox changes I take the index and pass in on to MidiOutput::openDevice. It works but I need to add the +1 to open the correct device. Why is that?

void MyPlugAudioProcessorEditor::comboBoxChanged(ComboBox *box) { String value = box->getText(); int deviceIndex = box->getSelectedItemIndex()+1; // off by 1?? midiOutput_ = MidiOutput::openDevice(deviceIndex); if(!midiOutput_){ label->setText("Device could not be opened :'(", false); }else{ label->setText("Opened "+value, false); } }


#2

You need to start the background thread for the device if you want to use this method to send MIDI messages. Have a look at: http://www.rawmaterialsoftware.com/juce/api/classMidiOutput.html
and the startBackgroundThread() method, you need to call it after you open the device.


#3

Ah yes thanks I missed that. I still don’t get any output though. Any other steps I need to be aware of?

The 2 byte midi F0 F7 turned out to come from a piece of code I had put somewhere for debugging:

MidiMessage msg; msg.setChannel(1); msg.setVelocity(127); msg.setNoteNumber(60); midiOutput_->sendMessageNow(msg);

I don’t understand why this would not generate a regular note. Is there maybe an example around for sending midi data? I had a look but I couldn’t find one yet.


#4

Hi 0x80,
about your second example… reading the MidiMessage docs tells us this:

[quote]void MidiMessage::setNoteNumber ( int newNoteNumber )
Changes the midi note number of a note-on or note-off message.

If the message isn’t a note on or off, this will do nothing.[/quote]

Since you’ve created a default, empty MidiMessage to begin with, setting a note on value in this way will presumably fail for the above reason.

The following code snippet works for me:

MidiOutput* midiOutput = MidiOutput::openDevice(0); midiOutput->sendMessageNow(MidiMessage::noteOn(1, 59, (uint8)100));

In the first example you gave, the velocity value was given as a float, but was 127.0. The docs say that the velocity should be given either as a uint8 from 0 - 127 or a float from 0.0 to 1.0. So that may have affected your result.

Now on to my problem… the following results in no MIDI output at all, and I’d be glad to know why!

[code] MidiOutput* midiOutput = MidiOutput::openDevice(0);
midiOutput->startBackgroundThread();

MidiBuffer thisMidiBuffer;
thisMidiBuffer.addEvent(MidiMessage::noteOn(1, 54, (uint8)100), 1);
thisMidiBuffer.addEvent(MidiMessage::noteOff(1, 54), 800);
midiOutput->sendBlockOfMessages(thisMidiBuffer, 10, 20000);[/code]


#5

Thanks Charles! I got things working now 8) I should probably try to read the docs a bit better and program when I’m feeling fit and not at night after a long days work :oops:

About your example/problem. Maybe the call to sendBlockOfMessages doesn’t copy your MidiBuffer instance, and since it will be executed async somewhere in the near future, your instance might already be deleted by the time the scheduler is trying to read the data from it? Try creating the midi buffer in a way that its persistent.


#6

Hi 0x80, having the MidiBuffer as a persistant instance seems like a good principle, unfortunately the MIDI output still doesn’t appear. Have you managed to send a block of MIDI messages?


#7

Oops no my happiness was premature. Only the direct messages are getting through. :cry:

I’m doing this from within an audio plugin project. Is this function with the threading somehow limited to standalone apps?


#8

Yes found it! Googled around a bit more and found some example in code by Vinnie here:
https://github.com/vinniefalco/AppletJUCE/pull/2.patch

Basically you need to get the current time in order to make your event relative to the now. This outputs the event 1sec from current time:
midiOutput_->sendBlockOfMessages(midiBuffer_, Time::getMillisecondCounter() + 1000, 44100);

:stuck_out_tongue: