Selecting a MIDI output port
The MidiOutput class contains a list of all of the
MIDI output ports which are available for your program.
Example 2 shows how to send a MIDI message to all MIDI output ports:
Example 2: sending MIDI message to all output ports.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#include "improv.h"
int main(void) {
MidiOutput midi;
int portCount = midi.getNumPorts();
for (int i=0; i<portCount; i++) {
midi.setPort(i);
midi.open();
midi.play(0, 60, 127);
cout << "Played a note on: "
<< midi.getName() << endl;
}
return 0;
}
|
|
Note that the midi port had to be opened the
first time a particular port was used.
Code explanations for Example 2:
-
- midi.getNumPorts()
- This line returns the total number of MIDI output ports
available to the program. All ports are indexed starting
from 0 to one less than the total count. The midi
variable can change ports using these valid numbers by calling
the setPort() function.
-
- midi.getName()
- This line of code returns a string provided by the
MIDI driver as a description of the MIDI output port.
It usually tells you what type of internal sound synthesizer
or external MIDI connection the port sends its data to.
Example 3 shows a useful piece of code that displays
all of the possible MIDI out port names. This code could
be used in a program that allows the user to select a
particular MIDI output port to send on.
Example 3: printing a menu of MIDI output ports.
#include "improv.h"
int main(void) {
MidiOutput midi;
int selection = -1;
int portCount = midi.getNumPorts();
for (int i=0; i<portCount; i++) {
midi.setPort(i);
cout << i << ":" << midi.getName() << endl;
}
cout << "Select an output port: ";
cin >> selection;
// play a note on the selected port:
midi.setPort(selection);
midi.open();
midi.play(0, 60, 127);
return 0;
}
|
|
Types of MIDI output
There are several C++ classes related to MIDI output in the
improv library, including the following classes:
- MidiOutPort
|
The lowest-level improv class for dealing
with MIDI output. This class defines the basic commands
for sending MIDI messages to the MIDI ports. All other
MIDI output classes are derived from this class and therefore
have the same functionality as this class. Use this class
only if you don't need any useful helper functions for
MIDI output.
|
- MidiPort
|
This class is not too useful, but exists
for completeness. It has the functionality of both
the
MidiInPort
and
MidiOutPort
classes.
|
- MidiOutput
|
The most useful general-purpose class for MIDI
output. It defined many convenience functions for using
the various MIDI messages. For example the function
MidiOutput::play(0, 60, 127) is equivalent to the
function MidiOutPort::rawsend(0x90, 60 127).
|
- Voice
|
Voice is a specialized type of MidiOutput.
The purpose of the Voice class is to keep track of
note-off commands. When ever a new note is played throgh
a Voice object, the previous note will automatically be
turned off if necessary.
|
- MidiPerform
|
A specialized form of MidiOutput which
controls the performance of the standard MIDI file.
|
- MidiIO
|
Combines the functions of MidiOutput
and MidiInput.
|
- Synthesizer
|
A specialized form of MidiIO which sorts
MIDI input data into buffers of notes and controllers.
|
- RadioBaton
|
A specialized form of MidiIO which parses
MIDI input data for Radio Baton messages as well as defined
special MIDI messages for communication with a Radio Baton
controller.
|
Monophonic looping
Barebones MIDI sequencer
The MidiPerform class can be
used to play standard MIDI files. Example 5 shows a program
for a simple MIDI sequencer.
Example 5: Simple MIDI sequencer.
#include "improv.h"
int main(int argc, char** argv) {
if (argc != 2) {
cout << "Usage: " << argv[0]
<< " midifile" << endl;
exit(1);
}
MidiPerform performance;
performance.setPort(0);
performance.open();
performance.read(argv[1]);
performance.setTempo(120);
performance.setTempoMethod(TEMPO_METHOD_AUTOMATIC);
while (1) {
performance.check();
millisleep(1);
}
return 0;
}
|
|
Code explanations for Example 5:
-
- performance.read(argv[1]);
- Read in a standard MIDI file.
-
- performance.setTempo(120);
- Set the tempo of the performance to 120 beats per minute.
-
- performance.setTempoMethod(TEMPO_METHOD_AUTOMATIC);
- Use automatic tempo control. You can also control the
tempo with a computer keyboard, or MIDI keyboard, etc.
-
- performance.check();
- Continuously check the performance for MIDI notes to play.
if you are using automatic tempo control, you know beforehand
when you will need to play the next note, so you could
calculate a specific length of time to sleep.
There is an example program, midiperform.cpp,
which is a more complex version of this programming example which
adds many user controls from the computer keyboard and synthesizer
keyboard.
|