#pragma comment(lib, "winmm")
#include <Windows.h>
#include <vector>
#include <map>
using namespace std;
typedef vector<DWORD> VSMSG;
typedef multimap<DWORD, VSMSG> SEQ;
// status
#define NOTE_OFF 0x8
#define NOTE_ON 0x9
#define PROGRAM_CHANGE 0xc
// program
#define ACOUSTIC_PIANO 0x00
// note number
#define G3 55
#define C4 60
#define D4 62
#define E4 64
#define G4 67
#define B4 71
#define C5 72
#define MAKESMSG(st,ch,d1,d2) ((st)<<4|(ch)|(d1)<<8|(d2)<<16)
#define MAKESMSG_(d1,d2) ((d1)|(d2)<<8)
#define CH 0
// 関数プロトタイプ宣言
void SeqInsert(DWORD ticks, DWORD smsg);
void SeqInsert(DWORD ticks, DWORD smsg1, DWORD smsg2, DWORD smsg3, DWORD smsg4);
// 外部変数
SEQ seq;
//==============================================================================
int main()
{
HMIDIOUT hmo;
DWORD ticks = 0;
int vel = 0x70;
SeqInsert(ticks, MAKESMSG(PROGRAM_CHANGE, CH, ACOUSTIC_PIANO, 0));
SeqInsert(ticks, MAKESMSG(NOTE_ON, CH, C4, vel),
MAKESMSG_(E4, vel), MAKESMSG_(G4, vel), MAKESMSG_(C5, vel));
ticks += 1500;
SeqInsert(ticks - 1, MAKESMSG(NOTE_OFF, CH, C4, 0),
MAKESMSG_(E4, 0), MAKESMSG_(G4, 0), MAKESMSG_(C5, 0));
SeqInsert(ticks, MAKESMSG(NOTE_ON, CH, G3, vel),
MAKESMSG_(D4, vel), MAKESMSG_(G4, vel), MAKESMSG_(B4, vel));
ticks += 1500;
SeqInsert(ticks - 1, MAKESMSG(NOTE_OFF, CH, G3, 0),
MAKESMSG_(D4, 0), MAKESMSG_(G4, 0), MAKESMSG_(B4, 0));
SeqInsert(ticks, MAKESMSG(NOTE_ON, CH, C4, vel),
MAKESMSG_(E4, vel), MAKESMSG_(G4, vel), MAKESMSG_(C5, vel));
ticks += 1500;
SeqInsert(ticks - 1, MAKESMSG(NOTE_OFF, CH, C4, 0),
MAKESMSG_(E4, 0), MAKESMSG_(G4, 0), MAKESMSG_(C5, 0));
// play
midiOutOpen(&hmo, MIDI_MAPPER, NULL, 0, CALLBACK_NULL);
DWORD start = timeGetTime();
for (SEQ::iterator it = seq.begin(); it != seq.end(); it++) {
while (timeGetTime() - start < (*it).first) Sleep(1);
for (size_t i = 0; i < (*it).second.size(); i++) {
midiOutShortMsg(hmo, (*it).second[i]);
}
}
midiOutReset(hmo);
midiOutClose(hmo);
return 0;
}
void SeqInsert(DWORD ticks, DWORD smsg)
{
VSMSG vsmsg;
vsmsg.push_back(smsg);
seq.insert(SEQ::value_type(ticks, vsmsg));
}
void SeqInsert(DWORD ticks, DWORD smsg1, DWORD smsg2, DWORD smsg3, DWORD smsg4)
{
VSMSG vsmsg;
vsmsg.push_back(smsg1);
vsmsg.push_back(smsg2);
vsmsg.push_back(smsg3);
vsmsg.push_back(smsg4);
seq.insert(SEQ::value_type(ticks, vsmsg));
}