← Back to list

How to Use MIDI in Swift to Play Chords in Your iOS/Mac app

Hello there, if you’ve ever wanted to use MiDi in your own music app or simply want to add a musical touch to your iOS/Mac project, you…

Carlos Mbendera in CodeX · 2023-07-26 12:41 · 45 claps · 3.1 min read
#swift #ios-development #swiftui #mac-development #audiotoolbox
Open on Medium ↗
Wiki topics: 📱 · Mobile Development 📟 · Gadgets & IoT 🎵 · Music & Audio

How to Use MIDI in Swift to Play Chords in Your iOS/Mac app

Hello there, if you’ve ever wanted to use MiDi in your own music app or simply want to add a musical touch to your iOS/Mac project, you might have come across MIDI(Musical Instrument Digital Interface).

In this article, I’ll explain how you can somewhat “easily”implement MIDI in Swift. We’ll be using Apple’s **AudioToolbox** framework.

Photo by GESPHOTOSS on Unsplash

Photo by GESPHOTOSS on Unsplash

Show Me The Code

Let’s begin with a brief overview of the basic implementation.

import AudioToolbox

First, import AudioToolbox. We will mainly use the AudioToolbox framework to manage and play MIDI sequences.

We’re going to create a createMusicSequence function that receives an array of chords, each represented as an array of UInt8 values (MIDI note numbers). The function then constructs a music sequence with these chords.

If you don’t want to read each step then skip to the bottom and see the complete function.


func createMusicSequence(chords: [[UInt8]] ) -> MusicSequence {
//Magic Here

Initialise an empty MusicSequence

var musicSequence: MusicSequence?
var status = NewMusicSequence(&musicSequence)

Next, set up a tempo track:

var tempoTrack: MusicTrack?
if MusicSequenceGetTempoTrack(musicSequence!, &tempoTrack) != noErr {
 assert(tempoTrack != nil, “Cannot get tempo track”)
}

Here, MusicSequenceGetTempoTrack retrieves the tempo track from the music sequence. The tempo track determines the speed of the music. You can set up different tempos at different points in the music sequence. In other words, the tempo track is responsible for the BPM (Beats Per Minute) of the sequence.

Now, we create a new track and adds each note in each chord to the track:

var track: MusicTrack?
status = MusicSequenceNewTrack(musicSequence!, &track)

var beat: MusicTimeStamp = 0.0
for batch in 0..<chords.count {
 for note: UInt8 in chords[batch] {
 var mess = MIDINoteMessage(channel: 0, note: note, velocity: 64, releaseVelocity: 0, duration: 1.0)
 status = MusicTrackNewMIDINoteEvent(track!, beat, &mess)
 }
 beat += 1
}

Each MIDINoteMessage specifies the properties of a MIDI note event, such as the note pitch (note), the intensity of the note (velocity), and the duration of the note (duration).

Finally, the function prints the music sequence to the console for debugging and returns it:


CAShow(UnsafeMutablePointer<MusicSequence>(musicSequence!))

return musicSequence!

Behold the complete function:

func createMusicSequence(chords: [[UInt8]] ) -> MusicSequence {

    var musicSequence: MusicSequence?
    var status = NewMusicSequence(&musicSequence)
    if status != noErr {
        print(" bad status \(status) creating sequence")
    }

    var tempoTrack: MusicTrack?
    if MusicSequenceGetTempoTrack(musicSequence!, &tempoTrack) != noErr {
        assert(tempoTrack != nil, "Cannot get tempo track")
    }

    //MusicTrackClear(tempoTrack, 0, 1)
    if MusicTrackNewExtendedTempoEvent(tempoTrack!, 0.0, 128.0) != noErr {
        print("could not set tempo")
    }
    if MusicTrackNewExtendedTempoEvent(tempoTrack!, 4.0, 256.0) != noErr {
        print("could not set tempo")
    }


    // add a track
    var track: MusicTrack?
    status = MusicSequenceNewTrack(musicSequence!, &track)
    if status != noErr {
        print("error creating track \(status)")
    }



    // make some notes and put them on the track
    var beat: MusicTimeStamp = 0.0

    for batch in 0..<chords.count {
        for note: UInt8 in chords[batch] {
            var mess = MIDINoteMessage(channel: 0,
                                       note: note,
                                       velocity: 64,
                                       releaseVelocity: 0,
                                       duration: 1.0 )
            status = MusicTrackNewMIDINoteEvent(track!, beat, &mess)
            if status != noErr {    print("creating new midi note event \(status)") }

        }// beat changes after this
        beat += 1
    }

    CAShow(UnsafeMutablePointer<MusicSequence>(musicSequence!))

    return musicSequence!
}

Calling The Function

We are going to write a small short function that uses all the code we wrote above so stay with me.

func createPlayer(chords : [[UInt8]]){
    var musicPlayer : MusicPlayer? = nil
    var player = NewMusicPlayer(&musicPlayer)

    player = MusicPlayerSetSequence(musicPlayer!, createMusicSequence(chords: chords))
    player = MusicPlayerStart(musicPlayer!)
}

Here is how we’d use it out in the wild.

let chords: [[UInt8]] = [[60, 64, 67], [62, 65, 69], [64, 67, 71]]
 // C, D, and E major chords
createPlayer(chords: chords)

Now an explanation. This function, createPlayer(chords: [[UInt8]]), accepts an array of arrays as input. Each inner array represents a chord, and each element in this array is a UInt8 representing a MIDI note.

Then we initialise a new MusicPlayer instance and bind it to the musicPlayer variable. Next, we set the music sequence for our player using MusicPlayerSetSequence(). The sequence is created using the helper function createMusicSequence(chords: chords). Finally, we start the MusicPlayer instance with MusicPlayerStart().

Photo by Kopfhörer Events Deutschland on Unsplash

Photo by Kopfhörer Events Deutschland on Unsplash

✨Yay! We did it!✨

✨Congratulations✨

Example Projects:

Here are a few projects I made using this implementation as a foundation.


메타데이터
post_id
48c9748b01e4
slug
how-to-use-midi-in-swift-to-play-chords-in-your-ios-mac-app-48c9748b01e4
url
https://medium.com/codex/how-to-use-midi-in-swift-to-play-chords-in-your-ios-mac-app-48c9748b01e4
canonical_url
https://medium.com/codex/how-to-use-midi-in-swift-to-play-chords-in-your-ios-mac-app-48c9748b01e4
author_url
https://medium.com/@carlosmbe
status
ok
fetched_at
2026-06-24 23:31:39