avatarSteven Curtis

Summary

This web content provides a technical guide on how to play MIDI notes using Swift's Playgrounds, detailing the necessary steps and offering code examples for creating and managing music sequences, tracks, and player instances for developers looking to incorporate musical elements into their applications.

Abstract

The article titled "Play MIDI Notes in Swift’s Playgrounds" introduces the concept of using MIDI (Musical Instrument Digital Interface) within Swift Playgrounds to produce musical sounds. It outlines the prerequisites for understanding the guide, including familiarity with Swift Playgrounds and the Singleton design pattern. The author emphasizes the use of the AudioToolbox framework, which is available in Swift Playgrounds, to handle audio playback. The guide covers setting up a Swift Playground for indefinite execution, creating a new music sequence and track, and constructing MIDI note events with specific parameters such as channel, note, velocity, release velocity, and duration. It also explains how to play a sequence of notes using a MusicPlayer instance. The article concludes with a discussion on using a Singleton pattern to manage music playback across different parts of an application, providing a practical example of a MusicPlayerManager. The author reflects on their personal journey, initially using AVPlayer and AVAudioPlayer for sound effects, and now favoring MIDI for its improved performance and flexibility.

Opinions

  • The author expresses that using AVPlayer and AVAudioPlayer for playing audio in apps was not an ideal experience due to performance issues and the quality of the samples used.
  • The author believes that incorporating MIDI into Swift Playgrounds is a more enjoyable and effective solution for audio playback in applications.
  • The author suggests that using a Singleton pattern for a MusicPlayerManager is the best approach for managing music playback when transitioning between views in an app, avoiding the complexity of creating and destroying instances.
  • The author provides a subjective opinion on the ease of using Swift's AudioToolbox framework, describing it as excellent news for developers.
  • The author encourages readers to explore MIDI notes for their own projects, providing a link to a resource for MIDI note references, and invites feedback or questions via Twitter, indicating a willingness to engage with the developer community.

Play MIDI Notes in Swift’s Playgrounds

Sounds good to me!

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!

The Playground setup

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

The MIDI steps

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? = nil
var musicSequenceStatus: OSStatus = NewMusicSequence(&sequence)
var track : MusicTrack? = nil
var 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? = nil
var 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

The MIDI steps: multiple notes

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

Swift
Swift Programming
iOS
Development
Software Development
Recommended from ReadMedium