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