Search code examples
iosaudiocore-audiofile-conversion

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.


Solution

  • If anyone else needs some code to do this here it is in Swift

    func convertAudioFile(sourceURL: CFURLRef, destinationURL: 
    CFURLRef, outputFormat: OSType , 
    outputSampleRate: Float64) ->  OSStatus
    {
    var error : OSStatus = noErr
    var destinationFile : ExtAudioFileRef = nil
    var sourceFile : ExtAudioFileRef = nil
    
    var srcFormat : AudioStreamBasicDescription = AudioStreamBasicDescription()
    var dstFormat : AudioStreamBasicDescription = AudioStreamBasicDescription()
    
    var audioConverter : AudioConverterRef = nil
    
    audioConverter = AudioConverterRef.init()
    
    ExtAudioFileOpenURL(sourceURL, &sourceFile)
    
    var thePropertySize: UInt32 = UInt32(strideofValue(srcFormat))
    
    ExtAudioFileGetProperty(sourceFile, kExtAudioFileProperty_FileDataFormat, &thePropertySize, &srcFormat)
    
    dstFormat.mSampleRate = (outputSampleRate == 0 ? srcFormat.mSampleRate : outputSampleRate)  //Set sample rate
    
    dstFormat.mFormatID = outputFormat
    dstFormat.mChannelsPerFrame = 1
    dstFormat.mBitsPerChannel = 16
    dstFormat.mBytesPerPacket = 2 * dstFormat.mChannelsPerFrame
    dstFormat.mBytesPerFrame = 2 * dstFormat.mChannelsPerFrame
    dstFormat.mFramesPerPacket = 1
    dstFormat.mFormatFlags = kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger // little-endian
    
    //Create destination file
    ExtAudioFileCreateWithURL(destinationURL, kAudioFileCAFType, &dstFormat, nil,
        AudioFileFlags.EraseFile.rawValue, &destinationFile)
    
    ExtAudioFileSetProperty(sourceFile, kExtAudioFileProperty_ClientDataFormat, thePropertySize, &dstFormat)
    ExtAudioFileSetProperty(destinationFile, kExtAudioFileProperty_ClientDataFormat, thePropertySize, &dstFormat)
    
    var size : UInt32 = UInt32(strideofValue(audioConverter))
    
    ExtAudioFileGetProperty(destinationFile, kExtAudioFileProperty_AudioConverter, &size, &audioConverter)
    
    var canResume : UInt32 = 0
    
    size = UInt32(strideofValue(canResume))
    
    error = AudioConverterGetProperty(audioConverter, kAudioConverterPropertyCanResumeFromInterruption, &size, &canResume)
    
    let bufferByteSize : UInt32 = 32768
    var srcBuffer = [UInt8](count: 32768, repeatedValue: 0)
    
    var sourceFrameOffset : ULONG = 0
    
    print("Converting audio file")
    
    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
        }
    
        ExtAudioFileRead(sourceFile, &numFrames, &fillBufList)
    
        if(numFrames == 0){
            error = noErr;
            break;
        }
    
        sourceFrameOffset += numFrames
    
        error = ExtAudioFileWrite(destinationFile, numFrames, &fillBufList)
    }
    
    ExtAudioFileDispose(destinationFile)
    ExtAudioFileDispose(sourceFile)
    
    let audioAsset = AVURLAsset.init(URL: destinationURL, options: nil)
    if(audioAsset.duration.seconds < 5.0){
        error = -2500
    }
    
    return error;