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. TheNote
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.
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.