【问题标题】:Unable to convert mp3 into PCM using AudioConverterFillComplexBuffer in AudioFileStreamOpen's AudioFileStream_PacketsProc callback无法使用 AudioFileStreamOpen 的 AudioFileStream_PacketsProc 回调中的 AudioConverterFillComplexBuffer 将 mp3 转换为 PCM
【发布时间】:2015-07-17 17:38:10
【问题描述】:

我在AudioFileStreamOpen 期间设置了一个AudioFileStream_PacketsProc 回调,它使用AudioConverterFillComplexBuffer 处理将音频数据包转换为PCM。我遇到的问题是在调用AudioConverterFillComplexBuffer 后我得到了-50 OSStatus (paramErr)。以下是AudioConverterFillComplexBuffer 中使用了哪些参数以及它们是如何制作的 sn-p:

        audioConverterRef = AudioConverterRef()

        // AudioConvertInfo is a struct that contains information
        // for the converter regarding the number of packets and 
        // which audiobuffer is being allocated
        convertInfo? = AudioConvertInfo(done: false, numberOfPackets: numberPackets, audioBuffer: buffer,
            packetDescriptions: packetDescriptions) 

        var framesToDecode: UInt32 = pcmBufferTotalFrameCount! - end

        var localPcmAudioBuffer = AudioBuffer()
        localPcmAudioBuffer.mData = pcmAudioBuffer!.mData.advancedBy(Int(end * pcmBufferFrameSizeInBytes!))

        var localPcmBufferList = AudioBufferList(mNumberBuffers: 1, mBuffers: AudioBuffer(mNumberChannels: 0, mDataByteSize: 0, mData: nil))
        localPcmAudioBuffer = localPcmBufferList.mBuffers
        localPcmAudioBuffer.mData = pcmAudioBuffer!.mData.advancedBy(Int(end * pcmBufferFrameSizeInBytes!))
        localPcmAudioBuffer.mDataByteSize = framesToDecode * pcmBufferFrameSizeInBytes!;
        localPcmAudioBuffer.mNumberChannels = pcmAudioBuffer!.mNumberChannels

        var localPcmBufferList = AudioBufferList(mNumberBuffers: 1, mBuffers: AudioBuffer(mNumberChannels: 0, mDataByteSize: 0, mData: nil))
        localPcmAudioBuffer = localPcmBufferList.mBuffers

        AudioConverterFillComplexBuffer(audioConverterRef, AudioConverter_Callback, &convertInfo, &framesToDecode, &localPcmBufferList, nil)

是什么可能导致参数错误?

如果需要,这里是回调的完整方法:

func handleAudioPackets(inputData: UnsafePointer<Void>, numberBytes: UInt32, numberPackets: UInt32, packetDescriptions: UnsafeMutablePointer<AudioStreamPacketDescription>) {
        if currentlyReadingEntry == nil {
            print("currentlyReadingEntry = nil")
            return
        }
        if currentlyReadingEntry.parsedHeader == false {
            print("currentlyReadingEntry.parsedHeader == false")
            return
        }

        if disposedWasRequested == true {
            print("disposedWasRequested == true")
            return
        }

        guard let audioConverterRef = audioConverterRef else {
            return
        }

        if seekToTimeWasRequested == true && currentlyReadingEntry.calculatedBitRate() > 0.0 {
            wakeupPlaybackThread()
            print("seekToTimeWasRequested == true && currentlyReadingEntry.calculatedBitRate() > 0.0")
            return
        }

        discontinuous = false

        var buffer = AudioBuffer()
        buffer.mNumberChannels = audioConverterAudioStreamBasicDescription.mChannelsPerFrame
        buffer.mDataByteSize = numberBytes
        buffer.mData = UnsafeMutablePointer<Void>(inputData)


        convertInfo? = AudioConvertInfo(done: false, numberOfPackets: numberPackets, audioBuffer: buffer,
            packetDescriptions: packetDescriptions)


        if packetDescriptions != nil && currentlyReadingEntry.processedPacketsCount < maxCompressedBacketsForBitrateCalculation {
            let count: Int = min(Int(numberPackets), Int(maxCompressedBacketsForBitrateCalculation - currentlyReadingEntry.processedPacketsCount!))
            for var i = 0;i < count;++i{
                let packetSize: Int32 = Int32(packetDescriptions[i].mDataByteSize)
                OSAtomicAdd32(packetSize, &currentlyReadingEntry.processedPacketsSizeTotal!)
                OSAtomicIncrement32(&currentlyReadingEntry.processedPacketsCount!)
            }
        }
        while true {
            OSSpinLockLock(&pcmBufferSpinLock)
            var used: UInt32 = pcmBufferUsedFrameCount!
            var start: UInt32 = pcmBufferFrameStartIndex!
            var end = (pcmBufferFrameStartIndex! + pcmBufferUsedFrameCount!) % pcmBufferTotalFrameCount!
            var framesLeftInsideBuffer = pcmBufferTotalFrameCount! - used
            OSSpinLockUnlock(&pcmBufferSpinLock)

            if framesLeftInsideBuffer == 0 {
                pthread_mutex_lock(&playerMutex)
                while true {
                    OSSpinLockLock(&pcmBufferSpinLock)
                    used = pcmBufferUsedFrameCount!
                    start = pcmBufferFrameStartIndex!
                    end = (pcmBufferFrameStartIndex! + pcmBufferUsedFrameCount!) % pcmBufferTotalFrameCount!
                    framesLeftInsideBuffer = pcmBufferTotalFrameCount! - used
                    OSSpinLockUnlock(&pcmBufferSpinLock)

                    if framesLeftInsideBuffer > 0 {
                        break
                    }

                    if (disposedWasRequested == true
                        || internalState == SSPlayerInternalState.Disposed) {
                        pthread_mutex_unlock(&playerMutex)
                        return
                    }

                    if (seekToTimeWasRequested == true && currentlyPlayingEntry.calculatedBitRate() > 0.0)
                    {
                        pthread_mutex_unlock(&playerMutex)
                        wakeupPlaybackThread()
                        return;
                    }

                    waiting = true
                    pthread_cond_wait(&playerThreadReadyCondition, &playerMutex)
                    waiting = false
                }
                pthread_mutex_unlock(&playerMutex)
            }
            var localPcmAudioBuffer = AudioBuffer()
            var localPcmBufferList = AudioBufferList(mNumberBuffers: 1, mBuffers: AudioBuffer(mNumberChannels: 0, mDataByteSize: 0, mData: nil))
            localPcmAudioBuffer = localPcmBufferList.mBuffers

            if end >= start {
                var framesAdded: UInt32 = 0
                var framesToDecode: UInt32 = pcmBufferTotalFrameCount! - end
                localPcmAudioBuffer.mData = pcmAudioBuffer!.mData.advancedBy(Int(end * pcmBufferFrameSizeInBytes!))
                localPcmAudioBuffer.mDataByteSize = framesToDecode * pcmBufferFrameSizeInBytes!;
                localPcmAudioBuffer.mNumberChannels = pcmAudioBuffer!.mNumberChannels

                AudioConverterFillComplexBuffer(audioConverterRef, AudioConverter_Callback, &convertInfo, &framesToDecode, &localPcmBufferList, nil)

                framesAdded = framesToDecode

                if status == 100 {
                    OSSpinLockLock(&pcmBufferSpinLock)
                    let newCount = pcmBufferUsedFrameCount! + framesAdded
                    pcmBufferUsedFrameCount = newCount
                    OSSpinLockUnlock(&pcmBufferSpinLock);

                    OSSpinLockLock(&currentlyReadingEntry!.spinLock!)
                    let newFramesAddedCount = currentlyReadingEntry.framesQueued! + Int64(framesAdded)
                    currentlyReadingEntry!.framesQueued! = newFramesAddedCount
                    OSSpinLockUnlock(&currentlyReadingEntry!.spinLock!)
                    return
                } else if status != 0 {
                    print("error")
                    return
                }
                framesToDecode = start

                if framesToDecode == 0 {

                    OSSpinLockLock(&pcmBufferSpinLock)
                    let newCount = pcmBufferUsedFrameCount! + framesAdded
                    pcmBufferUsedFrameCount = newCount
                    OSSpinLockUnlock(&pcmBufferSpinLock);

                    OSSpinLockLock(&currentlyReadingEntry!.spinLock!)
                    let newFramesAddedCount = currentlyReadingEntry.framesQueued! + Int64(framesAdded)
                    currentlyReadingEntry!.framesQueued! = newFramesAddedCount
                    OSSpinLockUnlock(&currentlyReadingEntry!.spinLock!)
                    continue
                }

                localPcmAudioBuffer.mData = pcmAudioBuffer!.mData
                localPcmAudioBuffer.mDataByteSize = framesToDecode * pcmBufferFrameSizeInBytes!
                localPcmAudioBuffer.mNumberChannels = pcmAudioBuffer!.mNumberChannels

                AudioConverterFillComplexBuffer(audioConverterRef, AudioConverter_Callback, &convertInfo, &framesToDecode, &localPcmBufferList, nil)
                let decodedFramesAdded = framesAdded + framesToDecode
                framesAdded = decodedFramesAdded

                if status == 100 {
                    OSSpinLockLock(&pcmBufferSpinLock)
                    let newCount = pcmBufferUsedFrameCount! + framesAdded
                    pcmBufferUsedFrameCount = newCount
                    OSSpinLockUnlock(&pcmBufferSpinLock);

                    OSSpinLockLock(&currentlyReadingEntry!.spinLock!)
                    let newFramesAddedCount = currentlyReadingEntry.framesQueued! + Int64(framesAdded)
                    currentlyReadingEntry!.framesQueued! = newFramesAddedCount
                    OSSpinLockUnlock(&currentlyReadingEntry!.spinLock!)
                    return
                } else if status == 0 {
                    OSSpinLockLock(&pcmBufferSpinLock)
                    let newCount = pcmBufferUsedFrameCount! + framesAdded
                    pcmBufferUsedFrameCount = newCount
                    OSSpinLockUnlock(&pcmBufferSpinLock);

                    OSSpinLockLock(&currentlyReadingEntry!.spinLock!)
                    let newFramesAddedCount = currentlyReadingEntry.framesQueued! + Int64(framesAdded)
                    currentlyReadingEntry!.framesQueued! = newFramesAddedCount
                    OSSpinLockUnlock(&currentlyReadingEntry!.spinLock!)
                    continue
                } else if status != 0 {
                    print("error")
                    return
                } else {
                    var framesAdded: UInt32 = 0
                    var framesToDecode: UInt32 = start - end
                    localPcmAudioBuffer.mData = pcmAudioBuffer!.mData.advancedBy(Int(end * pcmBufferFrameSizeInBytes!))
                    localPcmAudioBuffer.mDataByteSize = framesToDecode * pcmBufferFrameSizeInBytes!;
                    localPcmAudioBuffer.mNumberChannels = pcmAudioBuffer!.mNumberChannels

                    var  convertInfoo: UnsafePointer<Void> = unsafeBitCast(convertInfo, UnsafePointer<Void>.self)

                    status = AudioConverterFillComplexBuffer(audioConverterRef, AudioConverter_Callback, &convertInfoo, &framesToDecode, &localPcmBufferList, nil)

                    framesAdded = framesToDecode

                    if status == 100 {
                        OSSpinLockLock(&pcmBufferSpinLock)
                        let newCount = pcmBufferUsedFrameCount! + framesAdded
                        pcmBufferUsedFrameCount = newCount
                        OSSpinLockUnlock(&pcmBufferSpinLock);

                        OSSpinLockLock(&currentlyReadingEntry!.spinLock!)
                        let newFramesAddedCount = currentlyReadingEntry.framesQueued! + Int64(framesAdded)
                        currentlyReadingEntry!.framesQueued! = newFramesAddedCount
                        OSSpinLockUnlock(&currentlyReadingEntry!.spinLock!)
                        return
                    } else if status == 0 {
                        OSSpinLockLock(&pcmBufferSpinLock)
                        let newCount = pcmBufferUsedFrameCount! + framesAdded
                        pcmBufferUsedFrameCount = newCount
                        OSSpinLockUnlock(&pcmBufferSpinLock);

                        OSSpinLockLock(&currentlyReadingEntry!.spinLock!)
                        let newFramesAddedCount = currentlyReadingEntry.framesQueued! + Int64(framesAdded)
                        currentlyReadingEntry!.framesQueued! = newFramesAddedCount
                        OSSpinLockUnlock(&currentlyReadingEntry!.spinLock!)
                        continue
                    } else if status != 0 {
                        print("error")
                        return
                    }

                }
            }
        }
    }

【问题讨论】:

  • 你有一个可运行项目的链接吗,比如在 github 中?

标签: ios swift audiounit swift2 audio-converter


【解决方案1】:

Hej @3254523,我为您提供了一些可能的解决方案。尽管我不是该专业的专家,但我希望以正确的方式指导您。所以,问题肯定是:

AudioBufferList

这里是探测与 AudioBufferList 相关的 -50 OSStatus 提示的链接: http://lists.apple.com/archives/coreaudio-api/2012/Apr/msg00041.html https://forums.developer.apple.com/thread/6313

现在,我们必须专注于解决方案。查看您的 AudioBufferList,您没有分配任何值,但 mNumberBuffers 为 1。尝试按以下方式更改值(如第二个链接所示):

var localPcmBufferList = AudioBufferList(mNumberBuffers: 2, mBuffers: AudioBuffer(mNumberChannels: 2, mDataByteSize: UInt32(buffer.count), mData: &buffer))

如果仍然无法正常工作,我们必须集中精力正确纠正它,因此您可以在 AudioConverterFillComplexBuffer-50 OSStatus 的解决方案/strong> 虽然不是很快:

AudioConverterFillComplexBuffer return -50 (paramErr)

iPhone: AudioBufferList init and release

【讨论】:

  • 仍在尝试@juanmajmjr
  • 现在我将 mNumberBuffers 设置为 1,得到 1768846202(输入错误)。那会是什么?
  • Hej @3254523 ,这是另一种错误。尝试更改该数字并查看行为。您也可以在以下链接中找到更多信息,尽管问题并未完全解决:stackoverflow.com/questions/1374674/…
  • 你有skype/gchat @juanmajmjr 吗?
【解决方案2】:

一个不错的example 取自AudioKit


  • 音频文件服务(读取 MP3 格式并写入 AIFF 或 WAV)

  • 音频文件转换服务(将 MP3 数据转换为 PCM,或从 PCM 编码为其他编解码器,如果您要编写文件)

给定的转换器无法在两种编码格式之间进行转换。

你可以做 MP3 到 PCM 或 PCM 到 AAC

在做 MP3 转 AAC 时,需要两个转换器

【讨论】:

    【解决方案3】:

    tanersener/mobile-ffmpeg 轻松搞定

          let command = "-i input.mp3 -f s16le -acodec pcm_s16le -ac 1 -ar 44100  output.raw"
          let result = MobileFFmpeg.execute(command)
               switch result {
               case RETURN_CODE_SUCCESS:
                   print("command exe completed successfully.\n")
               case RETURN_CODE_CANCEL:
                   print("command exe cancelled by user.\n")
               default:
                   print("command exe failed with rc=\(result) and output=\(String(describing: MobileFFmpegConfig.getLastCommandOutput())).\n")
              }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多