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.
- Open Xcode 4
- Select File -> New -> New Project… from the menubar.
- In the “Choose a template for your new project” sheet, select System Plug-in in the category list on the left
- Choose Audio Unit Effect as a template type on the right and click Next
- 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 - 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:
- ~/Library/Audio/Plug-Ins/Components
- /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…
- Open AppleScript Editor in /Applications/Utilities
- 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 &"
- Select File -> Save As…
- Name it whatever you like. I used AU Lab 64-bit
- In the File Format: dropdown, select Application
- 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…
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
That’s one if my next couple of posts. Before that, though, I have a post on AU parameters that probably should come first, as it makes the view article clearer.
Also, apologies for the tardiness in updating and replying. We’re on a long vacation right now (though somehow I’m still working on projects… {><})
amonk,
Check out my new post on getting Cocoa Views to work…
Creating Audio Units with Cocoa Views on Mac OS X 10.7 (Lion)