Audio mixing on iPhone : Need advice

917 Views Asked by At

I'm using AudioQueue Service to play audio in my app. I need to play several audio files together. What I do now I just create as much audio queue as much i need to play files. I.e. I create two audio queue for two audio files and start them at the same time to have audio mixing effect.

So basically I would like to know is this an "elegant" way of doing it.

Please note, that I'm aware of Audio Unit service and its MixerHost example, please do not suggest that option, I need to do sound mixing exclusively using audio queue service.

1

There are 1 best solutions below

0
On
- (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];
}


- (BOOL) exportAudio {

    if (defaultSoundPath == nil || recordingSoundPath == nil) {

        [actvityIdicatiorView stopAnimating];
        [actvityIdicatiorView setHidden:YES];


        UIAlertView *alertView=[[UIAlertView alloc]initWithTitle:@"Select Sound" message:@"Both Sound is selected" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil];
        [alertView show];
        return NO;



    }

    AVMutableComposition *composition = [AVMutableComposition composition];
    if (audioMixParams) {
        [audioMixParams release];
        audioMixParams=nil;
    }
    audioMixParams = [[NSMutableArray alloc] initWithObjects:nil];

    //Add Audio Tracks to Composition

    NSString *sourceA= [[NSBundle mainBundle] pathForResource:@"Beach Soundscape" ofType:@"mp3"];

    //NSString *URLPath1 = pathToYourAudioFile1;

    NSURL *assetURL1 = [NSURL fileURLWithPath:sourceA];
    [self setUpAndAddAudioAtPath:assetURL1 toComposition:composition];

    NSString *sourceB = [[NSBundle mainBundle] pathForResource:@"DrumsMonoSTP" ofType:@"aif"];
    // NSString *URLPath2 = pathToYourAudioFile2;
    NSURL *assetURL2 = [NSURL fileURLWithPath:sourceB];
    [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";

    //    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    //
    //    NSString *fileName = @"someFilename";

    //NSString *exportFile = [[paths objectAtIndex:0] stringByAppendingFormat: @"/%@.m4a", fileName];

    mixingSoundPath= [[self mixingSoundFolder] stringByAppendingFormat: @"/Mixing%@.m4a", [self dateString]];
    [mixingSoundPath retain];

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

    static BOOL isComplete;

    // do the export
    [exporter exportAsynchronouslyWithCompletionHandler:^{

        int exportStatus = exporter.status;

        NSLog(@"exporter.......%i",exportStatus);


        switch (exportStatus) {

            case AVAssetExportSessionStatusFailed:
                //    NSError *exportError =exporter.error;
                isComplete=NO;
                NSLog (@"AVAssetExportSessionStatusFailed");


                NSLog (@"Error == %@", exporter.error);
                break;

            case AVAssetExportSessionStatusCompleted:
                [self mixingDidFinshing];

                isComplete=YES;
                break;
            case AVAssetExportSessionStatusUnknown:
                NSLog (@"AVAssetExportSessionStatusUnknown");
                isComplete=NO;

                break;
            case AVAssetExportSessionStatusExporting:
                isComplete=NO;

                NSLog (@"AVAssetExportSessionStatusExporting");

                break;
            case AVAssetExportSessionStatusCancelled:
                isComplete=NO;

                NSLog (@"AVAssetExportSessionStatusCancelled");

                break;
            case AVAssetExportSessionStatusWaiting:
                isComplete=NO;

                NSLog (@"AVAssetExportSessionStatusWaiting"); 

                break;
            default:  
                NSLog (@"didn't get export status"); 
                isComplete=NO;
                break;
        }


    }];

    return isComplete;

}