2017-12-28 26 views
1

複数のFile PlayerオーディオユニットをMultiChannelMixerユニットに供給してAUGraphをセットアップし、リモートI/O出力に送ります。この設定はうまくいきました。複数のファイルプレーヤーでのCore Audioサウンドメーター

私は個々のファイルプレーヤーの音量を計算できるようにコールバックを追加することに苦労しています。

private let meteringCallback: AURenderCallback = { (
    inRefCon, 
    ioActionFlags, 
    inTimeStamp, 
    inBusNumber, 
    frameCount, 
    ioData) -> OSStatus in 

    var status = noErr 

    var track: AUTrack = unsafeBitCast(inRefCon, to: AUTrack.self) 

    status = AudioUnitRender(track.fileAU!, 
          ioActionFlags, 
          inTimeStamp, 
          inBusNumber, 
          frameCount, 
          ioData!); 

    var samples = [Float]() 
    let ptr = ioData!.pointee.mBuffers.mData?.assumingMemoryBound(to: Float.self) 
    samples.append(contentsOf: UnsafeBufferPointer(start: ptr, count: Int(frameCount))) 

    // ... fancy algorithm calculating DB value ... 
} 

AUTrack simpleは、特定のトラックに関する情報を保持します。クラスインスタンス全体をコールバックに渡すことは、複数のファイルプレーヤーが存在するため、ここでは意味がありません。

ここでこのコールバックをどこかに設定する必要があります。そのため、ミキサーに入る各ファイルプレーヤーの値を取得できます。しかし、私はそれをやろうとすると-10877(無効な要素)エラーが発生します。

これでメータリングコールバックをセットアップしようとします。

// Set metering callback 
var meteringCallbackStruct = AURenderCallbackStruct(inputProc: meteringCallback, 
                inputProcRefCon: &self.tracks[1]) 
status = AudioUnitSetProperty(self.tracks[1].fileAU!, 
          kAudioUnitProperty_SetRenderCallback, 
          kAudioUnitScope_Output, 
          0, 
          &meteringCallbackStruct, 
        UInt32(MemoryLayout<AURenderCallbackStruct>.size)) 

私はこれをどのように解決するのかよく分かりません。

私は何らかの形でミキサーユニットに戻さない限り、このコールバックはサンプルを「食べる」でしょうか?

答えて

1

あなたはSwiftでコールバックを行うべきではありません。レンダースレッドの処理は、C/C++でのみ行う必要があります。

あなたはrender notifyを使用することができます。

AudioUnitAddRenderNotify(mixer, my_C_callback, nil) //my_C_callback should not reference Swift objects, or be a Swift callback. 

それはレンダリングコールバックとして同じ関数シグネチャを使用しています。プリレンダリングとポストレンダリングと呼ばれ、ポストレンダリングを処理します。 ioActionFlagsからこの情報を取得します。

int isPostRender = ioActionFlags & kAudioUnitRenderAction_PostRender; 

ただし、マルチチャンネルミキサーを使用しているため、入力レベルの監視機能が組み込まれているため、コールバックは不要です。

このように最初に有効にします。

//AudioUnit mixer; kAudioUnitSubType_MultiChannelMixer 

//Call Before AudioUnitInitialize() 
UInt32 meteringMode = 1; 
AudioUnitSetProperty(mixer, kAudioUnitProperty_MeteringMode, kAudioUnitScope_Input, 0, &meteringMode, sizeof(meteringMode)); 

次に、処理中にパラメータを読み取ってレベルを取得できます。

int channel = 0; 

AudioUnitParameterValue averageDecibles; 
AudioUnitGetParameter(mixer, kMultiChannelMixerParam_PreAveragePower, kAudioUnitScope_Input, channel, &averageDecibles); 

AudioUnitParameterValue peakHoldDecibles; 
AudioUnitGetParameter(mixer, kMultiChannelMixerParam_PrePeakHoldLevel, kAudioUnitScope_Input, channel, &peakHoldDecibles); 

スウィフト:

var meteringMode: UInt32 = 1; 
let propSize = UInt32(MemoryLayout<UInt32>.size) 
AudioUnitSetProperty(mixer, kAudioUnitProperty_MeteringMode, kAudioUnitScope_Input, 0, &meteringMode, propSize); 

var averageDecibles: AudioUnitParameterValue = 0 
AudioUnitGetParameter(mixer, kMultiChannelMixerParam_PreAveragePower, kAudioUnitScope_Input, channel, &averageDecibles); 

var peakHoldDecibles: AudioUnitParameterValue = 0 
AudioUnitGetParameter(mixer, kMultiChannelMixerParam_PrePeakHoldLevel, kAudioUnitScope_Input, channel, &peakHoldDecibles); 
+0

ありがとうございました。これは私のための大きな助けです、私は自分のミキサーを書く途中でした。私はヘッダーファイルでこれらのパラメータが欠けているとは思えません。 :D –

関連する問題