当前位置: 首页 > 面试题库 >

在Swift中使用AudioBufferList

荆钱明
2023-03-14
问题内容

我在Swift中有一个桥接函数,在C中其参数之一是AudioBufferList *。在Swift中,这会生成一个UnsafePointer<AudioBufferList>。我设法通过调用来尊重指针audioData[0](有更好的方法吗?)。但是,我在接下来的2层中苦苦挣扎:的.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 '()'

我尝试了各种类型的演员操作并使用多个索引进行访问,但无济于事……有什么主意吗?

下面是C和斯威夫特的定义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;
};

// SWIFT

struct AudioBufferList {
    var mNumberBuffers: UInt32
    var mBuffers: (AudioBuffer)
}

struct AudioBuffer {
    var mNumberChannels: UInt32
    var mDataByteSize: UInt32
    var mData: UnsafePointer<()>
}

问题答案:

编辑: 亚当·里特瑙尔的答案可能是现在最好的答案。要对此进行扩展,您可以查看iOS
8.3核心音频更改
中的新实用程序功能/类型。

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)

因此,访问这些缓冲区及其数据的规范方法是使用UnsafeArray。下面的代码提供了一些想法,但是UnsafePointerUnsafeArray没有得到很好的记录,因此这可能是错误的。

// ***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
...


 类似资料:
  • 问题内容: 我想在Swift 3.0中使用生成随机字节。这是我在Swift 2.2中所做的 在Swift 3中,我尝试这样做,因为我知道unsafemutablebytes的概念现在有所不同,但是它不允许我返回。如果我评论退货部分,它仍然会说 有谁知道如何解决这一问题? 谢谢 问题答案: 您已经关闭了,但是内部的封闭是从封闭而不是外部函数返回的。因此,仅应在闭包中调用该方法,并将结果传递回去。 对

  • 问题内容: 我正在尝试在Swift / Xcode6中使用UITextFieldDelegate,并且正在为应该使用stringByReplacingCharactersInRange的方式而苦苦挣扎。编译器错误为“无法将表达式的类型“字符串”转换为类型“ $ T8”。 Xcode 6 Beta 5的更新:问题是shouldChangeCharactersInRange提供了一个NSRange对象

  • 问题内容: 我正在尝试学习一些Swift lang,并且想知道如何将以下Objective-C转换为Swift: 更具体地说,我需要知道如何在新语法中使用。 问题答案: 正确的Swift运算符是: 当然,如果您还需要将视图分配给新的常量,那么语法就是您的孩子,就像Kevin提到的那样。但是,如果您不需要该值而只需要检查类型,则应使用运算符。

  • 问题内容: 在这种情况下,永远不会调用timerFunc()。我想念什么? 问题答案: 您可以创建一个计划的计时器,该计时器自动将其自身添加到运行循环并开始触发: 迅捷2 斯威夫特3,4,5 或者,您可以保留当前代码,并在准备就绪时将计时器添加到runloop中: 迅捷2 斯威夫特3,4,5

  • 如果你的应用与 Web 应用通信,从服务器返回的信息经常是 JSON 格式。你可以使用 Foundation 框架里的 JSONSerialization 类来转换 JSON 为 Swift 的数据类型,比如 Dictionary 、 Array 、 String 以及 Bool 。总之,由于你不能确定应用接收的 JSON 的结构体或者值,可以通过挑战来正确地反序列化模型对象。这篇文章描述了几种你

  • 问题内容: 在我的xcode项目中添加OpenCV 2框架后,我尝试搜索samlpes或与swift集成的教程。 有没有很好的教程呢? 问题答案: OpenCV是用C ++编写的框架。苹果的参考资料告诉我们 您不能将C 代码直接导入Swift。而是为C 代码创建一个Objective-C或C包装器。 因此,您不能直接在一个快速的项目中导入和使用OpenCV,但这实际上一点都不好,因为您(需要)继续