【问题标题】:Distortion from output Audio Unit输出音频单元的失真
【发布时间】:2016-05-02 02:35:22
【问题描述】:

当我运行这个简单的应用程序时,我听到了非常响亮而刺耳的失真声音。我只是实例化一个默认输出单元并分配一个渲染回调。并让程序在运行循环中运行。我没有从 Core Audio 中检测到任何错误,除了这种失真之外,一切正常。

#import <AudioToolbox/AudioToolbox.h>


OSStatus render1(void *inRefCon,
                 AudioUnitRenderActionFlags *ioActionFlags,
                 const AudioTimeStamp *inTimeStamp,
                 UInt32 inBusNumber,
                 UInt32 inNumberFrames,
                 AudioBufferList * ioData)
{
   return noErr;
}

int main(int argc, const char * argv[]) {
   AudioUnit timerAU;
   UInt32 propsize = 0;       

   AudioComponentDescription outputUnitDesc;
   outputUnitDesc.componentType          = kAudioUnitType_Output;
   outputUnitDesc.componentSubType       = kAudioUnitSubType_DefaultOutput;
   outputUnitDesc.componentManufacturer  = kAudioUnitManufacturer_Apple;
   outputUnitDesc.componentFlags         = 0;
   outputUnitDesc.componentFlagsMask     = 0;

   //Get RemoteIO AU from Audio Unit Component Manager
   AudioComponent outputComp = AudioComponentFindNext(NULL, &outputUnitDesc);

   if (outputComp == NULL) exit (-1);

   CheckError(AudioComponentInstanceNew(outputComp, &timerAU), "comp");       

   //Set up render callback function for the RemoteIO AU.
   AURenderCallbackStruct renderCallbackStruct;
   renderCallbackStruct.inputProc = render1;
   renderCallbackStruct.inputProcRefCon = nil;//(__bridge void *)(self);

   propsize = sizeof(renderCallbackStruct);

   CheckError(AudioUnitSetProperty(timerAU,
                                   kAudioUnitProperty_SetRenderCallback,
                                   kAudioUnitScope_Global,
                                   0,
                                   &renderCallbackStruct,
                                   propsize), "set render");

   CheckError(AudioUnitInitialize(timerAU), "init");       

  // tickMethod = completion;

   CheckError(AudioOutputUnitStart(timerAU), "start");

   CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1000, false);

}

【问题讨论】:

  • 请善意尝试通过正确格式化您的代码,使其更具可读性...

标签: core-audio


【解决方案1】:

您的问题似乎并不完整。我不知道消除输出噪声的副作用,这可能只是未定义的行为。我也不知道您的代码将用于什么。 kAudioUnitSubType_DefaultOutput 上有一个未完成的渲染回调,它什么都不做(它没有产生静音!)。我知道有两种使它静音的方法。

在回调中,ioData 缓冲区必须显式填充零,因为不能保证它们会被初始化为空:

Float32 * lBuffer0;
Float32 * lBuffer1;
lBuffer0 = (Float32 *)ioData->mBuffers[0].mData;
lBuffer1 = (Float32 *)ioData->mBuffers[1].mData;
memset(lBuffer0,  0, inNumberFrames*sizeof(Float32));
memset(lBuffer1,  0, inNumberFrames*sizeof(Float32));

其他可能性是保留未完成的回调,但将timerAU声明为outputUnitDesc.componentSubType = kAudioUnitSubType_HALOutput;
而不是
outputUnitDesc.componentSubType = kAudioUnitSubType_DefaultOutput;
并通过以下代码在设置渲染回调之前明确禁用 I/O:

UInt32 lEnableIO = 0;
CheckError(AudioUnitSetProperty(timerAU,
                            kAudioOutputUnitProperty_EnableIO,
                            kAudioUnitScope_Output,
                            0,   //output element
                            &lEnableIO,
                            sizeof(lEnableIO)),
"couldn't disable output");

我强烈建议您深入研究 CoreAudio API 并了解如何设置音频单元。这对于理解问题至关重要。我在您的代码中看到了一条提到RemoteIO AU 的评论。在 OSX 中没有像 RemoteIO AU 这样的东西。如果您尝试从 iOS 代码移植,请尝试了解差异。它们有据可查。

【讨论】:

  • 是的,谢谢,当我注销 ioData 的缓冲区时,我意识到失真是由程序堆中剩余的非 mem 设置内存引起的。我只是简单地循环它们并将我的浮点型样本归零,但我想你的 memset 调用更有效。确实这是来自 iOS 的一个端口,我知道 remoteIO 是一个 iOS 特定的构造,它只是我忘记删除的剩余评论。有趣的是,您建议禁用输出并且我可能会尝试使用 HAL 单元而不是其(可能是“子类”?)默认输出?这有什么意义?
  • 恰如其分地造成这种失真的原因来自我的程序意图,因为我只是将此渲染回调用作定期调用实时函数的来源,并且正在做我所有的音频单元声音在其他回调上输出或简单地将 midi 消息发送到 AUSampler。因此,未初始化的噪音,大概是在没有 AudioUnitRender() 调用的情况下发送到 HAL,如果我使用渲染回调来实际.. uh .. 渲染任何东西。我想知道我的“定序器”是否有比这个适当的回调更好的基础
  • @user5797668,AFAIK,kAudioUnitSubType_DefaultOutput 中的输出是 open,因此您必须以编程方式使系统分配的缓冲区静音才能获得静音。在kAudioUnitSubType_HALOutput 中,您可以在设置时禁用 I/O。我不敢称它为“子类化”,因为 CoreAudio API 是纯 C 语言。希望我的回答能帮到你。
  • 当然,我的意思是松散意义上的子类化,默认输出基于 HAL 并改进其功能。 CA 框架本身至少使用术语对象来描述其功能组件。无论如何,我感谢您的帮助,如果您对我的音序器/时序基础问题有任何想法,请告诉我
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-21
相关资源
最近更新 更多