Arrfab's blog - audiohttps://arrfab.net/2022-01-06T00:00:00+01:00Some tips and tricks, mostly around CentOSCombining multiples audio sinks with PulseAudio on CentOS Stream 82022-01-06T00:00:00+01:002022-01-06T00:00:00+01:00Fabian Arrotintag:arrfab.net,2022-01-06:/posts/2022/Jan/06/combining-multiples-audio-sinks-with-pulseaudio-on-centos-stream-8/<p>During winter break/holidays, I offered myself a new Bass and I mentioned this to one of my friends, who also offered himself a new guitar. As pandemic is still ongoing, he decided to just quickly record himself (video shot) and posted me the link and asked me to do the same.</p>
<p>Then became the simple problem to solve : while I have two nice Fender Amplifiers (<a href="https://www.fender.com/en-US/guitar-amplifiers/contemporary-digital/mustang-lt25/2311100000.html">Mustang LT</a> and <a href="https://www.fender.com/en-US/bass-amplifiers/contemporary-digital/rumble-lt25/2270100000.html">Rumble LT</a>) that are recognized natively by linux kernel on CentOS Stream 8 as valid input sources, I wanted to <em>also</em> combine that with a backing track (something playing on my computer, basically a youtube stream) and record that easily with the simple <a href="https://wiki.gnome.org/Apps/Cheese">Cheese video recording app</a> present by default in gnome.</p>
<p>I had so a look at <a href="https://www.freedesktop.org/wiki/Software/PulseAudio/">PulseAudio</a> and see if that was easily possible to combine the monitor device (basically the sound coming from your pc/speaker when you play something) with my amplifier as different input, and so then record in one shot that as a new stream/input that Cheese would transparently use (Cheese lets you specific a webcam but nothing wrt sound/microphone/input device)</p>
<p>Here is the solution : </p>
<ul>
<li>creating a new <code>sink</code> with the <a href="https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/Modules/#module-null-sink"><code>module-null-sink …</code></a></li></ul><p>During winter break/holidays, I offered myself a new Bass and I mentioned this to one of my friends, who also offered himself a new guitar. As pandemic is still ongoing, he decided to just quickly record himself (video shot) and posted me the link and asked me to do the same.</p>
<p>Then became the simple problem to solve : while I have two nice Fender Amplifiers (<a href="https://www.fender.com/en-US/guitar-amplifiers/contemporary-digital/mustang-lt25/2311100000.html">Mustang LT</a> and <a href="https://www.fender.com/en-US/bass-amplifiers/contemporary-digital/rumble-lt25/2270100000.html">Rumble LT</a>) that are recognized natively by linux kernel on CentOS Stream 8 as valid input sources, I wanted to <em>also</em> combine that with a backing track (something playing on my computer, basically a youtube stream) and record that easily with the simple <a href="https://wiki.gnome.org/Apps/Cheese">Cheese video recording app</a> present by default in gnome.</p>
<p>I had so a look at <a href="https://www.freedesktop.org/wiki/Software/PulseAudio/">PulseAudio</a> and see if that was easily possible to combine the monitor device (basically the sound coming from your pc/speaker when you play something) with my amplifier as different input, and so then record in one shot that as a new stream/input that Cheese would transparently use (Cheese lets you specific a webcam but nothing wrt sound/microphone/input device)</p>
<p>Here is the solution : </p>
<ul>
<li>creating a new <code>sink</code> with the <a href="https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/Modules/#module-null-sink"><code>module-null-sink</code></a> pulseaudio module</li>
<li>adding some inputs (basically the main audio .monitor device and my amplifier) to that sink with the <a href="https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/Modules/#module-loopback"><code>module-loopback</code></a> pulseaudio module</li>
<li>creating then a "fake" stream that can be used as input device (like a microphone) using the <a href="https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/Modules/#module-remap-source"><code>module-remap-source</code></a></li>
</ul>
<p>For example, when my Guitar amplifier is usb connected , it's shown like this : </p>
<div class="highlight"><pre><span></span>pacmd list-sources <span class="p">|</span> egrep <span class="s1">'(^\s+name: .*)|(^\s+device.description = .*)'</span>
name: <alsa_output.usb-Lenovo_ThinkPad_Thunderbolt_3_Dock_USB_Audio_000000000000-00.analog-stereo.monitor>
device.description <span class="o">=</span> <span class="s2">"Monitor of ThinkPad Thunderbolt 3 Dock USB Audio Analog Stereo"</span>
name: <alsa_input.usb-Lenovo_ThinkPad_Thunderbolt_3_Dock_USB_Audio_000000000000-00.mono-fallback>
device.description <span class="o">=</span> <span class="s2">"ThinkPad Thunderbolt 3 Dock USB Audio Mono"</span>
name: <alsa_input.usb-046d_HD_Pro_Webcam_C920_F4525F9F-02.analog-stereo>
device.description <span class="o">=</span> <span class="s2">"HD Pro Webcam C920 Analog Stereo"</span>
name: <alsa_input.usb-MICE_MICROPHONE_USB_MICROPHONE_201308-00.mono-fallback>
device.description <span class="o">=</span> <span class="s2">"Blue Snowball Mono"</span>
name: <alsa_output.pci-0000_00_1f.3.analog-stereo.monitor>
device.description <span class="o">=</span> <span class="s2">"Monitor of Built-in Audio Analog Stereo"</span>
name: <alsa_input.pci-0000_00_1f.3.analog-stereo>
device.description <span class="o">=</span> <span class="s2">"Built-in Audio Analog Stereo"</span>
name: <alsa_input.usb-FMIC_Mustang_LT_25_00000000001A-02.analog-stereo>
device.description <span class="o">=</span> <span class="s2">"Mustang LT 25 Analog Stereo"</span>
</pre></div>
<p>Now that we have the full name, we can use a simple bash wrapper script to either create a new input , based on bass/guitar amp preference, and this is the script : </p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span>
<span class="c1"># This little bash wrapper will just combine monitor and existing source from fender amplifier</span>
<span class="c1"># and create a virtual input that can be selected a default input for recording</span>
f_log<span class="o">()</span> <span class="o">{</span>
<span class="nb">echo</span> <span class="s2">"[+] </span><span class="nv">$0</span><span class="s2"> -> </span><span class="nv">$*</span><span class="s2">"</span>
<span class="o">}</span>
<span class="k">function</span> usage <span class="o">()</span> <span class="o">{</span>
cat <span class="s"><< EOF</span>
<span class="s">You need to call this script like this : $0 (-r) -i <input></span>
<span class="s"> -r : reset pulseaudio to default and so removes virtual input</span>
<span class="s"> -i : external amplifier to combine with source monitor [required param, values: (guitar|bass)]</span>
<span class="s">EOF</span>
<span class="o">}</span>
<span class="k">while</span> <span class="nb">getopts</span> <span class="s2">"hri:"</span> option
<span class="k">do</span>
<span class="k">case</span> <span class="si">${</span><span class="nv">option</span><span class="si">}</span> in
h<span class="o">)</span>
usage
<span class="nb">exit</span>
<span class="p">;;</span>
r<span class="o">)</span>
<span class="nv">action</span><span class="o">=</span>reset
<span class="p">;;</span>
i<span class="o">)</span>
<span class="nv">amplifier_model</span><span class="o">=</span><span class="si">${</span><span class="nv">OPTARG</span><span class="si">}</span>
<span class="p">;;</span>
?<span class="o">)</span>
usage
<span class="nb">exit</span>
<span class="p">;;</span>
<span class="k">esac</span>
<span class="k">done</span>
<span class="c1"># Checking first if we just need to reset pulseaudio</span>
<span class="k">if</span> <span class="o">[</span> <span class="s2">"</span><span class="si">${</span><span class="nv">action</span><span class="si">}</span><span class="s2">"</span> <span class="o">==</span> <span class="s2">"reset"</span> <span class="o">]</span> <span class="p">;</span> <span class="k">then</span>
f_log <span class="s2">"Resetting pulseaudio to defaults ..."</span>
pactl unload-module module-loopback
pactl unload-module module-null-sink
sleep <span class="m">2</span>
pulseaudio -k
<span class="nb">exit</span>
<span class="k">fi</span>
<span class="c1"># Parsing amplifier input to combine and exit if not specified</span>
<span class="c1"># One can use the following commands to know which sources are available</span>
<span class="c1"># pacmd list-sources | egrep '(^\s+name: .*)|(^\s+device.description = .*)'</span>
<span class="k">if</span> <span class="o">[</span> <span class="s2">"</span><span class="si">${</span><span class="nv">amplifier_model</span><span class="si">}</span><span class="s2">"</span> <span class="o">==</span> <span class="s2">"guitar"</span> <span class="o">]</span> <span class="p">;</span> <span class="k">then</span>
f_log <span class="s2">"Fender Mustang amplifier selected"</span>
<span class="nv">source_device</span><span class="o">=</span><span class="s2">"alsa_input.usb-FMIC_Mustang_LT_25_00000000001A-02.analog-stereo"</span>
<span class="nv">sink_name</span><span class="o">=</span><span class="s2">"monitor-and-amp"</span>
<span class="nv">fake_input_name</span><span class="o">=</span><span class="s2">"mustang-combined"</span>
<span class="k">elif</span> <span class="o">[</span> <span class="s2">"</span><span class="si">${</span><span class="nv">amplifier_model</span><span class="si">}</span><span class="s2">"</span> <span class="o">==</span> <span class="s2">"bass"</span> <span class="o">]</span> <span class="p">;</span> <span class="k">then</span>
f_log <span class="s2">"Fender Rumbler Amplifier selected"</span>
<span class="nv">source_device</span><span class="o">=</span><span class="s2">"alsa_input.usb-FMIC_Fender_LT_USB_Audio_Streaming_00000000001A-00.analog-stereo"</span>
<span class="nv">sink_name</span><span class="o">=</span><span class="s2">"monitor-and-bassamp"</span>
<span class="nv">fake_input_name</span><span class="o">=</span><span class="s2">"rumble-combined"</span>
<span class="k">else</span>
usage
<span class="nb">exit</span> <span class="m">1</span>
<span class="k">fi</span>
<span class="c1"># Now let's do the real work</span>
<span class="c1"># Common</span>
<span class="nv">monitor_device</span><span class="o">=</span><span class="s2">"alsa_output.usb-Lenovo_ThinkPad_Thunderbolt_3_Dock_USB_Audio_000000000000-00.analog-stereo.monitor"</span>
f_log <span class="s2">"Adding new sink [</span><span class="si">${</span><span class="nv">sink_name</span><span class="si">}</span><span class="s2">]"</span>
pactl load-module module-null-sink <span class="nv">sink_name</span><span class="o">=</span><span class="si">${</span><span class="nv">sink_name</span><span class="si">}</span> <span class="nv">sink_properties</span><span class="o">=</span>device.description<span class="o">=</span>Source-monitor-amp
sleep <span class="m">5</span>
f_log <span class="s2">"Adding monitor device [</span><span class="si">${</span><span class="nv">monitor_device</span><span class="si">}</span><span class="s2">] to created sink [</span><span class="si">${</span><span class="nv">sink_name</span><span class="si">}</span><span class="s2">]"</span>
pactl load-module module-loopback <span class="nv">source</span><span class="o">=</span><span class="si">${</span><span class="nv">monitor_device</span><span class="si">}</span> <span class="nv">sink_dont_move</span><span class="o">=</span><span class="nb">true</span> <span class="nv">sink</span><span class="o">=</span><span class="si">${</span><span class="nv">sink_name</span><span class="si">}</span>
sleep <span class="m">5</span>
f_log <span class="s2">"Adding external amplifier [</span><span class="si">${</span><span class="nv">source_device</span><span class="si">}</span><span class="s2">] to created sink [</span><span class="si">${</span><span class="nv">sink_name</span><span class="si">}</span><span class="s2">]"</span>
pactl load-module module-loopback <span class="nv">source</span><span class="o">=</span><span class="si">${</span><span class="nv">source_device</span><span class="si">}</span> <span class="nv">sink_dont_move</span><span class="o">=</span><span class="nb">true</span> <span class="nv">sink</span><span class="o">=</span><span class="si">${</span><span class="nv">sink_name</span><span class="si">}</span>
<span class="c1"># Create fake input combining all sinks </span>
f_log <span class="s2">"Creating now new virtual input [</span><span class="si">${</span><span class="nv">fake_input_name</span><span class="si">}</span><span class="s2">] to be used as input for recording"</span>
sleep <span class="m">5</span>
pactl load-module module-remap-source <span class="nv">source_name</span><span class="o">=</span><span class="si">${</span><span class="nv">fake_input_name</span><span class="si">}</span> <span class="nv">master</span><span class="o">=</span><span class="si">${</span><span class="nv">sink_name</span><span class="si">}</span>.monitor <span class="nv">source_properties</span><span class="o">=</span>device.description<span class="o">=</span><span class="si">${</span><span class="nv">fake_input_name</span><span class="si">}</span>
</pre></div>
</td></tr></table>
<p>Now that we have a script, I can just call it like that, example for my Guitar amp :</p>
<div class="highlight"><pre><span></span> .<span class="o">/</span><span class="nv">pulse</span><span class="o">-</span><span class="nv">audio</span><span class="o">-</span><span class="nv">amp</span><span class="o">-</span><span class="nv">combine</span> <span class="o">-</span><span class="nv">i</span> <span class="nv">guitar</span>
[<span class="o">+</span>] .<span class="o">/</span><span class="nv">pulse</span><span class="o">-</span><span class="nv">audio</span><span class="o">-</span><span class="nv">amp</span><span class="o">-</span><span class="nv">combine</span> <span class="o">-></span> <span class="nv">Fender</span> <span class="nv">Mustang</span> <span class="nv">amplifier</span> <span class="nv">selected</span>
[<span class="o">+</span>] .<span class="o">/</span><span class="nv">pulse</span><span class="o">-</span><span class="nv">audio</span><span class="o">-</span><span class="nv">amp</span><span class="o">-</span><span class="nv">combine</span> <span class="o">-></span> <span class="nv">Adding</span> <span class="nv">new</span> <span class="nv">sink</span> [<span class="nv">monitor</span><span class="o">-</span><span class="nv">and</span><span class="o">-</span><span class="nv">amp</span>]
<span class="mi">26</span>
[<span class="o">+</span>] .<span class="o">/</span><span class="nv">pulse</span><span class="o">-</span><span class="nv">audio</span><span class="o">-</span><span class="nv">amp</span><span class="o">-</span><span class="nv">combine</span> <span class="o">-></span> <span class="nv">Adding</span> <span class="nv">monitor</span> <span class="nv">device</span> [<span class="nv">alsa_output</span>.<span class="nv">usb</span><span class="o">-</span><span class="nv">Lenovo_ThinkPad_Thunderbolt_3_Dock_USB_Audio_000000000000</span><span class="o">-</span><span class="mi">00</span>.<span class="nv">analog</span><span class="o">-</span><span class="nv">stereo</span>.<span class="nv">monitor</span>] <span class="nv">to</span> <span class="nv">created</span> <span class="nv">sink</span> [<span class="nv">monitor</span><span class="o">-</span><span class="nv">and</span><span class="o">-</span><span class="nv">amp</span>]
<span class="mi">27</span>
[<span class="o">+</span>] .<span class="o">/</span><span class="nv">pulse</span><span class="o">-</span><span class="nv">audio</span><span class="o">-</span><span class="nv">amp</span><span class="o">-</span><span class="nv">combine</span> <span class="o">-></span> <span class="nv">Adding</span> <span class="nv">external</span> <span class="nv">amplifier</span> [<span class="nv">alsa_input</span>.<span class="nv">usb</span><span class="o">-</span><span class="nv">FMIC_Mustang_LT_25_00000000001A</span><span class="o">-</span><span class="mi">02</span>.<span class="nv">analog</span><span class="o">-</span><span class="nv">stereo</span>] <span class="nv">to</span> <span class="nv">created</span> <span class="nv">sink</span> [<span class="nv">monitor</span><span class="o">-</span><span class="nv">and</span><span class="o">-</span><span class="nv">amp</span>]
<span class="mi">28</span>
[<span class="o">+</span>] .<span class="o">/</span><span class="nv">pulse</span><span class="o">-</span><span class="nv">audio</span><span class="o">-</span><span class="nv">amp</span><span class="o">-</span><span class="nv">combine</span> <span class="o">-></span> <span class="nv">Creating</span> <span class="nv">now</span> <span class="nv">new</span> <span class="nv">virtual</span> <span class="nv">input</span> [<span class="nv">mustang</span><span class="o">-</span><span class="nv">combined</span>] <span class="nv">to</span> <span class="nv">be</span> <span class="nv">used</span> <span class="nv">as</span> <span class="nv">input</span> <span class="k">for</span> <span class="nv">recording</span>
<span class="mi">29</span>
</pre></div>
<p>And it then appears as new input that I can select as default under gnome : </p>
<p><img alt="gnome-settings" src="/images/gnome-control-center-sound.png"></p>
<p>I also have rebuilt/installed <a href="https://freedesktop.org/software/pulseaudio/pavucontrol/">pavucontrol</a> application, which can be handy to visualize all the streams and you can also control the volume in the recording tab :</p>
<p><img alt="pavucontrol-recording" src="/images/pavucontrol-recording.png"></p>
<p>You can then have lower input from the audio you're playing on laptop (for example a backing track found on youtube but anything played on laptop is going to the monitor device) but YMMV and you have to do a quick test first with your other input (my amp+instrument in my case)</p>
<p>Once done, you can use any app like audacity or cheese or else to just record. Probably easier and faster than complex (but more professional though) systems around Jack. As said, it's just to quickly record something and combine streams/sinks all together, nothing like a DAW system :-)</p>