# The following environment variables are used in this config:
#
#    ALSA_DEFAULT_PCM
#    ALSA_DEFAULT_CTL
#    ALSA_HIFI_PCM
#    ALSA_HIFI_CTL
#    ALSA_BLUETOOTH_MAC
#
# All are optional.
# HIFI should use the better sounding audio interface, if many exist. Defaults to DEFAULT if not set in environment.
# DEFAULT uses system_default if not set. See below for system_default description.
# BLUETOOTH_MAC is used for BlueALSA device.
#
# The point of the environmental variables is to support multiple audio devices, some of which might not use a mixer.
# One may define a HIFI device for use with certain media players for example, completely skipping resampling and basically achieving bit-perfect audio.
#
# Control devices corresponding to PCM devices are defined for program compatibility.
#
# To prevent reference loops, default PCM can be overwritten from this file, but system_default should always point to a system specific device, not defined here. For example this chain works:
#
#    ALSA_DEFAULT_PCM = eq
#    eq.slave.pcm = system_default
#    pcm.system_default = "pcm.mydevice"
#
# Write system specific (real) devices to /opt/system_alsa_devices.conf.
# In the file, define at least these two devices so that they point to some device defined in the same file:
# pcm.system_default = "pcm.my_device"
# ctl.system_default = "ctl.my_ctl"

</opt/system_alsa_devices.conf>

##################################
########## ABSTRACTIONS ##########
##################################

# Default device. Generic abstraction, does not point to any real device.
pcm.!default {
    @func refer
    name { @func concat
        strings [ "pcm."
            { @func getenv
                vars [ ALSA_DEFAULT_PCM ]
                default "system_default"
            }
        ]
    }
}
ctl.!default {
    @func refer
    name { @func concat
        strings [ "ctl."
            { @func getenv
                vars [ ALSA_DEFAULT_CTL ]
                default "system_default"
            }
        ]
    }
}

# Null output.
pcm.null {
    type null
}

# The go-to Hi-Fi device. May be used to override mixing/resampling etc.
pcm.hifi {
    @func refer
    name { @func concat
        strings [ "pcm."
            { @func getenv
                vars [ ALSA_HIFI_PCM ]
                default "default"
            }
        ]
    }
    hint {
        show on
        description "Hi-Fi output"
    }
}
ctl.hifi {
    @func refer
    name { @func concat
        strings [ "ctl."
            { @func getenv
                vars [ ALSA_HIFI_CTL ]
                default "default"
            }
        ]
    }
}

# General surround downmix movie setup.
pcm.movie {
    type plug
    slave {
        format float
        pcm {
            type multi
            slaves.speakers {
                pcm "hifi"
                channels 2
            }
            bindings.0.slave speakers
            bindings.0.channel 0
            bindings.1.slave speakers
            bindings.1.channel 1
        }
    }
    route_policy duplicate
    ttable {
        0.0 0.185
        1.1 0.185
        2.0 0.185
        3.1 0.185
        4.0 0.13
        4.1 0.13
        5.0 0.5
        5.1 0.5
    }
    hint {
        show on
        description "Movie setup, downmix 5.1 to stereo, custom matrix"
    }
}

# Another general movie setup with balanced sound matrix.
pcm.movie_balanced_matrix {
    type plug
    slave {
        format float
        pcm {
            type multi
            slaves.speakers {
                pcm "hifi"
                channels 2
            }
            bindings.0.slave speakers
            bindings.0.channel 0
            bindings.1.slave speakers
            bindings.1.channel 1
        }
    }
    route_policy duplicate
    ttable {
        0.0 0.29289
        1.1 0.29289
        2.0 0.29289
        3.1 0.29289
        4.0 0.20711
        4.1 0.20711
        5.0 0.20711
        5.1 0.20711
    }
    hint {
        show on
        description "Movie setup, downmix 5.1 to stereo, balanced matrix"
    }
}

# Plug device for bs2b.
pcm.binaural {
    type plug
    slave {
        rate 44100
        pcm {
            type ladspa
            slave.pcm "system_default"
            path "/usr/lib/ladspa"
            plugins [ {
                label bs2b # Bauer stereophonic-to-binaural DSP
                input {
                    # Lowpass frequency [Hz], feeding level [dB].
                    # 650, 9.5 = Jan Meier's preset.
                    controls [ 650 9.5 ]
                }
            } ]
        }
    }
    hint {
        show on
        description "Bauer stereophonic-to-binaural DSP @ 44.1 kHz"
    }
}

# Software volume control.
# Without using the device first, sometimes it is not visible to applications, e.g. volumeicon.
# To fix this, you can play a dummy wav first in a script: aplay -q -D softvol dummy.wav
pcm.softvol {
    @args [ CARD ]
    type softvol
    slave {
        pcm "system_default"
    }
    control {
        name "Soft Master"
        @args.CARD {
            type string
            default {
                @func refer
                name 'system_default.pcm.card'
            }
        }
    }
    hint {
        show on
        description "Software volume control"
    }
}

# WAV recording device.
pcm.wav {
    type file
    slave.pcm "system_default"
    format "wav"
    file { @func concat
        strings [
            { @func getenv
                vars [ HOME ]
                default "/dev/shm"
            }
        "/alsa_out.wav" ]
    }
    hint {
        show on
        description "WAV recording"
    }
}

# Virtual equalizer device.
pcm.eq {
    type plug
    slave.pcm {
        type equal
        slave.pcm "system_default"
    }
    hint {
        show on
        description "Equalizer"
    }
}
ctl.eq {
    type equal
}

# Bluetooth device.
# The control device is implicitly called ctl.bluealsa.
# Thus the control device defined here is for compatibility reasons only.
# Also notice the --a2dp-force-audio-cd parameter for bluealsa.
pcm.bluetooth {
    type plug
    slave.pcm {
        type bluealsa
        device { @func getenv
            vars [ ALSA_BLUETOOTH_MAC ]
            default "00:00:00:00:00:00"
        }
        profile "a2dp"
    }
    hint {
        show on
        description "Bluetooth audio device"
    }
}
ctl.bluetooth {
    type bluealsa
}

##########################
########## LOOP ##########
##########################

# Loop device substreams in device 0 correspond to substreams in device 1.
# In reality there are no ins and outs, just ends: they work both ways.

pcm.loop {
    type asym
    playback.pcm "loop_playback_in"
    capture.pcm "loop_record_out"
    hint {
        show on
        description "Asymmetric ALSA loopback device"
    }
}
ctl.loop {
    type hw
    card Loopback
}

pcm.loop_playback_in {
    type plug
    slave.pcm "hw:Loopback,0,0"
    hint {
        show on
        description "ALSA playback loop in"
    }
}

pcm.loop_playback_out {
    type plug
    slave.pcm "hw:Loopback,1,0"
    hint {
        show on
        description "ALSA playback loop out"
    }
}

# Mixing loopback device.
pcm.loop_playback_in_mix {
    type plug
    slave.pcm {
        type dmix
        ipc_key 10000
        slave {
            pcm "hw:Loopback,0,0"
            format S32_LE
            periods 4
            period_size 128
            rate 44100
        }
    }
    hint {
        show on
        description "Loopback in mixer device, outputs to loop_playback_out"
    }
}

pcm.loop_record_in {
    type plug
    slave.pcm "hw:Loopback,0,1"
    hint {
        show on
        description "ALSA record loop in"
    }
}

pcm.loop_record_out {
    type plug
    slave.pcm "hw:Loopback,1,1"
    hint {
        show on
        description "ALSA record loop out"
    }
}

# The vm devices are for use with virtual machines.
# KVM audio requires a hardware device but a loopback device is fine.

pcm.loop_vm_dac_in {
    type plug
    slave.pcm "hw:Loopback,0,4"
    hint {
        show on
        description "Loop: VM DAC in (use in guest)"
    }
}

pcm.loop_vm_dac_out {
    type plug
    slave.pcm "hw:Loopback,1,4"
    hint {
        show on
        description "Loop: VM DAC out (use in host)"
    }
}

pcm.loop_vm_adc_in {
    type plug
    slave.pcm "hw:Loopback,0,5"
    hint {
        show on
        description "Loop: VM ADC in (use in host)"
    }
}

pcm.loop_vm_adc_out {
    type plug
    slave.pcm "hw:Loopback,1,5"
    hint {
        show on
        description "Loop: VM ADC out (use in guest)"
    }
}
