Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS Code to Convert m4a to WAV

Does anyone have any code snippets that show how to convert an M4a file to WAV? I know there are libraries that convert the other way around.

Thanks.

like image 582
O2U Avatar asked Nov 30 '22 23:11

O2U


2 Answers

Just to update for Swift 3:

func convertAudio(_ url: URL, outputURL: URL) {
    var error : OSStatus = noErr
    var destinationFile: ExtAudioFileRef? = nil
    var sourceFile : ExtAudioFileRef? = nil

    var srcFormat : AudioStreamBasicDescription = AudioStreamBasicDescription()
    var dstFormat : AudioStreamBasicDescription = AudioStreamBasicDescription()

    ExtAudioFileOpenURL(url as CFURL, &sourceFile)

    var thePropertySize: UInt32 = UInt32(MemoryLayout.stride(ofValue: srcFormat))

    ExtAudioFileGetProperty(sourceFile!,
                            kExtAudioFileProperty_FileDataFormat,
                            &thePropertySize, &srcFormat)

    dstFormat.mSampleRate = 44100  //Set sample rate
    dstFormat.mFormatID = kAudioFormatLinearPCM
    dstFormat.mChannelsPerFrame = 1
    dstFormat.mBitsPerChannel = 16
    dstFormat.mBytesPerPacket = 2 * dstFormat.mChannelsPerFrame
    dstFormat.mBytesPerFrame = 2 * dstFormat.mChannelsPerFrame
    dstFormat.mFramesPerPacket = 1
    dstFormat.mFormatFlags = kLinearPCMFormatFlagIsPacked |
    kAudioFormatFlagIsSignedInteger

    // Create destination file
    error = ExtAudioFileCreateWithURL(
        outputURL as CFURL,
        kAudioFileWAVEType,
        &dstFormat,
        nil,
        AudioFileFlags.eraseFile.rawValue,
        &destinationFile)
    print("Error 1 in convertAudio: \(error.description)")

    error = ExtAudioFileSetProperty(sourceFile!,
                                    kExtAudioFileProperty_ClientDataFormat,
                                    thePropertySize,
                                    &dstFormat)
    print("Error 2 in convertAudio: \(error.description)")

    error = ExtAudioFileSetProperty(destinationFile!,
                                    kExtAudioFileProperty_ClientDataFormat,
                                    thePropertySize,
                                    &dstFormat)
    print("Error 3 in convertAudio: \(error.description)")

    let bufferByteSize : UInt32 = 32768
    var srcBuffer = [UInt8](repeating: 0, count: 32768)
    var sourceFrameOffset : ULONG = 0

    while(true){
        var fillBufList = AudioBufferList(
            mNumberBuffers: 1,
            mBuffers: AudioBuffer(
                mNumberChannels: 2,
                mDataByteSize: UInt32(srcBuffer.count),
                mData: &srcBuffer
            )
        )
        var numFrames : UInt32 = 0

        if(dstFormat.mBytesPerFrame > 0){
            numFrames = bufferByteSize / dstFormat.mBytesPerFrame
        }

        error = ExtAudioFileRead(sourceFile!, &numFrames, &fillBufList)
        print("Error 4 in convertAudio: \(error.description)")

        if(numFrames == 0){
            error = noErr;
            break;
        }

        sourceFrameOffset += numFrames
        error = ExtAudioFileWrite(destinationFile!, numFrames, &fillBufList)
        print("Error 5 in convertAudio: \(error.description)")
    }

    error = ExtAudioFileDispose(destinationFile!)
    print("Error 6 in convertAudio: \(error.description)")
    error = ExtAudioFileDispose(sourceFile!)
    print("Error 7 in convertAudio: \(error.description)")
}
like image 142
MScottWaller Avatar answered Dec 28 '22 22:12

MScottWaller


Here is an Objective-C version of MScottWaller's Swift 3 answer. You need to @import AudioToolbox.

-(void) convertAudio:(NSURL*)url outputURL:(NSURL*)outputURL
{
    OSStatus error = noErr;
    ExtAudioFileRef destinationFile = nil;
    ExtAudioFileRef sourceFile = nil;

    AudioStreamBasicDescription srcFormat;
    AudioStreamBasicDescription dstFormat;

    ExtAudioFileOpenURL((__bridge CFURLRef)url, &sourceFile);


    UInt32 thePropertySize = sizeof(srcFormat); //UInt32(MemoryLayout.stride(ofValue: srcFormat));;
    ExtAudioFileGetProperty(sourceFile, kExtAudioFileProperty_FileDataFormat, &thePropertySize, &srcFormat);

    dstFormat.mSampleRate = 44100;  //Set sample rate
    dstFormat.mFormatID = kAudioFormatLinearPCM;
    dstFormat.mChannelsPerFrame = 1;
    dstFormat.mBitsPerChannel = 16;
    dstFormat.mBytesPerPacket = 2 * dstFormat.mChannelsPerFrame;
    dstFormat.mBytesPerFrame = 2 * dstFormat.mChannelsPerFrame;
    dstFormat.mFramesPerPacket = 1;
    dstFormat.mFormatFlags = kLinearPCMFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;

    // Create destination file
    error = ExtAudioFileCreateWithURL(
                                      (__bridge CFURLRef)outputURL,
                                      kAudioFileWAVEType,
                                      &dstFormat,
                                      nil,
                                      kAudioFileFlags_EraseFile,
                                      &destinationFile);
    NSLog(@"Error 1 in convertAudio: %d - %@", error, [NSError errorWithDomain:NSOSStatusErrorDomain code:error userInfo:nil].description);

    error = ExtAudioFileSetProperty(sourceFile,
                                    kExtAudioFileProperty_ClientDataFormat,
                                    thePropertySize,
                                    &dstFormat);
    NSLog(@"Error 2 in convertAudio: %d - %@", error, [NSError errorWithDomain:NSOSStatusErrorDomain code:error userInfo:nil].description);

    error = ExtAudioFileSetProperty(destinationFile,
                                    kExtAudioFileProperty_ClientDataFormat,
                                    thePropertySize,
                                    &dstFormat);
    NSLog(@"Error 3 in convertAudio: %d - %@", error, [NSError errorWithDomain:NSOSStatusErrorDomain code:error userInfo:nil].description);

    const UInt32 bufferByteSize = 32768;
    UInt8 srcBuffer[bufferByteSize];// = [UInt8](repeating: 0, count: 32768)
    memset(srcBuffer, 0, bufferByteSize);
    unsigned long sourceFrameOffset = 0;

    while(true)
    {
        AudioBufferList fillBufList;
        fillBufList.mNumberBuffers = 1;
        fillBufList.mBuffers[0].mNumberChannels = 2;
        fillBufList.mBuffers[0].mDataByteSize = bufferByteSize;
        fillBufList.mBuffers[0].mData = &srcBuffer;

        UInt32 numFrames = 0;

        if(dstFormat.mBytesPerFrame > 0){
            numFrames = bufferByteSize / dstFormat.mBytesPerFrame;
        }

        error = ExtAudioFileRead(sourceFile, &numFrames, &fillBufList);
        NSLog(@"Error 4 in convertAudio: %d - %@", error, [NSError errorWithDomain:NSOSStatusErrorDomain code:error userInfo:nil].description);

        if(numFrames == 0)
        {
            error = noErr;
            break;
        }

        sourceFrameOffset += numFrames;
        error = ExtAudioFileWrite(destinationFile, numFrames, &fillBufList);
        NSLog(@"Error 5 in convertAudio: %d - %@", error, [NSError errorWithDomain:NSOSStatusErrorDomain code:error userInfo:nil].description);
    }

    error = ExtAudioFileDispose(destinationFile);
    NSLog(@"Error 6 in convertAudio: %d - %@", error, [NSError errorWithDomain:NSOSStatusErrorDomain code:error userInfo:nil].description);
    error = ExtAudioFileDispose(sourceFile);
    NSLog(@"Error 7 in convertAudio: %d - %@", error, [NSError errorWithDomain:NSOSStatusErrorDomain code:error userInfo:nil].description);
}
like image 26
Ian Avatar answered Dec 29 '22 00:12

Ian