iOS Audio Trimming

Muhammad Usama picture Muhammad Usama · Mar 14, 2012 · Viewed 12.9k times · Source

I searched a lot and couldn't find anything relevant... I am working on iOS audio files and here is what I want to do...

  1. Record Audio and Save Clip (Checked, I did this using AVAudioRecorder)
  2. Change the pitch (Checked, Did this using Dirac)
  3. Trimming :(

I have two markers i.e. starting & ending offset and using this info I want to trim recorded file and want to save it back. I don't want to use "seek" because later on I want to play all recorded files in sync (just like flash movie clips in timeline) and then finally I want to export as one audio file.

Answer

kyleobrien picture kyleobrien · May 28, 2012

Here's the code that I've used to trim audio from a pre-existing file. You'll need to change the M4A related constants if you've saved or are saving to another format.

- (BOOL)trimAudio
{
    float vocalStartMarker = <starting time>;
    float vocalEndMarker = <ending time>;

    NSURL *audioFileInput = <your pre-existing file>;
    NSURL *audioFileOutput = <the file you want to create>;

    if (!audioFileInput || !audioFileOutput)
    {
        return NO;
    }

    [[NSFileManager defaultManager] removeItemAtURL:audioFileOutput error:NULL];
    AVAsset *asset = [AVAsset assetWithURL:audioFileInput];

    AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:asset
                                                                            presetName:AVAssetExportPresetAppleM4A];

    if (exportSession == nil)
    {        
        return NO;
    }

    CMTime startTime = CMTimeMake((int)(floor(vocalStartMarker * 100)), 100);
    CMTime stopTime = CMTimeMake((int)(ceil(vocalEndMarker * 100)), 100);
    CMTimeRange exportTimeRange = CMTimeRangeFromTimeToTime(startTime, stopTime);

    exportSession.outputURL = audioFileOutput;
    exportSession.outputFileType = AVFileTypeAppleM4A;
    exportSession.timeRange = exportTimeRange;

    [exportSession exportAsynchronouslyWithCompletionHandler:^
     {
         if (AVAssetExportSessionStatusCompleted == exportSession.status)
         {
             // It worked!
         } 
         else if (AVAssetExportSessionStatusFailed == exportSession.status)
         {
             // It failed...
         }
     }];

    return YES;
}

There's also Technical Q&A 1730, which gives a slightly more detailed approach.