无法将AVAudioConverter转换为MPEG4AAC

时间:2019-01-15 23:26:06

标签: ios swift

所以我不确定我是否正确执行此操作,因为我是swift / ios开发的新手,但是我可以通过AudioQueue播放压缩的音频(因此我认为它有些正确)。我花了大约3天的时间将原始pcm转换为AAC。如果我将比特率设置为9600,则压缩后的数据大于源(例如,原始PCM大小= 2048,压缩后的(AAC)在2100-2300字节之间)。仅当我将比特率设置为较低的值(32000)时,它才会压缩为值得压缩的内容(大约740-760字节),但是质量非常低。

这正常吗? M4A是mp3的后继产品,wave和mp3之间的文件大小比较大约是10倍,我觉得还差得远。我认为m4a至少能使我达到mp3的水平。

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        var audioBufferList = AudioBufferList()
        var pcmData = Data()

        var blockBuffer : CMBlockBuffer?

        CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBuffer, bufferListSizeNeededOut: nil, bufferListOut: &audioBufferList, bufferListSize: MemoryLayout<AudioBufferList>.size, blockBufferAllocator: nil, blockBufferMemoryAllocator: nil, flags: 0, blockBufferOut: &blockBuffer)

        let buffers = UnsafeBufferPointer<AudioBuffer>(start: &audioBufferList.mBuffers, count: Int(audioBufferList.mNumberBuffers))

        for audioBuffer in buffers {
            let frame = audioBuffer.mData?.assumingMemoryBound(to: UInt8.self)
            pcmData.append(frame!, count: Int(audioBuffer.mDataByteSize))
        }

        let inDescriptionRef = CMSampleBufferGetFormatDescription(sampleBuffer)
        if inDescriptionRef != nil {
            var inDescription = CMAudioFormatDescriptionGetStreamBasicDescription(inDescriptionRef!)!.pointee
            var outDescriptionACC = AudioStreamBasicDescription()
            outDescriptionACC.mSampleRate = (inDescription.mSampleRate)
            outDescriptionACC.mFormatID = kAudioFormatMPEG4AAC//encoding mp3 not supported
            outDescriptionACC.mChannelsPerFrame = (inDescription.mChannelsPerFrame)
            outDescriptionACC.mFormatFlags = 0

            //create these objects once so we don't keep creating them
            if mConverterToAAC == nil {
                mInFormat = AVAudioFormat(streamDescription: &inDescription)!
                mOutFormat = AVAudioFormat(streamDescription: &outDescriptionACC)!
                mConverterToAAC = AVAudioConverter(from: mInFormat, to: mOutFormat)
                mConverterToAAC.bitRate = 96000
            }

            //convert the pcm data to PCMBuffer
            let inBuffer = toPCMBuffer(pcmData)

            //out buffer to hold compressed results
            let outBuffer = AVAudioCompressedBuffer(format: mOutFormat, packetCapacity: 8, maximumPacketSize: mConverterToAAC.maximumOutputPacketSize)

            //closure to get data to convert
            let newBufferAvailable = true
            let inputBlock : AVAudioConverterInputBlock = { inNumPackets, outStatus in
                if newBufferAvailable {
                    outStatus.pointee = AVAudioConverterInputStatus.haveData
                    return inBuffer
                }
                else{
                    outStatus.pointee = AVAudioConverterInputStatus.noDataNow
                    return nil
                }
            }

            //convert PCM to Compressed AAC
            var errorPtr : NSError?
            let convertStatus = mConverterToAAC.convert(to: outBuffer, error: &errorPtr, withInputFrom: inputBlock)
            print("ConverterStatusToACC=\(convertStatus), Name=\(Utilities().AudioConverterOutputStatusToStr(convertStatus))")
            if errorPtr != nil {
                print("ConverterStatusToACC Error Message=\(errorPtr!)")
            }
            else{
                let accData = Data(bytes: outBuffer.data, count: Int(outBuffer.byteLength))

                print("Original Data Size=\(pcmData.count)")
                print("Compressed Size   =\(accData.count)")

                pcmDataCount += pcmData.count
                accDataCount += accData.count
                let timeLapsed = util.getCurrentMillis() - mCurrentTime
                if timeLapsed > 1000 {
                    print("PCM Data=\(pcmDataCount), Compressed Data=\(accDataCount), TimeLapsed=\(timeLapsed)")
                    pcmDataCount = 0
                    accDataCount = 0;
                    mCurrentTime = util.getCurrentMillis()
                }
            }
        }
        else{
            print("inDescriptionRef is nil")
        }
    }

0 个答案:

没有答案