Midi Animation Starter Kit for iOS

Midi Animation Starter Kit for iOS

A starter kit and PDF tutorial that demonstrates and explains how to load, parse and play multi-instrument MIDI files in iOS, and how to create a real-time animation based on the MIDI notes.

  • Language: Objective-C
  • Released: Sep 2, 2012
    Last Update: Feb 13, 2014

The iPhone and iPad come with a very powerful audio library in the form of CoreAudio. It's fully featured, extremely flexible and consistently written. With a good knowledge of CoreAudio, you can make your audio processing dreams come true.

So you've read Apple's blurb and you're excited, time to crack open CoreAudio and find out that CoreAudio is written in C, it doesn't use object orientation and there's almost no documentation. It's also closed source and very unforgiving for the uninitiated.

This component is an objective-C library that wraps around CoreAudio and includes a comprehensive PDF guide of how to work with it to create MIDI based iOS apps.

What's included

  • Loading and parsing a MIDI file using CoreMidi: I'll show you how to load a MIDI file using CoreMidi and then access the MIDI events (Note, Tempo, Time Signature, etc...) individually. This puts you in full control and gives you access to all the information the file contains. I also clearly explain how the MIDI file fits together and what the important MIDI messages mean.

  • Lots of background information: In the tutorial I don't just explain how the example project works. I also give lots of background information and useful tips when processing MIDI files. I explain: bitwise operations, hex and binary, General Midi, how the percussion track work and much more! In fact the guide alone is over 5000 words long!

  • Writing a fully functional MIDI player: Step by step, I'll explain how to interpret the sequence of messages you retrieved from the MIDI file. The MIDI player uses multi-threading to play the sequence of MIDI messages in real-time. The MIDI clock class ensures that the MIDI file plays smoothly at the correct tempo. The MIDI player provides easy to use callback functions which give you access to all MIDI events in real-time. If you need events which I've aren't included it's easy to extend the framework to support all existing MIDI messages.

  • Audio Manager provides multi-timbral playback: CoreAudio on the iPhone only comes with a mono-timbral sampler. This means that you can only play your MIDI notes using one instrument sound. The Audio Manager which is included in the tutorial makes it easy to play your MIDI file using up to 10 instruments using a custom SoundFont. I show step by step how to setup a complex audio graph. I'll also show you how to set up the instruments based on information provided in the MIDI file. Doing this provides a rich sound as demonstrated in the video.

  • Putting it all together: In the final part of the tutorial I'll show how you can put all this together to create a rich MIDI based animation. The animation visualizes the notes as circles traveling from left to right across the screen. The vertical position of the circle depends on the value of the note. Notes pulse based on the metronome beat. Sharps and flats are circles with a random fill. This is a simple example but it could easily provide the basis of a cool game or MIDI playing app.

  • More than just a tutorial: The sample project, provided with the tutorial, provides a solid framework for your CoreMidi iOS project. The license allows you to use the framework in any number of your own projects. You can use this project as a learning exercise to learn CoreAudio and CoreMidi or base your whole project on the code.

This tutorial took me well over 100 hours to research and write. The information contained in this project just isn't available on the internet. If you're planning to write an app based on CoreMidi it's guaranteed to save you a substantial amount of time.

Hide

Installation Instructions

When you've downloaded the sample project unzip the directory to the desired location.

  • The directory contains the Xcode sample project and a PDF document containing a detailed explanation of the code.
  • In order for the MIDI file to be played it's necessary to download a SoundFont file. The SoundFont provides the instrument sounds for the MIDI file. Due to it's size, the SoundFont file is not included with the sample project.
  • The SoundFont can be downloaded here. Once downloaded, place the SoundFont file in the "Resources" directory of the Xcode project and you're ready to go!
You need to log-in or create an account
  • Create an account
  • Log-in

Please use your real name.

Activation link will be sent to this address.

Minimum 8 characters

Enter your password again

Clicking this button confirms you read and agreed to the terms of use and privacy policy.

X

Save your watchlist

Fill your details below to receive project updates from your watch list - including new versions, price changes and discounts.

I agree to the terms of use and privacy policy.

2 licenses, starting from From » $69.99 View Licenses 14 day money-back guarantee
  • support ios5.1 and 6
    AG Alexandro frisone Gomes
    2 years ago, 0 comments
    Was this helpful?
    Flag
Post a comment

Or enter your name and Email
  • KZ Kenis Zhu License holderApplication License 2 months ago
    Hi Ben, how to obtain the MIDI file Key Signature by using Midi Animation Starter Kit for iOS? Any example or tutorial? Many thanks Kenis
  • KZ Kenis Zhu License holderApplication License 2 months ago
    Hi Ben, there's a short question about the note duration. for (BMidiEvent * event in sequence.getSequence) { switch (event.eventType) { case Note: { BMidiNote * note = (BMidiNote *) event; NoteBase *noteBase = [MidiNumberNote instance][[NSString stringWithFormat:@"%i",note.note]]; NSLog(@"Channel: %i, note: %i, start time: %i, duration: %i", note.channel, note.note, note.getStartTime, note.getDuration ); then I got the below result: ...... PPNQ: 256 Tempo, BPM=0.000000, PPNQ=256, 32ndNotesPerBeat=0 ...... Channel: 0, note: 71, start time: 11008, duration: 256 Channel: 0, note: 73, start time: 11264, duration: 512 So the duration : 256 and 512, does it means 256 millisecond and 512 millisecond? and each Quarter Note is 256 milliseconds (cause PPQN = 256) please correct me if i am wrong. Many thanks Kenis
    • Ben Smiley Developer 2 months ago
      Hi Kenis, The duration is given in pulses. There's a better explanation in the PDF tutorial that comes with the starter kit. Basically, The PPNQ is pulses per quarter note. The BPM is beats per minute. If the music is has a time signature denominator of 4 then a beat is the same as a quarter note. Pulse length = 60/(BPM * PPNQ) A duration of 256 pulses would be 1 quarter note which would be a 1 second duration at 60 BPM. I hope this helps, Ben
  • Ben Smiley Developer 3 months ago
    Hi Kenis, First you need to create a new instance of the BMidiManager then call processMidiFile. // Create a new midi manager and load our midi file BMidiManager * midiManager = [BMidiManager new]; // The process midi file will return a our sequence of MIDI events BSequence * sequence = [midiManager processMidiFile:@"jingle"]; This will give you a BSequence object. So then you can loop over the sequence to get the notes: for (BMidiEvent * event in sequence.getSequence) { switch (event.eventType) { case BEnumNoteEvent: { BMidiNote * note = (BMidiNote *) event; NSLog(@"Channel: %i, note: %i, start time: %i, duration: %i, velocity: %i", note.channel, note.note, note.getStartTime, note.getDuration, note.velocity); } break; case BEnumTempoEvent: break; case BEnumChannelEvent: break; } } The core MIDI API doesn't map exactly to the raw MIDI commands. When it parses a file it converts note-on and note-off commands to notes with durations. i.e. time: 100 pulses - note-on, C6 time: 200 pulses - note-off, C6 Converts to: time: 100 pulses - note C6 duration 100 pulses It should be quite easy to go back to the original midi. First add a new "isNoteOff" property to BNoteEvent. Then create a new BSequence object. As you loop over the events (as I show above) add the event to the new sequence you made. Straightaway create a new BNoteEvent and copy the details from the current event but set "isNoteOff" to "yes" and set startTime to the original event's start time plus it's duration. // Create a new BSequence BSequence * newSequence = [[BSequence alloc] init]; // Loop over events (as above) for (BEvent * event ...) { BNoteEvent * note = (BNoteEvent *) event; // For each event add it to the new sequence newSequence addEvent: ... // Create a new note event object BNoteEvent * noteOffEvent = [BNoteEvent alloc]... // Copy the data from the original event noteOffEvent.note = note.note etc... // Set the isNoteOff property to yes noteOffEvent.isNoteOff = YES; // Set the start time to the original note + duration... noteOffEvent.startTime = note.startTime + note.getDuration; // Add it to the new sequence [newSequence addEvent: noteOffEvent] } // Re-sort the sequence by time [newSequence sortSequenceByStartTime] I hope this helps with your problem. Thanks, Ben
    • KZ Kenis Zhu License holderApplication License 3 months ago
      it works. many thanks
    • KZ Kenis Zhu License holderApplication License 3 months ago
      And one more thing. I wanna to record the song form iPhone Microphone. then convert it to Midi file and print out the midi note and duration. How to record song and convert it to midi file? Could you show me some sample code? thanks~~
    • Ben Smiley Developer 3 months ago
      Hi Kenis, I'm afraid what you want to do is extremely difficult. Recorded music comes as an analogue wave. It's a superposition of lots of different frequencies from the different instruments. To convert that to MIDI, you'd have to somehow decompose the wave into the component parts for each instrument. Then determine the notes played - which is complicated in itself because of harmonics and overtones. Given that there would be noise too, this is currently impossible for music containing more than one instrument. Sorry I couldn't be more help, Ben