Play MIDI Notes in Swift’s Playgrounds

Photo by Park Troopers on Unsplash

Prerequisites:

  • Coding in Swift Playgrounds (guide HERE)

A Singleton is covered in slight detail, some might benefit from the background information in a more in-depth article

Terminology

AudioToolbox: A framework to record and play audio

MIDI (Music Instrument Digital Interface): A standard for musical instruments, and can be used to play MIDI instruments on Apple Devices

MusicSequence: The music sequence previously attached to the audio engine

MusicTrack: Several music events, each timestamped using a series of beats

Motivation

I’ve created several Apps that require a small piece of audio to play (a *bing* or *chime*. I’ve experimented with AVPlayer and AVAudioPlayer, and looking around on the web for public domain chimes.

It wasn’t that fun I’ll admit that. The performance wasn’t where I wanted it to be, and the quality of the samples I used.

Well.

I’m a better developer now (probably). I can find a better solution (probably).

Why didn’t I think of MIDI before?

MIDI Audio — In a Playground

Look, Swift has you well covered in terms of providing AudioToolbox , and of course this Framework is avaliable in Playgrounds. This is excellent news!

Now since audio playback is asynchronous we will have to pull out one of our best tricks, that is the playground needsIndefiniteExecution . This means that our playground needs two lines of code:

import PlaygroundSupport

and

PlaygroundPage.current.needsIndefiniteExecution = true

It is with this in place, we can approach the challenge with a light heart and a full brain (or something).

Now don’t panic, there is a full playground at the end of this section of the article to help you out, and right here is a step-by-step explanation of how each section of code works.

With that clear, let us press on.

Create a new music sequence and a track

var sequence : MusicSequence? = nilvar musicSequenceStatus: OSStatus = NewMusicSequence(&sequence)var track : MusicTrack? = nilvar musicTrack = MusicSequenceNewTrack(sequence!, &track)var time = MusicTimeStamp(1.0)

A musicSequenceStatus is simply an OSStatus making sure that NewMusicSequence has created the 120 beats-per-minute tempo track on the sequence. The track is where will will lay down our mean beats (play the MIDI instruments).

So then we add an (empty) track to the sequence, again returning an OSStatus.

time as a MusicTimeStamp refers to time values in the sequence, and is measured in beats.

But we haven’t even got started yet. But we have all of the elements needed to make a note.

Drooooopppp

var note = MIDINoteMessage(channel: 0,
note: 85,
velocity: 64,
releaseVelocity: 0,
duration: 5.0)

This note is all very nice, let us explain each part in turn:

  • channel: The midi channel to be used
  • note: The midi note (This is A5, musician friends)
  • velocity: The force with which the note is played
  • releaseVelocity: The speed with which that the key is released
  • duration: The length of the note

We then create a rather attractively named MIDINoteEvent (which again returns an OSStatus), made up of the track (where the notes are played), time (time values in a sequence) and passing the note (that is the note to be played) by reference.

musicTrack = MusicTrackNewMIDINoteEvent(track, time, &note)

Now we have a MusicTrackNewMIDINoteEvent added, which is a music track containing a sequence and music track.

We can then create a MusicPlayer to, you know, play the track.

var musicPlayer : MusicPlayer? = nilvar player = NewMusicPlayer(&musicPlayer)player = MusicPlayerSetSequence(musicPlayer!, sequence)player = MusicPlayerStart(musicPlayer!)

The NewMusicPlayer takes the MusicPlayer passed by reference, which is then Set a sequence then actually started.

Awesome

Each note in turn will have a timestamp (obviously the next beat) and I can write each particular note as a UInt8.

var notes: [UInt8] = [71,69,62,72,71,69,67]

To create multiple notes you can use MusicTrackNewMIDINoteEvent multiple times. An example? Go on then:

I’ve put a guard statement in to prevent force unwrapping the track unnecessarily.

Have you guessed what the basic melody of the song is?

For that you might need the whole code. Go on, here it is:

The Singleton Story

You might want to play a sound effect just as you move between views. Or have some music playing as you move around your App.

Good luck with creating and destroying instances as such a proposal seems like a whole mess.

The best approach to take would be a MusicPlayerManager to manage the playing of music. No problem, master!

Conclusion:

MIDI allows us to have some fun with music, and this is even possible when using a Playground to make our creative musings real by using MIDI. If you want the MIDI notes for use in your own projects, you can use this rather splendid website. Now get going, you maestro, you.

Any questions? You can get in touch with me in a Twitter rant. HERE

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store