Instantly share code, notes, and snippets.

What would you like to do?
// CMS2AudioUnit.m
// CMS2
// Created by Clifton Marien on 8/6/18.
// Copyright © 2018 Clifton Marien. All rights reserved.
#import "CMS2AudioUnit.h"
#import <Cocoa/Cocoa.h>
#import <AVFoundation/AVFoundation.h>
// Define parameter addresses.
const AudioUnitParameterID myParam1 = 0;
@interface CMS2AudioUnit ()
@property (nonatomic, readwrite) AUParameterTree *parameterTree;
@property AUAudioUnitBus *inputBus;
@property AUAudioUnitBus *outputBus;
@property AUAudioUnitBusArray *inputBusArray;
@property AUAudioUnitBusArray *outputBusArray;
@implementation CMS2AudioUnit
@synthesize parameterTree = _parameterTree;
@synthesize inputBus = _inputBus;
@synthesize outputBus = _outputBus;
@synthesize inputBusArray = _inputBusArray;
@synthesize outputBusArray = _outputBusArray;
AUHostMusicalContextBlock _musicalContext;
AUMIDIOutputEventBlock _outputEventBlock;
AUHostTransportStateBlock _transportStateBlock;
AUScheduleMIDIEventBlock _scheduleMIDIEventBlock;
AudioStreamBasicDescription asbd; // local copy of the asbd that the render block can capture
- (instancetype)initWithComponentDescription:(AudioComponentDescription)componentDescription options:(AudioComponentInstantiationOptions)options error:(NSError **)outError {
self = [super initWithComponentDescription:componentDescription options:options error:outError];
if (self == nil) {
return nil;
// Create parameter objects.
AUParameter *param1 = [AUParameterTree createParameterWithIdentifier:@"param1" name:@"Parameter 1" address:myParam1 min:0 max:100 unit:kAudioUnitParameterUnit_Percent unitName:nil flags:0 valueStrings:nil dependentParameters:nil];
// Initialize the parameter values.
param1.value = 0.5;
// Create the parameter tree.
_parameterTree = [AUParameterTree createTreeWithChildren:@[ param1 ]];
// Create the input and output busses (AUAudioUnitBus).
// Create the input and output bus arrays (AUAudioUnitBusArray).
// A function to provide string representations of parameter values.
_parameterTree.implementorStringFromValueCallback = ^(AUParameter *param, const AUValue *__nullable valuePtr) {
AUValue value = valuePtr == nil ? param.value : *valuePtr;
switch (param.address) {
case myParam1:
return [NSString stringWithFormat:@"%.f", value];
return @"?";
self.maximumFramesToRender = 512;
AVAudioFormat *defaultFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:44100.0 channels:2];
asbd = *defaultFormat.streamDescription;
_inputBus = [[AUAudioUnitBus alloc]
initWithFormat:defaultFormat error:nil];
_outputBus = [[AUAudioUnitBus alloc]
initWithFormat:defaultFormat error:nil];
_inputBusArray = [[AUAudioUnitBusArray alloc] initWithAudioUnit:self busType:AUAudioUnitBusTypeInput busses: @[_inputBus]];
_outputBusArray = [[AUAudioUnitBusArray alloc] initWithAudioUnit:self busType:AUAudioUnitBusTypeOutput busses: @[_outputBus]];
return self;
#pragma mark - AUAudioUnit Overrides
// If an audio unit has input, an audio unit's audio input connection points.
// Subclassers must override this property getter and should return the same object every time.
// See sample code.
- (AUAudioUnitBusArray *)inputBusses {
return _inputBusArray;
// An audio unit's audio output connection points.
// Subclassers must override this property getter and should return the same object every time.
// See sample code.
- (AUAudioUnitBusArray *)outputBusses {
return _outputBusArray;
// Allocate resources required to render.
// Subclassers should call the superclass implementation.
- (BOOL)allocateRenderResourcesAndReturnError:(NSError **)outError {
if (![super allocateRenderResourcesAndReturnError:outError]) {
return NO;
// Validate that the bus formats are compatible.
// Allocate your resources.
return YES;
// Deallocate resources allocated in allocateRenderResourcesAndReturnError:
// Subclassers should call the superclass implementation.
- (void)deallocateRenderResources {
// Deallocate your resources.
[super deallocateRenderResources];
- (void)requestViewControllerWithCompletionHandler:(void (^)(NSViewController *viewController))completionHandler{
#pragma mark - AUAudioUnit (AUAudioUnitImplementation)
// Block which subclassers must provide to implement rendering.
- (AUInternalRenderBlock)internalRenderBlock {
// Capture in locals to avoid ObjC member lookups. If "self" is captured in render, we're doing it wrong. See sample code.
return ^AUAudioUnitStatus(AudioUnitRenderActionFlags *actionFlags, const AudioTimeStamp *timestamp, AVAudioFrameCount frameCount, NSInteger outputBusNumber, AudioBufferList *outputData, const AURenderEvent *realtimeEventListHead, AURenderPullInputBlock pullInputBlock) {
// Do event handling and signal processing here.
return noErr;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment