1

我无法将线性 PCM 缓冲区转换为压缩的 AAC ELD(增强型低延迟)缓冲区。

我从这个问题中得到了一些用于转换为 ilbc 格式的工作代码: AVAudioCompressedBuffer to UInt8 array,反之亦然

这种方法效果很好。

我将格式的输入更改为:

let packetCapacity = 8
let maximumPacketSize = 96
lazy var capacity = packetCapacity * maximumPacketSize // 768

let convertedSampleRate: Double = 16000

lazy var aaceldFormat: AVAudioFormat = {
    var descriptor = AudioStreamBasicDescription(mSampleRate: convertedSampleRate, mFormatID: kAudioFormatMPEG4AAC_ELD, mFormatFlags: 0, mBytesPerPacket: 0, mFramesPerPacket: 0, mBytesPerFrame: 0, mChannelsPerFrame: 1, mBitsPerChannel: 0, mReserved: 0)

    return AVAudioFormat(streamDescription: &descriptor)!
}()

转换为压缩缓冲区工作正常,我能够将缓冲区转换为 UInt8 数组。

但是,转换回 PCM 缓冲区不起作用。转换回缓冲区的输入块如下所示:

func convertToBuffer(uints: [UInt8], outcomeSampleRate: Double) -> AVAudioPCMBuffer? {
    // Convert to buffer
    let compressedBuffer: AVAudioCompressedBuffer = AVAudioCompressedBuffer(format: aaceldFormat, packetCapacity: AVAudioPacketCount(packetCapacity), maximumPacketSize: maximumPacketSize)
    compressedBuffer.byteLength = UInt32(capacity)
    compressedBuffer.packetCount = AVAudioPacketCount(packetCapacity)
    
    var compressedBytes = uints
    compressedBytes.withUnsafeMutableBufferPointer {
        compressedBuffer.data.copyMemory(from: $0.baseAddress!, byteCount: capacity)
    }
    
    guard let audioFormat = AVAudioFormat(
        commonFormat: AVAudioCommonFormat.pcmFormatFloat32,
        sampleRate: outcomeSampleRate,
        channels: 1,
        interleaved: false
    ) else { return nil }
    
    guard let uncompressor = getUncompressingConverter(outputFormat: audioFormat) else { return nil }
    
    var newBufferAvailable = true
    
    let inputBlock : AVAudioConverterInputBlock = {
        inNumPackets, outStatus in
        if newBufferAvailable {
            outStatus.pointee = .haveData
            newBufferAvailable = false
            return compressedBuffer
        } else {
            outStatus.pointee = .noDataNow
            return nil
        }
    }
    
    guard let uncompressedBuffer: AVAudioPCMBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat, frameCapacity: AVAudioFrameCount((audioFormat.sampleRate / 10))) else { return nil }
    
    var conversionError: NSError?
    uncompressor.convert(to: uncompressedBuffer, error: &conversionError, withInputFrom: inputBlock)
    
    if let err = conversionError {
        print("couldnt decompress compressed buffer", err)
    }
    
    return uncompressedBuffer
}

convert 方法后的错误块触发并打印出“输入缓冲区中剩余的位太少”。此外,似乎输入块只被调用一次。

我尝试了不同的代码,这似乎是最常见的结果之一。我也不确定问题是否出在从 pcm 缓冲区到 uint8 数组的初始转换中,尽管我得到一个 UInt8 数组,每 0.1 秒填充 768 个值(有时数组最后包含几个零,这不会以 ilbc 格式发生。

问题:

1.从 pcm 缓冲区到 uint8 数组的初始转换是否使用正确的方法完成?packetCapacity、capacity 和 maximumPacketSize 是否有效?-> 再次,似乎工作

2.我在转换回 pcm 缓冲区时遗漏了什么吗?另外,我是否以正确的方式使用变量?

3.有没有人在项目中不使用 C 的情况下实现了这种转换?

** 编辑:** 我还使用了这篇文章中的方法: Decode AAC to PCM format using AVAudioConverter Swift

它适用于 AAC 格式,但不适用于 AAC_LD 或 AAC_ELD

4

0 回答 0