2012-08-30 14 views
5

マイクロホンからの入力を受け取り、ハイパスフィルタオーディオユニットを通して実行し、スピーカーから再生するiOSアプリケーションを作成しています。私はこれをAUGraph APIを使ってうまく実行できました。その中に、リモートI/Oユニットとエフェクトオーディオユニット(kAudioUnitType_Effect,)の2つのノードを配置し、ioユニットの入力エレメントの出力スコープをエフェクトユニットの入力に接続し、エフェクトノードの出力をioユニットの出力要素の入力範囲。しかし、今では、処理されたオーディオサンプルに基づいて分析を行う必要があるので、バッファに直接アクセスする必要があります。これは、私が間違っていると私を訂正してください。)AUGraphConnectNodeInputを使用してエフェクトノードの出力とioユニットの出力エレメントを接続し、ioユニットの出力エレメントにレンダリングコールバック関数をアタッチしなければならないことを意味します。スピーカーが新しいサンプルを必要とするときはいつでもバッファーにアクセスできます。 私はそうしましたが、レンダリングコールバックでAudioUnitRender関数を呼び出すと-50エラーが発生します。私はレンダリングコールバックで何もしていないので、2つのオーディオユニット間のASBDの不一致のケースがあると思います(そして、AUGraphは前にそれを処理しました)。 ここでは、コードです:私は、私はAudioUnitRender呼び出しで-50エラーを取得しています前に言ったようにリモートI/Oレンダリングコールバック関数の作成に問題がある

@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 

、および:

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私はそれについてほとんど何も書類を見つけることはありません。

ご協力いただければ幸いです。

優れたスタートポイントチュートリアルを提供してくれたTim Bolstad(http://timbolstad.com/2010/03/14/core-audio-getting-started/)に感謝します。

答えて

0

オーディオのバッファを再生するためだけにRemoteIOを使用する簡単な使用例があります。おそらくグラフではなく最初のものから始めてください。

0

実際に必要な接続がすべて行われていることを確認してください。必要なほとんどすべてを初期化しているようですが、単にオーディオをパススルーしたい場合、レンダリングコールバック関数は必要ありません。

フィルタを実行する必要がある場合は、フィルタを実際に正しく接続していることを確認してください。ここで

は、私が働いているアプリからの抜粋です:

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

これはにRemoteIOの出力にミキサーからの出力を接続し、その後、マルチチャンネルミキサーユニットにRemoteIOユニットからの入力を接続しますスピーカー。

0

間違ったオーディオユニットをAudioUnitRenderに渡しているように見えます。 mEffectsの代わりにioUnitを渡す必要があると思います。いずれにせよ、渡しているすべてのパラメータをAudioUnitRenderに再度チェックしてください。 -50が返ってきたのを見ると、私はそれらのうちの1つにぶつかったからです。

関連する問題