我无法将线性 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