I'm currently trying to record a player node and input node at the same time but i'm having some difficulty. I can get them to record individually and at some point have set my code up to record both. The only problem is when I manage to do this the recorded content from the input node will play through the speakers as its recording creating an echo that eventually creates feedback that is too much to bear. So I've tried to shape my code as follows so the input node doesn't play through the speakers but i'm finding it difficult.
I'm trying to set up my code as follows:
Player Node Input Node (mic) | | | | | | | | | | v AVAudioConnectionPoint v Main Mixer ----------------------------------------->> Second Mixer | |
| |
| |
v Node Tap
Output
I've tried a number of combinations but I can't put them all here so i'll lay out some fundamental code and hope to Jesus someone has a little expertise in this area. First I create my engine and attach the nodes:
- (void)createEngineAndAttachNodes
{
_engine = [[AVAudioEngine alloc] init];
[_engine attachNode:_player];
_inputOne = _engine.inputNode;
_outputOne = _engine.outputNode;
}Then I make the engine connections (this is where I need to know where i'm going wrong.)
- (void)makeEngineConnections
{
_mainMixerOne = [_engine mainMixerNode];
_secondaryMixerOne = [_engine mainMixerNode];
_commonFormat = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatFloat32 sampleRate:44100 channels:2 interleaved:false];
AVAudioFormat *stereoFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:44100 channels:2];
[_engine connect:_player to:_mainMixerOne format:stereoFormat];
[_engine connect:_mainMixerOne to:_outputOne format:_commonFormat];
[_engine connect:_inputOne to:_secondaryMixerOne format:_commonFormat];
NSArray<AVAudioConnectionPoint *> *destinationNodes = [NSArray arrayWithObjects:[[AVAudioConnectionPoint alloc]
initWithNode:_mainMixerOne bus:1], [[AVAudioConnectionPoint alloc] initWithNode:_secondaryMixerOne bus:0], nil];
[_engine connect:_player toConnectionPoints:destinationNodes fromBus:0 format:_commonFormat];
}Whenever I try to directly connect one mixer to the other I get the error:
thread 1 exc_bad_access code=2Finally we have where I try and put this all together in my record function. The function you see will record the player but not the input.
-(void)setupRecordOne
{
NSError *error;
if (!_mixerFileOne) _mixerFileOne = [NSURL URLWithString:[NSTemporaryDirectory() stringByAppendingString:@"mixerOutput.caf"]];
/
AVAudioFile *mixerOutputFile = [[AVAudioFile alloc] initForWriting:_mixerFileOne settings:_commonFormat.settings error:&error];
NSAssert(mixerOutputFile != nil, @"mixerOutputFile is nil, %@", [error localizedDescription]);
[self startEngine];
[_secondaryMixerOne installTapOnBus:0 bufferSize:4096 format:_commonFormat block:^(AVAudioPCMBuffer *buffer, AVAudioTime *when) {
NSError *error;
BOOL success = NO;
success = [mixerOutputFile writeFromBuffer:buffer error:&error];
NSAssert(success, @"error writing buffer data to file, %@", [error localizedDescription]);
}];
_isRecording = YES;
}The only way I can record the input is by setting the node tap as follows:
[self startEngine];
[_inputOne installTapOnBus:0 bufferSize:4096 format:_commonFormat
block:^(AVAudioPCMBuffer *buffer, AVAudioTime *when) {
NSError *error;
BOOL success = NO;
success = [mixerOutputFile writeFromBuffer:buffer error:&error];
NSAssert(success, @"error writing buffer data to file, %@", [error localizedDescription]);
}];But then it wont record the player.
Please tell me there is someone out there who knows what to do.
Thanks,
Joshua