2

現在、プレイヤー ノードと入力ノードを同時に記録しようとしていますが、問題が発生しています。それらを個別に記録させることができ、ある時点で両方を記録するようにコードを設定しました。唯一の問題は、これを行うと、入力ノードから録音されたコンテンツがスピーカーから再生され、その録音がエコーを作成し、最終的に耐えられないほどのフィードバックを作成することです。そのため、入力ノードがスピーカーから再生されないように、次のようにコードを整形しようとしましたが、難しいと感じています。

次のようにコードを設定しようとしています。

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

しかし、それはプレーヤーを記録しません。

何をすべきかを知っている人がいると教えてください。

ありがとう、

ジョシュア

4

0 に答える 0