You’ve got the right idea, but there’s a difference between parameters and properties (confusingly). Parameters are things like filter cutoff frequency and mixer volume (things you might put on a knob and expose to a user). Properties are more “internal” and are things like sample rate, connection status, buffer size etc.
Listening to parameters is a bit more complicated than listening to properties for some reason. You create a listener, give the listener a callback/block to call, and then associate the listener with a parameter (or several parameters).
I’m doing this in the params example. First add an event listener to the app:
class ofApp : public ofBaseApp {
...
AUEventListenerRef auEventListener;
static void audioUnitParameterChanged(void * context,
void * object,
const AudioUnitEvent * event,
UInt64 hostTime,
AudioUnitParameterValue value);
};
then in ofApp::setup()
CFRunLoopRef runLoop = (CFRunLoopRef)GetCFRunLoopFromEventLoop(GetCurrentEventLoop());
AUEventListenerCreate(&ofApp::audioUnitParameterChanged,
this,
runLoop,
kCFRunLoopDefaultMode,
0.05, // minimum callback interval (seconds)
0.05, // callback granularity (for rate-limiting)
&auEventListener);
AudioUnitParameter param = {
.mAudioUnit = lowpass,
.mParameterID = kLowPassParam_CutoffFrequency,
.mScope = kAudioUnitScope_Global,
.mElement = 0
};
AUListenerAddParameter(auEventListener, this, ¶m);
and finally, implement the audioUnitParameterChanged
function declared in ofApp.h:
void ofApp::audioUnitParameterChanged(void *context, void *object, const AudioUnitEvent *event, UInt64 hostTime, AudioUnitParameterValue parameterValue)
{
cout << "param changed" << endl;
}
Note that that’s a static function, so you won’t be able to use the ofApp’s variables directly. By passing “this” into the previous functions above like I did, the context
arg in the callback will be a pointer to your app.
There’s block-based event listeners you can use as well if you understand blocks. These seem a bit less complicated.
You won’t necessarily be notified of all parameter changes this way. If you call the simple-ish AudioUnitSetParameter
like in the params example, you won’t get callbacks. If you need to get callbacks from that sort of event, switch to AUParameterSet
which does the same thing, but also notifies listeners. Parameter changes from the GUI should work, though.
If you wanted to listen to properties, the structure would be to add a static method to your ofApp like:
class ofApp : public ofBaseApp {
... // other stuff
static void audioUnitPropertyChanged(void * context,
AudioUnit unit,
AudioUnitPropertyID property,
AudioUnitScope scope,
AudioUnitElement element);
}
and setup the callback like:
void ofApp::setup() {
AudioUnitAddPropertyListener(unit,
kAudioUnitProperty_SetRenderCallback,
&ofApp::audioUnitPropertyChanged,
this);
}
void ofApp::audioUnitPropertyChanged(void *context, AudioUnit unit, AudioUnitPropertyID property, AudioUnitScope scope, AudioUnitElement element)
{
cout << "property changed" << endl;
}