将2个单声道文件写入1个双声道文件,左右声道分开

时间:2016-08-04 17:50:11

标签: ios audio avfoundation avaudioengine

我正在尝试将2个单声道音频文件写入单个2声道文件,其中第一个音频文件转到左声道,第二个音频文件转到右声道。 我将AVAudioEngine类与标准混音器一起使用,但这会混合2个音频文件并在左右声道中写入相同的内容。 这是我使用的代码:

//
//  ViewController.m
//  StereoMixer
//

#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>

extern void CheckError(NSError *error);

@interface ViewController ()

@property(nonatomic, strong) AVAudioEngine *engine;

@end

@implementation ViewController

-(void)viewDidLoad {
    [super viewDidLoad];

    NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];

    NSString *outputFile = [docsDir stringByAppendingPathComponent:@"output.caf"];
    NSString *bundlePath = [[NSBundle mainBundle] bundlePath];

    [self mergeAudioFilePath1:[bundlePath stringByAppendingPathComponent:@"1.m4a"]
               audioFilePath2:[bundlePath stringByAppendingPathComponent:@"2.m4a"]
           outputFilePath:outputFile];
}

-(void)mergeAudioFilePath1:(NSString *)audioFilePath1 audioFilePath2:(NSString *)audioFilePath2 outputFilePath:(NSString *)outputFilePath {
    _engine = [[AVAudioEngine alloc] init];

    AVAudioFormat *stereoFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:44100 channels:2];

    NSError *error = nil;

    AVAudioMixerNode *mainMixer = _engine.mainMixerNode;

    AVAudioFile *audioFile1 = [[AVAudioFile alloc] initForReading:[NSURL fileURLWithPath:audioFilePath1] error:&error];
    CheckError(error);
    AVAudioFile *audioFile2 = [[AVAudioFile alloc] initForReading:[NSURL fileURLWithPath:audioFilePath2] error:&error];
    CheckError(error);

    AVAudioPlayerNode *player1 = [[AVAudioPlayerNode alloc] init];
    AVAudioPlayerNode *player2 = [[AVAudioPlayerNode alloc] init];

    [_engine attachNode:player1];
    [_engine attachNode:player2];

    stereoFormat = [mainMixer outputFormatForBus:0];
    [_engine connect:player1 to:mainMixer fromBus:0 toBus:0 format:audioFile1.processingFormat];
    [_engine connect:player2 to:mainMixer fromBus:0 toBus:1 format:audioFile2.processingFormat];
    [_engine connect:mainMixer to:_engine.outputNode format:stereoFormat];


    [[NSFileManager defaultManager] removeItemAtPath:outputFilePath error:&error];
    AVAudioFile *outputFile = [[AVAudioFile alloc] initForWriting:[NSURL fileURLWithPath:outputFilePath]
                                                         settings:[_engine.inputNode inputFormatForBus:0].settings
                                                            error:&error];

    CheckError(error);

    if (![_engine startAndReturnError:&error]) {
        NSLog(@"Error in [engine startAndReturnError:&error]");
    }
    [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];
            NSAssert(success, @"error writing buffer data to file, %@", [error localizedDescription]);
            if (error) {
                NSLog(@"writebuffererror =%@",error);
            }
        } else {
            [mainMixer removeTapOnBus:0];
            NSLog(@"done");
        }

    }];

    [player1 scheduleFile:audioFile1 atTime:nil completionHandler:nil];
    [player2 scheduleFile:audioFile2 atTime:nil completionHandler:nil];

    [player1 play];
    [player2 play];
}

@end

void CheckError(NSError *error) {
    if (error == nil) return;
//    NSLog(@"Error: %@", error);
    NSError *newError = [NSError errorWithDomain:NSOSStatusErrorDomain
                                         code:error.code
                                     userInfo:nil];
    NSLog(@"Error: %@", [newError description]);

}

有什么想法吗?

0 个答案:

没有答案