Swift:从url中检索音频文件标记列表?

Mys*_*ake 10 audiotoolbox ios swift

我只想获得音频文件中的标记列表.我认为这将是一项不太难的简单的共同任务.但是,我几乎找不到任何示例代码或文档,所以我最终得到了这个:

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
}
Run Code Online (Sandbox Code Playgroud)

可悲的是,这不起作用:error: memory read failed for 0x0.

我只是想不通问题.我检查了网址和大小(两者都有效),但总是无法检索标记.任何帮助都会很棒!

编辑: 这种工作,但所有的数据是完全错误的,我无法理解单个音频文件如何有多个标记的AudioFileMarkerLists:

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
}
Run Code Online (Sandbox Code Playgroud)

编辑2:根据我到目前为止看到的大多数答案,这应该工作,但它返回一个空数组:

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

}
Run Code Online (Sandbox Code Playgroud)

编辑3: 我从Ryan的代码中删除了一堆错误检查和有用的东西,以便任何想要快速尝试找到问题的人:

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
}
Run Code Online (Sandbox Code Playgroud)

我只是希望Apple首先测试AudioFileMarkerList.

编辑4: 得益于Rhythmic Fistman和Ryan Francesconi!最后结果:

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
}
Run Code Online (Sandbox Code Playgroud)

Rhy*_*man 3

看起来您需要使用UnsafeBufferPointer来访问可变长度数组(如mMarkers)。所以而不是

out.append(markerList.mMarkers)
Run Code Online (Sandbox Code Playgroud)

只添加第一个元素,执行此操作

let markersBuffer = UnsafeBufferPointer<AudioFileMarker>(start: &data.pointee.mMarkers,
                                               count: Int(data.pointee.mNumberMarkers))

for marker in markersBuffer {
    markers.append(marker)
}
Run Code Online (Sandbox Code Playgroud)

以这个答案为蓝本