Getting Started Developing Audio Units on Mac OS X and Xcode 4 – My Experiences as a Beginner

Setting expectations

Just to set expectations, I have never developed Audio Units before, so this is a first time thing for me. All I’m trying to do is share my experiences as an enthusiastic, though not formally trained, developer.

Also, while the information that Apple provides for Audio Unit development is excellent, it is a bit out of date with respect to the tools usage and getting started as a new developer on both the platform and Audio Units.

The tools you’ll be using are all included in Xcode 4.

  • The Xcode IDE
  • AU Lab, located in /Developer/Applications/Audio
  • AUVal, a command line tool

So grab your copy of Xcode 4 over at the Apple Mac OS X Developer Center, and let’s get going!

Xcode 4 and the Audio Unit project templates

Follow these steps to setup your initial project.

  1. Open Xcode 4
  2. Select File -> New -> New Project… from the menubar.
  3. In the “Choose a template for your new project” sheet, select System Plug-in in the category list on the left
  4. Choose Audio Unit Effect as a template type on the right and click Next
  5. In the next page, name your Audio Unit and add your Company Identifier in the form of com.mycompany. Do Not select With Cocoa View at this point. Click Next
  6. Select the folder into which you will save your project via the standard save sheet and you’re good to go.

At this point, you have a basic, compilable Audio Unit project. Feel free to select Product -> Build and make sure that you don’t have any errors. I’m assuming you won’t because I’ve walked through this several times and haven’t run into errors, yet.

This basic Audio Unit has the following parameters that will be important a little bit later.

TYPE
aufx – This is the type specifier for a basic effects unit, as opposed to one that takes MIDI input. These are defined by Apple in AUComponent.h in the AudioUnit.framework. This value is set in your MyPlugin.r resource file.
SUBTYPE
Pass – This is a further, more-specific specifier. This particular one is user defined. There are some already defined in the AUComponent.h header, and you should follow those whenever possible. However, you are free to define your own. This value is set in your MyPluginVersion.h header.
MANF
Demo – This is the default Manufacturer ID for the template. You should replace it with your own creator code, when you get it from Apple. http://developer.apple.com/support/mac/creator-code-registration.html This value is set in your MyPluginVersion.h header.

Validating that your Audio Unit works

Step One: Copy your MyPlugin.component to the appropriate location

In order for Mac OS X to use your component, you need to copy it to one of the following locations:

  1. ~/Library/Audio/Plug-Ins/Components
  2. /Library/Audio/Plug-Ins/Components

Either will work, but for now, just copy it to the first location. If you happen to be unfamiliar with the ~ syntax, it just means your home folder. So, in this case, you’d just copy your MyPlugin.component to /Users/yourusername/Library/Audio/Plug-Ins/Components folder

But wait!!! Where is my Audio Unit to begin with???

Good question. It’s actually changed since the last version of Xcode. The easiest way to find it is to look Xcode’s Project Navigator pane. Find the folder named Products. Inside it, you will see your plugin. Control-click it and select Show in Finder.

Step Two: Run auval to validate your plug-in.

Open the Terminal.app and type in the following:

auval -v aufx Pass Demo

Remember those parameters (aufx, Pass, and Demo) we talked about earlier? Do they look familiar? They’re what we’re using to specify which Audio Unit to validate.

Why don’t AU Lab and AUVal see my plug-in?

If you’re doing this on one of the 64-bit Macs out there, as I am, you’re likely to run into a problem getting your just-compiled Audio Unit to show up in AU Lab.

In fact, when you run AUVal from the command line, you’re probably seeing something like this:

MachineName:~ username$ auval -v aufx Pass Demo

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
       AU Validation Tool
       Version: 1.6.1a1
        Copyright 2003-2007, Apple, Inc. All Rights Reserved.

       Specify -h (-help) for command options
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

--------------------------------------------------
VALIDATING AUDIO UNIT: 'aufx' - 'Pass' - 'Demo'
--------------------------------------------------
ERROR: Cannot get Component's Name strings
ERROR: Error from retrieving Component Version: -50

* * FAIL
--------------------------------------------------
TESTING OPEN TIMES:
FATAL ERROR: didn't find the component
MachineName:~ username$

So, what’s the deal?

Well, it’s really simple. By default, Xcode is compiling for your machine in 64-bit. Auval, by default, checks the list of 32-bit Audio Units by default. So, to check that your 64-bit version is good to go, use the following, instead:

auval -64 -v aufx Pass Demo

Now you should see something like different. It should look like this:

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
       AU Validation Tool
       Version: 1.6.1a1
        Copyright 2003-2007, Apple, Inc. All Rights Reserved.

       Specify -h (-help) for command options
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

--------------------------------------------------
VALIDATING AUDIO UNIT: 'aufx' - 'Pass' - 'Demo'
--------------------------------------------------
Manufacturer String: __MyCompanyName__
AudioUnit name: MyPlugin
Component Version: 1.0.0 (0x10000)

* * PASS
--------------------------------------------------
TESTING OPEN TIMES:
COLD:
Time to open AudioUnit:         0.537 ms
WARM:
Time to open AudioUnit:         0.016  ms
ERROR: Component Version mismatch: Res Vers = 0x10000, Comp Vers = 0xFFFFFFFF
FIRST TIME:
Time for initialization:        0.007 ms

* * FAIL
--------------------------------------------------
VERIFYING DEFAULT SCOPE FORMATS:
Input Scope Bus Configuration:
 Default Bus Count:1
    Default Format: AudioStreamBasicDescription:  2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved

Output Scope Bus Configuration:
 Default Bus Count:1
    Default Format: AudioStreamBasicDescription:  2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved

* * PASS
--------------------------------------------------
VERIFYING REQUIRED PROPERTIES:
  VERIFYING PROPERTY: Sample Rate
    PASS
  VERIFYING PROPERTY: Stream Format
    PASS
  VERIFYING PROPERTY: Maximum Frames Per Slice
    PASS
  VERIFYING PROPERTY: Last Render Error
    PASS

* * PASS
--------------------------------------------------
VERIFYING RECOMMENDED PROPERTIES:
  VERIFYING PROPERTY: Latency
    PASS
  VERIFYING PROPERTY: Tail Time
WARNING: Recommended Property is not supported

  VERIFYING PROPERTY: Bypass Effect
    PASS

* * PASS
--------------------------------------------------
VERIFYING OPTIONAL PROPERTIES:
  VERIFYING PROPERTY Host Callbacks
    PASS

* * PASS
--------------------------------------------------
VERIFYING SPECIAL PROPERTIES:

VERIFYING CUSTOM UI
Cocoa Views Available: 0

VERIFYING CLASS INFO
    PASS

TESTING HOST CALLBACKS
    PASS

* * PASS
--------------------------------------------------
PUBLISHED PARAMETER INFO:

# # # 1 Global Scope Parameters:
Parameter ID:0
Name: Parameter One
Parameter Type: Linear Gain
Values: Minimum = 0.000000, Default = 0.500000, Maximum = 1.000000
Flags: Readable, Writable
  -parameter PASS

Testing that parameters retain value across reset and initialization
  PASS

* * PASS
--------------------------------------------------
FORMAT TESTS:

Reported Channel Capabilities (implicit):
      [-1, -1]

Input/Output Channel Handling:
1-1   1-2   1-4   1-5   1-6   1-7   1-8   2-2   2-4   2-5   2-6   2-7   2-8   4-4   4-5   5-5   6-6   7-7   8-8
X                                         X                                   X           X     X     X     X     

* * PASS
--------------------------------------------------
RENDER TESTS:
Input Format: AudioStreamBasicDescription:  2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved
Output Format: AudioStreamBasicDescription:  2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved
Render Test at 512 frames
Slicing Render Test at 64 frames
  PASS

Render Test at 64 frames, sample rate: 22050 Hz
Render Test at 137 frames, sample rate: 96000 Hz
Render Test at 4096 frames, sample rate: 48000 Hz
Render Test at 4096 frames, sample rate: 192000 Hz
Render Test at 4096 frames, sample rate: 11025 Hz
Render Test at 512 frames, sample rate: 44100 Hz
  PASS

1 Channel Test:
In and Out Format: AudioStreamBasicDescription:  2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved
Render Test at 512 frames
  PASS

Checking connection semantics:
Connection format:
AudioStreamBasicDescription:  2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved
  PASS

Bad Max Frames - Render should fail
  PASS

Checking parameter setting
Using AudioUnitSetParameter
Using AudioUnitScheduleParameter
  PASS

* * PASS
--------------------------------------------------
AU VALIDATION SUCCEEDED.
--------------------------------------------------

You may notice that one section of the validation failed. Don’t worry, that’s just a versioning mismatch due to compiling for debugging rather than release. Also, we’ll address the need for building for both 32-bit and 64-bit later.

Setting up the tools

Now comes the fun part. You can actually see your Audio Unit working inside a host! Okay, it doesn’t do anything, but this way you’ll know that when you come up with that amazing algorithm, you’ll be able to get you DAW to use it.

So, there’s a little utility app that Apple ships with Xcode called AU Lab. It’s located in /Developer/Applications/Audio. It allows you to play existing audio or process incoming audio from your audio interface. It’s pretty straightforward to use, so go ahead and get a feel for it before the next step,

There’s just one catch with AU Lab. Just like with auval, AU Lab runs in 32-bit by default. This is because most existing Audio Unit development is in 32-bit, so it makes sense, I guess.

Anyway, if you’re running on a 64-bit Mac and have compiled your Audio Unit to be 64-bit, you’ll need to tweak AU Lab a little in order to see your Audio Unit

The first method is to find the AU Lab app, highlight it, select File -> Get Info and deselect Open in 32-bit mode.

While this method is okay, it’s a bit of a pain when you need to check two different versions regularly. So, I cooked up a different way to do this. Initially, I did this with a shell script, but the extra terminal window annoyed me, so I moved it to an AppleScript. Here’s what you do…

  1. Open AppleScript Editor in /Applications/Utilities
  2. Enter the following into the script window:
    do shell script "arch -x86_64 \"/Developer/Applications/Audio/AU Lab.app/Contents/MacOS/AU Lab\" > /dev/null 2>&1 &"
  3. Select File -> Save As…
    1. Name it whatever you like. I used AU Lab 64-bit
    2. In the File Format: dropdown, select Application
    3. In the Options: checkboxes, only select Run Only

Now, when you double click on this file, it will run AU Lab in 64-bit mode. I also create a regular link to AU Lab so I can easily start up AU Lab in 32-bit mode from the same place. Easy peasy.

Finally, now that you’re running AU Lab in the mode that you compiled with, you should be able to see your Audio Unit plug-in in the effects dropdown. It will probably still say something like __MyCompanyName__, but you’ll change that later.

Wrapping up this session

So, you’ve built your first Audio Unit in Xcode and installed it. I’ll be adding some more articles in the coming weeks detailing more discoveries and adjustments that we can make to our Audio Unit, so please stay tuned…

3 thoughts on “Getting Started Developing Audio Units on Mac OS X and Xcode 4 – My Experiences as a Beginner

  1. hey, this is helpful!

    i’m curious if you’ve had any luck building an AU instrument with a Cocoa View? There is no template for it, and I’m having a heck of a time getting the custom view to show up. If you decide to keep doing this blog that might big a cool topic….

    bk

Leave a Reply