2012-05-07 22 views
5

Ja próbuje dodać AudioUnit typu kAudioUnitSubType_Reverb2 do AUGraph i otrzymuję -10868 (kAudioUnitErr_FormatNotSupported) obsługiwany błąd na AUGraphInitialize. Zacząłem od przykładowej aplikacji AppleMixerEQGraphTest firmy Apple, w zasadzie dodałem nową AudioUnit dla pogłosu, ale nie mogę go uruchomić.AUGraphInitialize kod błędu -10868 podczas dodawania kAudioUnitSubType_Reverb2 do AUGraph

Oto kod -

- (void)initializeAUGraph 
{ 
    printf("initializeAUGraph\n"); 

    AUNode outputNode; 
    AUNode eqNode; 
    AUNode mixerNode; 
    AUNode reverbNode; 

    printf("create client ASBD\n"); 

    // client format audio goes into the mixer 
    mClientFormat.SetCanonical(2, true);       
    mClientFormat.mSampleRate = kGraphSampleRate; 
    mClientFormat.Print(); 

    printf("create output ASBD\n"); 

    // 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 AUGraph\n"); 

    // create a new AUGraph 
    result = NewAUGraph(&mGraph); 
    if (result) { printf("NewAUGraph result %ld %08X %4.4s\n", 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 nodes\n"); 

    // 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.4s\n", result, (char*)&result); return; } 

    result = AUGraphAddNode(mGraph, &eq_desc, &eqNode); 
    if (result) { printf("AUGraphNewNode 2 result %lu %4.4s\n", result, (char*)&result); return; } 

    result = AUGraphAddNode(mGraph, &mixer_desc, &mixerNode); 
    if (result) { printf("AUGraphNewNode 3 result %lu %4.4s\n", result, (char*)&result); return; } 

    result = AUGraphAddNode(mGraph, &reverb_desc, &reverbNode); 
    if (result) { printf("AUGraphNewNode 4 result %lu %4.4s\n", result, (char*)&result); return; } 

    // connect a node's output to a node's input 
    // mixer -> eq -> output 
    result = AUGraphConnectNodeInput(mGraph, mixerNode, 0, eqNode, 0); 
    if (result) { printf("AUGraphConnectNodeInput result %lu %4.4s\n", result, (char*)&result); return; } 

    result = AUGraphConnectNodeInput(mGraph, eqNode, 0, reverbNode, 0); 
    if (result) { printf("AUGraphConnectNodeInput result %lu %4.4s\n", result, (char*)&result); return; } 

    result = AUGraphConnectNodeInput(mGraph, reverbNode, 0, outputNode, 0); 
    if (result) { printf("AUGraphConnectNodeInput reverb result %lu %4.4s\n", result, (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.4s\n", result, (unsigned int)result, (char*)&result); return; } 

    // grab the audio unit instances from the nodes 
    result = AUGraphNodeInfo(mGraph, mixerNode, NULL, &mMixer); 
    if (result) { printf("AUGraphNodeInfo result %ld %08X %4.4s\n", result, (unsigned int)result, (char*)&result); return; } 

    result = AUGraphNodeInfo(mGraph, eqNode, NULL, &mEQ); 
    if (result) { printf("AUGraphNodeInfo result %ld %08X %4.4s\n", result, (unsigned int)result, (char*)&result); return; } 

    result = AUGraphNodeInfo(mGraph, reverbNode, NULL, &mReverb); 
    if (result) { printf("AUGraphNodeInfo reverb result %ld %08X %4.4s\n", result, (unsigned int)result, (char*)&result); return; } 

    // set bus count 
    UInt32 numbuses = 2; 

    printf("set input bus count %lu\n", numbuses); 

    result = AudioUnitSetProperty(mMixer, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &numbuses, sizeof(numbuses)); 
    if (result) { printf("AudioUnitSetProperty result %ld %08X %4.4s\n", result, (unsigned int)result, (char*)&result); return; } 

    for (int i = 0; i < numbuses; ++i) { 
     // setup render callback struct 
     AURenderCallbackStruct rcbs; 
     rcbs.inputProc = &renderInput; 
     rcbs.inputProcRefCon = &mUserData; 

     printf("set AUGraphSetNodeInputCallback\n"); 

     // set a callback for the specified node's specified input 
     result = AUGraphSetNodeInputCallback(mGraph, mixerNode, i, &rcbs); 
     if (result) { printf("AUGraphSetNodeInputCallback result %ld %08X %4.4s\n", result, (unsigned int)result, (char*)&result); return; } 

     printf("set input bus %d, client kAudioUnitProperty_StreamFormat\n", i); 

     // set the input stream format, this is the format of the audio for mixer input 
     result = AudioUnitSetProperty(mMixer, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, i, &mClientFormat, sizeof(mClientFormat)); 
     if (result) { printf("AudioUnitSetProperty result %ld %08X %4.4s\n", result, (unsigned int)result, (char*)&result); return; } 
    } 

    printf("get EQ kAudioUnitProperty_FactoryPresets\n"); 

    // 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, 0, &mEQPresetsArray, &size); 
    if (result) { printf("AudioUnitGetProperty result %ld %08X %4.4s\n", result, (unsigned int)result, (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_StreamFormat\n"); 

    // set the output stream format of the mixer 
    result = AudioUnitSetProperty(mMixer, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &mOutputFormat, sizeof(mOutputFormat)); 
    if (result) { printf("AudioUnitSetProperty result %ld %08X %4.4s\n", result, (unsigned int)result, (char*)&result); return; } 

    printf("set render notification\n"); 

    // 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.4s\n", result, (unsigned int)result, (char*)&result); return; } 

    printf("AUGraphInitialize\n"); 

    // 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.4s\n", result, (unsigned int)result, (char*)&result); return; } 
    // ---- result here is error code 10868 

    CAShow(mGraph); 
} 

Odpowiedz

4

Z jakiegoś powodu, niektóre węzły AU wziąć format strumień w obrocie domyślnie, podczas gdy inni się go w całkowitych. Jeśli formaty strumieni nie są zgodne, pojawia się ten błąd. Więc trzeba dodać Format Converter między węzłem korektor i węzła pogłosu:

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); 

upewnić, ustawić format strumienia wejścia węzła konwerter do formatu wyjściowego węzła Korektor:

AudioStreamBasicDescription eqStreamFormat; 
UInt32 streamFormatSize = sizeof(eqStreamFormat); 
result = AudioUnitGetProperty(eqUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &eqStreamFormat, &streamFormatSize); 
NSAssert (result == noErr, @"Unable to get eq output format. Error code: %d '%.4s'", (int) result, (const char *)&result); 

result = AudioUnitSetProperty(convertUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &eqStreamFormat, streamFormatSize); 
NSAssert (result == noErr, @"Unable to set converter input format. Error code: %d '%.4s'", (int) result, (const char *)&result); 

Wykonaj to samo dla wyjścia konwertera, ustawiając go w formacie wejściowym pogłosu. To powinno spowodować, że twój wykres zostanie zainicjowany i uruchomiony, ale daj mi znać, jeśli udało ci się zrobić, że węzeł reverb faktycznie coś zrobi, ponieważ to nie działa dla mnie.

Powiązane problemy