Main Content

Design and Play a MIDI Synthesizer

The MIDI protocol enables you to send and receive information describing sound. A MIDI synthesizer is a device or software that synthesizes sound in response to incoming MIDI data. In its simplest form, a MIDI synthesizer converts MIDI note messages to an audio signal. More complicated synthesizers provide fine-tune control of the resulting sound, enabling you to mimic instruments. In this tutorial, you create a monophonic synthesizer that converts a stream of MIDI note messages to an audio signal in real time.

To learn about interfacing with MIDI devices in general, see MIDI Device Interface.

Convert MIDI Note Messages to Sound Waves

MIDI note information is packaged as a NoteOn or NoteOff midimsg object in Audio Toolbox™. Both NoteOn and NoteOff midimsg objects have Note and Velocity properties:

  • Velocity indicates how hard a note is played. By convention, Note On messages with velocity set to zero represent note off messages. Representing note off messages with note on messages is more efficient when using Running Status.

  • Note indicates the frequency of the audio signal. The Note property takes a value between zero and 127, inclusive. The MIDI protocol specifies that 60 is Middle C, with all other notes relative to that note. Create a MIDI note on message that indicates to play Middle C.

channel = 1;
note = 60;
velocity = 64;
msg = midimsg('NoteOn',channel,note,velocity)
msg = 

  MIDI message:
    NoteOn          Channel: 1  Note: 60  Velocity: 64  Timestamp: 0  [ 90 3C 40 ]

To interpret the note property as frequency, use the equal tempered scale and the A440 convention:

frequency = 440 * 2^((msg.Note-69)/12)
frequency =

  261.6256

Some MIDI synthesizers use an Attack Decay Sustain Release (ADSR) envelope to control the volume, or amplitude, of a note over time. For simplicity, use the note velocity to determine the amplitude. Conceptually, if a key is hit harder, the resulting sound is louder. The Velocity property takes a value between zero and 127, inclusive. Normalize the velocity and interpret as the note amplitude.

amplitude = msg(1).Velocity/127
amplitude =

    0.5039

To synthesize a sine wave, create an audioOscillator System object™. To play the sound to your computer's default audio output device, create an audioDeviceWriter System object. Step the objects for two seconds and listen to the note.

osc = audioOscillator('Frequency',frequency,'Amplitude',amplitude);
deviceWriter = audioDeviceWriter('SampleRate',osc.SampleRate);

tic
while toc < 2
    synthesizedAudio = osc();
    deviceWriter(synthesizedAudio);
end

Synthesize MIDI Messages

To play an array of midimsg objects with appropriate timing, create a loop.

First, create an array of midimsg objects and cache the note on and note off times to the variable, eventTimes.

msgs = [midimsg('Note',channel,60,64,0.5,0), ...
        midimsg('Note',channel,62,64,0.5,.75), ...
        midimsg('Note',channel,57,40,0.5,1.5), ...
        midimsg('Note',channel,60,50,1,3)];
eventTimes = [msgs.Timestamp];

To mimic receiving notes in real time, create a for-loop that uses the eventTimes variable and tic and toc to play notes according to the MIDI message timestamps. Release your audio device after the loop is complete.

i = 1;
tic
while toc < max(eventTimes)
    if toc > eventTimes(i)
        msg = msgs(i);
        i = i+1;
        
        if msg.Velocity~= 0
            osc.Frequency = 440 * 2^((msg.Note-69)/12);
            osc.Amplitude = msg.Velocity/127;
        else
            osc.Amplitude = 0; 
        end
    end
    deviceWriter(osc());
end
release(deviceWriter)

Synthesize Real-Time Note Messages from MIDI Device

To receive and synthesize note messages in real time, create an interface to a MIDI device. The simplesynth example function:

  • receives MIDI note messages from a specified MIDI device

  • synthesizes an audio signal

  • plays them to your audio output device in real time

Save the simplesynth function to your current folder.

 simplesynth

To query your system for your device name, use mididevinfo. To listen to your chosen device, call the simplesynth function with the device name. This example uses an M-Audio KeyRig 25 device, which registers with device name USB 02 on the machine used in this example.

mididevinfo
  MIDI devices available:
  ID  Direction  Interface   Name
   0   output    MMSystem   'Microsoft MIDI Mapper'
   1    input    MMSystem   'USB MIDI Interface '
   2    input    MMSystem   'USB O2'
   3   output    MMSystem   'Microsoft GS Wavetable Synth'
   4   output    MMSystem   'USB MIDI Interface '
   5   output    MMSystem   'USB O2'

Call the simplesynth function with your device name. The simplesynth function listens for note messages and plays them to your default audio output device. Play notes on your MIDI device and listen to the synthesized audio.

simplesynth('USB 02')

Use Ctrl-C to end the connection.

See Also

Classes

Functions

External Websites