2 개의 CAF 파일을 로컬로 단일 파일로 변환하려고합니다. 이 2 개의 CAF 파일은 모노 스트림이며 이상적으로는 한 채널에서 마이크를, 다른 스피커에서 스피커를 가질 수 있도록 스테레오 파일로 제공하고 싶습니다.2 개의 모노 파일을 iOS에서 하나의 스테레오 파일로 변환하는 방법은 무엇입니까?
원래 AVAssetTrack 및 AVMutableCompositionTracks를 사용하여 시작했지만 믹싱을 해결할 수 없습니다. 병합 된 파일은 두 개의 파일을 인터리브 한 단일 모노 스트림이었습니다. 그래서 AVAudioEngine 경로를 선택했습니다.
필자는 두 파일을 입력 노드로 전달하고 믹서에 연결하고 스테레오 믹스를 얻을 수있는 출력 노드를 가질 수 있습니다. 출력 파일에는 스테레오 레이아웃이 있지만 Audacity에서 열어서 스테레오 레이아웃을 볼 때 오디오 데이터가 쓰이지 않는 것 같습니다. installTapOnBus 호출 주위에 dipatch sephamore 신호를 배치하는 것도별로 도움이되지 않았습니다. CoreAudio는 이해하기 어려웠으므로 통찰력은 인정 될 것입니다. ExtAudioFile에 이렇게
// obtain path of microphone and speaker files
NSString *micPath = [[NSBundle mainBundle] pathForResource:@"microphone" ofType:@"caf"];
NSString *spkPath = [[NSBundle mainBundle] pathForResource:@"speaker" ofType:@"caf"];
NSURL *micURL = [NSURL fileURLWithPath:micPath];
NSURL *spkURL = [NSURL fileURLWithPath:spkPath];
// create engine
AVAudioEngine *engine = [[AVAudioEngine alloc] init];
AVAudioFormat *stereoFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:16000 channels:2];
AVAudioMixerNode *mainMixer = engine.mainMixerNode;
// create audio files
AVAudioFile *audioFile1 = [[AVAudioFile alloc] initForReading:micURL error:nil];
AVAudioFile *audioFile2 = [[AVAudioFile alloc] initForReading:spkURL error:nil];
// create player input nodes
AVAudioPlayerNode *apNode1 = [[AVAudioPlayerNode alloc] init];
AVAudioPlayerNode *apNode2 = [[AVAudioPlayerNode alloc] init];
// attach nodes to the engine
[engine attachNode:apNode1];
[engine attachNode:apNode2];
// connect player nodes to engine's main mixer
stereoFormat = [mainMixer outputFormatForBus:0];
[engine connect:apNode1 to:mainMixer fromBus:0 toBus:0 format:audioFile1.processingFormat];
[engine connect:apNode2 to:mainMixer fromBus:0 toBus:1 format:audioFile2.processingFormat];
[engine connect:mainMixer to:engine.outputNode format:stereoFormat];
// start the engine
NSError *error = nil;
if(![engine startAndReturnError:&error]){
NSLog(@"Engine failed to start.");
}
// create output file
NSString *mergedAudioFile = [[micPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"merged.caf"];
[[NSFileManager defaultManager] removeItemAtPath:mergedAudioFile error:&error];
NSURL *mergedURL = [NSURL fileURLWithPath:mergedAudioFile];
AVAudioFile *outputFile = [[AVAudioFile alloc] initForWriting:mergedURL settings:[engine.inputNode inputFormatForBus:0].settings error:&error];
// write from buffer to output file
[mainMixer installTapOnBus:0 bufferSize:4096 format:[mainMixer outputFormatForBus:0] block:^(AVAudioPCMBuffer *buffer, AVAudioTime *when){
NSError *error;
BOOL success;
NSLog(@"Writing");
if((outputFile.length < audioFile1.length) || (outputFile.length < audioFile2.length)){
success = [outputFile writeFromBuffer:buffer error:&error];
NSCAssert(success, @"error writing buffer data to file, %@", [error localizedDescription]);
if(error){
NSLog(@"Error: %@", error);
}
}
else{
[mainMixer removeTapOnBus:0];
NSLog(@"Done writing");
}
}];
}
당신은 당신이 쓰고있는 AVAudioFile에 강한 참조를 보유하고 있습니까 : 여기
은 예입니다? – dave234@ Dave, 쓰기 전에 outputFile이 존재하지 않습니다. 강력한 참조 측면에서, 나는 audioFile을 mergedURL에 쓰도록 설정하고 있는데, 이는 mergedAudioFile의 fileURLWithPath입니다. outputFile을 참조하는 다른 객체/변수는 없으며 installTapOnBus 호출 후에도이를 파기하지는 않습니다. – A21
이 방법의 약점 중 하나는 파일의 지속 시간이 하나가 될 때까지 기다려야한다는 것입니다. 즉, AVAudioEngine을 고수한다면 두 파일을 먼저 재생 해 볼 수 있습니다. 그런 다음 해당 단계가 완료되면 탭을 설치하고 파일에 씁니다. 하지만 내가 직접해야한다면 C API를 사용할 것이다. – dave234