;
; uplink_echo.dspg
;

graphName uplink_echo

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; 	Macros
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

[def MIC_INPUT_CHANNEL_COUNT 1]
[def REF_INPUT_CHANNEL_COUNT 2]
[def MIC_CLIP_DATA_INPUT_CHANNEL_COUNT 1]
[def IO_BLOCK_SIZE 240]
[def IO_SAMPLE_RATE 24000]
[def ENABLE_MEDIA_CHAT 0]
[def ENABLE_SPATIAL_CHAT 0]

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; 	Constants
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ECV5
[def EC_MicEcleeXcorr 37]
[def EC_SxxTimeAligned 34]
[def EC_IRDelay 8]
[def EC_RelativeDeltaEIR 3]
[def EC_EcleeEnergy 69]

; RES_V5
[def kAUResidualEchoSuppressorV5Bus_InMainFreq 0]
[def kAUResidualEchoSuppressorV5Bus_InEcleeFreq 1]
[def kAUResidualEchoSuppressorV5Bus_InRefFreq 2]
[def kAUResidualEchoSuppressorV5Bus_InNsGainTime 3]
[def kAUResidualEchoSuppressorV5Bus_InExtNoiseTime 4]
[def kAUResidualEchoSuppressorV5Bus_InPolyEcleeFreq 5]
[def kAUResidualEchoSuppressorV5Bus_OutMainFreq 0]
[def kAUResidualEchoSuppressorV5Bus_OutEcleeFreq 1]
[def kAUResidualEchoSuppressorV5Bus_OutGainTime 2]
[def kAUResidualEchoSuppressorV5Bus_OutEstResedEcoPS 3]
[def kAUResidualEchoSuppressorV5Param_Speex_EchoSuppress 1]
[def kAUResidualEchoSuppressorV5param_Speex_PostGain 5]
[def kAUResidualEchoSuppressorV5param_Speex_ECAdapted 6]
[def kAUResidualEchoSuppressorV5param_Speex_ECMicEcleeXcorr 7]
[def kAUResidualEchoSuppressorV5param_Speex_ECSxxTimeAligned 13]
[def kAUResidualEchoSuppressorV5param_Echo2LvLinearEC 41]
[def kAUResidualEchoSuppressorV5param_ExternalVAD 49]

; MDNS
[def kAUMDNSParam_SpeechProbability 2]
[def kAUMDNSParam_NoiseSplEstimate 9]

; EchoGate_V3
[def kAUEchoGateV3_EcoEstInputBus 0]
[def kAUEchoGateV3_TimeAlignedRefInputBus 1]
[def kAUEchoGateV3_EsOutInputBus 2]
[def kAUEchoGateV3_EcoEstInputBusFreq 3]
[def kAUEchoGateV3_ResGainInputBus 4]
[def kAUEchoGateV3_NetSuppGainInputBus 5]
[def kAUEchoGateV3Param_CurrDLGain 0]

[def kAUEchoGateV3Param_SpeechProbability 2]
[def kAUEchoGateV3Param_SpeexSpeechProbability 3]
[def kAUEchoGateV3Param_RelativeDeltaEIR 4]
[def kAUEchoGateV3Param_CurrentGateScale 11]
[def kAUEchoGateV3Param_PlayBackScenario 14]
[def kAUEchoGateV3Param_AGCGain 17]
[def kAUEchoGateV3Param_PostGain 18]
[def kAUEchoGateV3Param_IRDelay 19]
[def kAUEchoGateV3Param_NoiseSPLEstimate 37]

; AGCV2
[def kAUAGCV2Param_CurrentGainDb 1]
[def kAUAGCV2Param_ExtNoiseSplEstimate 18]
[def kAUAGCV2Param_PostGainDb 27]
[def kAUAGCV2Param_ExtVadSpeechProbability 35]

;AUNeuralNet
[def kAUNeuralNetLatencySamples 14]
[def kAUNeuralNetSignalProbability 19]

; AUSignalCombiner
[def kAUSignalCombiner_NSInput 0]
[def kAUSignalCombiner_RESInput 1]

; Misc
[def kAUClipDetectorParameter_ClippingFlag 1]
[def kAUDSPGraphProperty_PropertyStripResourcePath prrp]
[def kAUNeuralNetParam_NeuralNetModelPathBaseOverride 40000]
[def kAudioUnitProperty_BypassEffect 21]

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;	I/O
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

in MicInput
in RefInput
in MicClipDataInput
out MicOutput

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;	Boxes
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
box MicClipDataChannelSelector (aufx clsl) 1 1
box MicPostSRCClipDetector (aufx cldt appl) 1 1
box MicPostSRCClipDetector_DeadEnd dead 1 0
box MicChannelSelector (aufx clsl) 1 1
box MicPreProcessingGain dbgn 1 1

; Mic ECv5
box Mic1LECV5 (aufx lec5) 2 3

; Parallel path alignments around VI DNN
box  VIAlignRefInput  delay 1 1
box  VIAlignInput     delay 1 1
box  NetDNNDelay      parameter_add 0 0

; VI DNN
box ecleeScaleForVI dbgn 1 1
box VIRESjoin      join 2 1
box VIDNN (aufx nnet appl) 1 1
box VIRESSplit     split 1 2
box VIAlignInputEclee delay 1 1

; EQ for speech and noise output streams from VIRES processing
box SpeechNoiseEQ (aufx tmst) 1 1
box SpeechNoiseEQJoiner join 2 1
box SpeechNoiseEQSplitter split 1 2

; WS support
; FFT of VIRES input
box DNN_bypass_FFT fft 1 1

; Enable/disable subset of channels for signal combiner based on eclee energy
box eclee_present parameter_greater_or_equal 0 0
box eclee_present_prop property_cast 0 0
box eclee_threshold dbgn 1 1
box eclee_threshold_dead dead 1 0

; Ambient MixBack related boxes
box NoiseExtractDiff adif 2 1
box AmbGain     dbgn 1 1    ; for scaling ambience
box VoiceAmbMix asum 2 1    ; adding scaled components

; Noise suppression
box MagDiffNSV4 (aufx mns4 appl) 4 4
box MagDiffNSV4_1_DeadEnd dead 1 0

; Components after Reverb + DNNs + MDNS
box MixFFT       fft 1 1
box AmbFFT       fft 1 1

; Constant ABLs
box UnityGain constant 0 1

; Residual echo suppressor (mic 1)
box VIEcleeFFT fft 1 1
box residual_echo adif 2 1  ; Estiamte post VI residual echo as a difference of VI input and ambient stream
box resEchoFFT fft 1 1
box EQForMDRES (aufx tmst) 1 1 ; Option to shape residual echo
box MDRESGain dbgn 1 1         ; Option to gain residual echo
box RES1V5 (aufx res5 appl) 6 4
box ResGainLimiter dbgn 1 1
box ResGainSelect amax 2 1
box ResGainApply amul 2 1
box ResOutDeadFreq dead 1 0

; Path selector for WS "flyover" path
box PathSelectorJoiner join 2 1
box PathSelector (aufx clsl) 1 1

; SignalCombiner for Parallel Paths
box SignalCombiner  (aufx sicm appl) 2 1  ; Combiner on Voice Path

; Echo gate (Mixed channel)
box GateV3 (aufx egt3 appl) 6 1
box GateRefFFT fft 1 1
box GateV3OutDeadEnd dead 1 0
box gateGain gain 1 1
box gateInputFFT fft 1 1
; Net Gain for gate
box AlignedInputFFT fft 1 1
box inputPS aabs 1 1
box outputPS aabs 1 1
box netGainForGate adiv 2 1
box EpsVal constant 0 1
box inputPSReg asum 2 1
; Boxes to override gate gain application when echo is low
box echo_absent parameter_greater_or_equal 0 0
box gateGainOverride parameter_max 0 0

; Gate output reblocker
box Outrb reblocker 1 1

; Post-gate AUs
box VAD (aufx dspg appl) 1 1
box VADDeadEnd dead 1 0
box Mute gain 1 1
box Deesser (aufx dees appl) 1 1
box AGCV2 (aufx agc2 appl) 1 1

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;	Wires
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; Inputs
wire MicClipDataInput MicClipDataChannelSelector ([IO_SAMPLE_RATE] [MIC_INPUT_CHANNEL_COUNT] [IO_BLOCK_SIZE])
wire MicClipDataChannelSelector MicPostSRCClipDetector ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire MicPostSRCClipDetector MicPostSRCClipDetector_DeadEnd ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire MicInput MicChannelSelector ([IO_SAMPLE_RATE] [MIC_INPUT_CHANNEL_COUNT] [IO_BLOCK_SIZE])
wire MicChannelSelector MicPreProcessingGain ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])

; Mic 1 LEC
wire MicPreProcessingGain (Mic1LECV5 0)   ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire RefInput (Mic1LECV5 1) ([IO_SAMPLE_RATE] [REF_INPUT_CHANNEL_COUNT] [IO_BLOCK_SIZE])

; ===============================================================================
; VI DNN and Ambience Extract
; ===============================================================================
; Input and outputs to VI-RES DNN
wire (Mic1LECV5 0)      (VIRESjoin 0) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire (Mic1LECV5 1) 		ecleeScaleForVI ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire ecleeScaleForVI 	(VIRESjoin 1) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire VIRESjoin    		(VIDNN 0)     ([IO_SAMPLE_RATE] 2 [IO_BLOCK_SIZE])
wire (VIDNN 0)    		VIRESSplit    ([IO_SAMPLE_RATE] 2 [IO_BLOCK_SIZE])

; Extract Noise from Voice + Noise --> Noise = Ambient - Voice
wire (VIRESSplit 1)       (NoiseExtractDiff 0) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire (VIRESSplit 0)       (NoiseExtractDiff 1) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])

; ===============================================================================
; Speech and noise shaping EQ
; ===============================================================================
wire (VIRESSplit 0)			(SpeechNoiseEQJoiner 0) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire (NoiseExtractDiff)		(SpeechNoiseEQJoiner 1) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire SpeechNoiseEQJoiner	SpeechNoiseEQ			([IO_SAMPLE_RATE] 2 [IO_BLOCK_SIZE])
wire SpeechNoiseEQ 			SpeechNoiseEQSplitter   ([IO_SAMPLE_RATE] 2 [IO_BLOCK_SIZE])

; ===============================================================================
; Adaptive mix of speech and ambience
; ===============================================================================
wire (SpeechNoiseEQSplitter 0) 		(VoiceAmbMix 0)   ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire (SpeechNoiseEQSplitter 1) 		AmbGain      	  ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire AmbGain      					(VoiceAmbMix 1)   ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])

wire VoiceAmbMix MixFFT ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire AmbGain     AmbFFT ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])

; Align VI input with VI output
wire (Mic1LECV5 0) VIAlignInput ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire (Mic1LECV5 1) VIAlignInputEclee ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire (Mic1LECV5 2) VIAlignRefInput ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])

; ===============================================================================
; MD Noise suppressor operating on DNN outputs
; ===============================================================================
wire MixFFT      		(MagDiffNSV4 0) (freq [IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire AmbFFT      		(MagDiffNSV4 1) (freq [IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire UnityGain         	(MagDiffNSV4 2) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire VIAlignInput      	(MagDiffNSV4 3) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire (MagDiffNSV4 0)   	(SignalCombiner [kAUSignalCombiner_NSInput]) (freq [IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire (MagDiffNSV4 1)   	(MagDiffNSV4_1_DeadEnd 0) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])

; ===============================================================================
; MD-RES References
; Unlike other devices, there is no natural MD-RES reference here based on a sensing mic.
; We use the second VI output (S+N) and subtract it from the aligned input (S+N+E) to get 
; the echo in the VI ambient stream.
; ===============================================================================
wire VIAlignInputEclee VIEcleeFFT ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire VIAlignInput 		(residual_echo 0) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire (VIRESSplit 1) 	(residual_echo 1) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire residual_echo 		EQForMDRES ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire EQForMDRES 		MDRESGain ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire MDRESGain 			resEchoFFT ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])

; ===============================================================================
; Post VI Residual echo suppressor
; ===============================================================================
wire MixFFT       		(RES1V5 [kAUResidualEchoSuppressorV5Bus_InMainFreq]) (freq [IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire VIEcleeFFT 		(RES1V5 [kAUResidualEchoSuppressorV5Bus_InEcleeFreq]) (freq [IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire GateRefFFT 		(RES1V5 [kAUResidualEchoSuppressorV5Bus_InRefFreq]) (freq [IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire (MagDiffNSV4 2)    (RES1V5 [kAUResidualEchoSuppressorV5Bus_InNsGainTime]) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire (MagDiffNSV4 3)	(RES1V5 [kAUResidualEchoSuppressorV5Bus_InExtNoiseTime]) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire resEchoFFT         (RES1V5 [kAUResidualEchoSuppressorV5Bus_InPolyEcleeFreq]) (freq [IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire (RES1V5 [kAUResidualEchoSuppressorV5Bus_OutMainFreq]) 		(ResOutDeadFreq 0) (freq [IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])


; In case we want to use external VAD for RES
wireParam (VIDNN [kAUNeuralNetSignalProbability]) (RES1V5 [kAUResidualEchoSuppressorV5param_ExternalVAD]) true

; In echo only situations, the RES calculates the gains to be applied to be 
; between <paramID_1> and -50dB for frequency up to <paramID_26>. We use this value
; to limit the gain that can be applied by the RES
wire UnityGain ResGainLimiter ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire (RES1V5 [kAUResidualEchoSuppressorV5Bus_OutGainTime]) (ResGainSelect 0) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire ResGainLimiter (ResGainSelect 1) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire MixFFT (ResGainApply 0) (freq [IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire (ResGainSelect) (ResGainApply 1) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire ResGainApply (SignalCombiner [kAUSignalCombiner_RESInput]) (freq [IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])

; ===============================================================================
; For WS mode, we want to use the input to the VIRES as the output when there is
; no echo. In presence of echo, we want to use the VIRES output with 0dB mixback,
; i.e. use VIRES as a echo suppressor and then process that signal through RES,
; NS, etc.
; For standard mode, we never use the input to VIRES as the output. We always
; want to enable use of RES and NS. 
; We achieve this based on the level of eclee. In WS mode, if eclee is present,
; we add RES and NS to the signal combiner and disable combining the VIRES
; input. In standard mode, we bias the threshold such that eclee is always present
; and thus VIRES input is never combiner. This biasing is implemented here.
; ===============================================================================
wire VIAlignInput eclee_threshold ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire eclee_threshold eclee_threshold_dead ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])

wireParam (Mic1LECV5 [EC_EcleeEnergy]) (eclee_present 0 input 0) true
wireParam (eclee_threshold 0 0 0) (eclee_present 0 input 1) true
wireParam (eclee_present 0 output 0) (eclee_present_prop 0 input 0) true
wireProperty (eclee_present_prop ui32 output 0) (PathSelector slcm)

; ===============================================================================
; Path selector to switch between echo control on or off
; ===============================================================================
; Wide spectrum channel in no echo
wire VIAlignInput DNN_bypass_FFT ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire DNN_bypass_FFT (PathSelectorJoiner 0) (freq [IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire SignalCombiner (PathSelectorJoiner 1) (freq [IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE]) 
wire PathSelectorJoiner PathSelector  (freq [IO_SAMPLE_RATE] 2 [IO_BLOCK_SIZE]) 

; ===============================================================================
; Mixed Signal: Echo gate
; ===============================================================================
; The net NS gain needed by the Gate is the gain applied by ALL the suppressors,
; in this case that includes VIRES, MagDiffNS, and the RES.
; Instead of accumulating all gains, it is easier to just get the output/input ratio
; for this section of processing.
wire VIAlignInput AlignedInputFFT ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE]) 
wire AlignedInputFFT inputPS (freq [IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE]) 
wire SignalCombiner outputPS (freq [IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE]) 
param eps1 1e-4
wireGraphParam eps1 (EpsVal 0)
wire inputPS (inputPSReg 0) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE]) 
wire EpsVal (inputPSReg 1) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE]) 
wire outputPS (netGainForGate 0) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE]) 
wire inputPSReg (netGainForGate 1) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE]) 

wire VIAlignRefInput GateRefFFT ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire PathSelector (GateV3 [kAUEchoGateV3_EsOutInputBus]) (freq [IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE]) 
wire GateRefFFT (GateV3 [kAUEchoGateV3_TimeAlignedRefInputBus]) (freq [IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE]) ; ref signal 
wire (RES1V5 [kAUResidualEchoSuppressorV5Bus_OutEstResedEcoPS]) (GateV3 [kAUEchoGateV3_EcoEstInputBus]) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE]) ; time-domain input used to establish formats only
wire (RES1V5 [kAUResidualEchoSuppressorV5Bus_OutEcleeFreq]) (GateV3 [kAUEchoGateV3_EcoEstInputBusFreq]) (freq [IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE]) ; linear echo estimate in freq
wire (RES1V5 [kAUResidualEchoSuppressorV5Bus_OutGainTime]) (GateV3 [kAUEchoGateV3_ResGainInputBus]) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE]) ; RES gain
wire netGainForGate (GateV3 [kAUEchoGateV3_NetSuppGainInputBus]) ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE]) ; net suppression gain
wire GateV3 GateV3OutDeadEnd ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])

wire PathSelector gateInputFFT (freq [IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE]) 
wire gateInputFFT gateGain ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])

; Echo VAD is low when echo is present, high when echo is absent or during DT
; The goal is to use a gain of 1 during DT and when no echo is present
param evth 0.6 ; echo VAD threshold to decide whether to use gate or not.
wireParam (VIDNN [kAUNeuralNetSignalProbability]) (echo_absent 0 input 0)
wireGraphParam evth (echo_absent 0 input 1)
wireParam (echo_absent 0 output 0) (gateGainOverride 0 input 0)
wireParam (GateV3 [kAUEchoGateV3Param_CurrentGateScale]) (gateGainOverride 0 input 1)
wireParam (gateGainOverride 0 output 0) (gateGain 0 0 0)
wire gateGain Outrb   ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE]) ; Net gain output reblocked 

; ===============================================================================
; VAD to support RESs and AGC
; ===============================================================================
wire Outrb  VAD    ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire VAD VADDeadEnd  ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])

; ===============================================================================
; Output AU chain
; ===============================================================================
wire Outrb Mute     ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire Mute Deesser      ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire Deesser AGCV2   ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])
wire AGCV2 MicOutput ([IO_SAMPLE_RATE] 1 [IO_BLOCK_SIZE])

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; 	Parameters
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
param uior 0 in ; vp::vx::Graph_Parameter_ID::UI_Orientation
wireGraphParam uior (GateV3 [kAUEchoGateV3Param_PlayBackScenario])

param ulvm 0 in ; vp::vx::Graph_Parameter_ID::Uplink_Near_End_Voice_Output_Mute
wireGraphParam ulvm (Mute 1)

param dlgn 0 in ; downlink gain (dB)
wireGraphParam dlgn (GateV3 [kAUEchoGateV3Param_CurrDLGain])

param uspb 0 out ; vp::vx::Graph_Parameter_ID::Uplink_Speech_Probability_Boolean_Value
wireGraphParam uspb (VAD uspb)

param uspf 0 out ; vp::vx::Graph_Parameter_ID::Uplink_Speech_Probability_Float_Value
wireGraphParam uspf (VAD uspf)

param unit 1 in ; unity constant parameter (generic unit)
wireGraphParam unit (UnityGain 0) ; zero input

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; 	Parameter wires
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; EC to RES
wireParam (Mic1LECV5 [EC_SxxTimeAligned]) (RES1V5 [kAUResidualEchoSuppressorV5param_Speex_ECSxxTimeAligned]) true
wireParam (Mic1LECV5 [EC_MicEcleeXcorr]) (RES1V5 [kAUResidualEchoSuppressorV5param_Speex_ECMicEcleeXcorr]) true

; Parameters to Gate
wireParam (Mic1LECV5 [EC_RelativeDeltaEIR]) (GateV3 [kAUEchoGateV3Param_RelativeDeltaEIR]) true
wireParam (Mic1LECV5 [EC_IRDelay]) (GateV3 [kAUEchoGateV3Param_IRDelay]) true
wireParam (MagDiffNSV4 [kAUMDNSParam_SpeechProbability]) (GateV3 [kAUEchoGateV3Param_SpeexSpeechProbability]) true
wireParam (AGCV2 [kAUAGCV2Param_CurrentGainDb]) (GateV3 [kAUEchoGateV3Param_AGCGain])
wireParam (AGCV2 [kAUAGCV2Param_PostGainDb]) (GateV3 [kAUEchoGateV3Param_PostGain])
wireParam (AGCV2 [kAUAGCV2Param_PostGainDb]) (RES1V5 [kAUResidualEchoSuppressorV5param_Speex_PostGain])

; Parameters to AGC 
wireParam (VAD uspb) (AGCV2 [kAUAGCV2Param_ExtVadSpeechProbability]) true
wireParam (MagDiffNSV4 [kAUMDNSParam_NoiseSplEstimate]) (AGCV2 [kAUAGCV2Param_ExtNoiseSplEstimate]) true

; Delay for parallel paths
wireParam (VIDNN [kAUNeuralNetLatencySamples]) (VIAlignInput 0 0 0)
wireParam (VIDNN [kAUNeuralNetLatencySamples]) (VIAlignInputEclee 0 0 0)
wireParam (VIDNN [kAUNeuralNetLatencySamples]) (VIAlignRefInput 0 0 0)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; 	Properties
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

property agcb in ; vp::vx::Graph_Property_ID::Uplink_AGC_Bypass
wireGraphProperty agcb (AGCV2 [kAudioUnitProperty_BypassEffect])

property tudp in ; vp::vx::Graph_Property_ID::Tuning_Directory_Path
wireGraphProperty tudp (VAD [kAUDSPGraphProperty_PropertyStripResourcePath])
wireGraphProperty tudp (VIDNN [kAUNeuralNetParam_NeuralNetModelPathBaseOverride])
