Skip to content

Instantly share code, notes, and snippets.

@brndd
Last active April 28, 2024 17:15
Show Gist options
  • Save brndd/ccec98a575f7c0422d50402937439227 to your computer and use it in GitHub Desktop.
Save brndd/ccec98a575f7c0422d50402937439227 to your computer and use it in GitHub Desktop.

Get more out of your USB audio interface with ALSA UCM configuration

Many audio enthusiasts these days use USB audio interfaces as the primary sound device on their computer. These ethusiast/studio devices tend to offer better audio quality and more hardware audio channels than the common integrated audio chips found in virtually every computer, and as they are usually USB class-compliant, they have good support on Linux.

One common problem with these devices is that the physical channel mapping on the device does not match the channel mapping exposed in software. For example, a device with two stereo outputs might show up as having a single 4-channel surround output in software. This is simply how the device reports itself to the driver, so it is strictly speaking an issue with the device itself rather than a software issue — however, we can solve the issue in software.

A common solution to this problem on Linux is to use PulseAudio, PipeWire or JACK to create virtual devices that route the audio to the correct channels on the physical device. In this article we will detail a lesser known but (in the author's opinion) more apt method: ALSA Use Case Manager profiles.

What is the ALSA Use Case Manager?

The ALSA Use Case Manager is a mechanism for controlling complex audio hardware establishing a relationship between hardware configurations and meaningful use cases that the end-user can relate with. (alsaucm man page)

In short, UCM is a configuration system for poorly behaving sound devices. It allows for per-device configuration files that tell ALSA (and other relevant parts of the system) how to present the device to the user in a way that makes sense. It is used to correct the behaviour of devices that do not work as expected out of the box, which is exactly the case for many USB audio interfaces.

The nice part about UCM configuration is that it is shipped with ALSA. This means that the correct configuration, once created by a helpful contributor, will be automatically distributed to every user of ALSA via updates, improving Linux audio for everybody! Well, for everyone who owns the device in question, at least.

This does come with the caveat that UCM configuration (as presented in this guide) is not designed for system-local configuration. For local configuration you may be able to adapt this guide for use with asoundrc, as described in the ALSA wiki: https://www.alsa-project.org/wiki/Asoundrc

Creating UCM2 configuration

For this article, we will be using configuration for the Behringer U-Phoria UMC204HD audio interface as an example. This device has two problems out of the box that we seek to correct: the two stereo outputs appear as a single 4-channel output, and the two mono inputs appear as a single 2-channel input. We would like to split these pairs up so that what we see in software matches the physical layout of the device. We also need to create some rules for volume controls so that the controls of the device (shown in e.g. alsamixer) correspond to the new channel mapping we wish to create.

UCM2 configuration lives under /usr/share/alsa/ucm2/ on Fedora. Note that there's also plain UCM configuration without the '2', but that is outdated and obsolete so we need not concern ourselves with it.

The relevant ALSA documentation lives at https://www.alsa-project.org/alsa-doc/alsa-lib/, but the author of this article has found it, at times, to be somewhat less informative than one might like (to ALSA's credit, it is a work in progress). This is why this guide was written.

For USB audio interfaces in particular, the directory of interest is /usr/share/alsa/ucm2/USB-Audio/. There are a few things we need to do here:

  1. Edit USB-Audio.conf to add a rule for our device.
  2. Create a directory to categorize our configs by manufacturer, if an appropriate one does not yet exist.
  3. Create two configuration files specific to our device under the manufacturer directory; in our case, Behringer/UMC204HD.conf and Behringer/UMC204HD-HiFi.conf.

Let us now walk through the process step-by-step.

Step 0: Noting down some information about our device

We will need a couple of identifiers for our device that will be used throughout the config creation process, so let's find out what those are first and write them down.

First, we need the USB device ID of our device. You can find this by running lsusb and looking for it:

$ lsusb
[...]
Bus 005 Device 003: ID 1397:0508 BEHRINGER International GmbH UMC204HD 192k
[...]

The identifier here is 1397:0508.

Next, we need the name ALSA uses for our device. We can find this via cat /proc/asound/cards, assuming the device is plugged in:

$ cat /proc/asound/cards
[...]
1 [U192k          ]: USB-Audio - UMC204HD 192k
                    BEHRINGER UMC204HD 192k at usb-0000:00:14.0-7.3, high speed
[...]

The name we want here is the one within square brackets: U192k.

Finally, let's see if our card has any controls that need mapping. Run amixer -c U192k controls (replacing U192k with the identifier of your card). The output will be something like this:

$ amixer -c U192k controls
numid=7,iface=CARD,name='UMC204HD 192k Internal Clock Validity'
numid=8,iface=MIXER,name='Mic Capture Switch'
numid=9,iface=MIXER,name='Mic Capture Switch',index=1
numid=10,iface=MIXER,name='Mic Capture Volume'
numid=11,iface=MIXER,name='Mic Capture Volume',index=1
numid=3,iface=MIXER,name='UMC204HD 192k Output Playback Switch'
numid=4,iface=MIXER,name='UMC204HD 192k Output Playback Switch',index=1
numid=5,iface=MIXER,name='UMC204HD 192k Output Playback Volume'
numid=6,iface=MIXER,name='UMC204HD 192k Output Playback Volume',index=1
numid=2,iface=PCM,name='Capture Channel Map'
numid=1,iface=PCM,name='Playback Channel Map'

If you can only see "Master Playback Volume", "Master Playback Switch", "Capture Volume" and "Capture Switch" (or something along these lines), your card probably has no special controls to worry about. In our case, though, we can see that there are a few controls, so we need to configure those too. We can run amixer -c U192k contents to see more details about the controls and guess what they do (the output can be long, so the following is an excerpt):

[...]
numid=18,iface=MIXER,name='Mic Capture Volume'
; type=INTEGER,access=rw---R--,values=2,min=0,max=127,step=0
: values=127,127
| dBminmax-min=-127.00dB,max=0.00dB
[...]
numid=13,iface=MIXER,name='UMC204HD 192k Output Playback Volume'
; type=INTEGER,access=rw---R--,values=4,min=0,max=127,step=0
: values=127,127,127,127
| dBminmax-min=-127.00dB,max=0.00dB
[...]

We can see that the ones labeled "Mic Capture" are stereo controls, and may presume that the left channel maps to Input 1 on our device and the right channel to Input 2. The ones labeled "UMC204HD 192k Output Playback" are 4-channel controls, where the first two channels correspond to the output labeled Line A on our device, and the last two to Line B. The rest of the controls don't matter to us, since we are just splitting channels.

If you have any doubts about what each control does, you can try adjusting them in alsamixer while playing or recording audio and seeing what happens. Note that on a live system alsamixer may display some autogenerated controls that might not exactly match what the amixer output shows; you can re-run amixer -c U192k contents after adjusting the controls in alsamixer and seeing whicih values, if any, change there.

Write down the USB ID of your device and the names of the controls you need to remap and move on to the next section.

Step 1: USB-Audio.conf

Let's begin by modifying /usr/share/alsa/ucm2/USB-Audio/USB-Audio.conf and adding a new section for the device we are configuring. We add the following among the other device definitions, preferably near the end of the file but before the boilerplate (which begins with If.mixremap { at the time of writing):

If.behringer-umc204hd { #The name specified here does not really matter; it's just the name of this If block
    Condition { #The actual condition we are checking in this If block
        Type String
        Haystack "${CardComponents}" #Where are we looking
        Needle "USB1397:0508" #What are we looking for?
    }
    True.Define { #If a match is found, define some variables
        ProfileName "Behringer/UMC204HD" #This is the config file we want to load
        MixerRemap yes #We set this to yes as we are remapping mixer controls; if you found no controls in Step 0, remove this line
    }
}

UCM2 configs can be quite complicated as they can contain a lot of logic and other nuances, but this is quite straightforward. I have commented each line with a short explanation of what it does.

In all likelihood your card can be detected with this exact same pattern of matching an USB ID. Some cards have many different models or revisions; for such cards you will have to use RegexMatch instead of a simple string search. Have a look at the other entries in USB-Audio.conf for examples of this.

The ProfileName line is where we define the name of the config file we're about to create in the next step, without the .conf extension.

Step 2: Device configuration file

Next up we create the configuration file we referred to on the ProfileName line of the previous step; /usr/share/alsa/ucm2/USB-Audio/Behringer/UMC204HD.conf. In our case the Behringer directory does not exist yet, so we have to create it, and then create a configuration file within.

This configuration file is also but a little stub:

Comment "Behringer UMC204HD" #The human-readable name of the device; this is freeform and may be shown to users
SectionUseCase."HiFi" { #This is freeform, but should preferably be a use case "verb" (see explanation)
        Comment "Default" #The human-readable name of the profile; this is freeform and may be shown to users in e.g. pavucontrol
        File "/USB-Audio/Behringer/UMC204HD-HiFi.conf" #The file which contains the profile config
}

For the list of valid use case verbs, see the ALSA documentation here: https://www.alsa-project.org/alsa-doc/alsa-lib/group__ucm.html. For a USB interface you will typically want to pick "HiFi".

The file specified here must have its path defined precisely as such, beginning from the root ucm2 directory.

Step 3: Device verb configuration file

Last but certainly not least we must create the verb configuration file we referred to in the previous section. This file will contain all of the actual rules for configuring our device. It is also quite long, so we shall tackle it one step at a time. This is where most of the differences between cards will also come into play, but for splitting channels it should be fairly similar for different devices.

We create /usr/share/alsa/ucm2/USB-Audio/Behringer/UMC204HD-HiFi.conf and continue on.

Device definitions

Let us begin by creating SectionDevice blocks for each physical port on our card. This is the layout we want the card to appear with to the user. I will only comment one block to avoid repetition, as the config keys are essentially the same for all four (with slight name differences for playback and capture).

SectionDevice."Line1" { #"Line1" here defines the type of device this is. See explanation below.
    Comment "Line A" #This is the human-readable name of this device. It is what the user will see in their audio mixer.
    Value {
        PlaybackPriority 200 #This is used to decide the default device. Higher number = higher piriority.
        PlaybackChannels 2 #How many channels device has; this one is a stereo output on the physical device.
        PlaybackPCM "umc204hd_line1:${CardId}" #The name defined here ("umc204hd_line1") will be used as the name of a different config block later. The :${CardId} part is an argument passed to that config block.
        PlaybackMixer "default:${CardId}" #If your card has no controls, omit this line; otherwise leave it as is (it should be "default" for all cards).
        PlaybackMixerElem "Line A" #This is the user-facing name of the control, shown in eg. alsamixer.
    }
}

SectionDevice."Line2" {
    Comment "Line B"

    Value {
        PlaybackPriority 100
        PlaybackChannels 2
        PlaybackPCM "umc204hd_line2:${CardId}"
        PlaybackMixer "default:${CardId}"
        PlaybackMixerElem "Line B"
    }
}

SectionDevice."Mic1" {
    Comment "Input 1"

    Value {
        CapturePriority 200
        CaptureChannels 1
        CapturePCM "umc204hd_mic1:${CardId}"
        CaptureMixer "default:${CardId}"
        CaptureMixerElem "Input 1"
    }
}

SectionDevice."Mic2" {
    Comment "Input 2"

    Value {
        CapturePriority 100
        CaptureChannels 1
        CapturePCM "umc204hd_mic2:${CardId}"
        CaptureMixer "default:${CardId}"
        CaptureMixerElem "Input 2"
    }
}

The string after SectionDevice defines the type of the device. See the ALSA documentation for more information: https://www.alsa-project.org/alsa-doc/alsa-lib/group__ucm__conf.html#autotoc_md9. It is supposedly recommended that they be one of the SND_USE_CASE_DEV constants listed on this page: https://www.alsa-project.org/alsa-doc/alsa-lib/group__ucm.html#gaa7abb8ce3d21b584c621869f7ebed3e6

For this example, I have chosen to describe my outputs as "Line" devices, as they are line-level outputs. For the inputs I have chosen "Mic", even though the physical inputs are actually multi-inputs that can accept both XLR devices and 6.35mm jacks for e.g. electric guitars (close enough!). Because there are two of each kind of device, we must append a number after each to enumerate them.

The rest of these should be well-explained by the comments. The PlaybackPCM and CapturePCM names are just what we will be calling config blocks we're about to create in the next step. It doesn't really matter what these are called, but you should make them descriptive.

PCM plugin definitions

Now to do the actual hard work of splitting the channels and defining the controls. This is done in a LibraryConfig block. At the very top of the file, we place this:

LibraryConfig.pcm.Config {
    #Contents will go here
}

Defining the channel splitting, part 1

First, let's define the config blocks we referred to earlier on the PlaybackPCM and CapturePCM lines. For these we will use the "empty" plugin which simply redirects to another plugin (which we will define later). We do this to avoid repeating ourselves too much.

I will again only comment one of these blocks, as they are all essentially the same. This is where the configuration gets very complicated, so I will not explain everything, just the lines you have to change; you may read more in the ALSA documentation: https://www.alsa-project.org/alsa-doc/alsa-lib/pcm_plugins.html

	pcm.umc204hd_line1 { #The part after the dot is the name of this config block, which we referred to in the section before
		@args [ CARD ] 
		@args.CARD.type string
		type empty
		slave.pcm {
			@func concat
			strings [ "umc204hd_stereo_out:" $CARD ",0,1" ] #"umc204hd_stereo_out" is the name of another config block we will soon create. We pass 3 parameters to it: the card ID and the channels we're passing to it (0 and 1 for first and second channel).
		}
	}

	pcm.umc204hd_line2 {
		@args [ CARD ]
		@args.CARD.type string
		type empty
		slave.pcm {
			@func concat
			strings [ "umc204hd_stereo_out:" $CARD ",2,3" ]
		}
	}

	pcm.umc204hd_mic1 {
		@args [ CARD ]
		@args.CARD.type string
		type empty
		slave.pcm {
			@func concat
			strings [ "umc204hd_mono_in:" $CARD ",0" ]
		}
	}

	pcm.umc204hd_mic2 {
		@args [ CARD ]
		@args.CARD.type string
		type empty
		slave.pcm {
			@func concat
			strings [ "umc204hd_mono_in:" $CARD ",1" ]
		}
	}

You should change the names of these blocks, as well as the name of the config block in the slave definition, to match your device.

This is also where we define which channels of the multichannel device (which we wish to split up) correspond to which virtual device. You will have to figure these out yourself (by using e.g. a patchbay like Catia to route audio to different channels and listening to where it ends up; or you could just guess), but they are probably contiguous. On our example device channels 0 and 1 are output A and channels 2 and 3 are output B. For inputs the story is equally simple.

Defining the channel splitting, part 2

Now let's define the final link in the PCM chain. We use the dshare plugin for splitting outputs and the dsnoop plugin for splitting inputs. These are essentially the same plugin with the same arguments, but dshare is for outputs and dsnoop is for inputs.

At the top of the LibraryConfig block, before the four blocks we just created, we place the following.

	pcm.umc204hd_stereo_out { #The name here should match the one in the slave definition we just created
		@args [ CARD CHN0 CHN1 ]
		@args {
			CARD.type string
			CHN0.type integer
			CHN1.type integer
		}
		type dshare
		ipc_key 572442 #This can be any value *but it must be unique on the system*. I just generated a random number.
		slave {
			pcm {
				type hw
				card $CARD
				device 0 #If your card has more than one device of this type you may have to change this line.
			}
			channels 4 #The number of channels on the hardware device we're splitting
		}
		bindings.0 $CHN0 #Bind channel 0 of this virtual device to whatever we got as a parameter (0 for Line A and 2 for Line B; see previous section)
		bindings.1 $CHN1 #Same but for channel 1 of the virtual device
	}

	pcm.umc204hd_mono_in {
		@args [ CARD CHN0 ]
		@args {
			CARD.type string
			CHN0.type integer
		}
		type dsnoop
		ipc_key 572542 #This can again be any value as long as it's unique. I added 100 to the random number I generated, because that's what some other configs did.
		slave {
			pcm {
				type hw
				card $CARD
				device 0
			}
			channels 2
		}
		bindings.0 $CHN0
	}

This is once again quite complicated, but odds are most other cards will be able to use a structure like this. However, if your card has more than one output or input device (for example, a theoretical card with 4 stereo outputs might have two 4-channel outputs where our example card only has one) you will have to tweak things a little. In these cases it would likely be a good idea to parameterize the value of the device line and then pass it from the config blocks from the previous sections like we do with the channels.

The bindings here can also be confusing. Remember that the number after the dot is the channel of the remapped virtual device we are creating, and the number we're passing as a parameter is the corresponding channel on the actual hardware device.

Defining the controls

Finally, we need to update the controls to match the channel splitting we just did — otherwise users won't be able to adjust the volume of the virtual devices we created in alsamixer (though many other tools will likely work even without these, because of PipeWire standing in between).

At the bottom of the LibraryConfig block, we place the following. It's a mouthful, but it's just a lot of repetition: for each split device we create a volume control and a switch (mute) control, for a total of 8 controls.

	ctl.default.map { #You should not need to change this line
		"name='Line A Playback Volume'"."name='UMC204HD 192k Output Playback Volume'" { #The names here can be fiddly. See explanation below.
			vindex.0 0 #The channel mapping here is much like in the bindings section of the previous blocks.
			vindex.1 1
		}
		"name='Line A Playback Switch'"."name='UMC204HD 192k Output Playback Switch'" {
			vindex.0 0
			vindex.1 1
		}
		"name='Line B Playback Volume'"."name='UMC204HD 192k Output Playback Volume'" {
			vindex.0 2
			vindex.1 3
		}
		"name='Line B Playback Switch'"."name='UMC204HD 192k Output Playback Switch'" {
			vindex.0 2
			vindex.1 3
		}
		"name='Input 1 Capture Volume'"."name='Mic Capture Volume'" {
			vindex.0 0
		}
		"name='Input 1 Capture Switch'"."name='Mic Capture Switch'" {
			vindex.0 0
		}
		"name='Input 2 Capture Volume'"."name='Mic Capture Volume'" {
			vindex.0 1
		}
		"name='Input 2 Capture Switch'"."Name='Mic Capture Switch'" {
			vindex.0 1
		}
	}

The names here can be a little fiddly. The second name must exactly match the name of the control from amixer -c U192k controls, which we looked at in Step 0. The first name should follow the same pattern, ie. append "Playback/Capture Volume/Switch" to whatever value you gave to PlaybackMixerElem or CaptureMixerElem in your SectionDevice blocks above. ALSA is very particular about these names, so it's important to get them right or things won't work.

Besides the names, this block is quite self-explanatory. If you're wondering about why we use "default" here instead of something else, that's... well, just something of an idiosyncracy. Otherwise the controls won't appear in alsamixer and generally just don't do anything.

The complete verb configuration file

With all the difficult configuration behind us, here is our completed file:

LibraryConfig.pcm.Config {
	pcm.umc204hd_stereo_out {
		@args [ CARD CHN0 CHN1 ]
		@args {
			CARD.type string
			CHN0.type integer
			CHN1.type integer
		}
		type dshare
		ipc_key 572442
		slave {
			pcm {
				type hw
				card $CARD
				device 0
			}
			channels 4
		}
		bindings.0 $CHN0
		bindings.1 $CHN1
	}

	pcm.umc204hd_mono_in {
		@args [ CARD CHN0 ]
		@args {
			CARD.type string
			CHN0.type integer
		}
		type dsnoop
		ipc_key 572542
		slave {
			pcm {
				type hw
				card $CARD
				device 0
			}
			channels 2
		}
		bindings.0 $CHN0
	}

	pcm.umc204hd_line1 {
		@args [ CARD ]
		@args.CARD.type string
		type empty
		slave.pcm {
			@func concat
			strings [ "umc204hd_stereo_out:" $CARD ",0,1" ]
		}
	}

	pcm.umc204hd_line2 {
		@args [ CARD ]
		@args.CARD.type string
		type empty
		slave.pcm {
			@func concat
			strings [ "umc204hd_stereo_out:" $CARD ",2,3" ]
		}
	}

	pcm.umc204hd_mic1 {
		@args [ CARD ]
		@args.CARD.type string
		type empty
		slave.pcm {
			@func concat
			strings [ "umc204hd_mono_in:" $CARD ",0" ]
		}
	}

	pcm.umc204hd_mic2 {
		@args [ CARD ]
		@args.CARD.type string
		type empty
		slave.pcm {
			@func concat
			strings [ "umc204hd_mono_in:" $CARD ",1" ]
		}
	}

	ctl.default.map {
		"name='Line A Playback Volume'"."name='UMC204HD 192k Output Playback Volume'" {
			vindex.0 0
			vindex.1 1
		}
		"name='Line A Playback Switch'"."name='UMC204HD 192k Output Playback Switch'" {
			vindex.0 0
			vindex.1 1
		}
		"name='Line B Playback Volume'"."name='UMC204HD 192k Output Playback Volume'" {
			vindex.0 2
			vindex.1 3
		}
		"name='Line B Playback Switch'"."name='UMC204HD 192k Output Playback Switch'" {
			vindex.0 2
			vindex.1 3
		}
		"name='Input 1 Capture Volume'"."name='Mic Capture Volume'" {
			vindex.0 0
		}
		"name='Input 1 Capture Switch'"."name='Mic Capture Switch'" {
			vindex.0 0
		}
		"name='Input 2 Capture Volume'"."name='Mic Capture Volume'" {
			vindex.0 1
		}
		"name='Input 2 Capture Switch'"."Name='Mic Capture Switch'" {
			vindex.0 1
		}
	}
}

SectionDevice."Line1" {
	Comment "Line A"
	Value {
		PlaybackPriority 200
		PlaybackChannels 2
		PlaybackPCM "umc204hd_line1:${CardId}"
		PlaybackMixer "default:${CardId}"
		PlaybackMixerElem "Line A"
	}
}

SectionDevice."Line2" {
	Comment "Line B"

	Value {
		PlaybackPriority 100
		PlaybackChannels 2
		PlaybackPCM "umc204hd_line2:${CardId}"
		PlaybackMixer "default:${CardId}"
		PlaybackMixerElem "Line B"
	}
}

SectionDevice."Mic1" {
	Comment "Input 1"

	Value {
		CapturePriority 200
		CaptureChannels 1
		CapturePCM "umc204hd_mic1:${CardId}"
		CaptureMixer "default:${CardId}"
		CaptureMixerElem "Input 1"
	}
}

SectionDevice."Mic2" {
	Comment "Input 2"

	Value {
		CapturePriority 100
		CaptureChannels 1
		CapturePCM "umc204hd_mic2:${CardId}"
		CaptureMixer "default:${CardId}"
		CaptureMixerElem "Input 2"
	}
}

As you can see, it's quite long! You might want to check that you composed your configuration correctly as we went through the steps.

Step 4: Testing and (probably) debugging

Save all the configuration files and prepare yourself for the moment of truth.

You can reload most of the configuration by restarting PipeWire and other pertinent components with: systemctl --user restart pipewire{,-pulse} wireplumber

If all goes well, PipeWire should come back online and you should see the new remapped devices you created in whatever audio mixer you use. If this is the case, hooray! Next try rebooting your system and then check alsamixer and amixer -c U192k controls to check if your custom controls show up and work as expected.

If things go wrong, you will likely have no audio at all out of the device you're attempting to configure. Alternatively, you may have audio but the controls don't work, which means that you just messed something up with the controls. This is where things can get quite frustrating, but here are some things you can try to troubleshoot your configuration.

Debugging

If you have no audio at all, the first order of business you should try is checking if PipeWire is outputting any errors when reading the UCM config. The easiest way to do this seems to be to check the output of spa-acp-tool -c 0 -vvvv info (replace 0 here with the numeric ID of the device from cat /proc/asound/cards) for any errors related to UCM. It's very verbose, so read through it carefully.

Failing that, you can try taking the contents of the LibraryConfig block (just the contents, not the beginning and end of the block itself) and sticking them in ~/.asoundrc. You can then use tools such as aplay and arecord to check the playback and recording respectively—these tools tend to have somewhat informative error messages. For example, arecord -Dumc204hd_mic1:U192k -f S32_LE -c 1 -v a.wav would try to record from the first input of our example device. You may have to adjust the parameters, particularly the -D parameter (which device is used) and the -f parameter (the sample format) for this to work on your device; see man arecord and any error output you're getting for details.

If the controls aren't working, double-check that you got all the names correctly. ALSA may also cache the control settings (and other card-specific configuration for that matter) under certain circumstances and this cache might not always get cleared properly. To clear it manually, you can run the following commands (this involves running rm -rf and rebooting your system, reckless copy-pasters beware):

systemctl stop alsa-restore
systemctl stop alsa-state
rm -rf /var/lib/alsa/*
reboot

There shouldn't be anything important under /var/lib/alsa/, but if you're feeling careful you might want to back up the contents of that directory before deleting them.

If all else fails, you can try asking for help on the alsa-devel mailing list, or submitting your unfinished config as a draft pull request on the alsa-ucm-conf GitHub repository and asking the maintainers for help with solving any remaining problems.

Step 5: Upstreaming!

Once your config is all ready and working, you should consider upstreaming it to the alsa-ucm-conf GitHub repository in a pull request. This way other users of the card can benefit from your efforts.

If for some reason you do not wish to upstream your configuration, you should keep in mind that updates to the alsa-ucm package will overwrite any changes to the configuration you've made. Instead of modifying the UCM configuration like we just did, you should consider exploring system-local configuration via asoundrc: https://www.alsa-project.org/wiki/Asoundrc

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment