2016-04-30 42 views
1

当我运行这个简单的应用程序时,我听到一个非常响亮而刺耳的失真声音。我只是实例化一个默认的输出单元并分配一个渲染回调。让程序在runloop中运行。我没有发现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); 

} 
+0

请尽量让你的代码更具可读性,通过正确格式化它... – user3078414

回答

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代码创建端口,请尝试了解差异。他们有据可查。

+0

是的,谢谢,我意识到,失真是由我的程序堆中剩余的非内存设置的内存引起的,当我注销ioData的缓冲区。我只是为了循环使用它们,并将我的浮点型样本归零,但我想你的memset调用更有效率。事实上,这是iOS的一个端口,我意识到remoteIO是一个iOS特定的结构,它只是我忘记删除的剩余评论。有趣的是,你会建议禁用输出,我可能会尝试HAL单元而不是它的(大概是“subclassed”?)默认输出?这意味着什么? –

+0

合适的原因这种失真来自我的程序意图,因为我只使用此渲染回调作为定期实时函数调用的来源,并在其他回调中完成我所有的音频单元声音输出或仅发送midi消息给AUSampler。因此,未初始化的噪声,大概是发送到HAL没有'AudioUnitRender()'调用,如果我使用渲染回调实际上......呃..将渲染任何东西。我想知道是否有更好的基础为我的“定序器”建立在正常的时间比这个拨出的回调 –

+0

@ user5797668,AFAIK,'kAudioUnitSubType_DefaultOutput'中的输出是_open_,所以你必须以编程方式沉默系统分配的缓冲区才能获得安静。在'kAudioUnitSubType_HALOutput'中,您可以在安装时禁用I/O。我不敢称它为“子类”,因为CoreAudio API是纯C的。我希望我的回答能够提供帮助。 – user3078414