diff --git a/CocoaSplit/CAMultiAudio/CAMultiAudioEngine.m b/CocoaSplit/CAMultiAudio/CAMultiAudioEngine.m index d812e4ee..34611df8 100644 --- a/CocoaSplit/CAMultiAudio/CAMultiAudioEngine.m +++ b/CocoaSplit/CAMultiAudio/CAMultiAudioEngine.m @@ -450,7 +450,9 @@ OSStatus encoderRenderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc } NSNumber *trackOutBus = outputTrack.outputBus; - [self.encodeMixer disconnectInputBus:input.effectsHead.connectedToBus fromOutputBus:trackOutBus.unsignedIntValue]; + CAMultiAudioConnection *inputConn = [self.graph findOutputConnection:input.headNode forNode:self.encodeMixer onBus:0]; + + [self.encodeMixer disconnectInputBus:inputConn.bus fromOutputBus:trackOutBus.unsignedIntValue]; [input.outputTracks removeObjectForKey:outputTrack.uuid]; return YES; } @@ -470,10 +472,10 @@ OSStatus encoderRenderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc NSNumber *trackOutBus = outputTrack.outputBus; - NSLog(@"EFFECT HEAD %@ ON BUS %d -> BUS %d", input.effectsHead, input.effectsHead.connectedToBus, trackOutBus.unsignedIntValue); - - [self.encodeMixer connectInputBus:input.effectsHead.connectedToBus toOutputBus:trackOutBus.unsignedIntValue]; - [input.outputTracks setObject:outputTrack forKey:outputTrack.uuid]; + CAMultiAudioConnection *inputConn = [self.graph findOutputConnection:input.headNode forNode:self.encodeMixer onBus:0]; + [self.encodeMixer connectInputBus:inputConn.bus toOutputBus:trackOutBus.unsignedIntValue]; + CAMultiAudioOutputTrackConnection *trackConn = [[CAMultiAudioOutputTrackConnection alloc] initWithTrack:outputTrack inBus:inputConn.bus]; + [input.outputTracks setObject:trackConn forKey:outputTrack.uuid]; return YES; } @@ -540,8 +542,9 @@ OSStatus encoderRenderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc [self.graph addNode:encNode]; [self.graph connectNode:self.encodeMixer toNode:encNode]; [self.graph connectNode:encNode toNode:self.previewMixer]; - [self.previewMixer setVolumeOnInputBus:encNode.connectedToBus volume:0.0f]; CAMultiAudioConnection *eConn = [self.graph inputConnection:encNode forBus:0]; + + [self.previewMixer setVolumeOnInputBus:eConn.bus volume:0.0f]; CAMultiAudioConnection *silenceConn = [self.graph findOutputConnection:self.silentNode forNode:self.encodeMixer onBus:0]; [self.encodeMixer setVolumeOnOutputBus:eConn.bus volume:1.0f]; diff --git a/CocoaSplit/CAMultiAudio/CAMultiAudioGraph.h b/CocoaSplit/CAMultiAudio/CAMultiAudioGraph.h index 75402b6a..ba4ed853 100644 --- a/CocoaSplit/CAMultiAudio/CAMultiAudioGraph.h +++ b/CocoaSplit/CAMultiAudio/CAMultiAudioGraph.h @@ -43,6 +43,9 @@ -(NSArray *)connectedInputBusses:(CAMultiAudioNode *)node; -(NSArray *)connectedOutputBusses:(CAMultiAudioNode *)node; -(CAMultiAudioConnection *)findOutputConnection:(CAMultiAudioNode *)node forNode:(CAMultiAudioNode *)forNode onBus:(UInt32)outBus; +-(bool)connectNode:(CAMultiAudioNode *)node usingConnections:(NSArray *)connections outBus:(UInt32)outBus format:(AVAudioFormat *)format; +-(bool)connectNode:(CAMultiAudioNode *)node usingConnections:(NSArray *)connections outBus:(UInt32)outBus; + diff --git a/CocoaSplit/CAMultiAudio/CAMultiAudioGraph.m b/CocoaSplit/CAMultiAudio/CAMultiAudioGraph.m index 6e7d170c..65a2667e 100644 --- a/CocoaSplit/CAMultiAudio/CAMultiAudioGraph.m +++ b/CocoaSplit/CAMultiAudio/CAMultiAudioGraph.m @@ -204,6 +204,33 @@ return YES; } +-(bool)connectNode:(CAMultiAudioNode *)node usingConnections:(NSArray *)connections outBus:(UInt32)outBus +{ + return [self connectNode:node usingConnections:connections outBus:outBus format:self.audioFormat]; +} + + +-(bool)connectNode:(CAMultiAudioNode *)node usingConnections:(NSArray *)connections outBus:(UInt32)outBus format:(AVAudioFormat *)format +{ + if (!_graphInst) + { + NSLog(@"ConnectNode: No AUGraph!"); + return NO; + } + + if (!node) + { + return NO; + } + + for(CAMultiAudioConnection *conn in connections) + { + [self connectNode:node toNode:conn.node format:format inBus:conn.bus outBus:outBus]; + } + + return YES; +} + -(bool)connectNode:(CAMultiAudioNode *)node toNode:(CAMultiAudioNode *)toNode { diff --git a/CocoaSplit/CAMultiAudio/CAMultiAudioInput.m b/CocoaSplit/CAMultiAudio/CAMultiAudioInput.m index 2f53b0b3..374e9c7f 100644 --- a/CocoaSplit/CAMultiAudio/CAMultiAudioInput.m +++ b/CocoaSplit/CAMultiAudio/CAMultiAudioInput.m @@ -162,42 +162,16 @@ } - self.downMixer = [[CAMultiAudioDownmixer alloc] initWithInputChannels:self.channelCount]; - if (![self.graph addNode:self.downMixer]) - { - - [self teardownGraph]; - return NO; - } - self.downMixer.muted = NO; - self.downMixer.volume = 1.0f; - CAMultiAudioNode *connectTo = self.converterNode; - if (!connectTo) - { - connectTo = self.downMixer; - } - - - - - if(![self.graph connectNode:self toNode:connectTo format:self.inputFormat]) + if (![self.graph connectNode:self toNode:self.converterNode format:self.inputFormat]) { [self teardownGraph]; return NO; } - if (self.converterNode) - { - - - if(![self.graph connectNode:self.converterNode toNode:self.downMixer]) - { - [self teardownGraph]; - return NO; - } - } + + AVAudioFormat *useFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:self.graph.audioFormat.sampleRate channelLayout:self.inputFormat.channelLayout]; CAMultiAudioDelay *delayNode; - CAMultiAudioNode *connectNode = self.downMixer; + CAMultiAudioNode *connectNode = self.converterNode; for(int i=0; i < 5; i++) { @@ -210,7 +184,7 @@ [self teardownGraph]; return NO; } - ret = [self.graph connectNode:connectNode toNode:delayNode]; + ret = [self.graph connectNode:connectNode toNode:delayNode format:useFormat]; if (!ret) { @@ -225,30 +199,34 @@ [self.delayNodes addObject:delayNode]; } - - self.effectsHead = connectNode; - [self.downMixer connectInputBus:0 toOutputBus:0]; - - + self.headNode = delayNode; + self.effectsHead = delayNode; return YES; } --(void)rebuildEffectChain +-(void)setupDownmixer { - [super rebuildEffectChain]; - [self.graph connectNode:self.effectsHead toNode:self.downMixer]; + AVAudioFormat *useFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:self.graph.audioFormat.sampleRate channelLayout:self.inputFormat.channelLayout]; + + + self.downMixer = [[CAMultiAudioDownmixer alloc] initWithInputChannels:useFormat.channelCount]; + [self.graph addNode:self.downMixer]; + [self.graph connectNode:self.headNode toNode:self.downMixer format:useFormat]; self.headNode = self.downMixer; + self.downMixer.volume = 1.0f; + self.downMixer.muted = NO; + [self.downMixer connectInputBus:0 toOutputBus:0]; + } + -(void)setupEffectsChain { [self setupGraph]; - //self.effectsHead = self; - // [super setupEffectsChain]; - self.headNode = self.effectsHead; - //[self.converterNode generateTone]; + [super setupEffectsChain]; + [self setupDownmixer]; } diff --git a/CocoaSplit/CAMultiAudio/CAMultiAudioNode.h b/CocoaSplit/CAMultiAudio/CAMultiAudioNode.h index a63d3768..115437c8 100644 --- a/CocoaSplit/CAMultiAudio/CAMultiAudioNode.h +++ b/CocoaSplit/CAMultiAudio/CAMultiAudioNode.h @@ -40,8 +40,6 @@ @property (assign) float volume; @property (assign) bool muted; @property (assign) bool enabled; -@property (readonly) CAMultiAudioNode *connectedTo; -@property (readonly) UInt32 connectedToBus; -(instancetype)initWithSubType:(OSType)subType unitType:(OSType)unitType; -(instancetype)initWithSubType:(OSType)subType unitType:(OSType)unitType manufacturer:(OSType)manufacturer; @@ -75,6 +73,7 @@ AudioComponentDescription unitDescr; CAMultiAudioVolumeAnimation *_volumeAnimation; + NSMutableArray *_currentEffectChain; } @property (assign) AUNode node; @@ -97,7 +96,6 @@ @property (strong) NSMutableDictionary *outputConnections; @property (readonly) CAMultiAudioNode *connectedTo; -@property (readonly) UInt32 connectedToBus; @property (assign) float volume; @@ -118,6 +116,8 @@ -(void)addEffect:(CAMultiAudioNode *)effect; -(void)addEffect:(CAMultiAudioNode *)effect atIndex:(NSUInteger)idx; -(void)generateTone; +-(void)reset; + @end diff --git a/CocoaSplit/CAMultiAudio/CAMultiAudioNode.m b/CocoaSplit/CAMultiAudio/CAMultiAudioNode.m index edd7366d..84b4ae2f 100644 --- a/CocoaSplit/CAMultiAudio/CAMultiAudioNode.m +++ b/CocoaSplit/CAMultiAudio/CAMultiAudioNode.m @@ -33,8 +33,6 @@ UInt32 inNumberFrames, @synthesize volume = _volume; @synthesize muted = _muted; @synthesize enabled = _enabled; -@synthesize connectedTo = _connectedTo; -@synthesize connectedToBus = _connectedToBus; -(instancetype)init { @@ -63,6 +61,7 @@ UInt32 inNumberFrames, self.nodeUID = [[NSUUID UUID] UUIDString]; self.inputConnections = [NSMutableDictionary dictionary]; self.outputConnections = [NSMutableDictionary dictionary]; + _currentEffectChain = [NSMutableArray array]; } return self; @@ -332,14 +331,9 @@ UInt32 inNumberFrames, - -(void)nodeConnected:(CAMultiAudioNode *)toNode inBus:(UInt32)inBus outBus:(UInt32)outBus { - if (outBus == 0) - { - _connectedTo = toNode; - _connectedToBus = inBus; - } + return; } @@ -443,60 +437,63 @@ UInt32 inNumberFrames, -(void)rebuildEffectChain { - //Disconnect every node from effectsHead -> headNode (including headNode) and then reconnect everything in effectchain array + bool restoreHeadNode = NO; + + NSArray *outConnections = nil; + CAMultiAudioNode *lastEffect = _currentEffectChain.lastObject; + AVAudioFormat *useFormat = [self.effectsHead outputFormatForBus:0]; + + if (lastEffect) + { + outConnections = [self.graph outputConnections:lastEffect forBus:0]; + if (lastEffect == self.headNode) + { + restoreHeadNode = YES; + } + } else { + outConnections = [self.graph outputConnections:self.effectsHead forBus:0]; + } + + + [self.effectsHead.graph disconnectNodeOutput:self.effectsHead]; + + for (CAMultiAudioNode *currNode in _currentEffectChain) + { + if (currNode && currNode.graph) + { + [currNode.graph disconnectNode:currNode]; + [currNode.graph removeNode:currNode]; + } + } + + + [_currentEffectChain removeAllObjects]; + + CAMultiAudioNode *currNode = self.effectsHead; - CAMultiAudioNode *headConn; - while (currNode && currNode != self.headNode) - { - CAMultiAudioNode *connNode = currNode.connectedTo; - [self.graph disconnectNode:currNode]; - if (currNode.deleteNode) - { - [self.graph removeNode:currNode]; - } - currNode = connNode; - } - - if (currNode) //This is headNode - { - headConn = currNode.connectedTo; - [self.graph disconnectNode:currNode]; - if (currNode.deleteNode) - { - [self.graph removeNode:currNode]; - } - - self.headNode = self.effectsHead; - } - - currNode = nil; + currNode = self.effectsHead; for (CAMultiAudioNode *eNode in self.effectChain) { [self.graph addNode:eNode]; - [self.graph connectNode:currNode toNode:eNode]; + [self.graph connectNode:currNode toNode:eNode format:useFormat]; + [_currentEffectChain addObject:eNode]; currNode = eNode; } - if (headConn && currNode) + if (outConnections && outConnections.count > 0) { - [self.graph connectNode:currNode toNode:headConn]; + + [currNode.graph connectNode:currNode usingConnections:outConnections outBus:0 format:useFormat]; + } - - if (currNode) + if (restoreHeadNode) { self.headNode = currNode; - } else { - self.headNode = self.effectsHead; } - - - //CAShow(self.graph.graphInst); - - } -(void)addEffect:(CAMultiAudioNode *)effect; @@ -569,6 +566,12 @@ UInt32 inNumberFrames, } +-(void)reset +{ + AudioUnitReset(self.audioUnit, kAudioUnitScope_Global, 0); + AudioUnitUninitialize(self.audioUnit); + AudioUnitInitialize(self.audioUnit); +} -(void) dealloc { if (self.graph) diff --git a/CocoaSplit/Interface/Audio/CAMultiAudioMatrixMixerWindowController.m b/CocoaSplit/Interface/Audio/CAMultiAudioMatrixMixerWindowController.m index 59c1b93c..3dbc84c8 100644 --- a/CocoaSplit/Interface/Audio/CAMultiAudioMatrixMixerWindowController.m +++ b/CocoaSplit/Interface/Audio/CAMultiAudioMatrixMixerWindowController.m @@ -57,9 +57,20 @@ -(void)openAddTrackPopover:(id)sender sourceRect:(NSRect)sourceRect { [self buildTrackMenu]; + NSInteger midItem = 0; - NSInteger midItem = _tracksMenu.itemArray.count/2; + if (_tracksMenu.itemArray.count == 0) + { + return; + } + + + if (_tracksMenu.itemArray.count > 2) + { + midItem = _tracksMenu.itemArray.count/2; + } NSPoint popupPoint = NSMakePoint(NSMaxY(sourceRect), NSMidY(sourceRect)); + [_tracksMenu popUpMenuPositioningItem:[_tracksMenu itemAtIndex:midItem] atLocation:popupPoint inView:sender]; } @@ -99,7 +110,7 @@ self.audioNode = node; self.downMixer = node.downMixer; - NSSortDescriptor *nameSort = [NSSortDescriptor sortDescriptorWithKey:@"value.name" ascending:YES comparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) { + NSSortDescriptor *nameSort = [NSSortDescriptor sortDescriptorWithKey:@"value.outputTrack.name" ascending:YES comparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) { NSString *name1 = obj1; NSString *name2 = obj2; diff --git a/CocoaSplit/Interface/Audio/CAMultiAudioMatrixMixerWindowController.xib b/CocoaSplit/Interface/Audio/CAMultiAudioMatrixMixerWindowController.xib index ec38fd5c..3a3e3bab 100644 --- a/CocoaSplit/Interface/Audio/CAMultiAudioMatrixMixerWindowController.xib +++ b/CocoaSplit/Interface/Audio/CAMultiAudioMatrixMixerWindowController.xib @@ -1,8 +1,8 @@ - + - + @@ -20,26 +20,26 @@ - - + + - + - + - - + + - + @@ -55,7 +55,7 @@ - + @@ -96,20 +96,20 @@ - + - + - + - + @@ -118,32 +118,32 @@ - + - + - + - - - + + + - - - + + + - + @@ -159,7 +159,7 @@ - + @@ -186,8 +186,8 @@ - - + + @@ -202,28 +202,28 @@ - + - + - -