我在Swift中有一个桥接函数,其中一个参数在C中是AudioBufferList *
。在Swift中,这会生成UnsafePointer<AudioBufferList>
。我设法通过调用audioData[0]
来指导指针(有更好的方法吗?)。但是我在接下来的两个层次中挣扎:.mBuffers
AudioBuffer
数组及其void *
/ UnsafePointer<()>
.mData
成员。
在C中它只是
Float32 *audioData = (Float 32*)abl->mBuffers[0]->mData;
output = audioData[sampleNum]...
在Swift中,第一个奇怪的事情是它不允许我访问mBuffers
的元素,但是当我作为属性访问它时非常高兴。换句话说,这有效,甚至有正确的数据(我认为mBuffers
的第一个成员)......
println(abl[0].mBuffers.mNumberChannels) // But .mBuffers should be an []!
其次,它让我打印出.mData
下标,但值始终为()
println(abl[0].mBuffers.mData[10]) // Prints '()'
我已经尝试了各种投射操作并使用多个索引进行访问,但无济于事......有什么想法吗?
为方便起见,以下是AudioBufferList
和AudioBuffer
的C和Swift定义...
// 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<()>
}
答案 0 :(得分:19)
我偶然发现了这个。奇怪的是,当它提出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
}
答案 1 :(得分:11)
编辑:Adam Ritenauer的答案可能是现在最好的答案。要对其进行扩展,您可以在the iOS 8.3 Core Audio changes中查看新的实用程序函数/类型。
UnsafeMutableAudioBufferListPointer
可用于读取/访问某些给定数据:
struct UnsafeMutableAudioBufferListPointer {
init(_ p: UnsafeMutablePointer<AudioBufferList>)
var count: Int
subscript (index: Int) -> AudioBuffer { get nonmutating set }
}
你可以在AudioBuffer&amp; amp; 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
实际上是一个可变大小的结构。这意味着它被声明为具有单个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...
这似乎适用于游乐场,但我很难测试真实的音频数据。特别是,我并非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
...
答案 2 :(得分:1)
我发现这个工作正常。 abl
是通过加载16位AIFF音频文件创建的AudioBufferList。
let mBuffers=abl.memory.mBuffers
let data=UnsafePointer<Int16>(mBuffers.mData)
let dataArray=UnsafeBufferPointer<Int16>(start:data, count: Int(mBuffers.mDataByteSize)/sizeof(Int16))
//checking resulting array
let count=dataArray.count //this matches the expected number of samples in my case
for i in 0..<count
{
print(dataArray[i]) //values look OK in my case
print(" ")
}
答案 3 :(得分:1)
这适用于Swift 1.2
var ddata: NSData
buf = AudioBuffer(mNumberChannels: 1, mDataByteSize: numberOfFrames * UInt32(sizeof(Float32)), mData: &ddata)
var audioBuffers = AudioBufferList(mNumberBuffers: 1, mBuffers: buf!)