Let’s Make an AUv3 (Audio Unit) MIDI Extension – Part 3: Presets

preset

AUv3 MIDI Presets

This is the 4th installment of the (AUv3) Audio Units MIDI Extension tutorial.

Original blog post.

In previous blog posts I created a working AUv3 MIDI processor that adds an interval to incoming MIDI note messages. The interval can be customized via an AUParameter.

Now I’ll show you how to make v3 presets.

Introduction

Take a look at AuAudioUnit.h if you haven’t yet. A lot of the “new” (AUv3( Audio Unit API is here.

This time look for what it offers for presets.

Minus the comments, we have this regarding presets:

The AUAudioUnitPreset class is not complicated. It is simply a name and number.

Let’s go through these members.

Defining Factory presets

We see that our Audio Unit’s superclass defines an array of AUAudioUnitPresets named factoryPresets. Clever naming. So, we need to create this array and return it in this property.

My first shot at this was to synthesize the inherited property into an array instance variable. Then, I created a method to instantiate the AUAudioUnitPresets.

If I had a lot of presets to create, this code looks pretty wet. So let’s DRY it out.

The thing is, we don’t really need a method to create the presets. Why not just override the array?

It’s works! Here they are.

What does FilterDemo do?

(Remember the previous blog post on C++? The FilterDemo’s filtering code is actually in a C++ class named FilterDSPKernel. You’ll see this a lot in audio unit code).

FilterDemo does this for two of the inherited properties: factoryPresets and currentPreset. If you don’t call @synthesize on a property, you will get a variable with the property name prefixed with an underscore. So, we see that the property currentPreset is not synthesized, but the variable _currentPreset is defined. They also define an array of AUAudioUnitPresets, and then “point” the inherited property factoryPresets to it. In their implementation they have an array of hard-coded presets, so they keep an index into it in order to set them.

So, for the interval MIDI plugin, I’ll do the same thing.

Now, let’s set them up in initWithComponentDescription.

I defined kDefaultFactoryPreset to be 0 which I used to initialize _currentFactoryPresetIndex.

I create the _presets array (which factoryPresets points to) using the createPreset method.

The _currentPreset is then set to the first preset.

Cool. We’re set up now.

How does FilterDemo handle accessing the currentPreset?

Here is their code. Actually there is nothing we need to change in this.
Borrow it!

What we can see here is that if the preset number is < 0, then the system considers it to be a User Defined Preset. We just return it since the system keeps track of it. How does FilterDemo handle setting the current preset? Once again, it checks to see if the preset number is a User Defined Preset or not - the handling is different. For a factory preset, it loops through the _preset array to find the matching preset, The parameters are retrieved from the tree and their values are set to the factory values. Then a bit of housekeeping to update _currentPreset and _currentFactoryPresetIndex.

For User Defined Presets, _currentPreset is simply set to the preset passed in.

What’s that “presetParameters” I’m using to set the value?

To actually define the factory preset values, I created a struct to hold the values. It is really simple in this plugin since there is only one parameter (the interval). But you can imagine that in a synth there would be a metric ton of them.

My modification to FilterDemo’s current preset setter is to change the AUParameter being updated of course.

Try it out!

Choose a preset and you’ll set it updating!

Defining User presets

Your audio unit inherits this property:

When you save a new preset, e.g. in AUM press the + in the Presets title bar, this property will be accessed. By default, the keys in this dictionary are: manufacturer, data, type, subtype, and version. What we need to do is add keys/values for our parameters to this dictionary. So, create a mutable dictionary, add to that and return it. You could just call setObject:forKey for each parameter, but adding a params dictionary is tidier if you have many parameters.

When the user preset is selected, the setter is called. So, grab the archived data you wrote in the getter, and then extract the parameter values. Here there is only one parameter, but you may have many.

There is also a fullStateForDocument property for “global” properties such as master tuning. If you need this, define accessors for it using the same procedure I described for fullState.

To test, set an interval from the segmented control, then save it as a “user defined preset”. (Press the + in AUM’s title bar). Choose a factory preset, note the value, then press your user preset. It should have the value you saved. If not, pet the cat and grab another espresso.

Summary

There is a new API for using presets that is bridged to the v2 API for compatibility. It’s actually quite a bit easier now.

Resources

AUAudioUnitPreset

Apple’s FilterDemo

Apple’s v2 Preset documentation.

v2: Audio Units – How to correctly save and restore Audio Unit presets

Previous posts in this series

Audio Units (AUv3) MIDI extension – Part 0: Getting Started

Audio Units (AUv3) MIDI extension – Part 1: Parameters

Audio Units (AUv3) MIDI extension – Part 2: C++

This is the same repo as the previous blog post, but there is a new target named AUParamsPresets containing this new code.
Github repo

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.