Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Powerbasic

MIDI Piano

4.92/5 (6 votes)
16 Apr 2017CPOL1 min read 14.8K   1.1K  
Midi keyboard with both mouse and computer keyboard control

Introduction

This is the C++ 64-bit transcription of an original PowerBASIC project written by Borje Hagsten.

The C++ version is built upon direct access to the core FLAT SDK API to produce a tiny standalone EXEcutable of only 36 KB. This was done by eliminating as much as possible most of the CRT, using the same approach done by Matt Pietrek's LibCTiny.lib, and the different techniques explained here.

This project has also been translated into WinDev p-code here.

About the Use of the Custom Control

Image 1

The GUI exposed a complete MIDI interface using either the mouse or the PC's keyboard to play the selected instrument.

You can press on F1 to display this information help:

Image 2

Using the Code

This project has been done with the latest C++ Visual Studio 2017 community free version.

For the fun of it, you can enable extra skinning by editing the lines of code shown below (at the end of Main.cpp).

C++
//if (skInitEngine (L"Reader.sks", L"")) {               // these 2 lines enable or disable
//    if (skSkinWindow(gP.hMain, (WCHAR*) SYSTOOLTIP)) { // the use of the WinLIFT skin engine.
          // Show the main window
          ShowWindow(gP.hMain, nCmdShow);
          UpdateWindow(gP.hMain);
          while (GetMessage(&msg, NULL, 0, 0)) {
              TranslateMessage(&msg);
              DispatchMessage(&msg);
          }
//    }
//}

then with the WinLIFT magic, the whole GUI will change to this:

Image 3

Points of Interest

You can reduce drastically the size of your 64-bit code if you follow these few steps:

  1. Always use direct call to the core FLAT API whenever available
  2. Prefer procedural code when there is no need to use a class to achieve the same thing
  3. Use explicit linking rather than implicit
  4. Get free of the runtime Library, using Multi-threaded (/MT) in the code generation

And here is an example on how to use explicit linking to MSVCRT to achieve ultimate granularity:

#define long_proc typedef long (__stdcall *zProc)
#define void_proc typedef void (__stdcall *zProc)
#define double_proc typedef double (__stdcall *zProc)

#define M_LOG2E 1.44269504088896340736 

HMODULE MSVCRT() {
    static HMODULE hModule;
    if (hModule == 0) { hModule = LoadLibrary(L"MSVCRT"); }
    return hModule;
}

double log2(IN double X) {
    double l2 = 0;
    HMODULE hModule = MSVCRT();
    if (hModule) {
        double_proc (double);
        zProc hProc = (zProc) GetProcAddress(hModule, "log");
        if (hProc) { l2 = hProc(X) * M_LOG2E; }
    }
    return l2;
}

void RandoMize(IN DWORD seed) {
    HMODULE hModule = MSVCRT();
    if (hModule) {
        void_proc (DWORD);
        zProc hProc = (zProc) GetProcAddress(hModule, "srand");
        if (hProc) { hProc(seed); }
    }
}

long Rand() {
    long nRand = 0;
    HMODULE hModule = MSVCRT();
    if (hModule) {
        long_proc ();
        zProc hProc = (zProc) GetProcAddress(hModule, "rand");
        if (hProc) { nRand = hProc(); }
    }
    return nRand;
}

size_t rnd(IN long nMin, IN long nMax) { // QWORD
    double dblRange = nMax - nMin;
    double dblMaxFactor = dblRange / RAND_MAX;
    double dblRandomNumber = (double) Rand();
    return (size_t) (nMin + dblMaxFactor * dblRandomNumber);
}

The End

Enjoy playing midi with this tiny piece of { unsafe } code. ;)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)