5

So I have two audio files, same format, potentially different length. I would like to combine these files (overlay the audio from one onto the other, NOT join them at ends).

Lets say I have two files:

  1. Audio File A, length 30 seconds, size 220k
  2. Audio File B, length 45 seconds, size 300k

What I'd like, a combines audio file:

  1. Audio File C, length 45 seconds, size 300k (I recognize this could be more)

Appreciate everyone's help!

Beat
  • 71
  • 1
  • 3
  • hi @Beat, I have the problem that the file size of Audio File C is very large. Do you also have this problem? If yes, how do you solve it? thx – Newbie Sep 13 '13 at 08:09

2 Answers2

5

Here's what I did in my app.

- (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];
    [self.audioMixParams addObject:trackMix];

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


- (IBAction)saveRecording
{
     AVMutableComposition *composition = [AVMutableComposition composition];
        audioMixParams = [[NSMutableArray alloc] initWithObjects:nil];

    //IMPLEMENT FOLLOWING CODE WHEN WANT TO MERGE ANOTHER AUDIO FILE
    //Add Audio Tracks to Composition
    NSString *URLPath1 = [[NSBundle mainBundle] pathForResource:@"mysound" ofType:@"mp3"];
    NSString *URLPath2 = [[NSBundle mainBundle] pathForResource:@"mysound2" ofType:@"mp3"];
    NSURL *assetURL1 = [NSURL fileURLWithPath:URLPath1];
    [self setUpAndAddAudioAtPath:assetURL1   toComposition:composition];

    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";
    NSURL *exportURL = [NSURL fileURLWithPath:exportFile];
    exporter.outputURL = exportURL;

// do the export
        [exporter exportAsynchronouslyWithCompletionHandler:^{
            int exportStatus = exporter.status;
            NSError *exportError = exporter.error;

            switch (exportStatus) {
                case AVAssetExportSessionStatusFailed:

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

Beware that I did do this a while ago, and you might have to work with it a tiny bit to make it work. But it did work at one point. Let me know if you're having problems.

gg13
  • 574
  • 6
  • 19
  • hi @gg13, I have used your suggested way to mix audios. But my problem is that the exported file is too much larger than original ones. Is there any way to render a file in a smaller filetype? – Newbie Sep 13 '13 at 02:04
  • I tried to change the exporter.outputFileType to other file format like AVFileTypeAIFC. However, it throws error. Then I read the supportedFileTypes property of the exporter, and I find out it only supports AVFileTypeAppleM4A (i.e. "com.apple.m4a-audio" the filetype that you suggested). Why is that? – Newbie Sep 13 '13 at 02:08
  • I see you're setting the volume for the trackmix to 0.8. Is this the only step necessary to avoid corrupting the quality? I know little of audio-mixing, and I'm getting bad results when combining files, so I'll try that, but do you know if it helps increasing the bitrate or something? Like, if I am combining two audio files at 44.1, would the result be better if the combined file is 88.2 (or the more common 96), or would there be no reason to do this? – Sti Aug 07 '14 at 18:55
  • This is awesome, thanks. FWIW, it happily compressed large input WAV files into a pretty small M4A. – Richard Jan 03 '16 at 22:46
0

If Audio Asset track is not found in selected asset.You can use this statement to check the sound of particular Video.

if([[songAsset tracksWithMediaType:AVMediaTypeAudio] firstObject]==NULL)
{
    NSLog(@"Sound is not Present");
}
else
{
    NSLog(@"Sound is Present");
    //You will initalise all things
    AVAssetTrack *sourceAudioTrack = [[songAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];

}
Vaibhav Sharma
  • 1,123
  • 10
  • 22