2012-08-30 17 views
5

मैं एक आईओएस ऐप लिख रहा हूं जो माइक्रोफ़ोन से इनपुट लेता है, इसे उच्च-पास फ़िल्टर ऑडियो इकाई के माध्यम से चलाता है, और इसे स्पीकर के माध्यम से वापस चलाता है। मैं AUGraph API का उपयोग कर सफलतापूर्वक ऐसा करने में सक्षम हूं। इसमें, मैंने दो नोड्स डाले: एक रिमोट आई/ओ यूनिट, और एक प्रभाव ऑडियो यूनिट (kAudioUnitType_Effect, kAudioUnitSubType_HighPassFilter), और आईओ यूनिट के इनपुट तत्व के आउटपुट स्कोप को प्रभाव इकाई के इनपुट में जोड़ा, और आईओ यूनिट के प्रभाव नोड का आउटपुट आउटपुट तत्व का इनपुट दायरा। लेकिन अब मुझे संसाधित ऑडियो नमूने के आधार पर कुछ विश्लेषण करने की आवश्यकता है, इसलिए मुझे बफर तक सीधे पहुंच की आवश्यकता है। इसका मतलब है (और अगर मैं गलत हूं तो कृपया मुझे सही करें) अब मैं प्रभाव नोड के आउटपुट और आईओ यूनिट के आउटपुट तत्व के बीच कनेक्शन बनाने के लिए AUGraphConnectNodeInput का उपयोग नहीं कर सकता, और आईओ इकाई के आउटपुट तत्व के लिए रेंडर कॉलबैक फ़ंक्शन संलग्न करना होगा, ताकि जब भी वक्ताओं को नए नमूने की आवश्यकता हो तो मैं बफर तक पहुंच सकता हूं। मैंने ऐसा किया है, लेकिन जब मैं AudioUnitRender फ़ंक्शन कॉलबैक में कॉल करता हूं तो मुझे एक -50 त्रुटि मिलती है। मेरा मानना ​​है कि मेरे पास दो ऑडियो इकाइयों के बीच एएसबीडी विसंगति का मामला है, क्योंकि मैं इसके बारे में कॉलबैक प्रस्तुत करने में कुछ भी नहीं कर रहा हूं (और ऑग्राफ ने पहले इसका ख्याल रखा था)। कोड यह रहा:रिमोट I/O को कॉलबैक फ़ंक्शन प्रस्तुत करने में समस्या

AudioController.h:

@interface AudioController : NSObject 
{ 
    AUGraph mGraph; 
    AudioUnit mEffects; 
    AudioUnit ioUnit; 
} 

@property (readonly, nonatomic) AudioUnit mEffects; 
@property (readonly, nonatomic) AudioUnit ioUnit; 

-(void)initializeAUGraph; 
-(void)startAUGraph; 
-(void)stopAUGraph; 

@end 

AudioController.mm:

@implementation AudioController 

… 

static OSStatus renderInput(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) 
{ 
    AudioController *THIS = (__bridge AudioController*)inRefCon; 

    AudioBuffer buffer; 

    AudioStreamBasicDescription fxOutputASBD; 
    UInt32 fxOutputASBDSize = sizeof(fxOutputASBD); 
    AudioUnitGetProperty([THIS mEffects], kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &fxOutputASBD, &fxOutputASBDSize); 

    buffer.mDataByteSize = inNumberFrames * fxOutputASBD.mBytesPerFrame; 
    buffer.mNumberChannels = fxOutputASBD.mChannelsPerFrame; 
    buffer.mData = malloc(buffer.mDataByteSize); 

    AudioBufferList bufferList; 
    bufferList.mNumberBuffers = 1; 
    bufferList.mBuffers[0] = buffer; 

    //TODO prender ARM y solucionar problema de memoria 

    OSStatus result = AudioUnitRender([THIS mEffects], ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &bufferList); 
    [THIS hasError:result:__FILE__:__LINE__]; 

    memcpy(ioData, buffer.mData, buffer.mDataByteSize); 

    return noErr; 
} 


- (void)initializeAUGraph 
{ 
    OSStatus result = noErr; 

    // create a new AUGraph 
    result = NewAUGraph(&mGraph); 

    AUNode outputNode; 
    AUNode effectsNode; 

    AudioComponentDescription effects_desc; 
    effects_desc.componentType = kAudioUnitType_Effect; 
    effects_desc.componentSubType = kAudioUnitSubType_LowPassFilter; 
    effects_desc.componentFlags = 0; 
    effects_desc.componentFlagsMask = 0; 
    effects_desc.componentManufacturer = kAudioUnitManufacturer_Apple; 

    AudioComponentDescription output_desc; 
    output_desc.componentType = kAudioUnitType_Output; 
    output_desc.componentSubType = kAudioUnitSubType_RemoteIO; 
    output_desc.componentFlags = 0; 
    output_desc.componentFlagsMask = 0; 
    output_desc.componentManufacturer = kAudioUnitManufacturer_Apple; 

    // Add nodes to the graph to hold the AudioUnits 
    result = AUGraphAddNode(mGraph, &output_desc, &outputNode); 
    [self hasError:result:__FILE__:__LINE__]; 
    result = AUGraphAddNode(mGraph, &effects_desc, &effectsNode); 
    [self hasError:result:__FILE__:__LINE__]; 

    // Connect the effect node's output to the output node's input 
    // This is no longer the case, as I need to access the buffer 
    // result = AUGraphConnectNodeInput(mGraph, effectsNode, 0, outputNode, 0); 
    [self hasError:result:__FILE__:__LINE__]; 

    // Connect the output node's input scope's output to the effectsNode input 
    result = AUGraphConnectNodeInput(mGraph, outputNode, 1, effectsNode, 0); 
    [self hasError:result:__FILE__:__LINE__]; 

    // open the graph AudioUnits 
    result = AUGraphOpen(mGraph); 
    [self hasError:result:__FILE__:__LINE__]; 

    // Get a link to the effect AU 
    result = AUGraphNodeInfo(mGraph, effectsNode, NULL, &mEffects); 
    [self hasError:result:__FILE__:__LINE__]; 

    // Same for io unit 
    result = AUGraphNodeInfo(mGraph, outputNode, NULL, &ioUnit); 
    [self hasError:result:__FILE__:__LINE__]; 

    // Enable input on io unit 
    UInt32 flag = 1; 
    result = AudioUnitSetProperty(ioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &flag, sizeof(flag)); 
    [self hasError:result:__FILE__:__LINE__]; 

    // Setup render callback struct 
    AURenderCallbackStruct renderCallbackStruct; 
    renderCallbackStruct.inputProc = &renderInput; 
    renderCallbackStruct.inputProcRefCon = (__bridge void*)self; 

    // Set a callback for the specified node's specified input 
    result = AUGraphSetNodeInputCallback(mGraph, outputNode, 0, &renderCallbackStruct); 
    [self hasError:result:__FILE__:__LINE__]; 

    // Get fx unit's input current stream format... 
    AudioStreamBasicDescription fxInputASBD; 
    UInt32 sizeOfASBD = sizeof(AudioStreamBasicDescription); 

    result = AudioUnitGetProperty(mEffects, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &fxInputASBD, &sizeOfASBD); 
    [self hasError:result:__FILE__:__LINE__]; 

    // ...and set it on the io unit's input scope's output 
    result = AudioUnitSetProperty(ioUnit, 
            kAudioUnitProperty_StreamFormat, 
            kAudioUnitScope_Output, 
            1, 
            &fxInputASBD, 
            sizeof(fxInputASBD)); 
    [self hasError:result:__FILE__:__LINE__]; 

    // Set fx unit's output sample rate, just in case 
    Float64 sampleRate = 44100.0; 

    result = AudioUnitSetProperty(mEffects, 
            kAudioUnitProperty_SampleRate, 
            kAudioUnitScope_Output, 
            0, 
            &sampleRate, 
            sizeof(sampleRate)); 
    [self hasError:result:__FILE__:__LINE__]; 

    // Once everything is set up call initialize to validate connections 
    result = AUGraphInitialize(mGraph); 
    [self hasError:result:__FILE__:__LINE__]; 
} 

@end 

जैसा कि मैंने पहले कहा, मैं AudioUnitRender कॉल पर एक -50 त्रुटि मिल रही है, और मुझे इसके बारे में कोई दस्तावेज नहीं मिल रहा है।

किसी भी मदद की बहुत सराहना की जाएगी।

टिम बोलस्टेड (http://timbolstad.com/2010/03/14/core-audio-getting-started/) के लिए धन्यवाद एक उत्कृष्ट प्रारंभिक बिंदु ट्यूटोरियल प्रदान करने के लिए धन्यवाद।

उत्तर

0

ऑडियो के बफर खेलने के लिए रिमोटियो का उपयोग करने के सरल कामकाजी उदाहरण हैं। शायद ग्राफ के बजाए उन लोगों में से एक के साथ शुरू करें।

0

यह सुनिश्चित करने के लिए जांचें कि आप वास्तव में सभी आवश्यक कनेक्शन बना रहे हैं। ऐसा लगता है कि आप सबसे अधिक आवश्यक सब कुछ शुरू कर रहे हैं, लेकिन यदि आप बस ऑडियो को पास करना चाहते हैं तो आपको कॉलबैक फ़ंक्शन प्रस्तुत करने की आवश्यकता नहीं है।

अब, यदि आप फ़िल्टर करना चाहते हैं, तो आपको एक की आवश्यकता हो सकती है, लेकिन फिर भी, सुनिश्चित करें कि आप वास्तव में घटकों को एक साथ जोड़ रहे हैं।

AUGraphConnectNodeInput(graph, outputNode, kInputBus, mixerNode, kInputBus); 
AUGraphConnectNodeInput(graph, mixerNode, kOutputBus, outputNode, kOutputBus); 

यह एक मल्टी चैनल मिक्सर इकाई के लिए RemoteIO इकाई से इनपुट से जोड़ता है, तो करने के लिए RemoteIO के उत्पादन के लिए मिक्सर से उत्पादन जोड़ता है:

यहाँ एक एप्लिकेशन से एक टुकड़ा मैं पर काम कर रहा हूँ वक्ता।

0

ऐसा लगता है कि आप गलत ऑडियो इकाई में AudioUnitRender पर जा रहे हैं। मुझे लगता है कि mEffects के बजाय आपको ioUnit में पास करने की आवश्यकता है। किसी भी मामले में, AudioUnitRender पर आपके द्वारा पारित किए जा रहे सभी पैरामीटर को दोबारा जांचें। जब मैं देखता हूं -50 ने इसे वापस कर दिया क्योंकि मैंने उनमें से एक को बॉट किया था।