Iphone iOS-AudioUnitRender在设备上返回错误-10876,但在模拟器中运行正常

Iphone iOS-AudioUnitRender在设备上返回错误-10876,但在模拟器中运行正常,iphone,audiounit,Iphone,Audiounit,我遇到了一个问题,使我无法捕获设备(iPhone4)上麦克风的输入信号。但是,代码在模拟器中运行良好。 该代码最初是从Apple的MixerHostAudio类中从MixerHost示例代码中采用的。在我开始添加捕获麦克风输入的代码之前,它在设备和模拟器上都运行良好。 不知是否有人能帮我。提前谢谢 以下是我的inputRenderCallback函数,它将信号输入混音器输入: static OSStatus inputRenderCallback ( void

我遇到了一个问题,使我无法捕获设备(iPhone4)上麦克风的输入信号。但是,代码在模拟器中运行良好。 该代码最初是从Apple的MixerHostAudio类中从MixerHost示例代码中采用的。在我开始添加捕获麦克风输入的代码之前,它在设备和模拟器上都运行良好。 不知是否有人能帮我。提前谢谢

以下是我的inputRenderCallback函数,它将信号输入混音器输入:

static OSStatus inputRenderCallback (

void                        *inRefCon,
AudioUnitRenderActionFlags  *ioActionFlags,
const AudioTimeStamp        *inTimeStamp, 
UInt32                      inBusNumber,
UInt32                      inNumberFrames,
AudioBufferList             *ioData) {
recorderStructPtr recorderStructPointer     = (recorderStructPtr) inRefCon;
    // ....
        AudioUnitRenderActionFlags renderActionFlags;
        err = AudioUnitRender(recorderStructPointer->iOUnit, 
                              &renderActionFlags, 
                              inTimeStamp, 
                              1, // bus number for input
                              inNumberFrames, 
                              recorderStructPointer->fInputAudioBuffer
                              );
                    // error returned is -10876
    // ....
}
这是我的相关初始化代码: 现在,我在混频器中只保留了1个输入,因此混频器似乎是多余的,但在添加输入捕获代码之前工作正常

// Convenience function to allocate our audio buffers
- (AudioBufferList *) allocateAudioBufferListByNumChannels:(UInt32)numChannels withSize:(UInt32)size {
    AudioBufferList*            list;
    UInt32                      i;

    list = (AudioBufferList*)calloc(1, sizeof(AudioBufferList) + numChannels * sizeof(AudioBuffer));
    if(list == NULL)
        return nil;

    list->mNumberBuffers = numChannels;
    for(i = 0; i < numChannels; ++i) {
        list->mBuffers[i].mNumberChannels = 1;
        list->mBuffers[i].mDataByteSize = size;
        list->mBuffers[i].mData = malloc(size);
        if(list->mBuffers[i].mData == NULL) {
            [self destroyAudioBufferList:list];
            return nil;
        }
    }
    return list;
}

// initialize audio buffer list for input capture
recorderStructInstance.fInputAudioBuffer = [self allocateAudioBufferListByNumChannels:1 withSize:4096];

// I/O unit description
AudioComponentDescription iOUnitDescription;
iOUnitDescription.componentType          = kAudioUnitType_Output;
iOUnitDescription.componentSubType       = kAudioUnitSubType_RemoteIO;
iOUnitDescription.componentManufacturer  = kAudioUnitManufacturer_Apple;
iOUnitDescription.componentFlags         = 0;
iOUnitDescription.componentFlagsMask     = 0;

// Multichannel mixer unit description
AudioComponentDescription MixerUnitDescription;
MixerUnitDescription.componentType          = kAudioUnitType_Mixer;
MixerUnitDescription.componentSubType       = kAudioUnitSubType_MultiChannelMixer;
MixerUnitDescription.componentManufacturer  = kAudioUnitManufacturer_Apple;
MixerUnitDescription.componentFlags         = 0;
MixerUnitDescription.componentFlagsMask     = 0;

AUNode   iONode;         // node for I/O unit
AUNode   mixerNode;      // node for Multichannel Mixer unit

// Add the nodes to the audio processing graph
result =    AUGraphAddNode (
                processingGraph,
                &iOUnitDescription,
                &iONode);

result =    AUGraphAddNode (
                processingGraph,
                &MixerUnitDescription,
                &mixerNode
            );

result = AUGraphOpen (processingGraph);

// fetch mixer AudioUnit instance
result =    AUGraphNodeInfo (
                processingGraph,
                mixerNode,
                NULL,
                &mixerUnit
            );

// fetch RemoteIO AudioUnit instance
result =    AUGraphNodeInfo (
                             processingGraph,
                             iONode,
                             NULL,
                             &(recorderStructInstance.iOUnit)
                             );


    // enable input of RemoteIO unit
UInt32 enableInput = 1;
AudioUnitElement inputBus = 1;
result = AudioUnitSetProperty(recorderStructInstance.iOUnit, 
                              kAudioOutputUnitProperty_EnableIO, 
                              kAudioUnitScope_Input, 
                              inputBus, 
                              &enableInput, 
                              sizeof(enableInput)
                              );
// setup mixer inputs
UInt32 busCount   = 1;

result = AudioUnitSetProperty (
             mixerUnit,
             kAudioUnitProperty_ElementCount,
             kAudioUnitScope_Input,
             0,
             &busCount,
             sizeof (busCount)
         );


UInt32 maximumFramesPerSlice = 4096;

result = AudioUnitSetProperty (
             mixerUnit,
             kAudioUnitProperty_MaximumFramesPerSlice,
             kAudioUnitScope_Global,
             0,
             &maximumFramesPerSlice,
             sizeof (maximumFramesPerSlice)
         );


for (UInt16 busNumber = 0; busNumber < busCount; ++busNumber) {

    // set up input callback
    AURenderCallbackStruct inputCallbackStruct;
    inputCallbackStruct.inputProc        = &inputRenderCallback;
inputCallbackStruct.inputProcRefCon  = &recorderStructInstance;

    result = AUGraphSetNodeInputCallback (
                 processingGraph,
                 mixerNode,
                 busNumber,
                 &inputCallbackStruct
             );

            // set up stream format
    AudioStreamBasicDescription mixerBusStreamFormat;
    size_t bytesPerSample = sizeof (AudioUnitSampleType);

    mixerBusStreamFormat.mFormatID          = kAudioFormatLinearPCM;
    mixerBusStreamFormat.mFormatFlags       = kAudioFormatFlagsAudioUnitCanonical;
    mixerBusStreamFormat.mBytesPerPacket    = bytesPerSample;
    mixerBusStreamFormat.mFramesPerPacket   = 1;
    mixerBusStreamFormat.mBytesPerFrame     = bytesPerSample;
    mixerBusStreamFormat.mChannelsPerFrame  = 2;
    mixerBusStreamFormat.mBitsPerChannel    = 8 * bytesPerSample;
    mixerBusStreamFormat.mSampleRate        = graphSampleRate;

    result = AudioUnitSetProperty (
                                   mixerUnit,
                                   kAudioUnitProperty_StreamFormat,
                                   kAudioUnitScope_Input,
                                   busNumber,
                                   &mixerBusStreamFormat,
                                   sizeof (mixerBusStreamFormat)
                                   );


}

// set sample rate of mixer output
result = AudioUnitSetProperty (
             mixerUnit,
             kAudioUnitProperty_SampleRate,
             kAudioUnitScope_Output,
             0,
             &graphSampleRate,
             sizeof (graphSampleRate)
         );


// connect mixer output to RemoteIO
result = AUGraphConnectNodeInput (
             processingGraph,
             mixerNode,         // source node
             0,                 // source node output bus number
             iONode,            // destination node
             0                  // desintation node input bus number
         );


// initialize AudioGraph
result = AUGraphInitialize (processingGraph);

// start AudioGraph
result = AUGraphStart (processingGraph);

// enable mixer input
result = AudioUnitSetParameter (
                     mixerUnit,
                     kMultiChannelMixerParam_Enable,
                     kAudioUnitScope_Input,
                     0, // bus number
                     1, // on
                     0
                  );
//分配音频缓冲区的便利函数
-(AudioBufferList*)AllocateAudioBufferListByNumChannel:(UInt32)大小为:(UInt32)的NumChannel{
音频缓冲列表*列表;
UInt32Ⅰ;
list=(AudioBufferList*)calloc(1,sizeof(AudioBufferList)+numChannels*sizeof(AudioBuffer));
if(list==NULL)
返回零;
列表->mNumberBuffers=numChannels;
对于(i=0;imbuffer[i].mNumberChannels=1;
list->mbuffer[i].mDataByteSize=size;
列表->MBuffer[i].mData=malloc(大小);
if(list->mbuffer[i].mData==NULL){
[自我毁灭列表:列表];
返回零;
}
}
退货清单;
}
//初始化输入捕获的音频缓冲区列表
recorderStructInstance.fInputAudioBuffer=[self-AllocateAudioBufferListByNumChannel:1,大小为4096];
//输入/输出单元说明
音频成分描述和单元描述;
iOUnitDescription.componentType=kAudioUnitType\u输出;
iOUnitDescription.componentSubType=kAudioUnitSubType\u RemoteIO;
iOUnitDescription.componentManufacturer=kAudioUnitManufacturer\u Apple;
iOUnitDescription.componentFlags=0;
iOUnitDescription.componentFlagsMask=0;
//多通道混频器单元描述
音频组件描述混音器单元描述;
MixerUnitDescription.componentType=kAudioUnitType\u混合器;
MixerUnitDescription.componentSubType=kAudioUnitSubType\u多通道混频器;
MixerUnitDescription.componentManufacturer=kAudioUnitManufacturer\u Apple;
MixerUnitDescription.componentFlags=0;
MixerUnitDescription.componentFlagsMask=0;
AUNode iONode;//I/O单元的节点
AUNode mixerNode;//用于多通道混频器单元的节点
//将节点添加到音频处理图中
结果=AUGraphAddNode(
处理图形,
&iOUnitDescription,
&离子电极);
结果=AUGraphAddNode(
处理图形,
&MixerUnitDescription,
&混合节点
);
结果=俄歇图形打开(处理图形);
//获取混音器音频单元实例
结果=AUGraphNodeInfo(
处理图形,
混合节点,
无效的
&混血儿
);
//获取RemoteIO音频单元实例
结果=AUGraphNodeInfo(
处理图形,
伊奥尼德,
无效的
&(recorderStructInstance.iOUnit)
);
//启用远程IO单元的输入
UInt32使能输入=1;
AudioUnitElement输入总线=1;
结果=AudioUnitSetProperty(recorderStructInstance.iOUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_输入,
输入总线,
&启用输入,
sizeof(启用输入)
);
//设置混音器输入
UInt32总线计数=1;
结果=AudioUnitSetProperty(
mixerUnit,
kAudioUnitProperty_ElementCount,
kAudioUnitScope_输入,
0,
&班次,
sizeof(总线计数)
);
UInt32最大帧片数=4096;
结果=AudioUnitSetProperty(
mixerUnit,
kAudioUnitProperty_MaximumFramesPerSlice,
考迪翁尼茨考普大学全球,
0,
&最大帧片数,
sizeof(最大帧片数)
);
用于(UInt16总线号=0;总线号<总线数;++总线号){
//设置输入回调
AURenderCallbackStruct输入callbackstruct;
inputCallbackStruct.inputProc=&inputRenderCallback;
inputCallbackStruct.inputProcRefCon=&recorderStructInstance;
结果=AUGraphSetNodeInputCallback(
处理图形,
混合节点,
公共汽车号码,
&inputCallbackStruct
);
//设置流格式
音频流基本描述混音器BusstreamFormat;
size\u t bytesPerSample=sizeof(AudioUnitSampleType);
mixerBusStreamFormat.mFormatID=kaudioformlinearpcm;
mixerBusStreamFormat.mFormatFlags=kAudioFormatFlagsAudioUnitCanonical;
mixerBusStreamFormat.mBytesPerPacket=bytesPerSample;
mixerBusStreamFormat.mFramesPerPacket=1;
mixerBusStreamFormat.mBytesPerFrame=bytesPerSample;
mixerBusStreamFormat.mChannelsPerFrame=2;
mixerBusStreamFormat.mBitsPerChannel=8*bytesPerSample;
mixerBusStreamFormat.mSampleRate=graphSampleRate;
结果=AudioUnitSetProperty(
mixerUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_输入,
公共汽车号码,
&mixerBusStreamFormat,
sizeof(mixerBusStreamFormat)
);
}
//设置混频器输出的采样率
结果=AudioUnitSetProperty(
mixerUnit,
K