【问题标题】:high performance buffers in objective-cObjective-c 中的高性能缓冲区
【发布时间】:2013-05-03 10:11:57
【问题描述】:

我想知道对于 Objective-c 中的音频数据,最适用的缓冲区实现类型是什么。我在 iPhone 上处理音频数据,我在录制或播放时对音频数据进行一些直接的数据操作/DSP,因此性能很重要。几个月以来我一直在做 iPhone 开发。目前我正在处理元素类型为 SInt16 或 Float32 的 c 数组,但我正在寻找更好的东西。

AFAIK,指针迭代 c 数组的性能在 Objective-c 环境中是无与伦比的。但是,指针算术和 c 数组很容易出错。您始终必须确保您不会越界访问数组。如果这样做,您不会立即收到运行时错误。而且您必须手动确保正确分配和释放数组。

因此,我正在寻找替代方案。有哪些高性能替代品? Objective-c 中有什么类似于 c++ 风格的 std::vector 的吗?

类似的意思是:

  • 性能不错
    • 可通过基于指针/迭代器的循环进行迭代
    • 没有将 Float32 或 SInt16 等基本数据类型装箱/拆箱到 Objective-c 对象的开销(顺便说一句,objective-c 中“基本数据类型”的正确词是什么?)
  • 边界检查
  • 可以在我的搜索列表实现中复制/读取/写入其他列表或数组的块
  • 包括内存管理

我已经搜索并阅读了很多内容,当然NSDataNSMutableArray 是上述解决方案之一。但是,由于基本数据类型的装箱/拆箱开销,它们不会使处理成本加倍吗?代码看起来非常丑陋,就像一个简单的“设置”操作变成了一些名为replaceObjectAtIndex:withObject: 的恐龙,这不是我关心的问题,但它仍然让我觉得这个类不是为我设计的。

【问题讨论】:

  • std::vector 有什么问题?您可以在 iOS 上使用 C++ 代码。此外,您提到的所有事情都会导致开销。此外,所有 Core Audio API 都适用于 C 数组。
  • 是的,如果你想要 std::vector,只需将你的实现文件重命名为 .mm 并继续前进。
  • 事实上,据我所知,几乎所有从事 iOS 音频开发(事实上,几乎所有其他平台上的音频开发)的人也都使用 C++。这包括几乎所有 Apple 的示例应用程序。
  • 另外,不要刻薄和无用,但 C 数组和指针算法不容易出错——程序员是。无论使用何种数据结构,程序员始终有责任“把事情做好”。
  • 使用std::vector 的明显警告是operator[] 没有检查边界,但速度很快。你会想要使用at() 方法。

标签: ios objective-c audio collections buffer


【解决方案1】:

NSMutableData 符合您的要求之一,因为它将 Objective-C 内存管理语义引入了普通 C 缓冲区。你可以这样做:

NSMutableData* data = [NSMutableData dataWithLength: sizeof(Float32) * numberOfFloats];
Float32* cFloatArray = (Float32*)[data mutableBytes];

然后您可以将cFloatArray 视为标准C 数组并使用指针迭代。当NSMutableData 对象被释放时,支持它的内存将被释放。它不提供边界检查,但它提供内存管理帮助,同时保持 C 数组的性能。

此外,如果您想从工具中获得一些帮助来解决边界检查问题,请阅读 Xcode 的 Malloc Scribble、Malloc Guard Edges 和 Guard Malloc 选项。这些将使运行时更加对边界问题更加敏感。在生产中没有用,但有助于解决开发过程中的问题。

【讨论】:

    【解决方案2】:

    Foundation 框架中提供的容器几乎没有提供音频处理功能,总体而言相当重量级,也不提供外部迭代器。

    此外,iOS 或 MacOSX 中与样本缓冲区交互的音频 API 都不是基于 Objective-C 的,也不是采用 Foundation 框架容器的任何参数。

    您很可能希望将 Accelerate Framework 用于 DSP 操作,其 API 均适用于 floats 或 int16s 的数组。

    虽然所有的 API 都是 C 风格的,但 C++ 和 STL 显然是满足您需求的首选武器,并且以 Objective-C++ 的名义与应用程序的其余部分完美交互。 STL 经常编译成与手工 C 语言一样高效的代码。

    要对缓冲区进行内存管理,也许可以使用std::array - 如果你想要边界检查或std::shared_ptrstd::unique_ptr,如果你不担心的话,可以使用自定义删除器。

    需要iterator 的地方——例如<algorithm> 中的算法函数——通常也可以使用指向基本类型的指针——比如你的样本缓冲区。

    【讨论】:

      猜你喜欢
      • 2014-03-18
      • 1970-01-01
      • 2020-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多