# Stereo to 5.1 upmix sink
#
# Copy this file into a conf.d/ directory such as
# ~/.config/pipewire/filter-chain.conf.d/
#
context.modules = [
    {   name = libpipewire-module-filter-chain
        args = {
            node.description = "Upmix Sink"
            filter.graph = {
                nodes = [
                    {   type = builtin name = copyFL label = copy }
                    {   type = builtin name = copyFR label = copy }
                    {   type = builtin name = copyOFL label = copy }
                    {   type = builtin name = copyOFR label = copy }
		    {
		        # this mixes the front left and right together
			# for filtering the center and subwoofer signal-
                        name   = mixF
                        type   = builtin
                        label  = mixer
                        control = {
                          "Gain 1" = 0.707
                          "Gain 2" = 0.707
                        }
                    }
                    {   
		        # filtering of the FC and LFE channel. We use a 2 channel
			# parametric equalizer with custom filters for each channel.
			# This makes it possible to run the filters in parallel.
                        type = builtin
                        name = eq_FC_LFE
                        label = param_eq
                        config = {
                            filters1 = [
			       # FC is a crossover filter (with 2 lowpass biquads)
                               { type = bq_lowpass freq = 12000 },
                               { type = bq_lowpass freq = 12000 },
                            ]
                            filters2 = [
			       # LFE is first a gain adjustment (with a highself) and
			       # then a crossover filter (with 2 lowpass biquads)
                               { type = bq_highshelf freq = 0 gain = -20.0 }, # gain -20dB
                               { type = bq_lowpass freq = 120 },
                               { type = bq_lowpass freq = 120 },
                            ]
		        }
                    }
		    {
		        # for the rear channels, we subtract the front channels. Do this
			# with a mixer with negative gain to flip the sign.
                        name   = subR
                        type   = builtin
                        label  = mixer
                        control = {
                          "Gain 1" = 0.707
                          "Gain 2" = -0.707
                        }
                    }
                    {
		        # a delay for the rear Left channel. This can be
			# replaced with the convolver below. */
                        type   = builtin
                        name   = delayRL
                        label  = delay
                        config = { "max-delay" = 1 }
                        control = { "Delay (s)" = 0.012 }
                    }
                    {
		        # a delay for the rear Right channel. This can be
			# replaced with the convolver below. */
                        type   = builtin
                        name   = delayRR
                        label  = delay
                        config = { "max-delay" = 1 }
                        control = { "Delay (s)" = 0.012 }
                    }
                    {
		        # an optional convolver with a hilbert curve to
			# change the phase. It also has a delay, making the above
			# left delay filter optional.
                        type   = builtin
                        name   = convRL
                        label  = convolver
                        config = {
                            gain = 1.0
			    delay = 0.012
                            filename = "/hilbert"
			    length = 33
			    latency = 0.0
			}
		    }
                    {
		        # an optional convolver with a hilbert curve to
			# change the phase. It also has a delay, making the above
			# right delay filter optional.
                        type   = builtin
                        name   = convRR
                        label  = convolver
                        config = {
                            gain = -1.0
			    delay = 0.012
                            filename = "/hilbert"
			    length = 33
			    latency = 0.0
			}
		    }
                 ]
                 links = [
                     { output = "copyFL:Out"  input="mixF:In 1" }
                     { output = "copyFR:Out"  input="mixF:In 2" }
                     { output = "copyFL:Out"  input="copyOFR:In" }
                     { output = "copyFR:Out"  input="copyOFL:In" }
                     { output = "mixF:Out"  input="eq_FC_LFE:In 1" }
                     { output = "mixF:Out"  input="eq_FC_LFE:In 2" }
                     { output = "copyFL:Out"  input="subR:In 1" }
                     { output = "copyFR:Out"  input="subR:In 2" }
		     # here we can choose to just delay or also convolve
		     #
                     #{ output = "subR:Out"  input="delayRL:In" }
                     #{ output = "subR:Out"  input="delayRR:In" }
                     { output = "subR:Out"  input="convRL:In" }
                     { output = "subR:Out"  input="convRR:In" }
                 ]
                 inputs = [ "copyFL:In" "copyFR:In" ]
                 outputs = [ 
		              "copyOFL:Out"
			      "copyOFR:Out"
		              "eq_FC_LFE:Out 1"
			      "eq_FC_LFE:Out 2"
		              # here we can choose to just delay or also convolve
                              #
		              #"delayRL:Out"
			      #"delayRR:Out"
		              "convRL:Out"
			      "convRR:Out"
			   ]
            }
            capture.props = {
                node.name = "effect_input.upmix_5.1"
                media.class = "Audio/Sink"
                audio.position = [ FL FR ]
            }
            playback.props = {
                node.name = "effect_output.upmix_5.1"
                audio.position = [ FL FR FC LFE RL RR ]
                stream.dont-remix = true
                node.passive = true
            }
        }
    }
]

