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.