Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exporting Wav Files Using AVAssetExportSession

Im trying to add a fade in to a wav file and then exporting a new file with the added fade using AVAssetExportSession. All the examples I have seen have seen are exporting as m4u Is it even possible to do this with wav or aif?

The error I get is:

AVAssetExportSessionStatusFailed Error Domain=AVFoundationErrorDomain Code=-11822 "Cannot Open" UserInfo=0x1f01c9f0 {NSLocalizedDescription=Cannot Open, NSLocalizedFailureReason=This media format is not supported.} 

My code looks like below

 NSString *inpath = [path stringByAppendingFormat:@"/%@",file];

    NSString *ename = [file stringByDeletingPathExtension];
    NSString *incname = [ename stringByAppendingString:@"1t"];
    NSString *outname = [incname stringByAppendingPathExtension:@"wav"];
    NSString *outpath = [path stringByAppendingFormat:@"/%@",outname];

    NSURL *urlpath = [NSURL fileURLWithPath:inpath];
    NSURL *urlout = [NSURL fileURLWithPath:outpath];



    NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
                                                        forKey:AVURLAssetPreferPreciseDurationAndTimingKey];
    AVURLAsset *anAsset = [[AVURLAsset alloc] initWithURL:urlpath options:options];


    //check the soundfile is greater than 50seconds
    CMTime assetTime = [anAsset duration];
    Float64 duration = CMTimeGetSeconds(assetTime);
    if (duration < 50.0) return NO;

    // get the first audio track
    NSArray *tracks = [anAsset tracksWithMediaType:AVMediaTypeAudio];
    if ([tracks count] == 0) return NO;

    AVAssetTrack *track = [tracks objectAtIndex:0];

    // create trim time range - 20 seconds starting from 30 seconds into the asset
    CMTime startTime = CMTimeMake(30, 1);
    CMTime stopTime = CMTimeMake(50, 1);
    CMTimeRange exportTimeRange = CMTimeRangeFromTimeToTime(startTime, stopTime);

    // create fade in time range - 10 seconds starting at the beginning of trimmed asset
    CMTime startFadeInTime = startTime;
    CMTime endFadeInTime = CMTimeMake(40, 1);
    CMTimeRange fadeInTimeRange = CMTimeRangeFromTimeToTime(startFadeInTime,
                                                            endFadeInTime);

    // setup audio mix
    AVMutableAudioMix *exportAudioMix = [AVMutableAudioMix audioMix];
    AVMutableAudioMixInputParameters *exportAudioMixInputParameters =
    [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:track];
    [exportAudioMixInputParameters setVolumeRampFromStartVolume:0.0 toEndVolume:1.0 timeRange:fadeInTimeRange];

    exportAudioMix.inputParameters = [NSArray arrayWithObject:exportAudioMixInputParameters];

    AVAssetExportSession *exportSession = [AVAssetExportSession
                                           exportSessionWithAsset:anAsset presetName:AVAssetExportPresetPassthrough];


    //NSArray *listof = [AVAssetExportSession exportPresetsCompatibleWithAsset:anAsset];
    //NSLog(@"LISTOF %@",listof);

    id desc = [track.formatDescriptions objectAtIndex:0];
    const AudioStreamBasicDescription *audioDesc = CMAudioFormatDescriptionGetStreamBasicDescription((CMAudioFormatDescriptionRef)desc);
    FourCharCode formatID = audioDesc->mFormatID;

    NSString *fileType = nil;
    NSString *ex = nil;

    switch (formatID) {

        case kAudioFormatLinearPCM:
        {
            UInt32 flags = audioDesc->mFormatFlags;
            if (flags & kAudioFormatFlagIsBigEndian) {
                fileType = @"public.aiff-audio";
                ex = @"aif";
            } else {
                fileType = @"com.microsoft.waveform-audio";
                ex = @"wav";
            }
        }
            break;

        case kAudioFormatMPEGLayer3:
            fileType = @"com.apple.quicktime-movie";
            ex = @"mp3";
            break;

        case kAudioFormatMPEG4AAC:
            fileType = @"com.apple.m4a-audio";
            ex = @"m4a";
            break;

        case kAudioFormatAppleLossless:
            fileType = @"com.apple.m4a-audio";
            ex = @"m4a";
            break;

        default:
            break;
    }



    exportSession.outputFileType = fileType;
    exportSession.outputURL = urlout;

    //exportSession.outputFileType = AVFileTypeWAVE; // output file type
    exportSession.timeRange = exportTimeRange; // trim time range
    exportSession.audioMix = exportAudioMix; // fade in audio mix


    // perform the export
    [exportSession exportAsynchronouslyWithCompletionHandler:^{

        if (AVAssetExportSessionStatusCompleted == exportSession.status) {
            NSLog(@"AVAssetExportSessionStatusCompleted");
        } else if (AVAssetExportSessionStatusFailed == exportSession.status) {
            // a failure may happen because of an event out of your control
            // for example, an interruption like a phone call comming in
            // make sure and handle this case appropriately
            NSLog(@"AVAssetExportSessionStatusFailed %@",exportSession.error);
        } else {
            NSLog(@"Export Session Status: %d", exportSession.status);
        }
    }];

    return YES;
    }
like image 345
user1347149 Avatar asked Nov 03 '22 23:11

user1347149


1 Answers

You can't do that with AVAssetExportSession because the presets are quite fixed in their usage. A preset value of AVAssetExportPresetPassthrough will keep your input formats on output.

As your task will be manipulating the audio sample buffers directly you should use the second variant that AVFoundation will give you: paired AVAssetReader and AVAssetWriter setup. You'll find proper sample code as in AVReaderWriterOSX from Apple developer source. This should also work with iOS besides you have different I/O format settings available. The availability to decompress audio as PCM and write back to uncompressed .wav file should be given.

like image 135
konran Avatar answered Nov 08 '22 12:11

konran