//=========================================================================== // A MIDI KEYBOARD COMPATIBLE WITH WINDOWS 7 // Nick Gessler // 25 January 2011 //=========================================================================== // physical channels 0-15 // keys 0-127 // patches 0-127 // program change 0-127 #include #pragma hdrstop #include "Unit1.h" #include // enables MIDI //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- //=========================================================================== // VARIABLES //=========================================================================== int midiport = 0; HMIDIOUT device; int pos; int posToKey[28] = { 35, 36, 38,40,41,43,45,47,48,50,52,53,55, 57,59,60,62,64,65,67,69,71,72,74,76,77,79,81 }; int tune[32] = { 0,0, 60,65,64,62,60,57,0,0, 60,65,64,62,63,64,0,0, 64,64,60,62,60,64,60,62, 48,52,48,50,48,41, }; int length = 32; int x, y; int key, lastKey; int instrument; int tempo = 220; int loudness = 100; union { public: unsigned long word; unsigned char data[4]; } message; //=========================================================================== // FUNCTIONS //=========================================================================== //--------------------------------------------------------- Play the Keyboard void selectKeyFromImage (void) { Form1->EditImageX->Text = x; Form1->EditImageY->Text = y; // The white keys: if (x > 32 && x < 496 && y > 59 && y < 126) { pos = (x-32)/16.57142857; key = posToKey[pos]; } else key = 00; // flag for "off the keyboard" // The black keys: if (y > 59 && y < 105) { if (x > 61 && x < 70) key = 37; if (x > 78 && x < 87) key = 39; if (x > 111 && x < 120) key = 42; if (x > 127 && x < 136) key = 44; if (x > 144 && x < 153) key = 46; if (x > 177 && x < 186) key = 49; if (x > 194 && x < 203) key = 51; if (x > 227 && x < 236) key = 54; if (x > 243 && x < 252) key = 56; if (x > 260 && x < 269) key = 58; if (x > 293 && x < 302) key = 61; if (x > 309 && x < 318) key = 63; if (x > 343 && x < 352) key = 66; if (x > 359 && x < 368) key = 68; if (x > 376 && x < 385) key = 70; if (x > 409 && x < 418) key = 73; if (x > 425 && x < 434) key = 75; if (x > 459 && x < 468) key = 78; if (x > 475 && x < 484) key = 80; } if ((key != lastKey && Form1->RadioGroupKeyStrike->ItemIndex == 1) && key != 0 || Form1->RadioGroupKeyStrike->ItemIndex == 0 && key != 0) { // we ignore multiple mouse move events from the same key // and we ignore mouse moves and downs off the keyboard message.data[0] = 0x90; // key on message.data[1] = key; midiOutShortMsg(device, message.word); lastKey = key; Form1->EditKey->Text = key; } if (key == 0) Form1->EditKey->Text = "0"; } //-------------------------------------------------------------- Play a Scale void playScale (void) { for (int key = 35; key < 82; key++) { message.data[0] = 0x90; // key on message.data[1] = key; midiOutShortMsg(device, message.word); Form1->EditKey->Text = key; Sleep(tempo); if (Form1->RadioGroupKeySustain->ItemIndex == 1) { message.data[0] = 0x80; // key off message.data[1] = key; midiOutShortMsg(device, message.word); } Application->ProcessMessages(); } } //----------------------------------------------------------------- Play Tune void playTune (void) { tempo = 1000 - Form1->TrackBarTempo->Position; for (int times = 0; times < 3; times++) { for (int note = 0; note < length; note++) { if (tune[note] != 0) { Form1->EditKey->Text = tune[note] + times; Application->ProcessMessages(); message.data[0] = 0x90; // key on message.data[1] = tune[note] + times; midiOutShortMsg(device, message.word); } Sleep(tempo); if (Form1->RadioGroupKeySustain->ItemIndex == 1) { message.data[0] = 0x80; // key off message.data[1] = tune[note] + times; midiOutShortMsg(device, message.word); } } tempo -= 30; Form1->TrackBarTempo->Position = 1000 - tempo; } tempo = 220; Form1->TrackBarTempo->Position = 1000 - tempo; } //------------------------------------------------------------- Play Random 1 void playRandom1 (void) { int key; for (int i = 0; i < 50; i++) { key = random(46) + 36; message.data[0] = 0x90; // key on message.data[1] = key; midiOutShortMsg(device, message.word); Form1->EditKey->Text = key; Sleep(tempo); if (Form1->RadioGroupKeySustain->ItemIndex == 1) { message.data[0] = 0x80; // key off message.data[1] = key; midiOutShortMsg(device, message.word); } Application->ProcessMessages(); } } //------------------------------------------------------------- Play Random 2 void playRandom2 (void) { int key; for (int i = 0; i < 50; i++) { key = random(46) + 36; message.data[0] = 0x90; // key on message.data[1] = key; midiOutShortMsg(device, message.word); Form1->EditKey->Text = key; Sleep(random(300) + 100); if (Form1->RadioGroupKeySustain->ItemIndex == 1) { message.data[0] = 0x80; // key off message.data[1] = key; midiOutShortMsg(device, message.word); } Application->ProcessMessages(); } } //=========================================================================== // EVENT HANDLERS //=========================================================================== //---------------------------------------------------------- Form Constructor __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //------------------------------------------------------------ On Form Create void __fastcall TForm1::FormCreate(TObject *Sender) { message.data[0] = 0x90; //message.data[1] = 60; message.data[2] = 100; //message.data[3] = 0; midiOutOpen(&device, midiport, 0, 0, CALLBACK_NULL); } //------------------------------------------------------- Keyboard Mouse Down void __fastcall TForm1::ImageKeyboardMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { if (Form1->RadioGroupKeyStrike->ItemIndex == 0) { x = X; y = Y; selectKeyFromImage(); } } //------------------------------------------------------- Keyboard Mouse Move void __fastcall TForm1::ImageKeyboardMouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { if (Form1->RadioGroupKeyStrike->ItemIndex == 1) { x = X; y = Y; selectKeyFromImage(); } } //------------------------------------------------------- Instrument ComboBox void __fastcall TForm1::ComboBoxPatchChange(TObject *Sender) { instrument = ComboBoxPatch->ItemIndex; if (instrument > 95) { instrument += 24; // special effects } Form1->EditInstrument->Text = instrument; message.data[0] = 0xC0; // choose instrument message.data[1] = instrument; midiOutShortMsg(device, message.word); //midiOutShortMsg(device, message.data[0]); //midiOutShortMsg(device, message.data[1]); //midiOutSetVolume(device, 0xFFFF); message.data[0] = 0x90; // note on message.data[1] = 60; // key number midiOutShortMsg(device, message.word); //midiOutShortMsg(device, message.data[1]); } //------------------------------------------------------------ Tempo TrackBar void __fastcall TForm1::TrackBarTempoChange(TObject *Sender) { tempo = 1000 - TrackBarTempo->Position; } //--------------------------------------------------------- Loudness TrackBar void __fastcall TForm1::TrackBarLoudnessChange(TObject *Sender) { loudness = TrackBarLoudness->Position; message.data[2] = loudness; } //--------------------------------------------------------- Play Scale Button void __fastcall TForm1::ButtonPlayScaleClick(TObject *Sender) { playScale(); } //---------------------------------------------------------- Play Tune Button void __fastcall TForm1::ButtonPlayTuneClick(TObject *Sender) { playTune(); } //------------------------------------------------------ Play Random 1 Button void __fastcall TForm1::ButtonPlayRandom1Click(TObject *Sender) { playRandom1(); } //------------------------------------------------------ Play Random 2 Button void __fastcall TForm1::ButtonRandom2Click(TObject *Sender) { playRandom2(); } //--------------------------------------------------------- Play Quiet Button void __fastcall TForm1::ButtonQuietClick(TObject *Sender) { for (int i = 35; i < 82; i++) { message.data[0] = 0x80; // note off message.data[1] = i; // for each key midiOutShortMsg(device, message.word); //midiOutShortMsg(device, message.data[1]); } } //---------------------------------------------------------- That's All Folks