|
| 1 | +// |
| 2 | +// AKAudioUnit.h |
| 3 | +// AudioKit |
| 4 | +// |
| 5 | +// Created by Aurelius Prochazka, revision history on Github. |
| 6 | +// Copyright © 2018 AudioKit. All rights reserved. |
| 7 | +// |
| 8 | + |
| 9 | +#import <AVFoundation/AVFoundation.h> |
| 10 | + |
| 11 | +@protocol AKKernelUnit |
| 12 | +-(AUImplementorValueProvider _Null_unspecified)getter; |
| 13 | +-(AUImplementorValueObserver _Null_unspecified)setter; |
| 14 | +@end |
| 15 | + |
| 16 | +@interface AKAudioUnit : AUAudioUnit<AKKernelUnit> |
| 17 | +@property AUAudioUnitBus * _Nonnull outputBus; |
| 18 | +@property AUAudioUnitBusArray * _Nonnull inputBusArray; |
| 19 | +@property AUAudioUnitBusArray * _Nonnull outputBusArray; |
| 20 | +@property AVAudioFormat * _Nonnull defaultFormat; |
| 21 | + |
| 22 | +- (void)start; |
| 23 | +- (void)stop; |
| 24 | +@property (readonly) BOOL isPlaying; |
| 25 | +@property (readonly) BOOL isSetUp; |
| 26 | + |
| 27 | +@property double rampDuration; |
| 28 | + |
| 29 | +-(AUImplementorValueProvider _Null_unspecified)getter; |
| 30 | +-(AUImplementorValueObserver _Null_unspecified)setter; |
| 31 | + |
| 32 | +@end |
| 33 | + |
| 34 | +//@protocol AUParameterCollection |
| 35 | +//- (AUValue)objectAtIndexedSubscript:(AUParameter *)idx; |
| 36 | +//- (void)setObject:(AUValue)obj atIndexedSubscript:(AUParameter *)idx; |
| 37 | +//@end |
| 38 | + |
| 39 | +@interface AUParameter(Ext) |
| 40 | +//-(_Nonnull instancetype)init:(NSString * _Nonnull)identifier |
| 41 | +// name:(NSString * _Nonnull)name |
| 42 | +// address:(AUParameterAddress)address |
| 43 | +// min:(AUValue)min |
| 44 | +// max:(AUValue)max |
| 45 | +// unit:(AudioUnitParameterUnit)unit |
| 46 | +// flags:(AudioUnitParameterOptions)flags; |
| 47 | + |
| 48 | ++(_Nonnull instancetype)parameterWithIdentifier:(NSString * _Nonnull)identifier |
| 49 | + name:(NSString * _Nonnull)name |
| 50 | + address:(AUParameterAddress)address |
| 51 | + min:(AUValue)min |
| 52 | + max:(AUValue)max |
| 53 | + unit:(AudioUnitParameterUnit)unit |
| 54 | + flags:(AudioUnitParameterOptions)flags; |
| 55 | + |
| 56 | ++(_Nonnull instancetype)parameterWithIdentifier:(NSString * _Nonnull)identifier |
| 57 | + name:(NSString * _Nonnull)name |
| 58 | + address:(AUParameterAddress)address |
| 59 | + min:(AUValue)min |
| 60 | + max:(AUValue)max |
| 61 | + unit:(AudioUnitParameterUnit)unit; |
| 62 | +//+(_Nonnull instancetype)frequency:(NSString * _Nonnull)identifier |
| 63 | +// name:(NSString * _Nonnull)name |
| 64 | +// address:(AUParameterAddress)address; |
| 65 | + |
| 66 | +@end |
| 67 | + |
| 68 | +@interface AUParameterTree(Ext) |
| 69 | ++(_Nonnull instancetype)treeWithChildren:(NSArray<AUParameter *> * _Nonnull)children; |
| 70 | +@end |
| 71 | + |
| 72 | +//@interface AVAudioNode(Ext) |
| 73 | +//-(instancetype)initWithComponent:(AudioComponentDescription)component; |
| 74 | +//@end |
| 75 | + |
| 76 | + |
| 77 | +#define standardKernelPassthroughs() \ |
| 78 | +- (void)start { _kernel.start(); } \ |
| 79 | +- (void)stop { _kernel.stop(); } \ |
| 80 | +- (BOOL)isPlaying { return _kernel.started; } \ |
| 81 | +- (BOOL)isSetUp { return _kernel.resetted; } \ |
| 82 | +- (void)setShouldBypassEffect:(BOOL)shouldBypassEffect { \ |
| 83 | + if (shouldBypassEffect) {\ |
| 84 | + _kernel.stop();\ |
| 85 | + } else {\ |
| 86 | + _kernel.start();\ |
| 87 | + }\ |
| 88 | +}\ |
| 89 | + |
| 90 | +#define standardSetup(str) \ |
| 91 | + self.rampDuration = AKSettings.rampDuration; \ |
| 92 | + self.defaultFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:AKSettings.sampleRate \ |
| 93 | + channels:AKSettings.channelCount]; \ |
| 94 | + _kernel.init(self.defaultFormat.channelCount, self.defaultFormat.sampleRate); \ |
| 95 | + _inputBus.init(self.defaultFormat, 8); \ |
| 96 | + self.inputBusArray = [[AUAudioUnitBusArray alloc] initWithAudioUnit:self \ |
| 97 | + busType:AUAudioUnitBusTypeInput \ |
| 98 | + busses:@[_inputBus.bus]]; |
| 99 | +#define standardGeneratorSetup(str) \ |
| 100 | + self.rampDuration = AKSettings.rampDuration; \ |
| 101 | + self.defaultFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:AKSettings.sampleRate \ |
| 102 | + channels:AKSettings.channelCount]; \ |
| 103 | + _kernel.init(self.defaultFormat.channelCount, self.defaultFormat.sampleRate); \ |
| 104 | + _outputBusBuffer.init(self.defaultFormat, 2); \ |
| 105 | + self.outputBus = _outputBusBuffer.bus; \ |
| 106 | + self.outputBusArray = [[AUAudioUnitBusArray alloc] initWithAudioUnit:self \ |
| 107 | + busType:AUAudioUnitBusTypeOutput \ |
| 108 | + busses:@[self.outputBus]]; |
| 109 | +#define parameterTreeBlock(str) \ |
| 110 | + __block AK##str##DSPKernel *blockKernel = &_kernel; \ |
| 111 | + self.parameterTree.implementorValueObserver = ^(AUParameter *param, AUValue value) { \ |
| 112 | + blockKernel->setParameter(param.address, value); \ |
| 113 | + }; \ |
| 114 | + self.parameterTree.implementorValueProvider = ^(AUParameter *param) { \ |
| 115 | + return blockKernel->getParameter(param.address); \ |
| 116 | + }; |
| 117 | + |
| 118 | +#define AUAudioUnitOverrides(str) \ |
| 119 | +\ |
| 120 | +- (BOOL)allocateRenderResourcesAndReturnError:(NSError **)outError { \ |
| 121 | + if (![super allocateRenderResourcesAndReturnError:outError]) { \ |
| 122 | + return NO; \ |
| 123 | + } \ |
| 124 | + if (self.outputBus.format.channelCount != _inputBus.bus.format.channelCount) { \ |
| 125 | + if (outError) { \ |
| 126 | + *outError = [NSError errorWithDomain:NSOSStatusErrorDomain \ |
| 127 | + code:kAudioUnitErr_FailedInitialization \ |
| 128 | + userInfo:nil]; \ |
| 129 | + } \ |
| 130 | + self.renderResourcesAllocated = NO; \ |
| 131 | + return NO; \ |
| 132 | + } \ |
| 133 | + _inputBus.allocateRenderResources(self.maximumFramesToRender); \ |
| 134 | + _kernel.init(self.outputBus.format.channelCount, self.outputBus.format.sampleRate); \ |
| 135 | + _kernel.reset(); \ |
| 136 | + return YES; \ |
| 137 | +} \ |
| 138 | +\ |
| 139 | +- (void)deallocateRenderResources { \ |
| 140 | + [super deallocateRenderResources]; \ |
| 141 | + _kernel.destroy(); \ |
| 142 | + _inputBus.deallocateRenderResources(); \ |
| 143 | +} \ |
| 144 | +\ |
| 145 | +- (AUInternalRenderBlock)internalRenderBlock { \ |
| 146 | + __block AK##str##DSPKernel *state = &_kernel; \ |
| 147 | + __block BufferedInputBus *input = &_inputBus; \ |
| 148 | + return ^AUAudioUnitStatus( \ |
| 149 | + AudioUnitRenderActionFlags *actionFlags, \ |
| 150 | + const AudioTimeStamp *timestamp, \ |
| 151 | + AVAudioFrameCount frameCount, \ |
| 152 | + NSInteger outputBusNumber, \ |
| 153 | + AudioBufferList *outputData, \ |
| 154 | + const AURenderEvent *realtimeEventListHead, \ |
| 155 | + AURenderPullInputBlock pullInputBlock) { \ |
| 156 | + AudioUnitRenderActionFlags pullFlags = 0; \ |
| 157 | + AUAudioUnitStatus err = input->pullInput(&pullFlags, timestamp, frameCount, 0, pullInputBlock); \ |
| 158 | + if (err != 0) { \ |
| 159 | + return err; \ |
| 160 | + } \ |
| 161 | + AudioBufferList *inAudioBufferList = input->mutableAudioBufferList; \ |
| 162 | + AudioBufferList *outAudioBufferList = outputData; \ |
| 163 | + if (outAudioBufferList->mBuffers[0].mData == nullptr) { \ |
| 164 | + for (UInt32 i = 0; i < outAudioBufferList->mNumberBuffers; ++i) { \ |
| 165 | + outAudioBufferList->mBuffers[i].mData = inAudioBufferList->mBuffers[i].mData; \ |
| 166 | + } \ |
| 167 | + } \ |
| 168 | + state->setBuffers(inAudioBufferList, outAudioBufferList); \ |
| 169 | + state->processWithEvents(timestamp, frameCount, realtimeEventListHead); \ |
| 170 | + return noErr; \ |
| 171 | + }; \ |
| 172 | +} |
| 173 | + |
| 174 | +#define AUAudioUnitGeneratorOverrides(str) \ |
| 175 | +\ |
| 176 | +- (BOOL)allocateRenderResourcesAndReturnError:(NSError **)outError { \ |
| 177 | + if (![super allocateRenderResourcesAndReturnError:outError]) { \ |
| 178 | + return NO; \ |
| 179 | + } \ |
| 180 | + _outputBusBuffer.allocateRenderResources(self.maximumFramesToRender); \ |
| 181 | + _kernel.init(self.outputBus.format.channelCount, self.outputBus.format.sampleRate); \ |
| 182 | + _kernel.reset(); \ |
| 183 | + return YES; \ |
| 184 | +} \ |
| 185 | +\ |
| 186 | +- (void)deallocateRenderResources { \ |
| 187 | + _outputBusBuffer.deallocateRenderResources(); \ |
| 188 | + [super deallocateRenderResources]; \ |
| 189 | +} \ |
| 190 | +\ |
| 191 | +- (AUInternalRenderBlock)internalRenderBlock { \ |
| 192 | + __block AK##str##DSPKernel *state = &_kernel; \ |
| 193 | + return ^AUAudioUnitStatus( \ |
| 194 | + AudioUnitRenderActionFlags *actionFlags, \ |
| 195 | + const AudioTimeStamp *timestamp, \ |
| 196 | + AVAudioFrameCount frameCount, \ |
| 197 | + NSInteger outputBusNumber, \ |
| 198 | + AudioBufferList *outputData, \ |
| 199 | + const AURenderEvent *realtimeEventListHead, \ |
| 200 | + AURenderPullInputBlock pullInputBlock) { \ |
| 201 | + _outputBusBuffer.prepareOutputBufferList(outputData, frameCount, true); \ |
| 202 | + state->setBuffer(outputData); \ |
| 203 | + state->processWithEvents(timestamp, frameCount, realtimeEventListHead); \ |
| 204 | + return noErr; \ |
| 205 | + }; \ |
| 206 | +} |
0 commit comments