mirror of
https://github.com/zakk4223/CocoaSplit.git
synced 2026-05-15 14:15:50 -06:00
Always uninitialize nodes when doing connections.
Guard some graph functions with @synchronized() Changing sample rate doesn't rebuild the graph; now requires a restart. (Can't reliably be done with encoders/streams active)
This commit is contained in:
parent
d14db2b8f0
commit
d9f5bff5fe
4 changed files with 115 additions and 95 deletions
|
|
@ -43,7 +43,7 @@
|
|||
|
||||
@property (strong) CAMultiAudioDownmixer *encodeMixer;
|
||||
//@property (strong) CSAacEncoder *encoder;
|
||||
@property (assign) UInt32 sampleRate;
|
||||
@property (assign) double sampleRate;
|
||||
@property (assign) int audioBitrate;
|
||||
@property (assign) double audio_adjust;
|
||||
@property (strong) NSArray *audioOutputs;
|
||||
|
|
|
|||
|
|
@ -84,10 +84,17 @@ OSStatus encoderRenderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc
|
|||
|
||||
if ([aDecoder containsValueForKey:@"sampleRate"])
|
||||
{
|
||||
self.sampleRate = [aDecoder decodeInt32ForKey:@"sampleRate"];
|
||||
UInt32 oldSampleRate = [aDecoder decodeInt32ForKey:@"sampleRate"];
|
||||
self.sampleRate = (double)oldSampleRate;
|
||||
}
|
||||
|
||||
|
||||
if ([aDecoder containsValueForKey:@"sampleRateDouble"])
|
||||
{
|
||||
self.sampleRate = [aDecoder decodeDoubleForKey:@"sampleRateDouble"];
|
||||
|
||||
}
|
||||
|
||||
if ([aDecoder containsValueForKey:@"audioBitrate"])
|
||||
{
|
||||
self.audioBitrate = [aDecoder decodeIntForKey:@"audioBitrate"];
|
||||
|
|
@ -242,7 +249,7 @@ OSStatus encoderRenderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc
|
|||
|
||||
-(void)encodeWithCoder:(NSCoder *)aCoder
|
||||
{
|
||||
[aCoder encodeInt32:self.sampleRate forKey:@"sampleRate"];
|
||||
[aCoder encodeDouble:self.sampleRate forKey:@"sampleRateDouble"];
|
||||
[aCoder encodeObject:self.outputNode.deviceUID forKey:@"selectedAudioId"];
|
||||
[aCoder encodeFloat:self.encodeMixer.volume forKey:@"streamVolume"];
|
||||
[aCoder encodeBool:!self.encodeMixer.enabled forKey:@"streamMuted"];
|
||||
|
|
@ -644,7 +651,8 @@ OSStatus encoderRenderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc
|
|||
|
||||
-(bool)buildGraph
|
||||
{
|
||||
self.graph = [[CAMultiAudioGraph alloc] initWithFormat:nil];
|
||||
AVAudioFormat *useFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:self.sampleRate channels:2];
|
||||
self.graph = [[CAMultiAudioGraph alloc] initWithFormat:useFormat];
|
||||
self.graph.engine = self;
|
||||
|
||||
|
||||
|
|
@ -1038,16 +1046,16 @@ OSStatus encoderRenderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
-(UInt32)sampleRate
|
||||
/*
|
||||
-(double)sampleRate
|
||||
{
|
||||
return _sampleRate;
|
||||
}
|
||||
|
||||
|
||||
-(void)setSampleRate:(UInt32)sampleRate
|
||||
-(void)setSampleRate:(double)sampleRate
|
||||
{
|
||||
UInt32 old_samplerate = _sampleRate;
|
||||
double old_samplerate = _sampleRate;
|
||||
_sampleRate = sampleRate;
|
||||
if (sampleRate > 0 && (sampleRate != old_samplerate))
|
||||
{
|
||||
|
|
@ -1058,6 +1066,7 @@ OSStatus encoderRenderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc
|
|||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
-(void)removeFileInput:(CAMultiAudioFile *)toRemove
|
||||
|
|
|
|||
|
|
@ -175,71 +175,71 @@
|
|||
|
||||
-(bool)connectNode:(CAMultiAudioNode *)node toNode:(CAMultiAudioNode *)toNode format:(AVAudioFormat *)format inBus:(UInt32)inBus outBus:(UInt32)outBus
|
||||
{
|
||||
|
||||
if (!node || !toNode)
|
||||
@synchronized(self)
|
||||
{
|
||||
NSLog(@"ConnectNode: Source or destination node is nil %@ -> %@", node, toNode);
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
NSLog(@"CONNECT %@:%d TO %@:%d FORMAT %@", node, outBus, toNode, inBus, format);
|
||||
AUNode inNode;
|
||||
AUNode connectTo;
|
||||
|
||||
OSStatus err;
|
||||
|
||||
UInt32 bus = inBus;
|
||||
|
||||
|
||||
[self disconnectNode:node outputBus:outBus];
|
||||
[self disconnectNode:toNode inputBus:inBus];
|
||||
|
||||
[node willConnectToNode:toNode inBus:bus outBus:outBus];
|
||||
|
||||
[toNode willConnectNode:node inBus:bus outBus:outBus];
|
||||
|
||||
|
||||
[toNode setInputStreamFormat:format bus:inBus];
|
||||
[node setOutputStreamFormat:format bus:outBus];
|
||||
|
||||
|
||||
AudioUnitConnection newConn;
|
||||
newConn.destInputNumber = inBus;
|
||||
newConn.sourceOutputNumber = outBus;
|
||||
newConn.sourceAudioUnit = node.audioUnit;
|
||||
|
||||
err = AudioUnitSetProperty(toNode.audioUnit, kAudioUnitProperty_MakeConnection, kAudioUnitScope_Input, inBus, &newConn, sizeof(newConn));
|
||||
|
||||
if (err)
|
||||
{
|
||||
NSLog(@"AudioUnitSetProperty(MakeConnection) failed for %@ -> %@, err: %d", node, toNode, err);
|
||||
if (!node || !toNode)
|
||||
{
|
||||
NSLog(@"ConnectNode: Source or destination node is nil %@ -> %@", node, toNode);
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
NSLog(@"CONNECT %@:%d TO %@:%d FORMAT %@", node, outBus, toNode, inBus, format);
|
||||
|
||||
OSStatus err;
|
||||
|
||||
UInt32 bus = inBus;
|
||||
|
||||
|
||||
[self disconnectNode:node outputBus:outBus];
|
||||
[self disconnectNode:toNode inputBus:inBus];
|
||||
|
||||
[node willConnectToNode:toNode inBus:bus outBus:outBus];
|
||||
|
||||
[toNode willConnectNode:node inBus:bus outBus:outBus];
|
||||
|
||||
|
||||
[toNode setInputStreamFormat:format bus:inBus];
|
||||
[node setOutputStreamFormat:format bus:outBus];
|
||||
|
||||
|
||||
AudioUnitConnection newConn;
|
||||
newConn.destInputNumber = inBus;
|
||||
newConn.sourceOutputNumber = outBus;
|
||||
newConn.sourceAudioUnit = node.audioUnit;
|
||||
|
||||
err = AudioUnitSetProperty(toNode.audioUnit, kAudioUnitProperty_MakeConnection, kAudioUnitScope_Input, inBus, &newConn, sizeof(newConn));
|
||||
|
||||
if (err)
|
||||
{
|
||||
NSLog(@"AudioUnitSetProperty(MakeConnection) failed for %@ -> %@, err: %d", node, toNode, err);
|
||||
NSLog(@"%@ OUTPUT %@", node, [node outputFormatForBus:outBus]);
|
||||
NSLog(@"%@ INPUT %@", toNode, [toNode inputFormatForBus:inBus]);
|
||||
return NO;
|
||||
}
|
||||
|
||||
[node nodeConnected:toNode inBus:bus outBus:outBus];
|
||||
|
||||
[toNode connectedToNode:node inBus:bus outBus:outBus];
|
||||
|
||||
NSMutableArray *outputsForBus = node.outputConnections[@(outBus)];
|
||||
if (!outputsForBus)
|
||||
{
|
||||
outputsForBus = [NSMutableArray array];
|
||||
node.outputConnections[@(outBus)] = outputsForBus;
|
||||
}
|
||||
[outputsForBus addObject:[[CAMultiAudioConnection alloc] initWithNode:toNode bus:inBus]];
|
||||
toNode.inputConnections[@(inBus)] = [[CAMultiAudioConnection alloc] initWithNode:node bus:outBus];
|
||||
NSLog(@"%@ OUTPUT %@", node, [node outputFormatForBus:outBus]);
|
||||
NSLog(@"%@ INPUT %@", toNode, [toNode inputFormatForBus:inBus]);
|
||||
return NO;
|
||||
}
|
||||
|
||||
[node nodeConnected:toNode inBus:bus outBus:outBus];
|
||||
|
||||
[toNode connectedToNode:node inBus:bus outBus:outBus];
|
||||
|
||||
NSMutableArray *outputsForBus = node.outputConnections[@(outBus)];
|
||||
if (!outputsForBus)
|
||||
{
|
||||
outputsForBus = [NSMutableArray array];
|
||||
node.outputConnections[@(outBus)] = outputsForBus;
|
||||
}
|
||||
[outputsForBus addObject:[[CAMultiAudioConnection alloc] initWithNode:toNode bus:inBus]];
|
||||
toNode.inputConnections[@(inBus)] = [[CAMultiAudioConnection alloc] initWithNode:node bus:outBus];
|
||||
NSLog(@"%@ OUTPUT %@", node, [node outputFormatForBus:outBus]);
|
||||
NSLog(@"%@ INPUT %@", toNode, [toNode inputFormatForBus:inBus]);
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
-(NSArray *)connectedInputBusses:(CAMultiAudioNode *)node
|
||||
{
|
||||
|
||||
return node.inputConnections.allKeys;
|
||||
}
|
||||
|
||||
|
|
@ -300,41 +300,44 @@
|
|||
return NO;
|
||||
}
|
||||
|
||||
CAMultiAudioConnection *inputConnection = node.inputConnections[@(inputBus)];
|
||||
|
||||
if (inputConnection)
|
||||
@synchronized (self)
|
||||
{
|
||||
CAMultiAudioConnection *inputConnection = node.inputConnections[@(inputBus)];
|
||||
|
||||
AudioUnitConnection breakConn;
|
||||
breakConn.destInputNumber = inputBus;
|
||||
breakConn.sourceOutputNumber = inputConnection.bus;
|
||||
breakConn.sourceAudioUnit = NULL;
|
||||
|
||||
OSErr err = AudioUnitSetProperty(node.audioUnit, kAudioUnitProperty_MakeConnection, kAudioUnitScope_Input, inputBus, &breakConn, sizeof(breakConn));
|
||||
if (err)
|
||||
if (inputConnection)
|
||||
{
|
||||
NSLog(@"AudioUnitSetProperty(MakeConnection) failed for node %@:%d, err %d", node, inputBus, err);
|
||||
}
|
||||
|
||||
if (updateOutputs)
|
||||
{
|
||||
CAMultiAudioNode *srcNode = inputConnection.node;
|
||||
if (srcNode)
|
||||
|
||||
AudioUnitConnection breakConn;
|
||||
breakConn.destInputNumber = inputBus;
|
||||
breakConn.sourceOutputNumber = inputConnection.bus;
|
||||
breakConn.sourceAudioUnit = NULL;
|
||||
|
||||
OSErr err = AudioUnitSetProperty(node.audioUnit, kAudioUnitProperty_MakeConnection, kAudioUnitScope_Input, inputBus, &breakConn, sizeof(breakConn));
|
||||
if (err)
|
||||
{
|
||||
NSMutableArray *newConns = [NSMutableArray array];
|
||||
NSArray *conns = [self outputConnections:srcNode forBus:inputConnection.bus];
|
||||
for(CAMultiAudioConnection *nConn in conns)
|
||||
{
|
||||
if (nConn.node != node)
|
||||
{
|
||||
[newConns addObject:nConn];
|
||||
}
|
||||
}
|
||||
|
||||
srcNode.outputConnections[@(inputConnection.bus)] = newConns;
|
||||
NSLog(@"AudioUnitSetProperty(MakeConnection) failed for node %@:%d, err %d", node, inputBus, err);
|
||||
}
|
||||
|
||||
if (updateOutputs)
|
||||
{
|
||||
CAMultiAudioNode *srcNode = inputConnection.node;
|
||||
if (srcNode)
|
||||
{
|
||||
NSMutableArray *newConns = [NSMutableArray array];
|
||||
NSArray *conns = [self outputConnections:srcNode forBus:inputConnection.bus];
|
||||
for(CAMultiAudioConnection *nConn in conns)
|
||||
{
|
||||
if (nConn.node != node)
|
||||
{
|
||||
[newConns addObject:nConn];
|
||||
}
|
||||
}
|
||||
|
||||
srcNode.outputConnections[@(inputConnection.bus)] = newConns;
|
||||
}
|
||||
}
|
||||
[node.inputConnections removeObjectForKey:@(inputBus)];
|
||||
}
|
||||
[node.inputConnections removeObjectForKey:@(inputBus)];
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -304,6 +304,8 @@ UInt32 inNumberFrames,
|
|||
-(bool)setInputStreamFormat:(AVAudioFormat *)format bus:(UInt32)bus
|
||||
{
|
||||
|
||||
AudioUnitUninitialize(self.audioUnit);
|
||||
|
||||
OSStatus err = AudioUnitSetProperty(self.audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, bus, format.streamDescription, sizeof(AudioStreamBasicDescription));
|
||||
|
||||
if (err)
|
||||
|
|
@ -311,7 +313,10 @@ UInt32 inNumberFrames,
|
|||
NSLog(@"Failed to set StreamFormat for input on node %@ with %d", self, err);
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
[self willInitializeNode];
|
||||
AudioUnitInitialize(self.audioUnit);
|
||||
[self didInitializeNode];
|
||||
return YES;
|
||||
|
||||
}
|
||||
|
|
@ -319,7 +324,8 @@ UInt32 inNumberFrames,
|
|||
|
||||
-(bool)setOutputStreamFormat:(AVAudioFormat *)format bus:(UInt32)bus
|
||||
{
|
||||
|
||||
AudioUnitUninitialize(self.audioUnit);
|
||||
|
||||
OSStatus err = AudioUnitSetProperty(self.audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, bus, format.streamDescription, sizeof(AudioStreamBasicDescription));
|
||||
|
||||
if (err)
|
||||
|
|
@ -327,7 +333,9 @@ UInt32 inNumberFrames,
|
|||
NSLog(@"Failed to set StreamFormat for output on node %@ with %d", self, err);
|
||||
return NO;
|
||||
}
|
||||
|
||||
[self willInitializeNode];
|
||||
AudioUnitInitialize(self.audioUnit);
|
||||
[self didInitializeNode];
|
||||
return YES;
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue