Newer
Older
# Audio Device Configuration
This document outlines the steps on how to configure an audio interface with Engine Core.
1. [Audio Device Configuration](#audio-device-configuration)
1. [ALSA](#alsa)
1. [Disabe an existing Pulse Audio Server](#disabe-an-existing-pulse-audio-server)
2. [Setting the output device using a device ID](#setting-the-output-device-using-a-device-id)
3. [Setting the input device](#setting-the-input-device)
1. [(A) Buffered audio](#a-buffered-audio)
2. [(B) Unbuffered audio](#b-unbuffered-audio)
2. [Pulse Audio](#pulse-audio)
3. [JACK](#jack)
Following three audio drivers & servers are supported by _Engine Core_:
1. ALSA: Recommended for native hardware access. Only one input and output per channel pair is available.
2. PulseAudio: This provides the most simple setup, but is not recommended for live audio input due to latencies.
3. Jack: Allows low latency audio routing for multiple input and outputs.
Out of the box Engine Core is configured to use ALSA `default` output. The input is disabled.
When using your audio device with ALSA you are pretty close to the actual hardware. It can be relatively hard to find some good settings though.
**Documentation:** While the [_Official ALSA_](https://www.alsa-project.org/wiki/Documentation) documentation is not an easy read, there is a superb [_ALSA, exposed!_](https://rendaw.gitlab.io/blog/2125f09a85f2.html#alsa-exposed) documentation available too.
### Disabe an existing Pulse Audio Server
Before starting, you need to ensure not having a Pulse Audio server running on your system. On Linux distributions like Ubuntu, PulseAudio is pre-installed and it can be tricky turning it off.
Having PulseAudio running in the background while thinking running native ALSA can be the root many evil latency problems. In such scenario audio is passed through all of these layers:
Audio Interface <--> ALSA <--> Pulse Audio <--> ALSA Plugin <--> Audio Stream
nano ~/.pulse/client.conf
(autospawn = no)
```conf
```bash
systemctl --user stop pulseaudio.socket
systemctl --user stop pulseaudio.service
You might even think about uninstalling PulseAudio altogether, as there are scenarios where the driver gets restarted upon ALSA device requests. Yes, even with having the PulseAudio service disabled and `autospawn = no` set in your PulseAudio configuration.
If you only want to do a quick ALSA test, without removing your nicely working PulseAudio server, you can prefix your bash commands with `pasuspender ...`. This disables PulseAudio only as long the passed executable is running.
### Defining the default audio device
Audio output can be set by defining the default audio device or some specific device ID. If you prefer the latter you can skip this chapter.
After first installation, Engine Core is configured to use the audio device set as `default`. You can set the default device in `/etc/asound.conf` or in a per user configuration in `~/asoundrc`. A simple defintion can look like this:
```ini
defaults.pcm.card 2
defaults.ctl.card 2
```
This configuration indicates that soundcard number 2 is the default one. If no such configuration exists ALSA automatically chooses card 0 to be the default one.
To get the available soundcard number type
```bash
cat /proc/asound/cards
0 [PCH ]: HDA-Intel - HDA Intel PCH
HDA Intel PCH at 0x7f410000 irq 133
1 [NVidia ]: HDA-Intel - HDA NVidia
HDA NVidia at 0x7f080000 irq 17
2 [K6 ]: USB-Audio - Komplete Audio 6
Native Instruments Komplete Audio 6 at usb-0000:00:14.0-5.2.1, high speed
```
The `asoundrc` configuration format allows the defintion of not only hardware devices but also complex virtual cards. For example it's possible to do live conversion using ALSA plugins or combine multiple devices into one.
> This file allows you to have more advanced control over your card/device. The .asoundrc file consists of definitions of the various cards available in your system. It also gives you access to the pcm plugins in alsa-lib. These allow you to do tricky things like combine your cards into one or access multiple I/Os on your multichannel card.
>
> From [alsa-project.org/wiki/Asoundrc](alsa-project.org/wiki/Asoundrc)
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
If your system has a default ALSA device configured you just need to enter the device id "default". This output device is already set in your sample configuration of `engine-core.ini`.
The background is that in addition to addressing the hardware through the included kernel drivers, ALSA configures the devices using plugins from the ALSA library (sample rate conversion, mixing) and this is based on experience with the actual audio devices. For more details checkout [https://alsa-project.org/wiki/Asoundrc](alsa-project.org/wiki/Asoundrc). But if you want some specific device, there is a variety of commands to obtain the device IDs from:
- To see only the physically available sound cards: `cat /proc/asound/cards`
- To see sound cards with all additional devices (e.g. HDMI): `aplay -l`
- To see devices configured by ALSA with additional plugins: `aplay -L`
- The default devices that should be used: `aplay -L | grep default`
The output of the last command may look like this:
```bash
aplay -L | grep default
default:CARD=PCH
sysdefault:CARD=PCH
default:CARD=K6
sysdefault:CARD=K6
```
The result means there are two sound cards configured as defaults, the onboard sound (`PCH`) and a USB one (`K6`).
Now, in `engine-core.ini` use:
```ini
output_device_0="default:CARD=PCH"
```
or just:
```ini
output_device_0="default:PCH"
```
Disadvantages can be:
- Modern distributions configure the ALSA devices with _dmix_, so that several devices can use the sound card at the same time. This can lead to unintentional audio being played independently of engine-core, e.g. if a desktop is running on the same computer.
- The default configuration might have higher latencies than would be possible. However, the latency of the default devices is like using PulseAudio and quite sufficient.
This can be avoided by directly addressing the hardware and setting the parameters buffer size and frame size in `engine-ini`. However, this requires a deep understanding of ALSA and experimentally finding the right parameters, so it is not recommended. A good starting point is to set only the parameter for the buffer size. Liquidsoap will adjust the remaining parameters automatically:
```ini
output_device_0="hw:2"
```
> #TODO Check if we should remove the alsa buffer recommendation here? According to my experience the frame-size is enough, as it also sets the buffer indirectly.
See [alsa-project.org/wiki/FramesPeriods](https://www.alsa-project.org/wiki/FramesPeriods) and [jan.newmarch.name/LinuxSound/Sampled/ALSA/](https://jan.newmarch.name/LinuxSound/Sampled/ALSA/) for more details.
### Setting the input device
Live analog audio input is disabled by default in Engine Core. Configuring live audio with low latencies can be tricky and depends on your system, Liquidsoap version, ALSA version and last but not least your audio interface.
First you'll need to set the input device ID. You can either set the `default` device or one specific device ID. The approach to get the correct device ID is similar to the one for the output device as outlined above. Here, all three example defintions are valid settings for the same card:
```ini
input_device_0="default"
input_device_0="hw:2,0"
input_device_0="sysdefault:CARD=K6"
```
Next you need to connect some external audio to the analog inputs of your audio interface. Double check if there is enough amplitude to avoid unnecessary searches for an error. Now you can try starting the engine with `run.sh`. Do you hear some sound? It might work, but probably you hear some audio glitches and see plenty buffer underruns in the logs. That's because you need to specific the proper frame-size, individual to you soundcard and ALSA driver.
Next you need to decide if you want:
- **(A) Buffered audio**: There's some latency involved, but it is relatively easy to configure.
- **(B) Unbuffered audio**: Almost real-time, currently only working with Liquidsoap 2
#### (A) Buffered audio
Buffered audio is relatively easy to configure, but introduce some latency. By tweaking these values to something your soundcard love, you get can get the latency relatively low.
First check if buffered audio is enabled. But it's the default anyway.
```ini
alsa_buffered_input="true"
alsa_buffered_output="true"
```
In that case you might need to tweak following settings, where the defaults are a good start. Maybe you are lucky and it works out of the box? :-)
```ini
frame_audio_size="1764"
If you don't experience any buffer underruns in the logs you can try to decrease the buffer size to for example `3528` or `1764`.
In case you get plenty of buffer unterruns then try to increase the buffer size and possibly the frame size to twice the given value.
When enabling unbuffered audio you can access the (almost) real-time capabilities of ALSA.
alsa_buffered_input="false"
```
In that case you need to tweak at least following setting, but it's one with some huge impact.
```ini
frame_audio_size="1764"
```
**Detecting the correct frame-size**
> WARNING: The current implementation of Engine Core is based on Liquidsoap 1.4 which doesn't provide a proper frame-size detection. Until we have [upgraded to Liquidsoap 2.0](https://gitlab.servus.at/aura/engine-core/-/issues/4) we don't recommend using live audio input. The steps below are based on Liquidsoap 2.0. Also, while live audio works good with a native installation of Engine Core, we couldn't get Liquidsoap to work glitch-free in an Docker environment. Feedback and tips are welcome.
Open the file `engine-core/tests/test_alsa_framesize.liq` in an editor. If you are using an other device than the default one, change `device="default"` to the one you are using.
Now perform following steps to find the correct frame-size:
1. Run the script with the initial `frame.audio.size` of zero: `engine-core/tests$ liquidsoap -v test_alsa_framesize.liq`
2. This causes plenty buffer underruns.
3. Liquidsoap reports the "correct" frame-size of e.g. 1764 in the logs: `[analog_input:3] Could not set buffer size to 'frame.size' (1764 samples), got 1881.`.
4. Now adapt the `frame.audio.size` in the script to `1764`.
5. This may have caused buffer underruns too
6. Now try to set the frame size to a multiple of "1764". For example frame size to 2 x 1764 = 3528. Run the script again.
7. Liquidsoap logs another mismatch in the logs: `[analog_input:3] Could not set buffer size to 'frame.size' (3528 samples), got 3529.`
8. Now the value is only off by 1. This might be because of a resolution problem. So now try to set the frame size to 3528 + 1 = 3529
9. Run the script again. Now the logs don't report an error like "Could not not set buffer size" anymore.
10. Watch the logs for a while. If there are still some buffer underruns try a higher number. Try another multiple by setting frame size to 2 x 3528 = 7056.
11. Run the script again. If there are no buffer underruns anymore and you hear clean sound without any glitches you have found an optimal value. Also watchout for any "Could not set buffer size" logs, they should be gone too.
The total steps needed and resulting values might be different based on your system and audio interface.
After you have found your own personal frame-size, use the value for the `frame_audio_size` in the `engine-core.ini` config. Then start the engine and double-check the logs there.
> _More testing and documentation on PulseAudio usage to be provided at a later stage. Feedback and tips are welcome._
A system which is already configured for PulseAudio needs no further configuration. The `default` ALSA device is emulated automatically using a PulseAudio ALSA plugin. The signal flow looks like following:
Audio Interface <--> ALSA <--> Pulse Audio <--> ALSA Plugin <--> Audio Stream
Obviously this is the reason for increased latencies. This should not be an issue for playing audio via files or streams, but might cause buffer issues with live audio. You can also set PulseAudio as the sound server in the Engine Core configuration, promising less latency:
Audio Interface <--> ALSA <--> Pulse Audio <--> Audio Stream
**Documentation:** Find more information in the [_PulseAudio_](https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/) documentation.
> _Supported, but not yet tested. Documentation will be updated as soon we have more information on the actual usage. We are happy for contributions on configuration and best practices._
**Documentation:** Find more information in the [_JACK Audio Connection Kit_](https://jackaudio.org/) documentation.