Studio Sound Tweaks

TL;DR
For full sound integration of JACK and non-JACK applications, you need to perform one of three configuration mods: either use an ALSA-JACK bridge, use JACK exclusively, or be lazy and just use JACK applications during the time you have JACK running. Also, there's a bug in Firefox.

If you are working with pro audio applications, then you'll be working with JACK, the low latency sound system for Linux with robust sound routing capabilities so that the internals of your computer are a fully stocked recording studio with an endless supply of virtual cables and patchbays.

Sound good? of course it does. But a peculiarity about JACK is that it seizes control of your sound card in order to ensure near-realtime performance; this means that the normal sound system that usually drives audio on a Linux desktop cannot access the same sound card.

In other words, if you are running applications through JACK in order to gain near-realtime performance and otherwise impossible audio routing capability, when you launch an applications that does not or cannot use JACK, that application will not have sound.

There are three options to deal with this. Regardless of which you choose, you must install alsa-plugins. This plugin pack is not included in the Slackermedia queue files because for to maximise its usefulness, you should have ffmpeg, JACK, and (optionally, if you use it) speex installed before building and installing alsa-plugins.

If you have these installed, then it is safe to install alsa-plugins. It is available from http://slackbuilds.org.

ALSA JACK Bridge

Skill Level: This is an intermediate solution, and the recommended Slackermedia solution.

The first method, outlined on http://jackaudio.org/faq/routing_alsa.html, is to create a dummy ALSA “loopback” device that can be used from within JACK. This means that while JACK is running, a non-JACK application can still play through your system sound cards by piping its way through JACK via an ALSA tunnel, of sorts.

If you are not a full-time musician, this is probably the best solution for you, as it balances ease-of-setup plus flexible functionality.

To set up the bridge device, edit (creating it if it does not already exist) the file ~/.asoundrc:

pcm.rawjack {
    type jack
    playback_ports {
        0 system:playback_1
        1 system:playback_2
    }
    capture_ports {
        0 system:capture_1
        1 system:capture_2
    }
}

pcm.jack {
    type plug
    slave { pcm "rawjack" }
    hint {
    description "JACK Audio Tunneling Kit"
    }
}

The first PCM definition defines a virtual audio device called pcm.rawjack that has 2 input channels and two output channels. Each channel definition consists of a number (starting from 0, as computers do), and a JACK port to which it connects. This port, which we arbitrarily call rawjack, requires that the sample rate, sample format, and all other attributes, match the system's JACK settings; it is, essentially, a mirror of ALSA, or an ALSA portal.

The purpose of this definition is to define a sound “jack”, that is, something we can plug into other ports. It is a signal sender (whether the signal is sound being output from an application, or a sound being received via input such as a microphone.

We add a second PCM definition for a device called pcm.jack. This uses our rawjack device but also converts between audio data formats.

Log out and log back in (or reboot if you prefer) and from now on, you can set the output device of any ALSA application to pcm.jack if you are using an ALSA-only application whilst running JACK.

Test this with this command:

aplay -D pcm.jack \
/usr/share/sounds/alsa/Front_Center.wav

Most, if not all, applications that you will normally use with or without JACK running are set to send sound to the “default” device.

The problem when running JACK is that the “default” device (ALSA) is useless; the new default device while JACK is running should be your JACK tunnel.

You could go into each application's Preferences or Settings menu and set the output to your bridge. For example, to configure VLC to pipe its output to the ALSA/JACK bridge:

You probably don't really want to do this manually.

However, you would need to set it back to ALSA so you could hear it when JACK is not running.

Obviously, there is a better way: automatic switching.

Automatic Switching

In order for applications to know to use the ALSA-JACK bridge that you have just set up, you should configure the default sound device as the ALSA-JACK bridge whenever JACK is running.

The easiest way to configure such a switch is a shell script wrapper around starting and stopping JACK.

First, you need to know what command you want to use to start jackd, and place this command, verbatim, into ~/.jackdrc. This is the standard JACK startup file, so it might be over-written by other front-ends to jackd (like QJackCtl, in particular) if you use them, but that's not necessarily a bad thing.

If you do not have a known-good command to start jackd, read the JACK section.

It's not a bad idea to get into the habit of backing up useful commands. For instance, something as simple as:

 
echo 'jackd -R -d alsa -P hw:0 -X seq' > ~/jackd.command

preserves the syntax and known-good command that you can refer to whenever you need.

Once you have constructed a good JACK command and placed it into ~/.jackdrc, create two versions of ~/.asoundrc: your current version, and another temporary one with this clause at the very end of the file:

  pcm.!default {
  type plug 
  slave { pcm "rawjack" }
  }

This sets the default device to the rawjack device you have created to serve as your ALSA-JACK bridge.

Next, create a patch file from the delta between the two files:

$ diff -u ~/.asoundrc ~/.asoundrc-temp > ~/.asoundrc-switch
$ rm ~/.asoundrc-temp

The resulting file (~/.asoundrc-switch):

--- $HOME/.asoundrc	   2015-06-03 01:28:04.732320885 +1200
+++ $HOME/.asoundrc-switch 2015-06-02 18:06:18.974253004 +1200
@@ -16,4 +16,9 @@
     hint {
     description "JACK Audio Tunneling Kit"
     }
+}
+
+pcm.!default {
+    type plug
+    slave { pcm "rawjack" }
 }
\ No newline at end of file

And finally, create the shell script wrapper that will activate or de-activate the bridge, and start and stop jackd. You can copy and paste the code from here, or you can check for updates at https://gitlab.com/slackermedia/cousteau

#!/bin/bash

# traps ctrl-c and others for this wrapper script
trap "patch -R ~/.asoundrc ~/.asoundrc-switch" 1 2 9 15

function jackgo() {
        echo "Starting jackd.."
        sleep 1
        printf "."
        sleep 1
        exec `< ~/.jackdrc`
}

function hijack()
{
    DEF=`grep default $HOME/.asoundrc`
    if [ -z "$DEF" ]; then
        patch ~/.asoundrc ~/.asoundrc-switch
        jackgo
    else
        jackgo
    fi
}

hijack &

# catches ctrl-c and others for jackd
killjack=$!
wait $killjack && patch -R ~/.asoundrc ~/.asoundrc-switch || \
    echo "Unable to restore ALSA config. Check your ~/.asoundrc file." && exit 1

exit 0

Save this script somewhere handy with a convenient name. I call mine cousteau.

Make it executable:

$ chmox +x ~/cousteau

To make it handy, place it in a directory in your PATH so that all you have to do to execute it is type cousteau in the terminal.

It's traditional in UNIX to have a $HOME/bin directory (where “bin” is short for “binary”, or in other words, an executable application):

$ mkdir ~/bin
$ touch ~/.bashrc
$ echo 'export PATH=$PATH:$HOME/bin
$ source ~/.bashrc
$ cp cousteau ~/bin

Or you may prefer to store it in a standard system-wide location:

$ su -c 'cp cousteau /usr/local/bin'

Now you can use your script to start JACK, and it your ~/.asoundrc file will be patched automatically for you. If jackd dies or is killed by some other process, or cousteau is killed by some other process (such as pressing ctrl-c in the terminal where cousteau is running), then ~/.asoundrc will be restored to normal.

This solution will create some latency: the ALSA JACK plugin has to use a buffer between the data being sent by the application and JACK itself to avoid clicks and dropouts.

This may or may not matter, depending on what you are using; playing media over the web tends to suffer, since the buffers for the data can get maligned. If all you are doing is auditioning short clips from sound effect or loop libraries, you probably won't notice, but if you're streaming a movie then the sound will suffer…but in that event, you should probably get back to work anyway.

Always-On JACK Daemon

Skill Level: This is a complex solution and requires advanced skills.

The second option is to run JACK all the time, no matter what. This is a more complex setup but it has your computer being an active JACK session all the time, meaning that you can route or hijack any sound to or from any device or application at a moment's notice.

If you are a full-time musician, then this most likely the best solution for you, but for ease of setup you may want to try the first solution to begin with and try this more complex one if it proves to be insufficient.

This method was outlined first on the JACK website, but is expanded and explained by AlienBob on his website, http://alien.slackbook.org/blog/setting-up-jack-audio-in-slackware/. See his original post for more information and a few more options.

Like the first method, this requires a dummy ALSA device to handle non-JACK applications. For that to work, load the snd-aloop module:

$ su -c '/sbin/modprobe snd-aloop'

So that this is loaded at boot by default, add it to the file /etc/rc.d/rc.local

$ su -c 'echo snd-aloop >> /etc/rc.d/rc.local'

And create a configuration file for it to define how many channels you require from your dummy device. If you are on a surround sound system, then you probably need 7 or 8 (8 is the default), but if you mix only in stereo then you can reduce the number of channels:

su -c 'echo \
"options snd-aloop pcm_substreams=2" > \
/etc/modprobe.d/alsaloop.conf

ALSA Configuration

In order for ALSA to tunnel its way through JACK, you must create a custom ~/.asoundrc file. If one exists, back it up and create this one. If needed, you can integrate your old changes into this one (but more than likely it will be JACK that you customise for system-wide audio, from here on out).

# hardware 0,0 : used for ALSA playback

pcm.loophw00 {
  type hw
  card Loopback
  device 0
  subdevice 0
  format S32_LE
  rate 48000
}

# hardware 0,1 : used for ALSA capture
pcm.loophw01 {
  type hw
  card Loopback
  device 0
  subdevice 1
  format S32_LE
  rate 48000
}

# playback PCM device: using loopback subdevice 0,0

pcm.amix {
  type dmix
  ipc_key 196101
  slave {
    pcm "loophw00"
    buffer_size 8192
    period_size 4096
    periods 2
  }
}

# capture PCM device: using loopback subdevice 0,1
pcm.asnoop {
  type dsnoop
  ipc_key 196102
  slave {
   pcm loophw01
   period_size 4096
   periods 2
  }
}

# software volume

pcm.asoftvol {
  type softvol
  slave.pcm "amix"
  control { name PCM }
  min_dB -51.0
  max_dB   0.0
}


# duplex dev combining PCM devs defined above

pcm.aduplex {
  type asym
  playback.pcm "asoftvol"
  capture.pcm "loophw01"
  hint {
    description "ALSA-JACK Bridge"
  }
}

# Mixer controls

ctl.amix {
    type hw
    card Loopback
}

ctl.asnoop {
    type hw
    card Loopback
}

ctl.aduplex {
    type hw
    card Loopback
}


# for jack alsa_out: looped-back signal
pcm.ploop {
  type hw
  card Loopback
  device 1
  subdevice 1
  format S32_LE
  rate 48000
}


# for jack alsa_in: looped-back signal
pcm.cloop {
  type hw
  card Loopback
  device 1
  subdevice 0
  format S32_LE
  rate 48000
}


# default device

pcm.!default {
  type plug
  slave.pcm "aduplex"
}

When you save that file, its content will re-define your ALSA configuration immediately. KDE may complain about hardware that was added or went missing; it is safe to ignore these warnings.

This new configuration creates a new full-duplex PCM device called pcm.aduplex with a description of “ALSA-JACK Bridge”. Set your ALSA devices to use this as their output.

Additionally, a PCM device for capturing input (pcm.cloop) and for playback (pcm.ploop) are created; these also will be connected to JACK. Your ALSA applications pipe their audio into one end of the loopback device, and JACK interprets the signal as incoming audio and plays it on your speakers.

Test your new setup's configuration with this command:

You will not hear anything at this point, since JACK has yet to be configured. However, you should also not receive an error back, so that is what you are testing for.

aplay -D pcm.jack \
/usr/share/sounds/alsa/Front_Center.wav

Assuming you get no error back, the ALSA side of the equation is set up. Now it's time to configure JACK.

JACK Configuration

Your JACK settings must match up with your ALSA settings, particularly the sample rate. Typical sample rates are 44100 and 48000 (or 96000 if you have very high-end gear). The example .asoundrc sets the sample rate to 48000 across the board, so if you use any value other than that, change it in ~/.asoundrc.

The command to start JACK can be saved in ~/.jackdrc so that whenever JACK is started, it knows exactly what state it should load.

For the hardware device name, check aplay:

aplay -l | grep card

A suitable command for this example setup:

/usr/bin/jackd -r -m -dalsa -r48000 -p1024 -n2 -m -H -D -Chw:SB -Phw:SB

Now JACK will start with the correct settings, but there's nothing to tell ALSA and JACK how to interact. This can be solved with AlienBob's custom connection script, which you should place in /usr/local/bin:

#!/bin/sh
# script loop2jack, located in /usr/local/bin
#
# Start jack if it is not already running:
/usr/bin/jack_control start

# loop client creation

/usr/bin/alsa_out -j ploop -dploop -q 1 2>&1 1> /dev/null &
/usr/bin/alsa_in -j  cloop -dcloop -q 1 2>&1 1> /dev/null &

# give it some time before connecting to system ports
sleep 1

# cloop ports -> jack output ports
/usr/bin/jack_connect cloop:capture_1 system:playback_1
/usr/bin/jack_connect cloop:capture_2 system:playback_2

# system microphone to "ploop" ports
/usr/bin/jack_connect system:capture_1 ploop:playback_1
/usr/bin/jack_connect system:capture_2 ploop:playback_2

# done
exit 0

Make the script exectuable:

chmod +x /usr/local/bin/loop2jack

And add it to ~/.xprofile (create this file if it does not already exist). If you do not boot into a graphical environment by default, add it to ~/.profile.

$ echo /usr/local/bin/loop2jack > \
~/.xprofile

Under this method, running JACK is required. If JACK is not running, you will hear nothing from your speakers because ALSA is set by default to route itself through JACK, rather than directly to your hardware.

The system-wide ALSA configuration file /etc/asound.conf should not but could, in theory, interfere with this setup. Your own ~/.asoundrc definitions are only prepended to asound.conf and do not replace them.

JACK Enabled Apps

Skill Level: This is the easiest solution; it requires no skill, but its limitations can be annoying.

The simplest solution, in terms of effort, is to just use JACK-enabled applications whilst you are running an active JACK session. It seems almost too simple, but in practise, depending on your workflow, it ends up being quite realistic.

The typical workflow for using a JACK-enabled application is that you decide that you want to use a set of pro audio apps to compose or edit sound. This probably means that you're not doing “normal” audio things as well; in other words, you probably don't have music playing in a media player, or a movie playing, you're probably not on a VOIP call, and so on. You're making music or editing sound, so by the nature of the work, you are using only JACK-enabled pro audio applications.

If the need should arise to launch an application that might not normally be JACK-enabled, there is the option to simply use an application that is JACK-enabled. For instance, if you are working in pro audio, but you need to launch a music player to compare sounds or review a demo track or listen to a temp track, then rather than using a player that can only play via ALSA (the default sound system), use a media player that can use JACK.

This method is technologically the easiest method, although it does require effort to find JACK-enabled alternatives to the normal tools that you might have become accustomed to using outside of JACK. And in some cases, it might not be pragmatic; for instance, quickly firing up Firefox to grab a Creative Commons sample from the internet becomes a much more complex thing than it should be if you can't preview the sound without quitting your DAW, your effect rack, synths, and stopping JACK.

The Firefox Bug

Regardless of the option you choose, there is a bug in Firefox that prevents sound from playing over an ALSA-JACK bridge. So if you need to play something with sound in a web browser whilst running JACK, Firefox is not the browser to use. Alternate browsers that do work include Chromium and Midori (build scripts for both are available from slackbuilds.org).

R S Q