我在Swift中有一个桥接函数,在C中其参数之一是AudioBufferList *。在Swift中,这会生成一个UnsafePointer<AudioBufferList>。我设法通过调用来尊重指针audioData[0](有更好的方法吗?)。但是,我在接下来的2层中苦苦挣扎:的.mBuffers数组AudioBuffer及其void */ UnsafePointer<()> .mData成员。
AudioBufferList *
UnsafePointer<AudioBufferList>
audioData[0]
.mBuffers
AudioBuffer
void *
UnsafePointer<()>
.mData
在C语言中
Float32 *audioData = (Float 32*)abl->mBuffers[0]->mData; output = audioData[sampleNum]...
在Swift中,第一个奇怪的事情是它不允许我访问的元素,mBuffers但是当我将其作为属性访问时非常高兴。换句话说,这有效并且甚至具有正确的数据(对于mBuffers我的第一位成员来说)…
mBuffers
println(abl[0].mBuffers.mNumberChannels) // But .mBuffers should be an []!
其次,让我打印.mData下标,但值始终是()
()
println(abl[0].mBuffers.mData[10]) // Prints '()'
我尝试了各种类型的演员操作并使用多个索引进行访问,但无济于事……有什么主意吗?
下面是C和斯威夫特的定义AudioBufferList,并AudioBuffer为了方便…
AudioBufferList
// C struct AudioBufferList { UInt32 mNumberBuffers; AudioBuffer mBuffers[1]; // this is a variable length array of mNumberBuffers elements // ...and a bit more for c++ } struct AudioBuffer { UInt32 mNumberChannels; UInt32 mDataByteSize; void* mData; };
…
// SWIFT struct AudioBufferList { var mNumberBuffers: UInt32 var mBuffers: (AudioBuffer) } struct AudioBuffer { var mNumberChannels: UInt32 var mDataByteSize: UInt32 var mData: UnsafePointer<()> }
编辑: 亚当·里特瑙尔的答案可能是现在最好的答案。要对此进行扩展,您可以查看iOS 8.3核心音频更改中的新实用程序功能/类型。
UnsafeMutableAudioBufferListPointer 可用于读取/访问某些给定数据:
UnsafeMutableAudioBufferListPointer
struct UnsafeMutableAudioBufferListPointer { init(_ p: UnsafeMutablePointer<AudioBufferList>) var count: Int subscript (index: Int) -> AudioBuffer { get nonmutating set } }
您可以使用AudioBuffer和AudioBufferList上的扩展来分配自己的扩展名:
extension AudioBufferList { static func sizeInBytes(maximumBuffers maximumBuffers: Int) -> Int static func allocate(maximumBuffers maximumBuffers: Int) -> UnsafeMutableAudioBufferListPointer } extension AudioBuffer { init<Element>(_ typedBuffer: UnsafeMutableBufferPointer<Element>, numberOfChannels: Int) }
旧答案:
这有点棘手,因为AudioBufferList它实际上是一个可变大小的结构。这意味着它被声明为具有single AudioBuffer,但实际上它具有mNumberBuffers成员指定的数量。这个概念不能很好地转化为Swift,这就是为什么您看到了var mBuffers: (AudioBuffer)。
mNumberBuffers
var mBuffers: (AudioBuffer)
因此,访问这些缓冲区及其数据的规范方法是使用UnsafeArray。下面的代码提供了一些想法,但是UnsafePointer并UnsafeArray没有得到很好的记录,因此这可能是错误的。
UnsafeArray
UnsafePointer
// ***WARNING: UNTESTED CODE AHEAD*** let foo: UnsafePointer<AudioBufferList> // from elsewhere... // This looks intuitive, but accessing `foo.memory` may be doing a copy. let bufs = UnsafeArray<AudioBuffer>(start: &foo.memory.mBuffers, length: Int(foo.memory.mNumberBuffers)) // This is another alternative that should work... let bufsStart = UnsafePointer<AudioBuffer>(UnsafePointer<UInt32>(foo) + 1) // Offset to mBuffers member let bufs = UnsafeArray<AudioBuffer>(start: bufsStart, length: Int(foo.memory.mNumberBuffers)) // Hopefully this isn't doing a copy, but it shouldn't be too much of a problem anyway. let buf: AudioBuffer = bufs[0] // or you could use a for loop over bufs, etc. typealias MySample = Float32 let numSamples = Int(buf.mDataByteSize / UInt32(sizeof(MySample))) let samples = UnsafeArray<MySample>(start: UnsafePointer<MySample>(buf.mData), length: numSamples) // Now use the samples array...
这似乎在操场上可行,但对我来说很难测试真实的音频数据。特别是,我不确定100%start: &foo.memory.mBuffers会按预期使用。(尽管数据似乎存在,但它返回的指针与原始指针不同。)试一下并报告!
start: &foo.memory.mBuffers
编辑:顺便调试一下,您可以例如:
(lldb) p foo (UnsafePointer<AudioBufferList>) $R1 = (value = Builtin.RawPointer = 0x0000000100700740) (lldb) expr -lc -- ((int*)0x0000000100700740)[0] (int) $2 = 42 (lldb) expr -lc -- ((int*)0x0000000100700740)[1] (int) $3 = 43 ...