我想知道是否有人有编写HAL AudioUnit渲染回调的经验,利用多核处理器和/或对称多处理的好处?
我的方案如下:
子类型kAudioUnitSubType_HALOutput的单个音频组件(及其呈现回调)负责附加合成n个独立、个别变化和实时更新的幅值和相位值的正弦波部分。它本身是一个相当直截了当的蛮力嵌套循环方法(每个部分,每个帧,每个通道)。
但是,在达到"n"部分数的某个上限时,处理器会重载并开始产生丢弃,而其他三个处理器仍然处于空闲状态。
除了关于加法合成是“处理器昂贵”的一般性讨论,比如说“可波化”,我还需要知道这是否能被正确地解决,这涉及到在多处理器或多核机器上利用多处理的优势?将呈现线程分解为子线程似乎不是正确的方法,因为呈现回调本身已经是一个时间约束线程,最后的输出在延迟方面必须是样本-acurate。是否有人在解决这一问题方面有过积极的经验和有效的方法?
系统: 10.7.x
CPU:四核i7
提前谢谢你,
CA
发布于 2014-03-18 05:04:48
这很有挑战性,因为OS不是为这样的东西而设计的。只有一个音频线程--它是操作系统中优先级最高的线程,并且没有办法以这个优先级创建用户线程(更不用说得到一组系统工程师的支持,他们为性能而调优,就像音频呈现线程一样)。我并不声称理解您的算法的细节,但是如果有可能将其分解成一些任务可以在较大的样本块上并行执行(允许吸收偶尔出现的线程饥饿期),那么您当然可以生成其他并行处理的高优先级线程。您需要使用某种无锁的数据结构来在这些线程和音频线程之间交换示例。卷积混响经常这样做,以允许合理的延迟,同时仍然在巨大的块大小。我想看看这些是如何实现的..。
发布于 2014-03-18 19:17:40
你查过Accelerate.framework了吗?您应该能够通过对向量执行操作来提高效率,而不是使用嵌套的for-循环。
如果你有正弦波部分的向量(长度n),振幅值和相位值,你可以应用vDSP_vadd或vDSP_vmul运算,然后是vDSP_sve。
发布于 2014-03-20 22:01:55
很抱歉回答我自己的问题,否则我不知道如何添加一些相关信息。编辑似乎行不通,评论太短了。首先,衷心感谢jtomschroeder向我指出了Accelerate.framework。
这对于所谓的基于IFFT的重叠/添加再合成是非常有效的。然而,我还没有找到一个将我所使用的程序矢量化的钥匙,这种过程被称为“振荡器-银行再合成”,并且因其处理器征税而臭名昭著(F.R. Moore: Computer Music的元素)。每个瞬时相位和振幅必须“动态”内插,并将最后值存储到控制结构中,以便进一步插值。时间和时间的方向取决于实时输入。并非所有的部分都存在,断点的放置是任意的,而且可能是不规则的。当然,我最关心的是组织数据以尽量减少数学运算的次数.
如果有人能给我举一个积极实践的例子,我会非常感激的。
//以下是简化的代码片段:
OSStatus AdditiveRenderProc(
void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
// local variables' declaration and behaviour-setting conditional statements
// some local variables are here for debugging convenience
// {... ... ...}
// Get the time-breakpoint parameters out of the gen struct
AdditiveGenerator *gen = (AdditiveGenerator*)inRefCon;
// compute interpolated values for each partial's each frame
// {deltaf[p]... ampf[p][frame]... ...}
//here comes the brute-force "processor eater" (single channel only!)
Float32 *buf = (Float32 *)ioData->mBuffers[channel].mData;
for (UInt32 frame = 0; frame < inNumberFrames; frame++)
{
buf[frame] = 0.;
for(UInt32 p = 0; p < candidates; p++){
if(gen->partialFrequencyf[p] < NYQUISTF)
buf[frame] += sinf(phasef[p]) * ampf[p][frame];
phasef[p] += (gen->previousPartialPhaseIncrementf[p] + deltaf[p]*frame);
if (phasef[p] > TWO_PI) phasef[p] -= TWO_PI;
}
buf[frame] *= ovampf[frame];
}
for(UInt32 p = 0; p < candidates; p++){
//store the updated parameters back to the gen struct
//{... ... ...}
;
} 返回noErr;}
https://stackoverflow.com/questions/22442693
复制相似问题