2017-12-28 42 views
1

몇 개의 File Player 오디오 장치가 MultiChannelMixer 장치로 공급되는 AUGraph 설정이 있으며,이 장치는 원격 I/O 출력으로 공급됩니다. 이 설정은 정상적으로 작동했습니다.여러 파일 플레이어의 코어 오디오 사운드 미터링

이제 개별 파일 플레이어의 사운드 레벨을 계산할 수있는 방법으로 콜백을 추가하는 데 어려움을 겪고 있습니다.

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. 

그것은 렌더링 콜백과 같은 함수 서명을 사용합니다. 그것은 pre와 post render라고 불리며, post render를 처리하려고합니다. 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

당신에게 너무 감사드립니다. 이것은 나를 위해 큰 도움이되고, 나는 내 자신의 믹서를 작성하는 중반이었다. 헤더 파일에서이 매개 변수를 놓친다 고 나는 믿을 수 없다. :디 –