2012-05-07 13 views
5

Tôi đang cố gắng thêm AudioUnit loại kAudioUnitSubType_Reverb2 vào số AUGraph và nhận được lỗi -10868 (kAudioUnitErr_FormatNotSupported) được hỗ trợ trên AUGraphInitialize. Điểm khởi đầu của tôi là ứng dụng mẫu iPhoneMixerEQGraphTest của Apple, về cơ bản tôi vừa thêm một AudioUnit mới cho reverb nhưng không thể làm cho nó hoạt động được.AUGraphInitialize mã lỗi -10868 khi thêm kAudioUnitSubType_Reverb2 vào AUGraph

Đây là mã -

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

Trả lời

4

Đối với một số lý do, một số nút AU mất một định dạng stream trong phao theo mặc định, trong khi những người khác mang nó trong số nguyên. Nếu định dạng luồng không khớp, bạn sẽ gặp phải lỗi này. Vì vậy, bạn cần phải thêm một Format Converter giữa nút cân bằng của bạn và nút reverb của bạ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); 

Hãy chắc chắn rằng bạn thiết lập các định dạng dòng đầu vào nút chuyển đổi sang định dạng đầu ra của nút cân bằng:

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

Và làm tương tự cho đầu ra của bộ chuyển đổi, thiết lập nó với định dạng đầu vào của reverb. Điều đó sẽ làm cho đồ thị của bạn khởi chạy và chạy, nhưng hãy cho tôi biết nếu bạn quản lý để làm cho nút reverb thực sự làm điều gì đó, bởi vì nó không hoạt động đối với tôi.

Các vấn đề liên quan