在iPhone上组合两个.caf文件

Sno*_*man 5 iphone objective-c avfoundation

我看了看并找了答案,但似乎找不到答案.很多人问过,但没有人得到答案.我有一个使用AVAudioRecorder录制音频的应用程序.现在我只想将两个或多个录音合并到一个可以通过电子邮件发送的文件中.有没有人知道如何做到这一点?

(这个答案建议使用一种叫做音频服务队列的东西,但我对此一无所知)

Mar*_*ong 8

它并不像你想象的那么容易.我使用AVFoundation框架来完成您要求创建iAmRingtones的所有内容.它需要从音频文件创建AVAssets并设置AVExportSession.最终结果很棒,但肯定需要一些工作.这里或多或少是我们在应用中创建导出功能的方式:

- (void) setUpAndAddAudioAtPath:(NSURL*)assetURL toComposition:(AVMutableComposition *)composition {

    AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:assetURL options:nil];  

    AVMutableCompositionTrack *track = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    AVAssetTrack *sourceAudioTrack = [[songAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];

    NSError *error = nil;
    BOOL ok = NO;

    CMTime startTime = CMTimeMakeWithSeconds(0, 1);
    CMTime trackDuration = songAsset.duration;
    CMTime longestTime = CMTimeMake(848896, 44100); //(19.24 seconds)
    CMTimeRange tRange = CMTimeRangeMake(startTime, trackDuration);

    //Set Volume
    AVMutableAudioMixInputParameters *trackMix = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:track];
    [trackMix setVolume:0.8f atTime:startTime];
    [audioMixParams addObject:trackMix];

    //Insert audio into track
    ok = [track insertTimeRange:tRange ofTrack:sourceAudioTrack atTime:CMTimeMake(0, 44100) error:&error];
}   
Run Code Online (Sandbox Code Playgroud)

从以下方法调用上述方法两次(每个音轨一次):

- (void) exportAudio {

    AVMutableComposition *composition = [AVMutableComposition composition];
    audioMixParams = [[NSMutableArray alloc] initWithObjects:nil];

    //Add Audio Tracks to Composition
    NSString *URLPath1 = pathToYourAudioFile1;
    NSURL *assetURL1 = [NSURL fileURLWithPath:URLPath1];
    [self setUpAndAddAudioAtPath:assetURL1 toComposition:composition];

    NSString *URLPath2 = pathToYourAudioFile2;
    NSURL *assetURL2 = [NSURL fileURLWithPath:URLPath2];
    [self setUpAndAddAudioAtPath:assetURL2 toComposition:composition];

    AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix];
    audioMix.inputParameters = [NSArray arrayWithArray:audioMixParams];

    //If you need to query what formats you can export to, here's a way to find out
    NSLog (@"compatible presets for songAsset: %@",
            [AVAssetExportSession exportPresetsCompatibleWithAsset:composition]);

    AVAssetExportSession *exporter = [[AVAssetExportSession alloc]
                                  initWithAsset: composition
                                  presetName: AVAssetExportPresetAppleM4A];
    exporter.audioMix = audioMix;
    exporter.outputFileType = @"com.apple.m4a-audio";
    NSString *fileName = @"someFilename";
    NSString *exportFile = [[util getDocumentsDirectory] stringByAppendingFormat: @"/%@.m4a", fileName];    

    // set up export 
    myDeleteFile(exportFile);
    NSURL *exportURL = [NSURL fileURLWithPath:exportFile];
    exporter.outputURL = exportURL; 

    // do the export
    [exporter exportAsynchronouslyWithCompletionHandler:^{
            int exportStatus = exporter.status;
            switch (exportStatus) {
                case AVAssetExportSessionStatusFailed: 
                    NSError *exportError = exporter.error;
                    NSLog (@"AVAssetExportSessionStatusFailed: %@", exportError);
                    break;

                case AVAssetExportSessionStatusCompleted: NSLog (@"AVAssetExportSessionStatusCompleted"); break;
                case AVAssetExportSessionStatusUnknown: NSLog (@"AVAssetExportSessionStatusUnknown"); break;
                case AVAssetExportSessionStatusExporting: NSLog (@"AVAssetExportSessionStatusExporting"); break;
                case AVAssetExportSessionStatusCancelled: NSLog (@"AVAssetExportSessionStatusCancelled"); break;
                case AVAssetExportSessionStatusWaiting: NSLog (@"AVAssetExportSessionStatusWaiting"); break;
                default:  NSLog (@"didn't get export status"); break;
    }
}];

    // start up the export progress bar
    progressView.hidden = NO;
    progressView.progress = 0.0;
    [NSTimer scheduledTimerWithTimeInterval:0.1
                                 target:self
                               selector:@selector (updateExportProgress:)
                               userInfo:exporter
                                repeats:YES];

}
Run Code Online (Sandbox Code Playgroud)