在 Objective-C 中处理大量音频样本
Posted
技术标签:
【中文标题】在 Objective-C 中处理大量音频样本【英文标题】:Manipulating a large array of audio samples in Objective-C 【发布时间】:2012-02-11 10:14:37 【问题描述】:我在 C 语言中有一组音频样本,我在这些样本上运行低通滤波器等算法。在处理之前,我正在考虑将我的数组转换为 Objective-C。这主要是因为我更喜欢这种语言并且它很方便(尤其是能够轻松获取数组的长度而不必处理指针)。
我想知道是否有任何理由说明这可能是个坏主意。或者,如果这样做有什么我不知道的缺点。比如处理如此大量样本的速度(?)。
【问题讨论】:
【参考方案1】:标准做法是使用 c 样式数组来处理音频数组。这是因为如果您必须使用带有 obj-c 消息传递的 Objective-c 容器对象来访问每个元素,那么性能会很差,而且正如您所注意到的,带有音频的样本数量可能会非常大。
这对于实时处理尤其如此,例如处理存在于系统音频 io 回调中的音频样本,它必须在一定的毫秒数内完成这项工作,否则声音会中断。
您可以做的是定义一个结构(甚至是一个目标 c 类),该结构具有音频缓冲区数组以及诸如大小、通道数等信息元素,以便在一个位置为您将其包装在一起。这样,当您访问缓冲区时,您就不需要陷入 obj-c 效率问题,并且您仍然可以获得缓冲区规范信息。
这是一个例子:
typedef struct filter_buffer
uint16_t* buffer;
int channels;
int num_frames;
filter_buffer;
然后你只需要一个初始化它的调用。
你可以用objective-c做一些事情,比如:
@interface FilterBuffer : NSObject
uint16_t* buffer;
int channels;
int num_frames;
-initWithBuffer:(unit16_t*)buf channels:(int)c numFrames:(int)n;
...//accessors etc
@end
@implementation FilterBuffer
-initWithBuffer:(unit16_t*)buf channels:(int)c numFrames:(int)n
if ((self = [super init))
buffer = buf;
channels = c;
num_frames = n;
return self;
...
@end
【讨论】:
虽然不是实时的。你认为这仍然是一个问题吗? 它会起作用,只是明显变慢了。我会考虑在 c 缓冲区周围定义一个 obj-c 包装器,而不是使用 NSMutableArray 之类的东西来跟踪每个样本。 是否有可能获得关于它的外观的代码的 sn-p。我有点菜鸟:)。 另外,我发现这与 CFArrays 有关。也许这就是我正在寻找的答案? developer.apple.com/library/ios/#documentation/CoreFoundation/… 我发布了一个使用普通数组(缓冲区)的示例。您正在那里查看动态数组。如果它只是对非实时处理代码进行原型设计,并且您真的对 NSMutableArray 感觉更舒服,我会在 CF 对应物上使用它。您以后可以随时更改。【参考方案2】:缺点是:
速度。它会明显变慢。 它不能实时使用,objc 消息传递速度明显较慢并且可能会锁定。 它不是便携式的。 它不会与其他库很好地集成。 根据您的处理方式,它可能会产生巨大的内存影响。使用NSNumbers
的数组(例如)将需要几倍 的内存。事实上,这就是你的帖子所暗示的——NSMutableArray
的 NSNumber
s。
您将无法正确地阅读或编写音频程序。您在现实世界中看到的程序通常是 C++ 和 C。
C 数组不是可怕的东西 =)
当您需要重用它时,您最终可能只是重写它,因为在大多数情况下,它是不适合这项工作的工具。
【讨论】:
【参考方案3】:由于性能原因,在内部循环中使用 Objective C 对象的 DSP 是不好的。出于这个原因,除其他外,您会发现大多数音频过滤器和 DSP 算法以纯 C、可能是 C++ 或类似的伪代码发布。所以你可能不得不习惯于阅读纯 C DSP 代码。
此外,C 是 Objective C 的真子集。
【讨论】:
以上是关于在 Objective-C 中处理大量音频样本的主要内容,如果未能解决你的问题,请参考以下文章