Some changes for effect chains.

AVAudioEngine may not be a suitable replacement for the previous audio engine....god damnit apple
This commit is contained in:
Zakk 2020-02-18 04:06:08 -05:00
parent 76919247b5
commit 0058c741f4
12 changed files with 265 additions and 106 deletions

View file

@ -22,6 +22,7 @@
effectDescr.componentSubType = subType;
effectDescr.componentType = unitType;
AVAudioUnitEffect *effectNode = [[AVAudioUnitEffect alloc] initWithAudioComponentDescription:effectDescr];
if (self = [self initWithAudioNode:effectNode])
@ -151,7 +152,9 @@
-(id)copyWithZone:(NSZone *)zone
{
CAMultiAudioEffect *newNode = [[CAMultiAudioEffect alloc] initWithSubType:unitDescr.componentSubType unitType:unitDescr.componentType manufacturer:unitDescr.componentManufacturer];
AVAudioUnitEffect *effectNode = (AVAudioUnitEffect *)self.avAudioNode;
CAMultiAudioEffect *newNode = [[CAMultiAudioEffect alloc] initWithSubType:effectNode.AUAudioUnit.componentDescription.componentSubType unitType:effectNode.AUAudioUnit.componentDescription.componentType manufacturer:effectNode.AUAudioUnit.componentDescription.componentManufacturer];
newNode.name = self.name;
return newNode;
}

View file

@ -202,7 +202,6 @@ OSStatus encoderRenderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc
}
}
}
[self.graph startGraph];
for (NSString *trackUUID in self.outputTracks)
{
CAMultiAudioOutputTrack *outTrack = self.outputTracks[trackUUID];
@ -212,6 +211,8 @@ OSStatus encoderRenderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc
}
}
[self.graph startGraph];
}
return self;
@ -505,7 +506,7 @@ OSStatus encoderRenderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc
AVAudioNodeBus nextMixerBus = trackMixer.nextInputBus;
AVAudioFormat *newFmt = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:input.inputFormat.sampleRate channels:self.graph.graphFormat.channelCount];
[self.graph addConnection:input.headNode toNode:trackMixer toBus:nextMixerBus withFormat:newFmt];
[self.graph addConnection:input.headNode toNode:trackMixer toBus:nextMixerBus withFormat:self.graph.graphFormat];
[input.outputTracks setObject:@{@"inputBus": @(nextMixerBus), @"outputTrack": outputTrack} forKey:outputTrack.uuid];
return YES;
}
@ -711,7 +712,6 @@ OSStatus encoderRenderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc
self.silentNode = [[CAMultiAudioSilence alloc] init];
self.encodeMixer = [[CAMultiAudioMixer alloc] init];
self.encodeMixer.nodeUID = @"__CS_ENCODE_MIXER_NODE";
@ -1310,6 +1310,8 @@ OSStatus encoderRenderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc
[self addAudioInputsObject:input];
});
}
[input didAttachInput];
[CaptureController.sharedCaptureController postNotification:CSNotificationAudioAdded forObject:self];
return YES;

View file

@ -23,6 +23,7 @@
//We need to hold references to all the nodes so this isn't a pain to use for clients
@property (strong) NSMutableArray *attachedNodes;
@property (assign) AUGraph graphInst;
@property (readonly) NSSet *nodeSet;
@property (assign) double sampleRate;
@ -41,7 +42,7 @@
-(bool)addConnection:(CAMultiAudioNode *)fromNode toNode:(CAMultiAudioNode *)toNode toBus:(AVAudioNodeBus)toBus withFormat:(AVAudioFormat *)format;
-(bool)disconnectNode:(CAMultiAudioNode *)node inputBus:(AVAudioNodeBus)inputBus;
-(bool)disconnectNode:(CAMultiAudioNode *)node;
-(bool)disconnectNodeOutput:(CAMultiAudioNode *)node;
-(bool)startGraph;
-(bool)stopGraph;

View file

@ -25,7 +25,7 @@
_sampleRate = samplerate;
_attachedNodes = [NSMutableArray array];
//set to canonical, 2 channel
self.graphFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:_sampleRate channels:2];
//Always force an input singleton
@ -64,7 +64,10 @@
NSLog(@"AUGraphStart failed, err %@", startError);
return NO;
}
for(CAMultiAudioNode *node in self.attachedNodes)
{
[node engineDidStart];
}
return YES;
}
@ -109,7 +112,7 @@
newNode.graph = self;
[newNode didAttachNode];
[self.attachedNodes addObject:newNode];
[newNode setupEffectsChain];
return YES;
}
@ -127,6 +130,7 @@
[_avEngine detachNode:node.avAudioNode];
[self.attachedNodes removeObject:node];
[node removeEffectsChain];
node.graph = nil;
return YES;
@ -221,6 +225,24 @@
}
-(bool)disconnectNodeOutput:(CAMultiAudioNode *)node
{
if (!_avEngine)
{
return NO;
}
if (!node || !node.avAudioNode)
{
return NO;
}
[_avEngine disconnectNodeOutput:node.avAudioNode];
return YES;
}
-(bool)disconnectNode:(CAMultiAudioNode *)node inputBus:(AVAudioNodeBus)inputBus
{
if (!_avEngine)

View file

@ -35,7 +35,7 @@
{
}
@property (strong) CAMultiAudioMixer *downMixer;
@property (strong) CAMultiAudioDelay *stupidNode;
@property (strong) NSMutableArray *delayNodes;
@property (strong) NSColor *nameColor;
@property (strong) CAMultiAudioMatrixMixerWindowController *mixerWindow;
@ -59,5 +59,6 @@
-(void)removeFromEngine;
-(void)addToOutputTrack:(CAMultiAudioOutputTrack *)trackName;
-(void)removeFromOutputTrack:(CAMultiAudioOutputTrack *)trackName;
-(void)didAttachInput;
@end

View file

@ -131,6 +131,7 @@
-(bool)teardownGraph
{
return YES;
if (!self.graph)
{
//!?!?!
@ -203,18 +204,28 @@
self.headNode = delayNode;
NSLog(@"HEAD NODE %@", self.headNode);
self.effectsHead = delayNode;
return YES;
}
-(void)didAttachInput
{
return;
}
-(void)setupDownmixer
{
AVAudioFormat *useFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:self.inputFormat.sampleRate channels:self.inputFormat.channelCount];
self.downMixer = [[CAMultiAudioMixer alloc] init];
self.stupidNode = [[CAMultiAudioDelay alloc] init];
self.stupidNode.delay = 0.0f;
[self.graph addNode:self.downMixer];
[self.graph connectNode:self.headNode toNode:self.downMixer withFormat:useFormat];
[self.graph addNode:self.stupidNode];
[self.graph connectNode:self.effectsHead toNode:self.stupidNode withFormat:useFormat];
[self.graph connectNode:self.stupidNode toNode:self.downMixer withFormat:useFormat];
self.headNode = self.downMixer;
self.downMixer.volume = 1.0f;
}
@ -222,7 +233,7 @@
-(void)setupEffectsChain
{
[self setupGraph];
// [super setupEffectsChain];
[super setupEffectsChain];
[self setupDownmixer];
}

View file

@ -18,5 +18,7 @@
@property (readonly) AVAudioNodeBus nextInputBus;
@property (assign) int inputChannelCount;
@property (assign) int outputChannelCount;
@end

View file

@ -78,6 +78,7 @@
AudioComponentDescription unitDescr;
CAMultiAudioVolumeAnimation *_volumeAnimation;
NSMutableArray *_currentEffectChain;
}
@ -120,12 +121,13 @@
-(void)willRemoveNode;
-(void)setupEffectsChain;
-(void)removeEffectsChain;
-(void)rebuildEffectChain;
-(void)didAttachNode;
-(void)addEffect:(CAMultiAudioNode *)effect;
-(void)addEffect:(CAMultiAudioNode *)effect atIndex:(NSUInteger)idx;
-(bool)busForOutput:(CAMultiAudioNode *)inputNode busOut:(UInt32 *)busOut;
-(bool)busForInput:(CAMultiAudioNode *)inputNode busOut:(UInt32 *)busOut;
-(void) remakeNode;
-(void)engineDidStart;
@end

View file

@ -70,6 +70,7 @@
self.volume = 1.0f;
self.headNode = self;
self.effectsHead = self;
_currentEffectChain = [NSMutableArray array];
}
return self;
}
@ -440,62 +441,92 @@
return;
}
-(void)engineDidStart
{
return;
}
-(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.avAudioNode outputFormatForBus:0];
if (lastEffect)
{
outConnections = [self.avAudioNode.engine outputConnectionPointsForNode:lastEffect.avAudioNode outputBus:0];
if (lastEffect == self.headNode)
{
restoreHeadNode = YES;
}
} else {
outConnections = [self.avAudioNode.engine outputConnectionPointsForNode:self.effectsHead.avAudioNode outputBus:0];
}
[self.effectsHead.graph disconnectNodeOutput:self.effectsHead];
for (CAMultiAudioNode *currNode in _currentEffectChain)
{
if (currNode.avAudioNode && currNode.avAudioNode.engine)
{
[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 withFormat:useFormat];
[_currentEffectChain addObject:eNode];
currNode = eNode;
}
if (headConn && currNode)
if (outConnections && outConnections.count > 0)
{
[self.graph connectNode:currNode toNode:headConn];
AVAudioUnitSampler *dummyNode = [[AVAudioUnitSampler alloc] init];
[self.avAudioNode.engine attachNode:dummyNode];
NSMutableArray *newConns = [NSMutableArray array];
for(AVAudioConnectionPoint *avpt in outConnections)
{
AVAudioConnectionPoint *newPoint = [[AVAudioConnectionPoint alloc] initWithNode:avpt.node bus:avpt.bus];
[newConns addObject:newPoint];
//Hacks?
AVAudioNode *destNode = avpt.node;
AVAudioNodeBus destBus = avpt.bus;
NSLog(@"CONNECTION %@ ON BUS %d WITH FORMAT %@", avpt.node, avpt.bus, useFormat);
}
//[dummyNode.engine disconnectNodeOutput:dummyNode];
if (newConns.count > 0)
{
[currNode.avAudioNode.engine connect:currNode.avAudioNode toConnectionPoints:newConns fromBus:0 format:useFormat];
}
}
if (currNode)
if (restoreHeadNode)
{
self.headNode = currNode;
} else {
self.headNode = self.effectsHead;
}
//CAShow(self.graph.graphInst);
}
-(void)addEffect:(CAMultiAudioNode *)effect;
@ -545,7 +576,7 @@
-(void)setupEffectsChain
{
// [self rebuildEffectChain];
[self rebuildEffectChain];
//Do restore here
}

View file

@ -34,6 +34,7 @@ struct cspcm_buffer_msg {
AVAudioFormat *_audioFormat;
TPCircularBuffer _completedBuffer;
bool _dataSeen;
bool _playPending;
}
@ -43,6 +44,7 @@ struct cspcm_buffer_msg {
@property (nonatomic, copy) void (^completedBlock)(CAMultiAudioPCM *pcmBuffer);
@property (strong) NSMutableArray *pauseBuffer;
@property (assign) bool save_buffer;
@property (readonly) bool isPlaying;
-(instancetype)initWithAudioFormat:(AVAudioFormat *)format;

View file

@ -60,6 +60,18 @@
}
-(bool)isPlaying
{
AVAudioPlayerNode *pNode = (AVAudioPlayerNode *)self.avAudioNode;
if (!pNode)
{
return NO;
}
return pNode.playing;
}
-(AVAudioFormat *)inputFormat
{
return _audioFormat;
@ -72,6 +84,8 @@
}
-(void)setEnabled:(bool)enabled
{
[super setEnabled:enabled];
@ -84,6 +98,20 @@
}
-(void)rebuildEffectChain
{
bool isPlaying = self.isPlaying;
if (isPlaying)
{
[self pause];
}
[super rebuildEffectChain];
if (isPlaying)
{
[self play];
}
}
-(void)startPendingProcessor
{
if (!_pendingQueue)
@ -161,10 +189,9 @@
return NO;
}
if (!pNode.playing)
if (!self.isPlaying)
{
[self play];
return NO;
}
@ -249,12 +276,23 @@
-(void)pause
{
self.save_buffer = YES;
[self flush];
if (self.avAudioNode)
{
AVAudioPlayerNode *pNode = (AVAudioPlayerNode *)self.avAudioNode;
[pNode pause];
}
}
-(void)stop
{
if (self.avAudioNode)
{
AVAudioPlayerNode *pNode = (AVAudioPlayerNode *)self.avAudioNode;
[pNode stop];
}
}
-(void)flush
{
if (self.audioUnit)
@ -269,12 +307,53 @@
if (self.avAudioNode)
{
AVAudioPlayerNode *pNode = self.avAudioNode;
AVAudioPlayerNode *pNode = (AVAudioPlayerNode *)self.avAudioNode;
[pNode play];
}
}
-(void)engineDidStart
{
[super engineDidStart];
bool ppending;
@synchronized (self) {
ppending = _playPending;
}
if (ppending)
{
[self play];
}
@synchronized (self) {
ppending = NO;
}
}
-(void)didAttachInput
{
[super didAttachInput];
AVAudioPlayerNode *pNode = (AVAudioPlayerNode *)self.avAudioNode;
if (!pNode.engine || !pNode.engine.running)
{
@synchronized (self) {
_playPending = YES;
}
return;
}
if (!self.isPlaying)
{
[self play];
}
}
-(void)dealloc
{

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15505" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14490.70"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15505"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@ -26,15 +26,15 @@
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="6qE-t2-zqe">
<rect key="frame" x="19" y="476" width="84" height="14"/>
<textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Stream Volume" id="clH-Fr-TJ1">
<font key="font" metaFont="smallSystem"/>
<font key="font" metaFont="palette"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="wwP-vq-QJZ">
<rect key="frame" x="18" y="529" width="65" height="14"/>
<rect key="frame" x="18" y="528" width="65" height="14"/>
<textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Samplerate" id="qPp-Ym-izV">
<font key="font" metaFont="smallSystem"/>
<font key="font" metaFont="palette"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
@ -42,7 +42,7 @@
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ssR-h6-svZ">
<rect key="frame" x="91" y="548" width="59" height="19"/>
<textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="lBZ-LI-XH0">
<font key="font" metaFont="smallSystem"/>
<font key="font" metaFont="palette"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
@ -51,10 +51,10 @@
</connections>
</textField>
<popUpButton horizontalHuggingPriority="249" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="67k-Zi-Ko9">
<rect key="frame" x="88" y="524" width="70" height="22"/>
<rect key="frame" x="88" y="523" width="70" height="22"/>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" controlSize="small" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="FJb-Og-tdf" id="uSC-7v-E4B">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="smallSystem"/>
<font key="font" metaFont="palette"/>
<menu key="menu" id="6Ra-rI-plD">
<items>
<menuItem title="Item 1" state="on" id="FJb-Og-tdf"/>
@ -69,20 +69,20 @@
</connections>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ycu-9s-oiz">
<rect key="frame" x="155" y="551" width="62" height="14"/>
<rect key="frame" x="155" y="550" width="62" height="14"/>
<constraints>
<constraint firstAttribute="width" constant="58" id="q2p-hX-TR0"/>
</constraints>
<textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="kbits/sec" id="S8r-Xg-ebh">
<font key="font" metaFont="smallSystem"/>
<font key="font" metaFont="palette"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="zuo-gj-1Pr">
<rect key="frame" x="18" y="507" width="63" height="14"/>
<rect key="frame" x="18" y="506" width="63" height="14"/>
<textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Audio Shift" id="6Pl-mK-60G">
<font key="font" metaFont="smallSystem"/>
<font key="font" metaFont="palette"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
@ -90,7 +90,7 @@
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="I72-n8-A7m">
<rect key="frame" x="91" y="504" width="59" height="19"/>
<textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="Utr-K4-fTZ">
<font key="font" metaFont="smallSystem"/>
<font key="font" metaFont="palette"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
@ -99,33 +99,33 @@
</connections>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="3S3-NA-Pfr">
<rect key="frame" x="157" y="507" width="49" height="14"/>
<rect key="frame" x="157" y="506" width="49" height="14"/>
<textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="seconds" id="ktg-pa-9dP">
<font key="font" metaFont="smallSystem"/>
<font key="font" metaFont="palette"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="nao-kV-Rtm">
<rect key="frame" x="19" y="551" width="40" height="14"/>
<rect key="frame" x="19" y="550" width="40" height="14"/>
<constraints>
<constraint firstAttribute="width" constant="36" id="8wR-h0-BoG"/>
</constraints>
<textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Bitrate" id="FVz-ie-6Zt">
<font key="font" metaFont="smallSystem"/>
<font key="font" metaFont="palette"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="GNm-og-wRf">
<rect key="frame" x="19" y="372" width="101" height="14"/>
<rect key="frame" x="19" y="372" width="86" height="14"/>
<textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Monitor volume" id="IAm-lt-PXz">
<font key="font" metaFont="smallSystem"/>
<font key="font" metaFont="palette"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="VfC-wl-7Ed" customClass="CSAudioLevelView">
<customView ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="VfC-wl-7Ed" customClass="CSAudioLevelView">
<rect key="frame" x="20" y="362" width="106" height="10"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="startValue">
@ -148,7 +148,7 @@
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="5HX-Gi-83X">
<rect key="frame" x="19" y="420" width="84" height="14"/>
<textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Monitor Output" id="41g-2s-fF7">
<font key="font" metaFont="smallSystem"/>
<font key="font" metaFont="palette"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
@ -160,7 +160,7 @@
</constraints>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" controlSize="small" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="KN8-OL-txf" id="SEL-4J-m1s">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="smallSystem"/>
<font key="font" metaFont="palette"/>
<menu key="menu" id="sce-bW-EMX">
<items>
<menuItem title="Item 1" state="on" id="KN8-OL-txf"/>
@ -175,7 +175,7 @@
<binding destination="dRe-6o-71e" name="selectedObject" keyPath="selection.outputNode" previousBinding="0xx-Dh-gkf" id="xe5-nZ-TZL"/>
</connections>
</popUpButton>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="zwp-mN-H4b" customClass="CSAudioLevelView">
<customView ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zwp-mN-H4b" customClass="CSAudioLevelView">
<rect key="frame" x="21" y="463" width="106" height="10"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="startValue">
@ -192,44 +192,41 @@
<binding destination="dRe-6o-71e" name="audioLevels" keyPath="selection.streamAudioPowerLevels.output" id="cxT-di-4rA"/>
</connections>
</customView>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="3Xs-zj-OzR">
<rect key="frame" x="212" y="-102" width="277" height="669"/>
</customView>
<button translatesAutoresizingMaskIntoConstraints="NO" id="NeC-nP-8fw">
<button ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NeC-nP-8fw">
<rect key="frame" x="135" y="435" width="25" height="27"/>
<constraints>
<constraint firstAttribute="height" constant="27" id="cG3-Bd-HAO"/>
</constraints>
<buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="Mute_Icon" imagePosition="only" alignment="center" alternateImage="Speaker_Icon" controlSize="small" imageScaling="proportionallyUpOrDown" inset="2" id="HFf-ty-SwM" customClass="CSNSButtonCellThemed">
<behavior key="behavior" pushIn="YES" changeContents="YES" lightByContents="YES"/>
<font key="font" metaFont="smallSystem"/>
<font key="font" metaFont="palette"/>
</buttonCell>
<connections>
<binding destination="dRe-6o-71e" name="value" keyPath="selection.encodeMixer.enabled" id="gtc-5g-Cnh"/>
</connections>
</button>
<slider verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="HYJ-UD-4rz">
<slider verticalHuggingPriority="750" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HYJ-UD-4rz">
<rect key="frame" x="21" y="441" width="106" height="15"/>
<sliderCell key="cell" controlSize="small" continuous="YES" alignment="left" maxValue="1" doubleValue="1" tickMarkPosition="above" sliderType="linear" id="SQd-fM-eQ9"/>
<connections>
<binding destination="dRe-6o-71e" name="value" keyPath="selection.encodeMixer.volume" id="XeD-QF-UUJ"/>
</connections>
</slider>
<slider verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="YVY-IW-xNH">
<slider verticalHuggingPriority="750" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="YVY-IW-xNH">
<rect key="frame" x="20" y="340" width="106" height="15"/>
<sliderCell key="cell" controlSize="small" continuous="YES" state="on" alignment="left" maxValue="1" doubleValue="0.5" tickMarkPosition="above" sliderType="linear" id="UnM-n9-fXM"/>
<connections>
<binding destination="dRe-6o-71e" name="value" keyPath="selection.previewMixer.volume" id="1SB-e2-Okh"/>
</connections>
</slider>
<button translatesAutoresizingMaskIntoConstraints="NO" id="S23-4m-kb7">
<button ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="S23-4m-kb7">
<rect key="frame" x="135" y="336" width="25" height="23"/>
<constraints>
<constraint firstAttribute="height" constant="23" id="iQU-OE-rbO"/>
</constraints>
<buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="Mute_Icon" imagePosition="only" alignment="center" alternateImage="Speaker_Icon" controlSize="small" imageScaling="proportionallyUpOrDown" inset="2" id="6fp-6X-2wk" customClass="CSNSButtonCellThemed">
<behavior key="behavior" pushIn="YES" changeContents="YES" lightByContents="YES"/>
<font key="font" metaFont="smallSystem"/>
<font key="font" metaFont="palette"/>
</buttonCell>
<connections>
<binding destination="dRe-6o-71e" name="value" keyPath="selection.previewMixer.enabled" id="GY9-T8-HVd"/>
@ -243,14 +240,14 @@
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" columnSelection="YES" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowSizeStyle="automatic" viewBased="YES" id="YfJ-xY-GcZ">
<rect key="frame" x="0.0" y="0.0" width="138" height="133"/>
<autoresizingMask key="autoresizingMask"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn width="135" minWidth="40" maxWidth="1000" id="Gka-Lc-OMt">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
<font key="font" metaFont="smallSystem"/>
<font key="font" metaFont="palette"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
@ -265,9 +262,11 @@
<rect key="frame" x="1" y="1" width="135" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LJs-YP-fm3">
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="LJs-YP-fm3">
<rect key="frame" x="0.0" y="0.0" width="135" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<constraints>
<constraint firstAttribute="height" constant="17" id="rJn-W0-qBH"/>
</constraints>
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" title="Table View Cell" id="RW3-FA-3VW">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -278,6 +277,11 @@
</connections>
</textField>
</subviews>
<constraints>
<constraint firstItem="LJs-YP-fm3" firstAttribute="centerY" secondItem="KTu-PC-R34" secondAttribute="centerY" id="0mo-hD-oyc"/>
<constraint firstItem="LJs-YP-fm3" firstAttribute="centerX" secondItem="KTu-PC-R34" secondAttribute="centerX" id="a8f-8n-7jL"/>
<constraint firstItem="LJs-YP-fm3" firstAttribute="leading" secondItem="KTu-PC-R34" secondAttribute="leading" constant="2" id="uhC-xg-RLZ"/>
</constraints>
<connections>
<outlet property="textField" destination="LJs-YP-fm3" id="eEN-nj-y7a"/>
</connections>
@ -304,7 +308,7 @@
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="8BQ-Ld-p55">
<rect key="frame" x="19" y="282" width="72" height="14"/>
<textFieldCell key="cell" controlSize="small" lineBreakMode="clipping" title="Audio Tracks" id="szd-Om-2xO">
<font key="font" metaFont="smallSystem"/>
<font key="font" metaFont="palette"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
@ -317,7 +321,7 @@
</constraints>
<buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" image="NSAddTemplate" imagePosition="overlaps" alignment="center" controlSize="small" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="caC-7M-URI">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="smallSystem"/>
<font key="font" metaFont="palette"/>
</buttonCell>
<connections>
<action selector="addAudioTrack:" target="-2" id="Kp6-Qm-Mq6"/>
@ -331,27 +335,27 @@
</constraints>
<buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" image="NSRemoveTemplate" imagePosition="overlaps" alignment="center" controlSize="small" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="EQD-RZ-rXn">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="smallSystem"/>
<font key="font" metaFont="palette"/>
</buttonCell>
<connections>
<action selector="removeAudioTrack:" target="-2" id="Vpk-YM-Bjv"/>
</connections>
</button>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="3Xs-zj-OzR">
<rect key="frame" x="223" y="20" width="277" height="547"/>
</customView>
</subviews>
<constraints>
<constraint firstItem="ssR-h6-svZ" firstAttribute="leading" secondItem="67k-Zi-Ko9" secondAttribute="leading" id="0rd-we-8mU"/>
<constraint firstItem="wwP-vq-QJZ" firstAttribute="baseline" secondItem="67k-Zi-Ko9" secondAttribute="baseline" id="1ZV-jK-xHF"/>
<constraint firstItem="3Xs-zj-OzR" firstAttribute="leading" secondItem="67k-Zi-Ko9" secondAttribute="trailing" constant="57" id="41R-jK-RRC"/>
<constraint firstItem="3Xs-zj-OzR" firstAttribute="leading" secondItem="tVX-Ff-Ma1" secondAttribute="trailing" constant="52" id="44N-8o-cIp"/>
<constraint firstAttribute="bottom" secondItem="3Xs-zj-OzR" secondAttribute="bottom" constant="-102" id="4AL-iV-4YT"/>
<constraint firstItem="tVX-Ff-Ma1" firstAttribute="top" secondItem="YVY-IW-xNH" secondAttribute="bottom" constant="67" id="4i9-j4-rgS"/>
<constraint firstItem="3Xs-zj-OzR" firstAttribute="leading" secondItem="NeC-nP-8fw" secondAttribute="trailing" constant="52" id="58h-KA-Osu"/>
<constraint firstItem="zwp-mN-H4b" firstAttribute="top" secondItem="6qE-t2-zqe" secondAttribute="bottom" constant="3" id="5OV-Of-H0C"/>
<constraint firstItem="8BQ-Ld-p55" firstAttribute="leading" secondItem="YfJ-xY-GcZ" secondAttribute="leading" id="7G4-aC-Cdt"/>
<constraint firstItem="YVY-IW-xNH" firstAttribute="top" secondItem="VfC-wl-7Ed" secondAttribute="bottom" constant="8" symbolic="YES" id="8IU-Lb-SOm"/>
<constraint firstItem="HYJ-UD-4rz" firstAttribute="top" secondItem="zwp-mN-H4b" secondAttribute="bottom" constant="8" symbolic="YES" id="Ay5-fN-fB6"/>
<constraint firstItem="5HX-Gi-83X" firstAttribute="top" secondItem="HYJ-UD-4rz" secondAttribute="bottom" constant="8" symbolic="YES" id="Bv5-VX-85i"/>
<constraint firstItem="ssR-h6-svZ" firstAttribute="baseline" secondItem="ycu-9s-oiz" secondAttribute="baseline" id="CFu-eQ-9j9"/>
<constraint firstAttribute="bottom" secondItem="3Xs-zj-OzR" secondAttribute="bottom" constant="20" symbolic="YES" id="CPP-IF-dBb"/>
<constraint firstItem="ssR-h6-svZ" firstAttribute="top" secondItem="se5-gp-TjO" secondAttribute="top" constant="20" symbolic="YES" id="EID-Wu-I4L"/>
<constraint firstItem="zuo-gj-1Pr" firstAttribute="baseline" secondItem="I72-n8-A7m" secondAttribute="baseline" id="Fer-GO-waz"/>
<constraint firstItem="nao-kV-Rtm" firstAttribute="leading" secondItem="6qE-t2-zqe" secondAttribute="leading" id="Fin-Aa-pcJ"/>
@ -365,24 +369,24 @@
<constraint firstAttribute="bottom" secondItem="tVX-Ff-Ma1" secondAttribute="bottom" constant="139" id="M2u-L6-kX8"/>
<constraint firstItem="5HX-Gi-83X" firstAttribute="leading" secondItem="GNm-og-wRf" secondAttribute="leading" id="MKO-FK-0BN"/>
<constraint firstItem="VfC-wl-7Ed" firstAttribute="top" secondItem="GNm-og-wRf" secondAttribute="bottom" id="MYa-Yq-mkU"/>
<constraint firstItem="3Xs-zj-OzR" firstAttribute="leading" secondItem="zwp-mN-H4b" secondAttribute="trailing" constant="85" id="Ml8-4M-l15"/>
<constraint firstAttribute="trailing" secondItem="3Xs-zj-OzR" secondAttribute="trailing" constant="9" id="OUJ-2O-sAX"/>
<constraint firstItem="3Xs-zj-OzR" firstAttribute="leading" secondItem="ycu-9s-oiz" secondAttribute="trailing" constant="8" symbolic="YES" id="OWV-VS-o5r"/>
<constraint firstItem="wwP-vq-QJZ" firstAttribute="top" secondItem="nao-kV-Rtm" secondAttribute="bottom" constant="8" symbolic="YES" id="PK5-Ei-aeq"/>
<constraint firstAttribute="trailing" secondItem="3Xs-zj-OzR" secondAttribute="trailing" constant="20" symbolic="YES" id="QIM-PC-s9x"/>
<constraint firstItem="zwp-mN-H4b" firstAttribute="leading" secondItem="HYJ-UD-4rz" secondAttribute="leading" id="QnO-WN-YWt"/>
<constraint firstItem="67k-Zi-Ko9" firstAttribute="leading" secondItem="wwP-vq-QJZ" secondAttribute="trailing" constant="10" id="Tof-Tr-8Fz"/>
<constraint firstItem="6qE-t2-zqe" firstAttribute="top" secondItem="I72-n8-A7m" secondAttribute="bottom" constant="14" id="Tut-Vy-cfu"/>
<constraint firstItem="HYJ-UD-4rz" firstAttribute="centerY" secondItem="NeC-nP-8fw" secondAttribute="centerY" id="U94-on-nVe"/>
<constraint firstItem="ssR-h6-svZ" firstAttribute="top" secondItem="3Xs-zj-OzR" secondAttribute="top" id="UaN-IC-IJB"/>
<constraint firstItem="S23-4m-kb7" firstAttribute="leading" secondItem="YVY-IW-xNH" secondAttribute="trailing" constant="9" id="Uj3-Vd-wQh"/>
<constraint firstItem="3Xs-zj-OzR" firstAttribute="top" secondItem="ssR-h6-svZ" secondAttribute="top" id="VVV-zE-Q3E"/>
<constraint firstItem="nEN-AL-HsO" firstAttribute="top" secondItem="5HX-Gi-83X" secondAttribute="bottom" constant="8" symbolic="YES" id="Xd9-IV-HZX"/>
<constraint firstItem="5Wd-t5-JVx" firstAttribute="leading" secondItem="YfJ-xY-GcZ" secondAttribute="leading" id="YHt-LW-dvP"/>
<constraint firstItem="VfC-wl-7Ed" firstAttribute="leading" secondItem="YVY-IW-xNH" secondAttribute="leading" id="cE2-OL-8u9"/>
<constraint firstItem="2E7-sM-zOC" firstAttribute="leading" secondItem="5Wd-t5-JVx" secondAttribute="trailing" id="ed2-9U-fKo"/>
<constraint firstItem="GNm-og-wRf" firstAttribute="top" secondItem="nEN-AL-HsO" secondAttribute="bottom" constant="8" symbolic="YES" id="faU-Dz-RKX"/>
<constraint firstItem="NeC-nP-8fw" firstAttribute="leading" secondItem="S23-4m-kb7" secondAttribute="leading" id="htH-h3-Bzf"/>
<constraint firstItem="3Xs-zj-OzR" firstAttribute="leading" secondItem="3S3-NA-Pfr" secondAttribute="trailing" constant="8" symbolic="YES" id="iBp-A4-8FT"/>
<constraint firstItem="ycu-9s-oiz" firstAttribute="leading" secondItem="ssR-h6-svZ" secondAttribute="trailing" constant="7" id="iOY-Wb-6Qk"/>
<constraint firstItem="VfC-wl-7Ed" firstAttribute="trailing" secondItem="YVY-IW-xNH" secondAttribute="trailing" id="jEF-c3-wTv"/>
<constraint firstItem="3Xs-zj-OzR" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="223" id="kPB-Ss-a2V"/>
<constraint firstItem="nao-kV-Rtm" firstAttribute="baseline" secondItem="ssR-h6-svZ" secondAttribute="baseline" id="kR3-Fh-tVk"/>
<constraint firstItem="zuo-gj-1Pr" firstAttribute="leading" secondItem="VfC-wl-7Ed" secondAttribute="leading" id="kjm-sX-WXA"/>
<constraint firstItem="HYJ-UD-4rz" firstAttribute="leading" secondItem="5HX-Gi-83X" secondAttribute="leading" id="mev-XH-Jjt"/>
@ -392,7 +396,6 @@
<constraint firstItem="NeC-nP-8fw" firstAttribute="trailing" secondItem="S23-4m-kb7" secondAttribute="trailing" id="qn9-eb-BZb"/>
<constraint firstItem="YVY-IW-xNH" firstAttribute="centerY" secondItem="S23-4m-kb7" secondAttribute="centerY" id="r5r-8a-WKU"/>
<constraint firstItem="nEN-AL-HsO" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="22" id="rQr-Fh-Rqa"/>
<constraint firstItem="3Xs-zj-OzR" firstAttribute="leading" secondItem="GNm-og-wRf" secondAttribute="trailing" constant="94" id="sHQ-WJ-AoC"/>
<constraint firstItem="ssR-h6-svZ" firstAttribute="leading" secondItem="nao-kV-Rtm" secondAttribute="trailing" constant="34" id="siP-Hq-1Zi"/>
<constraint firstItem="nao-kV-Rtm" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="21" id="siu-kj-gyv"/>
<constraint firstItem="I72-n8-A7m" firstAttribute="baseline" secondItem="3S3-NA-Pfr" secondAttribute="baseline" id="soK-UH-qLa"/>