EN | Arduino: processing MIDI data

5UfGenJ

A few months ago I decided to start building an all analog, modular synthesizer, which is still in it’s build process. Some time after that, my school asked us to take on a project of our choice. I decided to create code for a MIDI to CV interface to complement the modular. This video explain it’s overall functions and modes.

 

Basically, this « pseudolibrary », aka a .h file which is just located in the sketch’s folder uses the MIDI.h library to read for incoming signals. When an incoming signal is received, it gets to a function which manages it. If there is no output which carries that that type of output, it’s ignored. If one of the outputs does carry this type of signal, the signal goes on to a function which determines to which output the signal has to be sent by looking up it’s type and parameters if it has any (for example, a CC’s id). When a match is found, the value gets sent to a function which maps the value so that the output voltage makes sense (for notes, it’s mapped in either Hz/V or V/oct). For notes and data that are linked to individual voices (gate, note, velocity and poly aftertouch), there are a few extra steps relative to polyphony gestion.

Circuit schematic

4N35gray90FR

This is the circuit I’m currently using to connect the MIDI input to the Arduino. If you plan on building an interface, I’m strongly recommending to use a DAC with a minimal resolution 12 bit over 5 volts if you want to get decent accuracy. Take into account that, using volts/oct, the steps are 0.083v each, so just a small error can cause a lot of detuning.

I also recommend using a MCP4728, which is a 4 output 12 bit DAC you can get for 3$. Someone has also written a library for it, which you can get here. This library was written on an older version of the Arduino IDE, and some basic function syntax has changed since, which causes the library to fail to compile. Fixing it is quite easy and is described in this thread.

Basic use

To make this work properly, we have to do a few things. First off, at the top of your file, you must include the MIDI.h library and initialize it (get it here if you don’t already have it).

#include "MIDI.h"
MIDI_CREATE_DEFAULT_INSTANCE();

Before we include MIDItoCV.h, we must define a few values it needs.

//#define HZV // uncomment this for hertz/volt mode
//#define VOCT // uncomment this for volt/octave mode
#define AMOUNTOUTPUTS 4 // this is the amount of outputs you have
#define CHANNEL 1 // this is the MIDI channel you want to use
#define POLY 4 // this is the maximum amount of polyphony/voices. more voices = less avaliable RAM

Ok! now we can include MIDItoCV.h Here’s the download link for my code , released under Creative Commons liscence BY. Remember, MIDItoCV.h is not a library! you must put it in your sketch’s folder!

#include "MIDItoCV.h"

In your setup, you must call setupMIDItoCV(), a function that sets up variables and inner-workings of MIDItoCV:

void setup()
{
setupMIDItoCV();
}

Finally, you need to put MIDI.read() in your loop so that we read incoming MIDI data.

void loop()
{
MIDI.read();
}

Now, you may use a few functions in your setup to assign modes, parameters and ways to output data to each of your outputs. Note that you are not limited to using these functions in the setup.

Let’s start with assigning a mode. The function used for that is setoutputaction(outputnumber, mode, parameter)

  • outputnumber is the number of the output, ranging from 1 to AMOUNTOUTPUTS you defined earlier.
  • mode can be one of the 8 modes; NONE, NOTE, VELOCITY, GATE, POLYAT, CHANNELAT, BEND, or CC.
  • parameter is additional parameter that is only used for polyphonic modes and CC. For polyphonic modes, (NOTE, VELOCITY, GATE and POLYAT), the parameter is the number of the voice. For CC, it simply is the continuous controller id.

Next, let’s see how we can output data. The function we have to do that is a bit special. Here’s what it looks like: setoutputfunction(outputnumber, outputfunction)

  • outputnumber is the output’s number
  • outputfunction is a function to which the output value is passed

If you were a bit confused about the last parameter, it’s essentially the name of a function which takes a value and outputs it where you want. Here’s an example.

int outputfunction1(int value) // this is the function that takes the received value and outputs it
{
analogWrite(6, value); // our output is pin 6 using analogWrite
}

setoutputfunction(1, outputfunction1); // we set the output to use our output function

Now, the program needs some info about the way you are outputting your data to correctly output volts per octave or hertz per volt. Here’s the function: setoutputrange(outputnumber, minvalue, maxvalue, minvoltage, maxvoltage)

  • outputnumber is the output’s number
  • minvalue is what your output function expects as a minimum value
  • maxvalue is what your output function expects as a maximum value
  • minvoltage is the voltage your output function will output when at minvalue, in millivolts
  • maxvoltage is the voltage your output function will output when at maxvalue, in millivolts

Let’s have an example.

int outputfunction1(int value) // Cette fonction reçoit les données de l'output 1 et l'écrit par PWM sur la pin 6
{
analogWrite(6, value); // la valeur est écrite sur la pin 6
}

setoutputfunction(1, outputfunction1); // on définit la fonction de sortie
setoutputrange(1, 0, 255, 0, 5000); // analogWrite prend des valeurs de 0 à 255 produit des voltages de 0V à 5V

Since it’s quite likely that your outputs use the same way of outputting data (the same range of values over the same voltage), it would be annoying to have to define their output range/voltage parameters individually, which is why the function setoutputrangeall(minvalue, maxvalue, minvoltage, maxvoltage) eexists. The parameters are the same as the last functions apart from the absence of the outputnumber parameter, since you are selecting all outputs.

A in-depth guide covering advanced functions should be released soon.

Written by Simon Demeule, 2015

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s