AudioFileReadPacketData传递有效文件时返回-50
我花了一些时间试图自己debugging,但我似乎无法得到AudioFileReadPacketData
正确读取传入的数据。 这几乎基于Apple AudioQueueServices Guide
。
class SVNPlayer: SVNPlayback { var queue: AudioQueueRef? var audioFormat: AudioStreamBasicDescription! var playbackFile: AudioFileID? var packetDesc: AudioStreamPacketDescription! var isDone = false var packetPosition: Int64 = 0 var numPacketsToRead = UInt32() private let callback: AudioQueueOutputCallback = { aqData, inAQ, inBuffer in guard let userData = aqData else { return } let audioPlayer = Unmanaged<SVNPlayer>.fromOpaque(userData).takeUnretainedValue() var buffer = inBuffer.pointee if audioPlayer.isDone { return } var numBytes: UInt32 = 0 var nPackets = audioPlayer.numPacketsToRead
这是扔-50的线
var code = AudioFileReadPacketData(audioPlayer.playbackFile!, false, &numBytes, &audioPlayer.packetDesc!, audioPlayer.packetPosition, &nPackets, buffer.mAudioData)
这反过来在AudioQueueEnqueueBuffer
上AudioQueueEnqueueBuffer
if nPackets > 0 { buffer.mAudioDataByteSize = numBytes AudioQueueEnqueueBuffer(inAQ, &buffer, nPackets, &audioPlayer.packetDesc!) audioPlayer.packetPosition += Int64(nPackets) } else { AudioQueueStop(inAQ, false) audioPlayer.isDone = true } } func prepareToPlayback(with fileURL: URL) throws { let pointer = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()) // get an unmananged reference to self var format = AudioStreamBasicDescription() var formatSize = UInt32(MemoryLayout<AudioStreamBasicDescription>.stride) var audioFileID: AudioFileID? // open the recorded file try osStatus { AudioFileOpenURL(fileURL as CFURL, AudioFilePermissions.readPermission, 0, &audioFileID) } playbackFile = audioFileID // get the full audio data format from the file try osStatus { AudioFileGetProperty(playbackFile!, kAudioFilePropertyDataFormat, &formatSize, &format) } try osStatus { AudioQueueNewOutput(&format, callback, pointer, nil, nil, 0, &queue) } var bufferByteSize = UInt32() try deriveBufferByteSize(with: playbackFile!, format: format, duration: 0.5, outBufferByteSize: &bufferByteSize, outNumPackets: &numPacketsToRead) let isFormatVBR = format.mBytesPerPacket == 0 || format.mFramesPerPacket == 0 if isFormatVBR { packetDesc = AudioStreamPacketDescription(mStartOffset: 0, mVariableFramesInPacket: numPacketsToRead, mDataByteSize: UInt32(MemoryLayout<AudioStreamPacketDescription>.stride)) // this may fail i dunno } // we don't provide packet descriptions for constant bit rate formats (like linear PCM) packetDesc = AudioStreamPacketDescription() try copyEncoderCookieToQueue(with: playbackFile!, queue: &queue!) var bufferRef: AudioQueueBufferRef? isDone = false packetPosition = 0 for _ in 0..<3 { try osStatus { AudioQueueAllocateBuffer(queue!, bufferByteSize, &bufferRef) } guard let buffer = bufferRef else { print("couldn't get buffer"); return } callback(pointer, queue!, buffer) if isDone { break } } } func start() throws { try osStatus { AudioQueueStart(queue!, nil) } repeat { CFRunLoopRunInMode(CFRunLoopMode.defaultMode, 0.25, false) } while !isDone CFRunLoopRunInMode(CFRunLoopMode.defaultMode, 2, false) isDone = true AudioQueueStop(queue!, true) //clean up AudioQueueDispose(queue!, true) AudioFileClose(playbackFile!) } // we only use time here as a guideline // we're really trying to get somewhere between 16K and 64K buffers, but not allocate too much if we don't need it private func deriveBufferByteSize(with file: AudioFileID, format: AudioStreamBasicDescription, duration: Double, outBufferByteSize: inout UInt32, outNumPackets: inout UInt32) throws { // we need to calculate how many packets we read at a time, and how big a buffer we need. // we base this on the size of the packets in the file and an approximate duration for each buffer. // // first check to see what the max size of a packet is, if it is bigger than our default // allocation size, that needs to become larger var maxPacketSize: UInt32 = 0 var propertySize = UInt32(MemoryLayout<UInt32>.size(ofValue: maxPacketSize)) try osStatus { AudioFileGetProperty(file, kAudioFilePropertyPacketSizeUpperBound, &propertySize, &maxPacketSize) } let maxBufferSize: Int = 0x10000 let minBufferSize: Int = 0x4000 let uMaxBufferSize = UInt32(maxBufferSize) let uMinBufferSize = UInt32(minBufferSize) if format.mFramesPerPacket == 0 { let numPacketesForTime = format.mSampleRate / Double(format.mFramesPerPacket) * duration outBufferByteSize = UInt32(numPacketesForTime) * maxPacketSize } else { // if frames per packet is zero, then the codec has no predictable packet == time // so we can't tailor this (we don't know how many Packets represent a time period // we'll just return a default buffer size outBufferByteSize = uMaxBufferSize > maxPacketSize ? uMaxBufferSize : maxPacketSize } // limit the size to our default if outBufferByteSize > uMaxBufferSize && outBufferByteSize > maxPacketSize { outBufferByteSize = uMaxBufferSize } // make sure it doesnt get too small - we dont want to save small chunks to disk else if outBufferByteSize < uMinBufferSize { outBufferByteSize = uMinBufferSize } outNumPackets = outBufferByteSize / maxPacketSize } private func copyEncoderCookieToQueue(with file: AudioFileID, queue: inout AudioQueueRef) throws { var propertySize = UInt32() try osStatus { AudioFileGetPropertyInfo(file, kAudioFilePropertyMagicCookieData, &propertySize, nil) } if propertySize > 0 { var magicCookie = UInt8(MemoryLayout<UInt8>.size(ofValue: UInt8(propertySize))) try osStatus { AudioFileGetProperty(file, kAudioFilePropertyMagicCookieData, &propertySize, &magicCookie) } try osStatus { AudioQueueSetProperty(queue, kAudioQueueProperty_MagicCookie, &magicCookie, propertySize) } } } }
我认为问题在于你试图读取0字节的数据包数据 – numBytes
实际上是input和输出。
尝试设置它
var numBytes = buffer.mAudioDataBytesCapacity