The VS1053 and VS1003 audio codecs support real time MIDI. While the VS1003 only provides a few instruments, the VS1053 has 128 melodic instruments and quite a few additional percussion instruments!

When GPIO0 is low and GPIO1 is high during boot, real-time MIDI mode is activated. Unfortunately these pins are not available on most breakout boards. In this case a patch can be used to activate it.

When real time MIDI is active, you can send MIDI messages directly to the serial VS1003 input pin, but this is not available most of the time either. Fortunately you can also send the data via SPI, you just need to make sure that each MIDI byte is received as 2 byte word. I have extended my driver library to perform this conversion automatically. So with this we can use any MIDI Library that supports the output to Arduino Streams. Fortunately I have implemented such a library quite some time ago.

Example

Here is a simple example

#include "AudioTools.h"
#include "AudioLibs/VS1053Stream.h"
#include "Midi.h"


VS1053Stream vs1053; // final output
MidiStreamOut midi_out(vs1053);
uint8_t note = 65; // 0 to 128
uint8_t amplitude = 128; // 0 to 128
uint8_t instrument = 0;

void selectInstrument(uint8_t instrument, uint8_t bank=0x00){
  midi_out.controlChange(BANK_SELECT, bank);
  // Patch change, select instrument
  midi_out.programChange(instrument);
}

void setup() {
    Serial.begin(115200);
    AudioLogger::instance().begin(Serial, AudioLogger::Info);  

 // setup vs1053
  auto cfg = vs1053.defaultConfig();
  cfg.is_midi = true; // vs1053 is accepting streaming midi data
  // Use your custom pins or define in AudioCodnfig.h
  //cfg.cs_pin = VS1053_CS; 
  //cfg.dcs_pin = VS1053_DCS;
  //cfg.dreq_pin = VS1053_DREQ;
  //cfg.reset_pin = VS1053_RESET;
  vs1053.begin(cfg);
  vs1053.setVolume(1.0);

}

void loop() {
    Serial.println();
    Serial.print("playing ");
    Serial.println(++note);

    midi_out.noteOn(note, amplitude );
    delay(900);
    midi_out.noteOff(note, 20 );
    delay(200);
    if (note>=90) {
      note = 64;
      Serial.println();
      Serial.print("selecting Instrument ");
      Serial.println(++instrument);
      selectInstrument(instrument);
    }
}

As you can see we just need to give a VS1053Stream object as argument to a MidiStreamOut object!
This and further vs1053 examples can be found on Github.

Dependencies

You need to install the following libraries:

Final Comments

So far I could only test this on a VS1003 since I don’t have any working VS1053 yet.


0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published.