Glenn Andreas - Glenn started Mac programming in the Fall of 84 when he conned his boss into buying him a Lisa and the original IM. Since then, hes written the game Theldrow, worked for Palomar Software writing printer drivers, and done various freelance programming jobs, including a sped up version of the Stylewriter driver (which never shipped), and some work on the printing portions of Bedrock (which also never shipped). Hes currently working a day job which involves hacking the BSD kernel, while trying to finish his latest game Chimera (which will hopefully ship one day).

Editors Introduction

Glenn tried to use Apple docs to figure out how to generate MIDImusic with QuickTime 2.0. He ran into the common insufficient documentation (whats that error number, again?) roadblock, and dove in to figure out how things really operate. In doing so, he ran some risk of learning how to do things the wrong way, so we gave some good folks at Apple a crack at his article. While calling the approach a bit hackish because he defines his own headers, they say he pretty much got it right. While there are easier ways to put MIDItunes into QuickTime movies and play them as background music, this article shows you how to drive from the APIlevel. Its rather like using the Sound Manager with QuickTime.

Two caveats - the flags in TuneStop are not implemented (the article suggests they are) and TuneResume doesnt.

Be sure to check out the real documentation when it comes available, and enjoy MusicTest in the meantime!

The Motivation

As I worked on my latest project, I wanted to have background music. I was originally planning on writing some sort of auto mixing my own sound buffers from hell sound manager hack, and while these are fun to write, it would take a great deal of resources to get it correct. Then I heard that QuickTime 2.0 would include the ability to play music, as music. Sort of like MIDI I heard. Call me a crazy, but Id rather just make a few component manager calls rather than spend months writing my own music playing routines (besides having all my work done for me, QT 2.0 can play the music through an external MIDI device as well for even better quality with almost no system load). So, I got a beta of QT 2.0, and immediately dove into the Macintosh Music Architecture document. This was rather like diving in the shallow end of the pool. Given that the header code and the documentation didnt synch all that well, and assuming that the underlying code followed yet another convention, I did what any resourceful programmer would do - I dropped into MacsBug.

Fortunately for me, MoviePlayer was able to correctly play some of the sample music movies included on the beta CD. And, also fortunately for me, the whole music architecture is build uses the component manager (which, by the way for those who have never really looked at it, is really cool). So I set a breakpoint at the beginning of the Tune Player Component, and watched every call made by QuickTime as it played music. And finally, after countless reboots, I was able to make my Mac play music from my own programs.

At this point, I saw this as an opportunity for a little fortune and glory. Given that the only existing document I had on how to play music was inaccurate, I figured that I would write this article explaining just what it will take for you to easily add background music to your current or future project. Note that this article is in no way official documentation, it is simply what I have discovered on how things works. Ill only present a subset of the routines available (see the header files for QuickTime 2.0 which appear in the August Developer CD for more details), and all examples will be based on what Ive found in snooping around (so if I say that this parameter is zero, that means that Ive always seen this parameter as zero, not that it has to be - but unless you like rebooting, you might want to leave it as zero). Also, I will attempt to avoid as much music theory as possible, since not only are there good books on this already, my knowledge is weak in that area, and I wouldnt want to provide misleading information. This will be in Pascal, and Ill simplify the header file so we dont have to include dozens of other files (because QuickTime wants Aliases which wants AppleTalk which wants, well, you get the idea). First, however, lets look at a quick bit of pseudo-code and see what it is we are going to do.

Overview

In order to play music, we need two important pieces of information - what notes to play, and what instruments to play them on. This first part is the body of the tune, while the second is what is called the header of the tune. In QuickTime, the tune header, along with some additional information, is stored in the media handler information (in the resource fork), while the tune body is stored in the actual data (on the data fork). For this article, we will store both in a single resource, starting with what the media handler information would be (as defined in MusicDescription record), with the tune body appended onto the end.

Here, then, are the basic steps we will use to play music:

 Create a tune player component

 Feed the music header the header from our resource

 Tell it to start playing the body from our resource

 Wait until it finishes

 Make sure to tell it to stop playing

 Dispose and clean up.

But before we get to the code, lets look how the music is stored (this is important, so dont skip ahead).

Storage of Musical Notes

Music is stored as a series of commands. Each command usually takes one longint, but can take two or more. Examples of these commands are to play a given note on a given instrument at a given pitch and given volume for a given duration, or to have a given instrument wait a given duration. And thanks to the Time part of QuickTime, multiple instruments can all be synched together, or their tempo can just as easily be changed (but for you QuickTime junkies, I will not be getting into time bases).

These commands are similar to MIDI commands, if you are familiar with them. If you arent, by the end of this section youll know that MIDI commands are similar to QuickTime music commands. These commands are tagged with what the command is in the high three or four bits, with the remaining bits (or following long word or words) providing the parameters. Note that all commands are multiples of four bytes long, so you can easily scan them as an array of LongInts.

Before we get to the commands themselves, we need to look at some of the parameters first. Almost all commands require a integer parameter to specify which instrument the command affects. An instrument is just that - a single instrument. QuickTime provides 30 some odd instruments to choose from. You can have more than one instrument playing in a given song (so you can have Dueling -insert your favorite instrument here-). Also, a single instrument can play more than one note at a time (being able to play a chord). Before playing the song, you tell the tune player component how many instruments there are and what they are, but well get into this later.

Other parameters are fairly self explanatory.

Volume (also called velocity, because it refers to how hard you strike the key on a keyboard), ranges from 0 (silent) to 63.

Duration is specified in units that are specific to the tune component (in our examples we use 1/600ths of a second). Warning, some music theory follows: Based on the default time units, and assuming 4/4 time (which means that a quarter note is 1/2 second long), below is a quick table of duration values and the length of notes they produce:

Units at 600/second Note produced

75 sixteenth note

150 eight note

300 quarter note

600 half note

1200 whole note

Pitch, which ranges from 0 to 127, corresponds to the same values MIDI uses. Pitch ranges from C five octaves below middle C (0) to G five octaves above middle C (127). Middle C has the value of 60. A complete table of these values can be found on page 2-43 of the recently published IM:Sound. While it is possible to play what is called microtonal values, which can be just about any pitch (they are represented with fixed point numbers), this is done via a different, much less convenient, interface.

One other thing to be aware of is that most commands have an extended form that usually takes two long words instead of one. This allows more bits for each parameter, but in all my snooping Ive yet to come across anything that uses them. For the sake of simplicity, Ill also restrict myself to just the commands that are commonly used. In the commands below, Ill show all thirty two bits, with the most significant bit on the left, with a space between each four bits for easier reading.

Our first command is the rest command:

000- ---- dddd dddd dddd dddd dddd dddd

The 000 is the rest command. The next five bits would normally be for the instrument, but for the rest command are unused (and should be set to zero). Those are followed by twenty-four bits of duration d. This just instructs the instrument not to start any more commands until that time has passed.

The next command is the note command:

001i iiii pppp ppvv vvvv vddd dddd dddd

The 001 is the note command, the is are five bits representing what instrument (0-31), and the ds are again duration (though for this command there are only 11 bits, so the value ranges from 0 to 2047, or in our examples, over 3 seconds). The six bits of ps are our pitch, again as a MIDI note value, and the seven bits of vs are the volume.

These two commands are enough to start playing music. However, if you wanted to play a scale, and you just issued eight note commands with increasing pitches, you would get one short polyphonic cacophony - all the notes would play at the same time, as a chord, rather than as eight sequential notes. To achieve the desired effect (each note in sequence), you need to issue eight note-rest command pairs, to allow time for one note to play before starting the next.

One final command in this example is needed - a command to have it stop. Without it, it will start playing whatevers in memory, and soon youll be rebooting. The command to stop playing is the marker command:

011- ---- ssss ssss xxxx xxxx xxxx xxxx

The 011 is the marker command, the -s are unused (and should be set to zero). The eight bits of s are the marker event subtype, and the xs are the marker event value. The only values Ive seen are zero for both, which is used to mark the end of the playing - all music command lists end with the value $60000000.

For the sake of completeness, here are the rest of the commands (though we will only be using one of them):

010i iiii cccc cccc xxxx xxxx xxxx xxxx

Control: i is instrument, c is controller, x is the value to set that controller to.

This is the general command, which isnt used in playing the music, but rather is used when you set up the tune player component. It is this command that is used to tell the player what instruments are what. The is, of course, are the instrument, the ts represent one of the following:

1 Note request

2 Instrument

3 Flat Instrument

4 Part Name

5 Part Key

Ive only seen Note Request, so that is all that I will talk about. The ls represent the length of the entire command, including any general data. This value is in long words, and includes both long words of the command. Finally, between the two commands is some amount of additional data. Heres an example to help explain this - this is the command from the header portion of some music, and it instructs the tune player that instrument zero is a normal piano:

The $F0000017 says that this is a general event for instrument zero, and the whole thing is $17 (23) long words long. Following that is $15 long words, which actually are a data structure known as a NoteRequest. The last long word $C0010017 says that it is, surprisingly enough, a note request, and the whole thing was $17 long words long. Why this value is repeated in both places Im not sure - perhaps there is some sort of integrity check.

Before we get to the code, lets make some Rez definitions so we can create our music - I am currently working on a music editor that will produce these music resources, but I can hardly include the source for that as well in this article (especially since it isnt done yet). It should be done and available in a variety of online places by the time you read this. [Check out our online places. See p.2 for details - Ed stb]

Musi Resources

I made a simple Music.r file (see listing 1) which will allow us to use Rez to create and edit music. Here is our sample input:

This says that we have one instrument, the grand piano, to be played on any synthesizer. If you want to just play around, you can change the last two 1s to other values to play other instruments without having to change the name. Id advise leaving the polyphony 1 and 0x10000 as is, as well as the synthesizer type and name.

After the header we play a C# in octave 3 (37) at average volume (64) for 3 seconds (1800, since our time scale will have 600 units per second). We rest for those three seconds to let the note play. We then play a B in octave 2 (11) for 1 1/2 second, and also rest to let the note play. We next play a chord of four notes for 3 seconds: E in octave 3 (28), G in octave 3 (31), B in octave 4 (35), and E in octave 1 (4). We let that play and rest for an additional 2 1/2 seconds. We end the thing with our marker command (we could have made that last command part of the rez template like we did for the header, but we might as well mark the end explicitly).

Heres the hex dump of that resource, formatted to show what is going on a little better:

There are many more calls in QuickTimeComponents.h than Ill document here, since the focus is to show what it takes to play music in the background of your application. Instead we will just look at the major routines for the tune player component, and ignore both the note allocator and low level music component. This is all from listing 2, my Music.p interface file derived from QuickTimeComponents.h. Im also going to assume that youve got access to header files and documentation for the Component Manager (found in IM:More Macintosh Toolbox).

This specifies how many units per second the duration parameter in the music commands stand for. QuickTime uses 600, we use 600. The parameter is actually a TimeScale, but we dont want to have to include all of the QuickTime interface files to find out that it is a longint.

This is the magic call to actually start playing. You pass in the tune player in tp, and a pointer to the start of the music opwords (make sure that everything is locked down) in tune. TuneRate contains a fixed value which lets you adjust how fast or slow the resulting tune is played. TuneStartPosition and TuneStopPosition specify, in time units, what section of the music to play. The music starts at zero, so to play everything, we pass in 0 and $7FFFFFFF. QueueFlags have the following values:

This routine will give you the status of the currently playing tune. Tune is the current tune, while TunePtr points to where in that tune we currently are. Time is how many time units have passed. QueueCount is how many tunes, including this one are currently queued up. QueueTime is how many time units worth of tunes are queued up waiting to be played.

This pair of routines allows you to change the volume of the playing tune. Dont ask me how the volume is returned in TuneGetVolume, since there is no fixed value returned and no fixed var parameter, but that is what the call is.

FUNCTION TunePreroll (tp: TunePlayer): ComponentResult;

This call is important, because it will reserve all the note channels for the instruments, load everything it can into memory, and do any other possible preparation for playing the given music.

FUNCTION TuneUnroll (tp: TunePlayer): ComponentResult;

This is the opposite of TunePreroll in that it unreserves all the note channels that have been locked down. This call is typically called before suspending your application (after stopping the current music), so other applications can play their music.

Putting It All Together

Now that weve got the basic calls, and a simple little bit of music to play, lets look at what calls need to made and in what order. This is the code from a simple application that just gets the music resource and plays it, busy waiting while playing, and quitting when done. We will just comment on the basic calls - to see all the details (where we actually check errors), see listing 3, MusicTest.p.

The first thing to do is to load in the resource we are playing and lock it down:

The next step is to tell it the time units. We use the value 600 since that is what QuickTime movies normally use.

result := TuneSetTimeScale(tp, 600);

We then need to tell the tune component what instruments are used. We get this data from our resource.

result := TuneSetHeader(tp, @h^^.headerData);

Now that weve told it what instruments to use, we want to reserve those instruments and do any other sort of pre-play allocation we can.

result := TunePreRoll(tp);

We can now say how loud we want to play it. We will use normal volume, which is a fixed point one.

result := TuneSetVolume(tp, $10000);

Now we make the magic call to actually start the music playing. It will automatically play in the background, there is no extra stuff needed to do (unlike the sound manager). We pass in the start of the body of music, as based on our resource, tell it to play at normal tempo, play everything, start playing now, and we dont have any callbacks.

We can then wait and check to see how we doing. When the music stops, the queueCount field of the TuneStatus record will drop from 1 to 0. There are other ways to determine if we are done, but we wont get into them, since the queueCount field is simple enough.

Thats all there is to playing. When we are done, (or in our example, when the user clicks the button), we need to free up everything we allocate.

result := TuneStop(tp, kStopFadeout);
err := CloseComponent(tp);

Thats all there is to playing music. There are many more calls, include ones to present a dialog to the user to allow them to select an instrument, but we dont have space to get into those here. The calls are all found in the QuickTime 2.0 interface files, while the documentation should be in a tech note or future article.

Listing 1 - Music.r

This is our combined header/body resource for playing music with QuickTime
2.0's tune player component.

/* 3 */
PROGRAM MusicTest;
USES
Components, Music;
VAR
h: MusicDescriptionHandle;
tp: TunePlayer;
result: ComponentResult;
theTuneStatus: TuneStatus;
err: OSErr;
LABEL
10; { used for error cleanup }
BEGIN
{ Get the music resource and lock it down }
h := MusicDescriptionHandle(GetResource('Musi', 128));
IF h = NIL THEN
ExitToShell;
HLock(Handle(h));
{ open the default tune player }
tp := OpenDefaultComponent(kTunePlayerType,
ResType(LongInt(kAnyComponentType)));
IF tp = NIL THEN
ExitToShell;
{ tell that we have 600 units per second }
result := TuneSetTimeScale(tp, 600);
IF result noErr THEN
GOTO 10;
{ Set the header, to tell what instruments are used }
result := TuneSetHeader(tp, @h^^.headerData);
IF result noErr THEN
GOTO 10;
{ Have it allocate whatever resources are needed }
result := TunePreRoll(tp);
IF result noErr THEN
GOTO 10;
{ We want to play at normal volume }
result := TuneSetVolume(tp, $10000);
IF result noErr THEN
GOTO 10;
{ Queue up the music, normal tempo, play everything now }
result := TuneQueue(tp, Pointer(ORD4(h^) + h^^.size),
$10000, 0, $7FFFFFFF, kTuneStartNow, NIL, 0);
IF result noErr THEN
GOTO 10;
REPEAT
result := TuneGetStatus(tp, theTuneStatus);
IF result noErr THEN
GOTO 10;
{ spin until we click the button or no music left queued up }
UNTIL Button | (theTuneStatus.queueCount = 0);
{ We get here either by getting an error or having everything finish
}
{ Regardless, we need to stop and clean up everything }
10:
IF result noErr THEN
DebugStr('Music result');
IF tp NIL THEN
result := TuneStop(tp, kStopFadeout);
IF tp NIL THEN
err := CloseComponent(tp);
{ And we are done }
END.

PCalc is a full-featured, scriptable scientific calculator with support for hexadecimal, octal, and binary calculations, as well as an RPN mode, programmable functions, and an extensive set of unit... Read more

FileZilla 3.10.2 - Fast and reliable FTP...

FileZilla (ported from Windows) is a fast and reliable FTP client and server with lots of useful features and an intuitive interface.
Version 3.10.2:
Note: Now requires a 64-bit Intel processor.... Read more

The Hit List 1.1.11 - Advanced reminder...

The Hit List manages the daily chaos of your modern life. It's easy to learn - it's as easy as making lists. And it's powerful enough to let you plan, then forget, then act when the time is right.... Read more

Bartender 1.2.32 - Organize your menu ba...

Bartender lets you organize your menu bar apps.
Features:
Lets you tidy your menu bar apps how you want.
See your menu bar apps when you want.
Hide the apps you need to run, but do not need to... Read more

ClamXav 2.7.5 - Free virus checker, base...

ClamXav is a free virus checker for OS X. It uses the tried, tested, and very popular ClamAV open source antivirus engine as a back end.
I hope you like and use ClamXav a lot and that it helps keep... Read more

xScope 4.1.2 - Onscreen graphic measurem...

xScope is powerful set of tools that are ideal for measuring, inspecting, and testing on-screen graphics and layouts. Its tools float above your desktop windows and can be accessed via a toolbar,... Read more

MacFamilyTree 7.3.3 - Create and explore...

MacFamilyTree gives genealogy a facelift: it's modern, interactive, incredibly fast, and easy to use. We're convinced that generations of chroniclers would have loved to trade in their genealogy... Read more

Skype 7.5.0.738 - Voice-over-internet ph...

Skype allows you to talk to friends, family and co-workers across the Internet without the inconvenience of long distance telephone charges. Using peer-to-peer data transmission technology, Skype... Read more

PushPal 3.0 - Mirror Android notificatio...

PushPal is a client for Pushbullet, which automatically shows you all of your phone's notifications right on your computer. This means you can see who's calling or read text messages even if your... Read more

At this point it’s pretty safe to say that no MOBA is going to dethrone Dota 2 and League of Legends anytime soon. After all, if Batman can’t do it, nobody can. However, with a genre as popular and profitable as this one, there’s still room for... | Read more »

Final February Fun at 148Apps
How do you know what apps are worth your time and money? Just look to the review team at 148Apps. We sort through the chaos and find the apps you’re looking for. The ones we love become Editor’s Choice, standing out... | Read more »

GDC 2015 – Does Not Commute is Definitel...

GDC 2015 – Does Not Commute is Definitely a Game You Should Keep an Eye on
Posted by Rob Rich on March 2nd, 2015 [ permalink ]
We were teased about Mediocre Games’ (Smash Hit,
| Read more »

F84 Games & POW! Announce Stan Lee V...

F84 Games has announced that it is working with legendary comic creator Stan Lee and POW! Entertainment to produce Stan Lee’s Hero Command. The game will be a action adventure of heroic proportions.
| Read more »

Setlyst Keeps Your Set Straight So You C...

Setlyst Keeps Your Set Straight So You Can Focus On Rocking Out.
Posted by Jessica Fisher on March 2nd, 2015 [ permalink ]
Universal App - Designed for iPhone and iPad
| Read more »

Space is Vast, So Space Agency Has a Vas...

Space is Vast, So Space Agency Has a Vast New Update!
Posted by Jessica Fisher on March 2nd, 2015 [ permalink ]
Universal App - Designed for iPhone and iPad
| Read more »

Size DOES Matter Review

Size DOES Matter Review
By Campbell Bird on March 2nd, 2015
Our Rating: :: HARD TO BEATUniversal App - Designed for iPhone and iPad
This rhythm game has a unique control scheme and performance system that make it feel like a true... | Read more »

The first ever action 3D card battler Al...

On the other hand, you probably haven’t played an action 3D card battler – until now. Step forward, All Star Legion.
All Star Legion is a 3D QTE-based action RPG card battler, but fear not – the game itself isn’t as convoluted as its description.... | Read more »

Travel Back to the 1980s With the Making...

Headup Games has released a hilarious making of video for its upcoming title, Pixel Heroes: Byte & Magic. The game is a RPG/Roguelike where you control three heroes set to save the township of Pixton from an evil cult called The Sons of Dawn.... | Read more »

Price Scanner via MacPrices.net

Sale! 15-inch 2.2GHz Retina MacBook Pro for $...

Best Buy has the 15″ 2.2GHz Retina MacBook Pro on sale for $1774.99 $1799.99, or $225 off MSRP. Choose free home shipping or free local store pickup (if available). Price valid for online orders... Read more

27-inch 3.5GHz 5K iMac in stock today and on...

B&H Photo has the 27″ 3.5GHz 5K iMac in stock today and on sale for $2299 including free shipping plus NY sales tax only. Their price is $200 off MSRP, and it’s the lowest price available for... Read more

Apple Launches Free Web-Based Pages and Other...

Apple’s new Web-only access to iWork productivity apps is a free level of iCloud service available to anyone, including people who don’t own or use Apple devices. The service includes access to Apple... Read more

Survey Reveals Solid State Disk (SSD) Technol...

In a recent SSD technology use survey, Kroll Ontrack, a firm specializing in data recovery, found that while nearly 90 percent of respondents leverage the performance and reliability benefits of SSD... Read more

Save up to $600 with Apple refurbished Mac Pr...

The Apple Store is offering Apple Certified Refurbished Mac Pros for up to $600 off the cost of new models. An Apple one-year warranty is included with each Mac Pro, and shipping is free. The... Read more

Apple CEO Tim Cook will deliver the George Washington University’s Commencement address to GWU grads on May 17, at which time he will also be awarded an honorary doctorate of public service from the... Read more

Apple restocks refurbished Mac minis for up t...

The Apple Store has restocked Apple Certified Refurbished 2014 Mac minis, with models available starting at $419. Apple’s one-year warranty is included with each mini, and shipping is free:
- 1.4GHz... Read more

Walmart has the 16GB iPad Air 2 WiFi on sale for $446.99 on their online store for a limited time. Choose free shipping or free local store pickup (if available). Sale price for online orders only,... Read more

Jobs Board

*Apple* Solutions Consultant - Retail Sales...

**Job Summary** As an Apple Solutions Consultant (ASC) you are the link between our customers and our products. Your role is to drive the Apple business in a retail
Read more

*Apple* Pay Automation Engineer - iOS System...

**Job Summary** At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring passion and dedication to your job
Read more

Sr. Technical Services Consultant, *Apple*...

**Job Summary** Apple Professional Services (APS) has an opening for a senior technical position that contributes to Apple 's efforts for strategic and transactional
Read more

Event Director, *Apple* Retail Marketing -...

…This senior level position is responsible for leading and imagining the Apple Retail Team's global engagement strategy and team. Delivering an overarching brand
Read more

*Apple* Pay - Site Reliability Engineer - Ap...

**Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring
Read more

MacTech is a registered trademark of Xplain Corporation. Xplain, "The journal of Apple technology", Apple Expo, Explain It, MacDev, MacDev-1, THINK Reference, NetProfessional, Apple Expo, MacTech Central, MacTech Domains, MacNews, MacForge, and the MacTutorMan are trademarks or service marks of Xplain Corporation. Sprocket is a registered trademark of eSprocket Corporation. Other trademarks and copyrights appearing in this printing or software remain the property of their respective holders. Not responsible for typographical errors.

All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.