Har*_*ngh 16 pointers casting objective-c ios swift
我在Swift中有一个桥接函数,其中一个参数在C中AudioBufferList *.在Swift中,这会生成一个UnsafePointer<AudioBufferList>.我设法通过调用来引用指针audioData[0](有更好的方法吗?).但我正在努力接下来的两个层次:他们和他们/ 成员的.mBuffers阵列. AudioBuffervoid *UnsafePointer<()> .mData
在C中它就是这样
Float32 *audioData = (Float 32*)abl->mBuffers[0]->mData;
output = audioData[sampleNum]...
Run Code Online (Sandbox Code Playgroud)
在Swift中,第一个奇怪的事情是它不会让我访问元素,mBuffers但是当我作为属性访问它时非常高兴.换句话说,这工作,甚至有正确的数据(对于mBuffers我认为的第一个成员)...
println(abl[0].mBuffers.mNumberChannels) // But .mBuffers should be an []!
Run Code Online (Sandbox Code Playgroud)
其次,让我打印出.mData下标,但价值总是如此()
println(abl[0].mBuffers.mData[10]) // Prints '()'
Run Code Online (Sandbox Code Playgroud)
我已经尝试了各种铸造操作和访问多个索引但无济于事......任何想法?
以下是C和Swift定义AudioBufferList,AudioBuffer为方便起见......
// 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;
};
Run Code Online (Sandbox Code Playgroud)
...
// SWIFT
struct AudioBufferList {
var mNumberBuffers: UInt32
var mBuffers: (AudioBuffer)
}
struct AudioBuffer {
var mNumberChannels: UInt32
var mDataByteSize: UInt32
var mData: UnsafePointer<()>
}
Run Code Online (Sandbox Code Playgroud)
Ada*_*uer 20
我偶然发现了这个.奇怪的是,当它提出UnsafeMutableAudioBufferListPointer时,前面的类型实际上正在使用Swift.您可以使用UnsafeMutablePointer参数进行初始化.此类型是MutableCollectionType,并提供对包含的音频缓冲区的下标和生成器访问.
例如,您可以使用以下代码将ABL设置为静音
func renderCallback(ioData: UnsafeMutablePointer<AudioBufferList>) -> OSStatus {
let abl = UnsafeMutableAudioBufferListPointer(ioData)
for buffer in abl {
memset(buffer.mData, 0, Int(buffer.mDataByteSize))
}
return noErr
}
Run Code Online (Sandbox Code Playgroud)
jtb*_*des 10
编辑: Adam Ritenauer的答案可能是现在最好的答案.要对其进行扩展,您可以查看iOS 8.3 Core Audio更改中的新实用程序功能/类型.
UnsafeMutableAudioBufferListPointer 可用于读取/访问某些给定数据:
struct UnsafeMutableAudioBufferListPointer {
init(_ p: UnsafeMutablePointer<AudioBufferList>)
var count: Int
subscript (index: Int) -> AudioBuffer { get nonmutating set }
}
Run Code Online (Sandbox Code Playgroud)
你可以使用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)
}
Run Code Online (Sandbox Code Playgroud)
老答案:
这有点棘手,因为AudioBufferList它实际上是一个可变大小的结构.这意味着它被声明为具有单个AudioBuffer,但实际上它具有该mNumberBuffers成员指定的数量.这个概念并不能很好地转化为Swift,这就是你看到的原因var mBuffers: (AudioBuffer).
因此,访问这些缓冲区及其数据的规范方法将使用UnsafeArray.下面的代码提供了一些想法,但UnsafePointer并UnsafeArray没有得到很好的记录,所以这可能是错误的.
// ***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...
Run Code Online (Sandbox Code Playgroud)
这似乎在操场上有效,但我很难测试真实的音频数据.特别是,我不是100%确定使用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
...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6933 次 |
| 最近记录: |