2017-06-01 3 views
2

これを自分でデバッグしようとしましたが、渡されたデータを正しく読み取るためにAudioFileReadPacketDataを取得できませんでした。これはほぼ直接Apple AudioQueueServices Guideに基づいています。AudioFileReadPacketDataは、有効なファイルが渡されたときに-50を返します。

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 

これは私が問題はあなたが0を読み取ろうとしているということだと思います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) } 
    } 
    } 
} 

答えて

1

にクラッシュ順番である-50

var code = AudioFileReadPacketData(audioPlayer.playbackFile!, false, &numBytes, &audioPlayer.packetDesc!, audioPlayer.packetPosition, &nPackets, buffer.mAudioData) 

を投げているラインでありますバイトのパケットデータ - numBytesは、実際には入力と出力の両方に使用されます。

は、それはそれだったように思えるこの

var numBytes = buffer.mAudioDataBytesCapacity 
+0

うんにそれを設定してみてください。再度、感謝します! – aBikis

+0

あなたは大歓迎です! –

関連する問題