调用 AudioObjectGetPropertyData 之前的 UnsafeMutableAudioBufferListPointer 分配
UnsafeMutableAudioBufferListPointer allocation before calling AudioObjectGetPropertyData
我一直在尝试使用来自 swift 的 Apple CoreAudio。
我找到了许多关于如何枚举设备上的流和频道的示例。
但是,在调用 UnsafeMutablePointer<AudioBufferList>.allocate()
.
时,它们似乎都使用了不正确的大小
他们首先请求属性数据大小,即returns字节数。
然后他们使用这个字节数来分配那个大小的(不安全的)AudioBufferList
(使用字节数作为列表的大小!)。
请看下面我的评论:
var address = AudioObjectPropertyAddress(
mSelector:AudioObjectPropertySelector(kAudioDevicePropertyStreamConfiguration),
mScope:AudioObjectPropertyScope(kAudioDevicePropertyScopeInput),
mElement:0)
var propsize = UInt32(0);
var result:OSStatus = AudioObjectGetPropertyDataSize(self.id, &address, 0, nil, &propsize);
if (result != 0) {
return false;
}
// ABOVE: propsize is set to number of bytes that property data contains, typical number are 8 (no streams), 24 (1 stream, 2 interleaved channels)
// BELOW: propsize is used for AudioBufferList capacity (in number of buffers!)
let bufferList = UnsafeMutablePointer<AudioBufferList>.allocate(capacity:Int(propsize))
result = AudioObjectGetPropertyData(self.id, &address, 0, nil, &propsize, bufferList);
if (result != 0) {
return false
}
let buffers = UnsafeMutableAudioBufferListPointer(bufferList)
for bufferNum in 0..<buffers.count {
if buffers[bufferNum].mNumberChannels > 0 {
return true
}
}
这一直有效,因为它分配的内存比 UnsafeMutablePointer<AudioBufferList>
所需的多得多,但这显然是错误的。
我一直在寻找一种方法来根据 AudioObjectGetPropertyDataSize()
返回的字节数正确分配 UnsafeMutablePointer<AudioBufferList>
,但一整天都找不到任何东西。请帮助 ;)
根据 AudioObjectGetPropertyDataSize()
[=15 返回的字节数正确分配 UnsafeMutablePointer<AudioBufferList>
=]
您不应分配 UnsafeMutablePointer<AudioBufferList>
,而应分配确切大小的原始字节并将其转换为 UnsafeMutablePointer<AudioBufferList>
。
像这样的东西:
let propData = UnsafeMutableRawPointer.allocate(byteCount: Int(propsize), alignment: MemoryLayout<AudioBufferList>.alignment)
result = AudioObjectGetPropertyData(self.id, &address, 0, nil, &propsize, propData);
if (result != 0) {
return false
}
let bufferList = propData.assumingMemoryBound(to: AudioBufferList.self)
我完全同意使用 UnsafeMutableRawPointer.allocate(byteCount:alignment:)
的公认答案(尽管它也应该与调用 deallocate()
配对以获取设备流配置,但只是想分享另一个选项完整性(这个问题不应该被投票)
如果你确实需要根据字节数计算缓冲区的数量(我不确定是否真的有这样的需要),可以做到。
第一次将代码转换为 Swift 时,我使用了类似的东西:
let numBuffers = (Int(propsize) - MemoryLayout<AudioBufferList>.offset(of: \AudioBufferList.mBuffers)!) / MemoryLayout<AudioBuffer>.size
if numBuffers == 0 { // Avoid trying to allocate zero buffers
return false
}
let bufferList = AudioBufferList.allocate(maximumBuffers: numBuffers)
defer { bufferList.unsafeMutablePointer.deallocate() }
err = AudioObjectGetPropertyData(id, &address, 0, nil, &propsize, bufferList.unsafeMutablePointer)
同样,我实际上并不推荐这种方法来获取流配置 - IMO 不必要地复杂,并且我已经采用了类似于公认答案的方法。因此,除了作为学术练习外,这可能没有任何价值。
我一直在尝试使用来自 swift 的 Apple CoreAudio。
我找到了许多关于如何枚举设备上的流和频道的示例。
但是,在调用 UnsafeMutablePointer<AudioBufferList>.allocate()
.
他们首先请求属性数据大小,即returns字节数。
然后他们使用这个字节数来分配那个大小的(不安全的)AudioBufferList
(使用字节数作为列表的大小!)。
请看下面我的评论:
var address = AudioObjectPropertyAddress(
mSelector:AudioObjectPropertySelector(kAudioDevicePropertyStreamConfiguration),
mScope:AudioObjectPropertyScope(kAudioDevicePropertyScopeInput),
mElement:0)
var propsize = UInt32(0);
var result:OSStatus = AudioObjectGetPropertyDataSize(self.id, &address, 0, nil, &propsize);
if (result != 0) {
return false;
}
// ABOVE: propsize is set to number of bytes that property data contains, typical number are 8 (no streams), 24 (1 stream, 2 interleaved channels)
// BELOW: propsize is used for AudioBufferList capacity (in number of buffers!)
let bufferList = UnsafeMutablePointer<AudioBufferList>.allocate(capacity:Int(propsize))
result = AudioObjectGetPropertyData(self.id, &address, 0, nil, &propsize, bufferList);
if (result != 0) {
return false
}
let buffers = UnsafeMutableAudioBufferListPointer(bufferList)
for bufferNum in 0..<buffers.count {
if buffers[bufferNum].mNumberChannels > 0 {
return true
}
}
这一直有效,因为它分配的内存比 UnsafeMutablePointer<AudioBufferList>
所需的多得多,但这显然是错误的。
我一直在寻找一种方法来根据 AudioObjectGetPropertyDataSize()
返回的字节数正确分配 UnsafeMutablePointer<AudioBufferList>
,但一整天都找不到任何东西。请帮助 ;)
根据 AudioObjectGetPropertyDataSize()
[=15 返回的字节数正确分配 UnsafeMutablePointer<AudioBufferList>
=]
您不应分配 UnsafeMutablePointer<AudioBufferList>
,而应分配确切大小的原始字节并将其转换为 UnsafeMutablePointer<AudioBufferList>
。
像这样的东西:
let propData = UnsafeMutableRawPointer.allocate(byteCount: Int(propsize), alignment: MemoryLayout<AudioBufferList>.alignment)
result = AudioObjectGetPropertyData(self.id, &address, 0, nil, &propsize, propData);
if (result != 0) {
return false
}
let bufferList = propData.assumingMemoryBound(to: AudioBufferList.self)
我完全同意使用 UnsafeMutableRawPointer.allocate(byteCount:alignment:)
的公认答案(尽管它也应该与调用 deallocate()
配对以获取设备流配置,但只是想分享另一个选项完整性(这个问题不应该被投票)
如果你确实需要根据字节数计算缓冲区的数量(我不确定是否真的有这样的需要),可以做到。
第一次将代码转换为 Swift 时,我使用了类似的东西:
let numBuffers = (Int(propsize) - MemoryLayout<AudioBufferList>.offset(of: \AudioBufferList.mBuffers)!) / MemoryLayout<AudioBuffer>.size
if numBuffers == 0 { // Avoid trying to allocate zero buffers
return false
}
let bufferList = AudioBufferList.allocate(maximumBuffers: numBuffers)
defer { bufferList.unsafeMutablePointer.deallocate() }
err = AudioObjectGetPropertyData(id, &address, 0, nil, &propsize, bufferList.unsafeMutablePointer)
同样,我实际上并不推荐这种方法来获取流配置 - IMO 不必要地复杂,并且我已经采用了类似于公认答案的方法。因此,除了作为学术练习外,这可能没有任何价值。