简体   繁体   中英

Optional value nil found after using AudioFileGetProperty() with kAudioFilePropertyDataFormat

I'm trying to use swift AudioToolbox API to playback an audio file. However, when I get the AudioStreamBasicDescription using AudioFileGetProperty() the app crashes when I try to unwrap the value, saying "Unexpectedly found nil while unwrapping an optional value". This makes no sense because:

1) The OSStatus after I call AudioFileGetProperty() is zero. 2) I can see that the value is "nil" at first in the console, but after calling AudioFileGetProperty() it changes to "Some" and suddenly it is populated with values.

Perhaps am I using pointers incorrectly? Am I using optionals incorrectly?

 func playAudioFileWithToolbox(){
        var aqData = AQPlayerState()
        let url2 = bundle.path(forResource: "dave_speaking", ofType: "m4a")!
        var filePathArray = Array(url2.utf8)
        let audioFileUrl = CFURLCreateFromFileSystemRepresentation(nil, &filePathArray, filePathArray.count, false)
        //Problem: how do we pass aqData.mAudioFile? Initially it is nil
        //We are supposed to pass by reference
        let status = AudioFileOpenURL(audioFileUrl!, permissions, 0, &(aqData.mAudioFile))

        var dataFormatSize:UInt32 = UInt32(MemoryLayout<AudioStreamBasicDescription>.size)

//Here I populate aqData.mDataFormat
        var propertyStatus = AudioFileGetProperty(aqData.mAudioFile!, kAudioFilePropertyDataFormat, &dataFormatSize, &(aqData.mDataFormat))


//Next line crashes saying that it is unwrapping an optional value
        var audioStreamDescription = aqData.mDataFormat! 
}
struct AQPlayerState{
    var mDataFormat:AudioStreamBasicDescription?
    var mQueue:AudioQueueRef?
    var mBuffers:AudioQueueBufferRef?
    var mAudioFile: AudioFileID?
    var bufferByteSize:UInt32 = 0
    var mCurrentPacket:Int64 = 0
    var mNumPacketsToRead:UInt32 = 0
    var mPacketDescs : UnsafeMutablePointer<AudioStreamPacketDescription>?
    var mIsRunning : Bool = false
    init(){

    }
}

So I figured out I was using a combination of pointers and optional values incorrectly. Because mDataFormat was by itself an optional:

var mDataFormat:AudioStreamBasicDescription?

passing a reference to it didn't make much sense, ie, &mDataFormat.

Therefore I changed this variable to make it non-optional:

var mDataFormat:AudioStreamBasicDescription = AudioStreamBasicDescription()

That way, there was memory allocated to it, as well as an address, and it now made sense to do something like this:

&aqData.mDataFormat

var propertyStatus = AudioFileGetProperty(aqData.mAudioFile!, kAudioFilePropertyDataFormat, &dataFormatSize, &aqData.mDataFormat)

Anyway I am still learning how to combine optionals with pointers so any additional feedback you can give me would help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM