2012-05-07 8 views
5

Estoy intentando añadir una AudioUnit de tipo kAudioUnitSubType_Reverb2 a un AUGraph y estoy recibiendo un error -10868 (kAudioUnitErr_FormatNotSupported) apoyado en AUGraphInitialize. Mi punto de partida fue la aplicación de muestra iPhoneMixerEQGraphTest de Apple, básicamente acabo de agregar una nueva AudioUnit para la reverb, pero no puedo hacer que funcione.AUGraphInitialize un código de error -10868 cuando se añade a kAudioUnitSubType_Reverb2 AUGraph

Este es el código -

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

Respuesta

4

Por alguna razón, algunos nodos de la UA toman un formato de flujo de flotación por defecto, mientras que otros lo toman en números enteros. Si los formatos de flujo no coinciden, obtendrá este error. Así que hay que añadir un conversor de formatos entre el nodo de ecualizador y el nodo de reverberación:

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

asegúrese de configurar el formato de flujo de la entrada de nodo convertidor para el formato de salida del nodo ecualizador:

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

Y haga lo mismo con la salida del convertidor, configurándolo con el formato de entrada de la reverberación. Eso debería hacer que tu gráfica se inicialice y se ejecute, pero avísame si lograste hacer que el nodo de reverberación realmente hiciera algo, porque no funciona para mí.

Cuestiones relacionadas