Is there a simple, application-independent way to record audio on
given sound card?
Yes ! There is !
What you are looking for is to simply record the output of your sound card.
The easiest way would probably be to wire its outputs to its inputs… the aloop alsa driver will provide a wireless way.
A/ So first ensure the driver is loaded & appropriately initialized :
arecord -l
can tell you this, displaying (on my system):
card 0: Loopback [Loopback], device 0: Loopback PCM [Loopback PCM]
Subdevices: 8/8
Subdevice #0: subdevice #0
Subdevice #1: subdevice #1
Subdevice #2: subdevice #2
Subdevice #3: subdevice #3
Subdevice #4: subdevice #4
Subdevice #5: subdevice #5
Subdevice #6: subdevice #6
Subdevice #7: subdevice #7
card 0: Loopback [Loopback], device 1: Loopback PCM [Loopback PCM]
Subdevices: 8/8
Subdevice #0: subdevice #0
Subdevice #1: subdevice #1
Subdevice #2: subdevice #2
Subdevice #3: subdevice #3
Subdevice #4: subdevice #4
Subdevice #5: subdevice #5
Subdevice #6: subdevice #6
Subdevice #7: subdevice #7
Of course depending on your implementation, the card id can differ from the above list.
If you don't obtain that output then it might be because the driver is not loaded therefore fire : modprobe snd-aloop
.
In case you still don't succeed then ensure that the driver is selected in the kernel .config file (grep for CONFIG_SND_ALOOP)
B/ Basically ensure it works as expected
This driver provides a pair of cross-connected devices, forming a full-duplex loopback soundcard. The first application opening one device, will force the second application, trying to open the other device, to use its established parameters. Therefore no rate, format or channel number conversion is done. The consequence of this is, that you have to start the playback application first.
So let's ensure it works as expected :
1/ Find whatever .wav file and play it to card 0 device 0 subdevice 0 : aplay -D hw:0,0,0 whatever.wav
2/ Record from associated cross-connected device card 0 device 1 subdevice 0: arecord -D hw:0,1,0 record.wav
Of course you might need to adapt the card id to your configuration.
3/ Ensure it just works by playing record.wav on your alsa default device : aplay record.wav
. If you can't hear anything, this will probably be because of some basic alsa misconfiguration. (I can elaborate if needed)
Of course, working like this (directing playback to the loopback, output won't be sent to your default playback device, so you won't be able to hear anything while recording.
This is anyhow possible via some particular alsa configuration.
C/ Get both audio playing in your ears and enable recording
Warning! : This will be the hardest part of the work since alsa configuration files have always needed an appreciable part of… magic.
For this, you'll need to conceive from scratch either the /etc/asound.conf file (if your config is meant system-wide) or $HOME/.asoundrc (if the config is meant for your sole user) in order to create a couple of virtual sound devices.
1/ Start defining quasi aliases
pcm.MAUDIO{
type hw
card M2496
device 0
subdevice 0
nonblock true}
ctl.MAUDIO{
type hw
card M2496}
This example being related to my own system with :
- MAUDIO (choose whatever you want instead) acting as an alias for future reference to the hardware sound device,
- M2496 coming from the CARD=M2496 associated to my preferred hardware device for sound playback (you should adapt according to your output of
aplay -L
)
- nonblock true because you don't want Alsa to lock the character special file (/dev/snd/pcmwhatever) associated to the device driver of your sound card. (So than any other application can also open it if needed)
Then going on with the loopback device :
pcm.loopin {
type plug
slave.pcm "hw:Loopback,0,0"
}
pcm.loopout {
type plug
slave.pcm "hw:Loopback,1,0"
}
2/ Of course you want a mixer
pcm.dmixer{
type dmix
ipc_key 219345
slave{
pcm MAUDIO
format S32_LE
period_size 1024
buffer_size 4096 }}
For the ipc_key choose whatever unique shared memory key (check using ipcs -ma
that the one you choose is not used).
period_size and buffer_size values depend on your expectations in terms of latency (lower the values, lower the latency) and the performances of your system (lower the values, higher the probability of XRuns)
3/ Of course you want everything to work as before (without conf)
pcm.!default{
type plug
slave.pcm "dmixer"
hint{
show on
description "Alsa Default Device"}}
This will define the alsa default device described as such on all apps enabling the selection of audio output devices.
All we need now is to define a pseudo device able to duplicate it's input to both, the hardware sound device and the loopback device. This will be achieved thanks to alsa's multi plugin.
4/ Routing audio to hardware sound device and duplicate to loopback
pcm.multi {
type route;
slave.pcm {
type multi;
slaves.a.pcm "MAUDIO";
slaves.b.pcm "loopin";
slaves.a.channels 2;
slaves.b.channels 2;
bindings.0.slave a;
bindings.0.channel 0;
bindings.1.slave a;
bindings.1.channel 1;
bindings.2.slave b;
bindings.2.channel 0;
bindings.3.slave b;
bindings.3.channel 1;
}
ttable.0.0 1;
ttable.1.1 1;
ttable.0.2 1;
ttable.1.3 1;
}
Note that instead of slaves.a.pcm "MAUDIO", you may prefer slaves.a.pcm "dmixer"
For commodity, define an alias :
pcm.pbnrec {
type plug
slave.pcm "multi"
hint{
show on
description "Alsa Playback & Record"}}
D/ Let's GO!
Shutdown & Reboot if you chose configuring system wide or logout login if you chose configuring user's own .asoundrc.
From then, under any honest audio app enabling you to select the preferred audio output device, you should be able to choose the "Alsa Playback & Record" device, start playing then, on the command line, either :
- arecord on the "loopout" device
- ffmpeg on the "loopout" device if wishing resampling / other file formats.
- Fire whatever more convenient audio recording desktop utility like audacity.
E/ Ha! This works as it should with players A,B,C but not with D,E,F apps
Unfortunately, many suboptimal apps won't enable you to select the desired output device. Browsers in particular.
Because they will output to alsa default pcm, you'll need to adapt your configuration file and change the pcm.!default description as detailed above for something looking like :
pcm.!default {
type plug
slave.pcm "pbnrec"
}
F/ FTS! That still doesn't work with Firefox and Chrome.
1/ Chrome
To be honest… I cannot tell since I use chromium.
Chromium will default to pulseaudio output unless specifying the --alsa-output-device option.
So, one should try launching chrome --alsa-output-device='default'
and hear if it works, it does indeed up to my current chromium 96
2/ Firefox
For whatever somber reason, Firefox decided to privilege pluseaudio so there is AFAIK no way to workaround this… with the official binary.
However, building Firefox from sources, there is some make option which enables the build of an alsa backend.
I can't tell how to achieve this under Debian, but this is almost certainly possible.
All I can tell is that it works for me up to my current 91.4.0 version.
CREDITS : Since OP wanted authoritative sources, everything in this answer was elaborated from :
ALTERNATIVE
A sound server can stand as a viable alternative to the alsa fiddlings described here above. (to the cost of some processing power)
The sound server of choice has, for decades, always be the Jack Audio Connection Kit. Pulseaudio never managed to compete.
But… this is another story.
ADDITIONAL INFORMATION FOLLOWING COMMENTS
1/ Sample rate
The snd-aloop driver is, in itself, not constrained to whatever fixed sample rate. Any of its subdevices can operate at a different sample rate if desired.
However, the application that will be the first to open a subdevice will determine the sample rate (since no conversion is done) for the cross-paired subdevice.
In practice, this means that the playback application outputing at PBSource Hz, the recording application will capture samples at PBSource Hz sample rate.
In case this is not convenient, resampling needs to be done, it will be on behalf of the recording app.
ffmpeg can achieve this on the fly, as would desktop recording apps (most likely thanks to ffmpeg)
In practice, this also means that the pseudo device used to push sound to the hardware sound device will have its input sampled at PBSource Hz.
There can indeed be a mismatch with the sound device (fixed) HW hz sample rate, this leading to bad sound.
Alsa provides two ways to overcome this, either by :
- Using the rate plugin which will force the resampling to a given frequency. This is somehow suboptimal since alsa will then resample systematically. (even if the sample rate of the source and the given sample rate are identical)
- Using the dmix plugin (cf. above §C-2,3) which will automatically resample but only when needed.
One can even select the preferred resampling algo via the definition of defaults.pcm.rate_converter.