|
|||||||||||||||||||||
|
|||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionUsing the Windows low-level MIDI API is not necessarily easy. There are a lot of details to keep track of, and it can get a bit frustrating when you are trying to write a MIDI application. The goal of my small wrapper library is to elevate some of the grunt work that goes into using the Windows low-level MIDI API by encapsulating the functions into C++ classes. With these classes, most of the dirty work is handled behind the scenes. This leaves you free to concentrate on more important matters. The LibraryThe MIDI library is encapsulated in the
Let's look at each part of the library. midi.h - Useful ConstantsThe midi.h header file contains many useful constants. For example, the MIDIInDevice.h - The CMIDIInDevice and CMIDIReceiver ClassesThe Before To begin receiving MIDI data, call the The Short messages are represented by the Finally, once you are finished using the To make short messages and system exclusive messages easier to work with, I've added three new classes: A code snippet is worth a thousand words, so let's look at an example of using the #include "StdAfx.h"
#include <iostream>
#include "MIDIInDevice.h"
#include "ShortMsg.h"
using midi::CMIDIInDevice;
using midi::CMIDIReceiver;
// My class for receiving MIDI messages
class MyReceiver : public CMIDIReceiver
{
public:
// Receives short messages
void ReceiveMsg(DWORD Msg, DWORD TimeStamp);
// Receives long messages
void ReceiveMsg(LPSTR Msg, DWORD BytesRecorded, DWORD TimeStamp)
{}
// Called when an invalid short message is received
void OnError(DWORD Msg, DWORD TimeStamp)
{ std::cout << "Invalid short message received!\n"; }
// Called when an invalid long message is received
void OnError(LPSTR Msg, DWORD BytesRecorded, DWORD TimeStamp) {}
};
// Function called to receive short messages
void MyReceiver::ReceiveMsg(DWORD Msg, DWORD TimeStamp)
{
midi::CShortMsg ShortMsg(Msg, TimeStamp);
std::cout << "Command: " <<
static_cast<int>(ShortMsg.GetCommand());
std::cout << "\nChannel: " <<
static_cast<int>(ShortMsg.GetChannel());
std::cout << "\nDataByte1: " <<
static_cast<int>(ShortMsg.GetData1());
std::cout << "\nDataByte2: " <<
static_cast<int>(ShortMsg.GetData2());
std::cout << "\nTimeStamp: " <<
static_cast<int>(ShortMsg.GetTimeStamp());
std::cout << "\n\n";
}
int main(void)
{
try
{
// Make sure there is a MIDI input device present
if(CMIDIInDevice::GetNumDevs() > 0)
{
MyReceiver Receiver;
CMIDIInDevice InDevice(Receiver);
// We'll use the first device - we're not picky here
InDevice.Open(0);
// Start recording
InDevice.StartRecording();
// Wait for some MIDI messages
::Sleep(10000);
// Stop recording
InDevice.StopRecording();
// Close the device
InDevice.Close();
}
else
{
std::cout << "No MIDI input devices present!\n";
}
}
catch(const std::exception &Err)
{
std::cout << Err.what();
}
return 0;
}
Some notes about the code above:
MIDIOutDevice.h - The CMIDIOutDevice ClassThe Here is another code example: #include "StdAfx.h"
#include <iostream>
#include "midi.h"
#include "MIDIOutDevice.h"
#include "ShortMsg.h"
using midi::CMIDIOutDevice;
using midi::CShortMsg;
// Some useful constants
const unsigned char CHANNEL = 0;
const unsigned char NOTE_ID = 64;
const unsigned char VELOCITY = 127;
int main(void)
{
try
{
// Make sure there is an output device present
if(CMIDIOutDevice::GetNumDevs() > 0)
{
CMIDIOutDevice OutDevice;
// Use the first device
OutDevice.Open(0);
// Create note-on message
CShortMsg NoteOnMsg(midi::NOTE_ON, CHANNEL, NOTE_ID,
VELOCITY, 0);
// Turn note on
NoteOnMsg.SendMsg(OutDevice);
// Wait a bit
::Sleep(5000);
// Create note-off message
CShortMsg NoteOffMsg(midi::NOTE_OFF, CHANNEL, NOTE_ID, 0, 0);
// Turn note off
NoteOffMsg.SendMsg(OutDevice);
// Close device
OutDevice.Close();
}
else
{
std::cout << "No MIDI output devices present!\n";
}
}
catch(const std::exception &Err)
{
std::cout << Err.what();
}
return 0;
}
Some comments:
The MIDIDeviceDemo Demonstration AppThe demo application uses the small MIDI library I've created for input and output. The piano keyboard is interactive. Clicking on a key with the mouse triggers a note. You can also play the piano from the computer keyboard. The keys from 'Z' to '/' correspond to the piano. To change the range of the computer keyboard, press keys 1-5. The '1' key represents the lowest range, and the '5' key represents the highest range. If a MIDI keyboard is connected to the computer, playing keys on the keyboard will cause the corresponding notes on the keyboard display to change colors. Incoming channel messages are displayed as well. The application has very little practical value, but it does show how the library works. Hopefully, you will find this small library as useful as I have. I would appreciate any comments or suggestions for future revisions. Take care! History
| ||||||||||||||||||||