ALSA multiple playback and record

Pulseaudio gives some advantages over a bare alsa setup, but it has many drawbacks I won’t discuss here.

You can get some of the main advantages of alsa+pulseaudio on your SBC by setting up a loopback device and using ‘dmix’ to handle multiple streams of audio.

1) Loopback device: This lets you record what your soundcard is playing. Necessary to run visualizers as well. YOU NEED module snd-aloop available for your kernel. MANY kernel builders FORGET to enable alsa snd-aloop. Please don’t do this! Build it as a module or right in the kernel! THANKS.
Alsa Project full-duplex loopback driver documentation

If you have module snd-aloop, you can modprobe snd-aloop or automatically load it on boot the usual way.

2) Create an alsa configuration file in your home directory ~/.asoundrc (Thanks to Anko from Frankfurt!)

# set card number to the number of your output alsa device
# list devices with aplay -l
# in my case it is:
#     card 2: Device [USB PnP Audio Device], device 0: USB Audio pcm.snd_card { 
    type hw
    card 2
}

ctl.!default { # default control; alsamixer will use this
    type hw
    card 2
}

# software mixer for sound card
pcm.dmixer {
    type dmix
    ipc_key 1024
    ipc_perm 0666 # allow other users
    slave.pcm "snd_card"
    slave {
        period_time 0
        period_size 1024
        buffer_size 4096
        channels 2 # must match bindings
    }
    bindings {
        0 0
        1 1
    }
}

# software mixer for loopback device
pcm.dmixerloop {
    type dmix
    ipc_key 2048
    ipc_perm 0666 # allow other users
    slave.pcm "hw:Loopback,0,0"
    slave {
        period_time 0
        period_size 1024
        buffer_size 4096
        channels 2 # must match bindings
    }
    bindings {
        0 0
        1 1
    }
}

# allows multiple programs to capture simultaneously
pcm.dsnooper {
    type dsnoop
    ipc_key 2048
    ipc_perm 0666 
    slave.pcm "snd_card"
    slave 
    {
        period_time 0
        period_size 1024
        buffer_size 4096
        channels 2 
    }
    bindings {
        0 0
        1 1
    }
}

pcm.!default {
    type asym
    playback.pcm "out"
    capture.pcm "dsnooper"
}

# Multi, splitting onto usual card and loopback
pcm.out {
    type plug
    slave.pcm {
        type multi
        slaves {
            a { channels 2 pcm "dmixer" }
            b { channels 2 pcm "dmixerloop" }
        }
        bindings {
            0 { slave a channel 0 }
            1 { slave a channel 1 }
            2 { slave b channel 0 }
            3 { slave b channel 1 }
        }
    }
    ttable [
        [ 1 0 1 0 ]   # left  -> a.left,  b.left
        [ 0 1 0 1 ]   # right -> a.right, b.right
    ]
}

This has fixed all my years of ALSA headaches. Hope it helps to share to the Khadas community!

1 Like