I just want to get a list of the markers in an audio file. I thought this would be an easy common task that wouldn't be too difficult. However, I can barely find any example code or documentation, so I ended up with this:
private func getMarkers(_ url: CFURL) -> AudioFileMarkerList {
var file: AudioFileID?
var size: UInt32 = 0
var markers = AudioFileMarkerList()
AudioFileOpenURL(url, .readPermission, kAudioFileWAVEType, &file)
AudioFileGetPropertyInfo(file!, kAudioFilePropertyMarkerList, &size, nil)
AudioFileGetProperty(file!, kAudioFilePropertyMarkerList, &size, &markers)
return markers
}
Sadly, this doesn't work: error: memory read failed for 0x0
.
I just can't figure out the problem. I checked the url and the size (which are both valid), but it always fails to retrieve the markers. Any help with this would be fantastic!
EDIT: This sort of works, but all the data is completely wrong, and I can't understand how a single audio file can have multiple AudioFileMarkerLists of markers:
private func getMarkers(_ url: CFURL) -> [AudioFileMarkerList] {
var file: AudioFileID?
var size: UInt32 = 0
AudioFileOpenURL(url, .readPermission, kAudioFileWAVEType, &file)
AudioFileGetPropertyInfo(file!, kAudioFilePropertyMarkerList, &size, nil)
let length = NumBytesToNumAudioFileMarkers(Int(size))
var markers = [AudioFileMarkerList](repeating: AudioFileMarkerList(), count: length)
AudioFileGetProperty(file!, kAudioFilePropertyMarkerList, &size, &markers)
return markers
}
EDIT 2: According to most answers I've seen so far, this should work, but it returns an empty array:
private func getMarkers(_ url: CFURL) -> [AudioFileMarkerList] {
var file: AudioFileID?
var size: UInt32 = 0
AudioFileOpenURL(url, .readPermission, kAudioFileWAVEType, &file)
AudioFileGetPropertyInfo(file!, kAudioFilePropertyMarkerList, &size, nil)
let length = NumBytesToNumAudioFileMarkers(Int(size))
var markers = [AudioFileMarkerList]()
markers.reserveCapacity(length)
AudioFileGetProperty(file!, kAudioFilePropertyMarkerList, &size, &markers)
return markers
}
EDIT 3: I got rid of a bunch of error checking and useful stuff from Ryan's code for anyone wanting to quickly try and find the problem:
private func getMarkers(_ url: CFURL) -> [AudioFileMarker]? {
var file: AudioFileID?
var size: UInt32 = 0
var markers: [AudioFileMarker] = []
AudioFileOpenURL(url, .readPermission, kAudioFileWAVEType, &file)
AudioFileGetPropertyInfo(file!, kAudioFilePropertyMarkerList, &size, nil)
let length = NumBytesToNumAudioFileMarkers(Int(size))
let data = UnsafeMutablePointer<AudioFileMarkerList>.allocate(capacity: length)
AudioFileGetProperty(file!, kAudioFilePropertyMarkerList, &size, data)
markers.append(data.pointee.mMarkers)
data.deallocate(capacity: length)
return markers
}
I just hope Apple actually tested AudioFileMarkerList in the first place.
EDIT 4: SOLVED thanks to Rhythmic Fistman and Ryan Francesconi! Final result:
private func getMarkers(_ url: CFURL) -> [AudioFileMarker]? {
var file: AudioFileID?
var size: UInt32 = 0
var markerList: [AudioFileMarker] = []
AudioFileOpenURL(url, .readPermission, kAudioFileWAVEType, &file)
AudioFileGetPropertyInfo(file!, kAudioFilePropertyMarkerList, &size, nil)
let length = NumBytesToNumAudioFileMarkers(Int(size))
let data = UnsafeMutablePointer<AudioFileMarkerList>.allocate(capacity: length)
AudioFileGetProperty(file!, kAudioFilePropertyMarkerList, &size, data)
let markers = UnsafeBufferPointer<AudioFileMarker>(start: &data.pointee.mMarkers, count: length)
for marker in markers {
markerList.append(marker)
}
data.deallocate(capacity: length)
return markerList
}