Запись микрофона и музыки одновременно с AVAudioEngine

В настоящее время я пытаюсь записать узел игрока и входной узел одновременно, но у меня возникли некоторые трудности. Я могу заставить их записывать по отдельности, и в какой-то момент я установил свой код для записи обоих. Единственная проблема заключается в том, что когда мне удается это сделать, записанный контент с входного узла будет воспроизводиться через динамики, поскольку его запись создает эхо, которое в конечном итоге создает обратную связь, которая слишком велика, чтобы выдержать ее. Итак, я попытался сформировать свой код следующим образом, чтобы входной узел не воспроизводился через динамики, но мне трудно.

Я пытаюсь настроить свой код следующим образом:

Player Node                       Input Node (mic)
    |                                    |
    |                                    |
    |                                    |
    v       AVAudioConnectionPoint       v
Main Mixer ----------------------->>Second Mixer
    |                                    |
    |                                 Node Tap
    |
    v
  Output

Я перепробовал несколько комбинаций, но не могу поместить их все здесь, поэтому я выложу некоторый фундаментальный кодекс и надеюсь, что у Иисуса есть небольшой опыт в этой области.

Сначала я создаю свой движок и присоединяю узлы:

- (void)createEngineAndAttachNodes
{
_engine = [[AVAudioEngine alloc] init];
[_engine attachNode:_player];
_inputOne = _engine.inputNode;
_outputOne = _engine.outputNode;
}

Затем я делаю соединения с двигателем (это где я должен знать, где я иду не так.)

- (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];


//Fan out mainMixer

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];

}

Всякий раз, когда я пытаюсь напрямую подключить один микшер к другому, я получаю сообщение об ошибке:

thread 1 exc_bad_access code=2

Наконец, у нас есть место, где я пытаюсь все это объединить в своей функции записи. Функция, которую вы видите, будет записывать плеер, но не вводить.

-(void)setupRecordOne
{

NSError *error;
if (!_mixerFileOne) _mixerFileOne = [NSURL URLWithString:[NSTemporaryDirectory() stringByAppendingString:@"mixerOutput.caf"]];

  //  AVAudioMixerNode *mainMixer = [_engine mainMixerNode];
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;
}

Единственный способ, которым я могу записать ввод, это настроить узел следующим образом:

    [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]);
}];

Но тогда он не будет записывать плеер.

Пожалуйста, скажите мне, что есть кто-то, кто знает, что делать.

Спасибо,

Джошуа

0 ответов

Другие вопросы по тегам