Я хотел бы знать, как получить байты AVAudioCompressedBuffer, а затем восстановить AVAudioCompressedBuffer из байтов.
Приведенный ниже код берет AVAudioPCMBuffer, сжимает его с помощью AVAudioConverter в AVAudioCompressedBuffer (iLBC) и получает байты, затем преобразует байты обратно в AVAudioCompressedBuffer (iLBC), распаковывает обратно в AVAudioPCMBuffer и воспроизводит буфер. Что-то не так с преобразованием AVAudioCompressedBuffer в байты и обратно. Если я пропущу это преобразование, звук будет воспроизводиться так, как ожидалось.
Я даже могу сопоставить содержимое сжатых буферов и сжатых буферов2, что наводит меня на мысль, что механизм получения байтов не совсем правильный.
// Do iLBC Compression
let compressedBuffer: AVAudioCompressedBuffer = self.compress(inBuffer: buffer)
// packetCapacity: 4, maximumPacketSize: 38
// self.player.scheduleBuffer(self.uncompress(inBuffer: compressedBuffer)) // This works perfectly
// Convert Buffer to Byte Array
let pointer1: UnsafeMutablePointer = compressedBuffer.data.bindMemory(to: UInt8.self, capacity: 152)
var audioByteArray = [UInt8](repeating: 0, count: 152)
pointer1.withMemoryRebound(to: UInt8.self, capacity: 152) { srcByteData in
audioByteArray.withUnsafeMutableBufferPointer {
$0.baseAddress!.initialize(from: srcByteData, count: 152)
}
}
// Convert Byte Array to Buffer
let compressedBuffer2: AVAudioCompressedBuffer = AVAudioCompressedBuffer(format: AVAudioFormat.init(streamDescription: &self.descriptor)!, packetCapacity: 4, maximumPacketSize: 38)
let destination = compressedBuffer2.data
audioByteArray.withUnsafeBufferPointer {
let src = UnsafeRawPointer($0.baseAddress!).bindMemory(to: UInt8.self, capacity: 152)
destination.copyMemory(from: src, byteCount: 152)
}
// Do iLBC Decompression
let uncompressedBuffer: AVAudioPCMBuffer = self.uncompress(inBuffer: compressedBuffer2)
// Works perfectly with inBuffer: compressedBuffer
// Play Buffer
self.player.scheduleBuffer(uncompressedBuffer)
// Plays fine when 'let uncompressedBuffer: AVAudioPCMBuffer = self.uncompress(inBuffer: compressedBuffer)'
Функции сжатия и распаковки
let format = AVAudioFormat.init(commonFormat: AVAudioCommonFormat.pcmFormatFloat32, sampleRate: 16000, channels: 1, interleaved: false)
var compressedFormatDescriptor = AudioStreamBasicDescription(mSampleRate: 8000, mFormatID: kAudioFormatiLBC, mFormatFlags: 0, mBytesPerPacket: 0, mFramesPerPacket: 0, mBytesPerFrame: 0, mChannelsPerFrame: 1, mBitsPerChannel: 0, mReserved: 0)
func compress(inBuffer : AVAudioPCMBuffer) -> AVAudioCompressedBuffer {
let inputFormat = inBuffer.format
let converter = AVAudioConverter(from: inputFormat, to: self.compressedFormat!)
let outBuffer = AVAudioCompressedBuffer(format: self.compressedFormat!, packetCapacity: 4, maximumPacketSize: 38)
let inputBlock : AVAudioConverterInputBlock = { inNumPackets, outStatus in
outStatus.pointee = AVAudioConverterInputStatus.haveData
return inBuffer
}
var error : NSError?
converter!.convert(to: outBuffer, error: &error, withInputFrom: inputBlock)
return outBuffer
}
func uncompress(inBuffer : AVAudioCompressedBuffer) -> AVAudioPCMBuffer {
let inputFormat = inBuffer.format
let outputFormat = format
let converter = AVAudioConverter(from: inputFormat, to: outputFormat!)
let inputBlock : AVAudioConverterInputBlock = { inNumPackets, outStatus in
outStatus.pointee = AVAudioConverterInputStatus.haveData
return inBuffer
}
var error : NSError?
let outBuffer: AVAudioPCMBuffer = AVAudioPCMBuffer(pcmFormat: outputFormat!, frameCapacity: 1600)!
converter!.convert(to: outBuffer, error: &error, withInputFrom: inputBlock)
return outBuffer
}