2017-12-28 17 views
1

Ich habe ein AUGraph-Setup mit ein paar File Player-Audiogeräten, die in eine MultichannelMixer-Einheit gespeist werden, die dann in einen Remote I/O-Ausgang eingespeist wird. Dieses Setup hat gut funktioniert.Core Audio-Soundmessung für mehrere Dateiplayer

Jetzt habe ich gekämpft, um einen Rückruf so hinzufügen, dass ich den Geräuschpegel der einzelnen Datei-Player berechnen kann.

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 ... 
} 

AIRrack simple enthält Informationen zu diesem bestimmten Track. Die Übergabe der gesamten Klasseninstanz an den Rückruf (wie in den Beispielen üblich) ist hier nicht sinnvoll, da mehrere Dateiplayer vorhanden sind.

Jetzt muss ich diesen Callback irgendwo einstellen, damit ich den Wert von jedem der Dateiplayer erfassen kann, die in den Mixer eingespeist werden. Trotzdem bekomme ich immer einen Fehler von -10877 (ungültiges Element), wenn ich das versuche.

Ich versuche, die Messung Callback mit diesem einzurichten.

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

Ich bin nicht ganz sicher, wie man das löst.

Und würde dieser Callback die Samples nicht "essen", wenn ich sie nicht irgendwie an die Mixereinheit zurückgebe?

Antwort

1

Sie sollten den Rückruf nicht in Swift durchführen. Render-Thread-Verarbeitung sollte nur in C/C++ erfolgen.

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

Er verwendet die gleiche Funktion Signatur wie die Callback-Render:

können Sie ein render notify verwenden. Es wird Pre- und Post-Render genannt, Sie wollen Post-Rendering verarbeiten. Sie erhalten diese Informationen von den ioActionFlags.

int isPostRender = ioActionFlags & kAudioUnitRenderAction_PostRender; 

Da Sie jedoch den Mehrkanal-Mixer verwenden, ist die Eingangspegelüberwachung integriert, so dass Sie den Rückruf nicht benötigen.

Sie aktivieren es zuerst so.

Dann während der Verarbeitung können Sie die Ebenen durch Lesen von Parametern erhalten.

int channel = 0; 

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

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

Swift:

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

Vielen Dank. Das ist eine große Hilfe für mich, ich war schon halb dabei meinen eigenen Mixer zu schreiben. Ich kann nicht glauben, dass ich diese Parameter in den Header-Dateien verpasst habe. : D –