Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trim audio with iOS

I want to implement a feature that lets the user trim an audio file (.caf) which he perviously recorded. The recording part already works, but how can i add a trimming feature similar to the one in the Voicememos app. Is there an api for the audio trimmer apple uses? Any help would be great...

like image 779
JNK Avatar asked Nov 21 '10 14:11

JNK


1 Answers

How about using the AVFoundation? Import the audio file into an AVAsset (composition etc), then you can export it - setting preferred time + duration - to a file.

I wrote a stock function awhile ago that exports an asset to a file, you can also specify an audiomix. As below it exports all of the file, but you could add a NSTimeRange to exporter.timeRange and there you go. I haven't tested that though, but should work(?). Another alternative could be to adjust time ranges when creating the AVAsset + tracks. Of course the exporter only handles m4a (AAC). Sorry if this wasn't what you wanted.

-(void)exportAsset:(AVAsset*)asset toFile:(NSString*)filename overwrite:(BOOL)overwrite withMix:(AVAudioMix*)mix {
//NSArray* availablePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:asset];

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

if (exporter == nil) {
    DLog(@"Failed creating exporter!");
    return;
}

DLog(@"Created exporter! %@", exporter);

// Set output file type
DLog(@"Supported file types: %@", exporter.supportedFileTypes);
for (NSString* filetype in exporter.supportedFileTypes) {
    if ([filetype isEqualToString:AVFileTypeAppleM4A]) {
        exporter.outputFileType = AVFileTypeAppleM4A;
        break;
    }
}
if (exporter.outputFileType == nil) {
    DLog(@"Needed output file type not found? (%@)", AVFileTypeAppleM4A);
    return;
}

// Set outputURL
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* parentDir = [NSString stringWithFormat:@"%@/", [paths objectAtIndex:0]];

NSString* outPath = [NSString stringWithFormat:@"%@%@", parentDir, filename];

NSFileManager* manager = [NSFileManager defaultManager];
if ([manager fileExistsAtPath:outPath]) {
    DLog(@"%@ already exists!", outPath);
    if (!overwrite) {
        DLog(@"Not overwriting, uh oh!");
        return;
    }
    else {
        // Overwrite
        DLog(@"Overwrite! (delete first)");
        NSError* error = nil;
        if (![manager removeItemAtPath:outPath error:&error]) {
            DLog(@"Failed removing %@, error: %@", outPath, error.description);
            return;
        }
        else {
            DLog(@"Removed %@", outPath);
        }
    }
}

NSURL* const outUrl = [NSURL fileURLWithPath:outPath];
exporter.outputURL = outUrl;
// Specify a time range in case only part of file should be exported
//exporter.timeRange =

if (mix != nil)
    exporter.audioMix = mix; // important

DLog(@"Starting export! (%@)", exporter.outputURL);
[exporter exportAsynchronouslyWithCompletionHandler:^(void) {
    // Export ended for some reason. Check in status
    NSString* message;
    switch (exporter.status) {
        case AVAssetExportSessionStatusFailed:
            message = [NSString stringWithFormat:@"Export failed. Error: %@", exporter.error.description];
            DLog(@"%@", message);
            [self showAlert:message];
            break;
        case AVAssetExportSessionStatusCompleted: {
            /*if (playfileWhenExportFinished) {
             DLog(@"playfileWhenExportFinished!");
             [self playfileAfterExport:exporter.outputURL];
             playfileWhenExportFinished = NO;
             }*/
            message = [NSString stringWithFormat:@"Export completed: %@", filename];
            DLog(@"%@", message);
            [self showAlert:message];
            break;
        }
        case AVAssetExportSessionStatusCancelled:
            message = [NSString stringWithFormat:@"Export cancelled!"];
            DLog(@"%@", message);
            [self showAlert:message];
            break;
        default:
            DLog(@"Export unhandled status: %d", exporter.status);
            break;
    }       
}];
}
like image 177
Jonny Avatar answered Sep 18 '22 04:09

Jonny