iphone – 在向AUGraph添加kAudioUnitSubType_Reverb2时,AUGraph
发布时间:2020-12-14 19:22:15 所属栏目:百科 来源:网络整理
导读:我正在尝试将类型为kAudioUnitSubType_Reverb2的AudioUnit添加到AUGraph,并在AUGraphInitialize上获得-10868(kAudioUnitErr_FormatNotSupported)支持的错误.我的出发点是Apple的iPhoneMixerEQGraphTest示例应用程序,我基本上只是为混响添加了一个新的AudioUn
我正在尝试将类型为kAudioUnitSubType_Reverb2的AudioUnit添加到AUGraph,并在AUGraphInitialize上获得-10868(kAudioUnitErr_FormatNotSupported)支持的错误.我的出发点是Apple的iPhoneMixerEQGraphTest示例应用程序,我基本上只是为混响添加了一个新的AudioUnit,但无法让它工作.
这是代码 – - (void)initializeAUGraph { printf("initializeAUGraphn"); AUNode outputNode; AUNode eqNode; AUNode mixerNode; AUNode reverbNode; printf("create client ASBDn"); // client format audio goes into the mixer mClientFormat.SetCanonical(2,true); mClientFormat.mSampleRate = kGraphSampleRate; mClientFormat.Print(); printf("create output ASBDn"); // output format mOutputFormat.SetAUCanonical(2,false); mOutputFormat.mSampleRate = kGraphSampleRate; mOutputFormat.Print(); OSStatus result = noErr; // load up the audio data [self performSelectorInBackground:@selector(loadFiles) withObject:nil]; printf("new AUGraphn"); // create a new AUGraph result = NewAUGraph(&mGraph); if (result) { printf("NewAUGraph result %ld %08X %4.4sn",result,(unsigned int)result,(char*)&result); return; } // create three CAComponentDescription for the AUs we want in the graph // output unit CAComponentDescription output_desc(kAudioUnitType_Output,kAudioUnitSubType_RemoteIO,kAudioUnitManufacturer_Apple); // iPodEQ unit CAComponentDescription eq_desc(kAudioUnitType_Effect,kAudioUnitSubType_AUiPodEQ,kAudioUnitManufacturer_Apple); // multichannel mixer unit CAComponentDescription mixer_desc(kAudioUnitType_Mixer,kAudioUnitSubType_MultiChannelMixer,kAudioUnitManufacturer_Apple); // reverb unit CAComponentDescription reverb_desc(kAudioUnitType_Effect,kAudioUnitSubType_Reverb2,kAudioUnitManufacturer_Apple); printf("add nodesn"); // create a node in the graph that is an AudioUnit,using the supplied AudioComponentDescription to find and open that unit result = AUGraphAddNode(mGraph,&output_desc,&outputNode); if (result) { printf("AUGraphNewNode 1 result %lu %4.4sn",(char*)&result); return; } result = AUGraphAddNode(mGraph,&eq_desc,&eqNode); if (result) { printf("AUGraphNewNode 2 result %lu %4.4sn",&mixer_desc,&mixerNode); if (result) { printf("AUGraphNewNode 3 result %lu %4.4sn",&reverb_desc,&reverbNode); if (result) { printf("AUGraphNewNode 4 result %lu %4.4sn",(char*)&result); return; } // connect a node's output to a node's input // mixer -> eq -> output result = AUGraphConnectNodeInput(mGraph,mixerNode,eqNode,0); if (result) { printf("AUGraphConnectNodeInput result %lu %4.4sn",(char*)&result); return; } result = AUGraphConnectNodeInput(mGraph,reverbNode,outputNode,0); if (result) { printf("AUGraphConnectNodeInput reverb result %lu %4.4sn",(char*)&result); return; } // open the graph AudioUnits are open but not initialized (no resource allocation occurs here) result = AUGraphOpen(mGraph); if (result) { printf("AUGraphOpen result %ld %08X %4.4sn",(char*)&result); return; } // grab the audio unit instances from the nodes result = AUGraphNodeInfo(mGraph,NULL,&mMixer); if (result) { printf("AUGraphNodeInfo result %ld %08X %4.4sn",(char*)&result); return; } result = AUGraphNodeInfo(mGraph,&mEQ); if (result) { printf("AUGraphNodeInfo result %ld %08X %4.4sn",&mReverb); if (result) { printf("AUGraphNodeInfo reverb result %ld %08X %4.4sn",(char*)&result); return; } // set bus count UInt32 numbuses = 2; printf("set input bus count %lun",numbuses); result = AudioUnitSetProperty(mMixer,kAudioUnitProperty_ElementCount,kAudioUnitScope_Input,&numbuses,sizeof(numbuses)); if (result) { printf("AudioUnitSetProperty result %ld %08X %4.4sn",(char*)&result); return; } for (int i = 0; i < numbuses; ++i) { // setup render callback struct AURenderCallbackStruct rcbs; rcbs.inputProc = &renderInput; rcbs.inputProcRefCon = &mUserData; printf("set AUGraphSetNodeInputCallbackn"); // set a callback for the specified node's specified input result = AUGraphSetNodeInputCallback(mGraph,i,&rcbs); if (result) { printf("AUGraphSetNodeInputCallback result %ld %08X %4.4sn",(char*)&result); return; } printf("set input bus %d,client kAudioUnitProperty_StreamFormatn",i); // set the input stream format,this is the format of the audio for mixer input result = AudioUnitSetProperty(mMixer,kAudioUnitProperty_StreamFormat,&mClientFormat,sizeof(mClientFormat)); if (result) { printf("AudioUnitSetProperty result %ld %08X %4.4sn",(char*)&result); return; } } printf("get EQ kAudioUnitProperty_FactoryPresetsn"); // get the eq's factory preset list -- this is a read-only CFArray array of AUPreset structures // host owns the retuned array and should release it when no longer needed UInt32 size = sizeof(mEQPresetsArray); result = AudioUnitGetProperty(mEQ,kAudioUnitProperty_FactoryPresets,kAudioUnitScope_Global,&mEQPresetsArray,&size); if (result) { printf("AudioUnitGetProperty result %ld %08X %4.4sn",(char*)&result); return; } /* this code can be used if you're interested in dumping out the preset list printf("iPodEQ Factory Preset List:n"); UInt8 count = CFArrayGetCount(mEQPresetsArray); for (int i = 0; i < count; ++i) { AUPreset *aPreset = (AUPreset*)CFArrayGetValueAtIndex(mEQPresetsArray,i); CFShow(aPreset->presetName); }*/ printf("set output kAudioUnitProperty_StreamFormatn"); // set the output stream format of the mixer result = AudioUnitSetProperty(mMixer,kAudioUnitScope_Output,&mOutputFormat,sizeof(mOutputFormat)); if (result) { printf("AudioUnitSetProperty result %ld %08X %4.4sn",(char*)&result); return; } printf("set render notificationn"); // add a render notification,this is a callback that the graph will call every time the graph renders // the callback will be called once before the graph’s render operation,and once after the render operation is complete result = AUGraphAddRenderNotify(mGraph,renderNotification,&mUserData); if (result) { printf("AUGraphAddRenderNotify result %ld %08X %4.4sn",(char*)&result); return; } printf("AUGraphInitializen"); // now that we've set everything up we can initialize the graph,this will also validate the connections result = AUGraphInitialize(mGraph); if (result) { printf("AUGraphInitialize result %ld %08X %4.4sn",(char*)&result); return; } // ---- result here is error code 10868 CAShow(mGraph); } 解决方法
出于某种原因,一些AU节点默认采用float格式的流格式,而其他节点则采用整数形式.如果流格式不匹配,则会出现此错误.因此,您需要在均衡器节点和混响节点之间添加格式转换器:
AudioComponentDescription convertUnitDescription; convertUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple; convertUnitDescription.componentType = kAudioUnitType_FormatConverter; convertUnitDescription.componentSubType = kAudioUnitSubType_AUConverter; convertUnitDescription.componentFlags = 0; convertUnitDescription.componentFlagsMask = 0; result = AUGraphAddNode (graph,&convertUnitDescription,&convertNode); NSCAssert (result == noErr,@"Unable to add the converted unit to the audio processing graph. Error code: %d '%.4s'",(int) result,(const char *)&result); 确保将转换器节点输入的流格式设置为均衡器节点输出的格式: AudioStreamBasicDescription eqStreamFormat; UInt32 streamFormatSize = sizeof(eqStreamFormat); result = AudioUnitGetProperty(eqUnit,&eqStreamFormat,&streamFormatSize); NSAssert (result == noErr,@"Unable to get eq output format. Error code: %d '%.4s'",(const char *)&result); result = AudioUnitSetProperty(convertUnit,streamFormatSize); NSAssert (result == noErr,@"Unable to set converter input format. Error code: %d '%.4s'",(const char *)&result); 并对转换器的输出执行相同操作,使用混响的输入格式进行设置.这应该使您的图形初始化并运行,但是如果您设法使混响节点实际上做某事,请告诉我,因为它对我不起作用. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |