使用AudioConverter Swift将.m4a文件转换为.aiff

我正在尝试将.m4a格式的给定音频文件转换为.aiff格式,使用 this post的答案.我已将代码转换为Swift 3.0.
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()

    var audioConverter : AudioConverterRef? = nil

    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 = kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsSignedInteger

    //Create destination file
    ExtAudioFileCreateWithURL(outputURL as CFURL,kAudioFileaifFType,&dstFormat,nil,AudioFileFlags.eraseFile.rawValue,&destinationFile)

    ExtAudioFileSetProperty(sourceFile!,kExtAudioFileProperty_ClientDataFormat,thePropertySize,&dstFormat)
    ExtAudioFileSetProperty(destinationFile!,&dstFormat)

    var size : UInt32 = UInt32(MemoryLayout.stride(ofValue: audioConverter))

    ExtAudioFileGetProperty(destinationFile!,kExtAudioFileProperty_AudioConverter,&size,&audioConverter)

    var canResume : UInt32 = 0

    size = UInt32(MemoryLayout.stride(ofValue: canResume))

    error = AudioConverterGetProperty(audioConverter!,kAudioConverterPropertyCanResumeFromInterruption,&canResume)

    let bufferByteSize : UInt32 = 32768
    var srcBuffer = [UInt8](repeating: 0,count: 32768)
    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!)
}

问题是audioConverter似乎在这一行是零

error = AudioConverterGetProperty(audioConverter!,&canResume)

而我似乎无法弄清楚为什么.我错过了什么?

跳过AudioConverterGetProperty

你实际上没有使用它.
以下代码片段将音频文件转换aifF:它以一种支持的格式读取sourceFile,创建aifF编码器,并使用bufferByteSize缓冲区循环它.错误处理得当.

完整代码,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,&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 = kAudioFormatFlagIsBigEndian |
                             kAudioFormatFlagIsSignedInteger

    // Create destination file
    error = ExtAudioFileCreateWithURL(
        outputURL as CFURL,&destinationFile)
    reportError(error: error)

    error = ExtAudioFileSetProperty(sourceFile!,&dstFormat)
    reportError(error: error)

    error = ExtAudioFileSetProperty(destinationFile!,&dstFormat)
    reportError(error: error)

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

    while(true){
        var fillBufList = audiobufferlist(
            mNumberBuffers: 1,mData: &srcBuffer
            )
        )
        var numFrames : UInt32 = 0

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

        error = ExtAudioFileRead(sourceFile!,&fillBufList)
        reportError(error: error)

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

        sourceFrameOffset += numFrames
        error = ExtAudioFileWrite(destinationFile!,&fillBufList)
        reportError(error: error)
    }

    error = ExtAudioFiledispose(destinationFile!)
    reportError(error: error)
    error = ExtAudioFiledispose(sourceFile!)
    reportError(error: error)
}

支持方式:

func reportError(error: Osstatus) {
    // Handle error
}

调用

let sourceUrl = URL(string: Bundle.main.path(forResource: "sample",ofType: "mp3")!)
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory,.userDomainMask,true)
let documentsDirectory = URL(string: paths.first!)
let destUrl = documentsDirectory?.appendingPathComponent("converted.aiff")
if let sourceUrl = sourceUrl,let destUrl = destUrl {
    print("from \(sourceUrl.absoluteString) to \(destUrl.absoluteString)")
    convertAudio(sourceUrl,outputURL: destUrl)
}

相关文章

软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘...
现实生活中,我们听到的声音都是时间连续的,我们称为这种信...
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿...
【Android App】实战项目之仿抖音的短视频分享App(附源码和...
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至...
因为我既对接过session、cookie,也对接过JWT,今年因为工作...