CoreAudio:AudioUnit 既不能停止也不能未初始化

Posted

技术标签:

【中文标题】CoreAudio:AudioUnit 既不能停止也不能未初始化【英文标题】:CoreAudio: AudioUnit can neither be stopped nor uninitialized 【发布时间】:2016-06-03 14:00:08 【问题描述】:

我编写了一个命令行 c 工具,生成一个正弦波并在默认音频输出上使用 CoreAudio 播放它。我正在初始化一个 AURenderCallbackStruct 并使用 AudioUnitInitialize 初始化 AudioUnit(如本论坛中已讨论的那样)。所有这些都按预期工作,但是在关闭程序时,我无法关闭 AudioUnit,既不使用 AudioOutputUnitStop(player.outputUnit); 也不使用 AudioOutputUnitStop(player.outputUnit); 也不 AudioComponentInstanceDispose(player.outputUnit);

这些调用在代码中的出现顺序不会改变行为。 该程序编译后没有错误消息,但只要程序的其余部分正在运行,正弦信号仍然可以听到。

这是我用于初始化 AudioUnit 的代码:

void CreateAndConnectOutputUnit (ToneGenerator *player) 

    AudioComponentDescription outputcd = 0;
    outputcd.componentType = kAudioUnitType_Output;
    outputcd.componentSubType = kAudioUnitSubType_DefaultOutput;
    outputcd.componentManufacturer = kAudioUnitManufacturer_Apple;

    AudioComponent comp = AudioComponentFindNext (NULL, &outputcd);
    if (comp == NULL) 
        printf ("can't get output unit");
        exit (-1);
    

    AudioComponentInstanceNew(comp, &player->outputUnit);

    // register render callback
    AURenderCallbackStruct input;
    input.inputProc = SineWaveRenderCallback;
    input.inputProcRefCon = player;
    AudioUnitSetProperty(player->outputUnit,
                         kAudioUnitProperty_SetRenderCallback,
                         kAudioUnitScope_Output,
                         0,
                         &input,
                         sizeof(input);

    // initialize unit
    AudioUnitInitialize(player->outputUnit);

在我的主程序中,我正在启动 AudioUnit 和正弦波。

void main 
    // code for doing various things

    ToneGenerator player = 0;         // create a sound object
    CreateAndConnectOutputUnit (&player);
    AudioOutputUnitStart(player.outputUnit);

    // waiting to listen to the sine wave
    sleep(3);

    // attempt to stop the sound output
    AudioComponentInstanceDispose(player.outputUnit);
    AudioUnitUninitialize(player.outputUnit);
    AudioOutputUnitStop(player.outputUnit);

    //additional code that should be executed without sine wave being audible

由于我对这两个论坛以及 Xcode 编程都是新手,我希望我能以一种您可以帮助我的方式来解释这个问题,我希望我没有错过某个地方的答案论坛,同时寻找解决方案。

提前感谢您的时间和投入,

斯蒂芬

【问题讨论】:

我会首先确保事情以相反的顺序发生:InstanceNew;Initialize;Start --> Stop;Uninitialize;InstanceDispose,并检查所有函数的返回值。 (它们返回错误代码是有原因的,而不是应该忽略它们。) 非常感谢您的回答 molbdnilo。更改顺序似乎合乎逻辑,但不会改变行为。这些函数抛出错误 -2147450879。我没有找到有关这些错误的有用信息。我正在使用这个函数来捕捉错误:link. 【参考方案1】:

您应该按逻辑顺序管理和取消管理您的音频单元。在已经未初始化的音频单元上停止播放是没有意义的,实际上之前在播放过程中处理了。而不是这样,请尝试以下顺序:

AudioOutputUnitStop(player.outputUnit);           //first stops playback
AudioUnitUninitialize(player.outputUnit);         //then deallocates unit's resources
AudioComponentInstanceDispose(player.outputUnit); //finally disposes of the AU itself

您所追求的正弦波命令行应用程序是this textbook 中精心设计的课程。请逐步阅读。

最后但并非最不重要的一点是,您的问题与 C++ 无关,CoreAudio 是一个纯 C API,因此您的标题和标签中的 C++ 都是错误且具有误导性的。

【讨论】:

非常感谢您的反馈。如上所述,我确实改变了调用函数的顺序,没有改变。我的代码实际上是基于链接的教科书。如果我运行原始代码,它似乎可以工作,因此我希望问题出现在附加代码中。我会深入研究这个。我还更正了指向 c++ 的链接。 为陡峭的学习曲线和最大的阅读集中度做好准备。这个 API 非常冗长。在我看来,您正在尝试设计控制单元寿命的方法,比sleep(3) 更有意义。重要的是,您不要在您的 AU 仍在播放时“断开”程序的其余部分。【参考方案2】:

音频单元在异步线程中运行,当您调用 AudioOutputUnitStop 时,该线程实际上可能不会立即停止。因此,在可能仍在运行的音频单元上调用 AudioUnitUninitialize 和 AudioComponentInstanceDispose 之前等待几分之一秒(至少几个音频回调缓冲区持续时间)可能会更好。

此外,请检查以确保您的 player.outputUnit 值在您停止单元时是有效的单元(而不是未初始化或已丢弃的变量)。

【讨论】:

以上是关于CoreAudio:AudioUnit 既不能停止也不能未初始化的主要内容,如果未能解决你的问题,请参考以下文章

CoreAudio基础概念

使用 MIDI 键盘 OSX 控制 AudioUnit

无法设置 MultiChanelMixer AudioUnit 总线的输入音量

CoreAudio,iOS:无法通过 RemoteIO 使用单声道输入和立体声输出

停止 AudioUnit 录制后出错

启动 AVAssetReader 停止对远程 I/O AudioUnit 的回调