Why do I need to use the Virtual Piano MIDI Keyboard to connect to Coolsoft Virtual MIDI Synth on Windows?

I have duplicated the hardware and code from this tutorial: https://docs.arduino.cc/tutorials/generic/midi-device

and everything works fine as long as I have VPMK setup between my Leonardo (clone) and the Coolsoft synth.

I am puzzled as to why VPMK is needed at all and, if so, are there are any alternatives to achieve the connection?

My concern is that running through a separate program like VPMK will introduce (more) latency on Windows.

What is VPMK? I know it is not legal services which a search shows. Also post a sketch as to how you have put it together.

VMPK - Virtual MIDI Piano Keyboard

The code and the instructions to use VMPK is in the Arduino tutorial article in my first post, but here is the code:

/*

   This examples shows how to make a simple seven keys MIDI keyboard with volume control

   Created: 4/10/2015

   Author: Arturo Guadalupi <a.guadalupi@arduino.cc>



   http://www.arduino.cc/en/Tutorial/MidiDevice

*/

#include "MIDIUSB.h"
#include "PitchToNote.h"
#define NUM_BUTTONS  7

const uint8_t button1 = 2;

const uint8_t button2 = 3;

const uint8_t button3 = 4;

const uint8_t button4 = 5;

const uint8_t button5 = 6;

const uint8_t button6 = 7;

const uint8_t button7 = 8;

const int intensityPot = 0;  //A0 input

const uint8_t buttons[NUM_BUTTONS] = {button1, button2, button3, button4, button5, button6, button7};

const byte notePitches[NUM_BUTTONS] = {C3, D3, E3, F3, G3, A3, B3};

uint8_t notesTime[NUM_BUTTONS];

uint8_t pressedButtons = 0x00;

uint8_t previousButtons = 0x00;

uint8_t intensity;

void setup() {

  for (int i = 0; i < NUM_BUTTONS; i++)

    pinMode(buttons[i], INPUT_PULLUP);
}

void loop() {

  readButtons();

  readIntensity();

  playNotes();
}

// First parameter is the event type (0x0B = control change).
// Second parameter is the event type, combined with the channel.
// Third parameter is the control number number (0-119).
// Fourth parameter is the control value (0-127).

void controlChange(byte channel, byte control, byte value) {

  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};

  MidiUSB.sendMIDI(event);
}

void readButtons()
{

  for (int i = 0; i < NUM_BUTTONS; i++)

  {

    if (digitalRead(buttons[i]) == LOW)

    {

      bitWrite(pressedButtons, i, 1);

      delay(50);

    }

    else

      bitWrite(pressedButtons, i, 0);

  }
}

void readIntensity()
{

  int val = analogRead(intensityPot);

  intensity = (uint8_t) (map(val, 0, 1023, 0, 127));
}

void playNotes()
{

  for (int i = 0; i < NUM_BUTTONS; i++)

  {

    if (bitRead(pressedButtons, i) != bitRead(previousButtons, i))

    {

      if (bitRead(pressedButtons, i))

      {

        bitWrite(previousButtons, i , 1);

        noteOn(0, notePitches[i], intensity);

        MidiUSB.flush();

      }

      else

      {

        bitWrite(previousButtons, i , 0);

        noteOff(0, notePitches[i], 0);

        MidiUSB.flush();

      }

    }

  }
}

// First parameter is the event type (0x09 = note on, 0x08 = note off).
// Second parameter is note-on/note-off, combined with the channel.
// Channel can be anything between 0-15. Typically reported to the user as 1-16.
// Third parameter is the note number (48 = middle C).
// Fourth parameter is the velocity (64 = normal, 127 = fastest).

void noteOn(byte channel, byte pitch, byte velocity) {

  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};

  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {

  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};

  MidiUSB.sendMIDI(noteOff);
}

I suspect that the problem is Coolsoft Virtual MIDI Synth because I just tried the same setup (sketch and hardware) plugged* into an Android phone running the Fluidsynth app and it worked immediately.

If Coolsoft Virtual MIDI Synth is the problem then is there another synth I can use on Windows? Maybe Qsynth/Fluidsynth?

  • You need a USB 'On the Go' (OTG) adapter for the phone.