diff --git a/README.md b/README.md index 4ae9859a02bd702d7cc59e944e35c286581b930f..dab236c1566df54cc00ed05517c6c974fd06b28a 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ For full utilization Engine Core might be combined with [Engine](https://gitlab. - **ReplayGain** normalization done using passed [ReplayGain](https://en.wikipedia.org/wiki/ReplayGain) meta data. - **Track Service** notifications when used in conjunction with [Engine API](https://gitlab.servus.at/aura/engine-api) -This project is part of [Aura Radio Software Suite](https://gitlab.servus.at/aura/meta), specifically build for the requirements of community radios. +This project is part of [Aura Radio Software Suite](https://gitlab.servus.at/aura/meta), specifically build for the requirements of community radio stations. <!-- TOC --> @@ -33,7 +33,9 @@ This project is part of [Aura Radio Software Suite](https://gitlab.servus.at/aur To [install the AURA Suite](https://gitlab.servus.at/aura/meta) we recommend using [Docker](https://www.docker.com/) and [Docker Compose](https://docs.docker.com/compose/). -In certain scenarios like for development you might want to do a bare metal installation though. In that case you'll need to have following installed: +> IMPORTANT: For live audio input inside Docker there are currently unknown latency issues. After the [move the Liquidsoap 2.0](https://gitlab.servus.at/aura/engine-core/-/issues/4) it should be somewhat better. Therefore we right now recommend to do a bare-metal installation for Engine Core. All other AURA components can be deployed using Docker though. + +You'll need to have following installed before proceeding: - [git](https://git-scm.com/) - [OPAM (OCaml Package Manager)](https://opam.ocaml.org/) @@ -63,7 +65,9 @@ The aformentioned `audio` folder is the base for retrieving audio files. Engine ## Advanced Configuration -Review the settings in your `engine-core.ini` to fine-tune the heart of your engine. If you are experiencing issues also check out the [Frequently Asked Questions (FAQ)](docs/frequently-asked-questions.md). +By default only audio output is enabled using the systems default device. If you want to use another audio interface or enable live audio, check the [Audio Device Configuration](docs/audio-device-configuration.md) document. + +Also review the other settings in your `engine-core.ini` to fine-tune the heart of your engine. If you are experiencing issues also check out the [Frequently Asked Questions (FAQ)](docs/frequently-asked-questions.md). ## Other AURA Components @@ -71,6 +75,7 @@ After successfully running Engine Core you might look into getting started with ## Read more +- [Audio Device Configuration](docs/audio-device-configuration.md) - [Frequently Asked Questions (FAQ)](docs/frequently-asked-questions.md) ## About diff --git a/docs/audio-device-configuration.md b/docs/audio-device-configuration.md new file mode 100644 index 0000000000000000000000000000000000000000..00f2fc546ea778bb34bc309b508c0a27fe59e3b4 --- /dev/null +++ b/docs/audio-device-configuration.md @@ -0,0 +1,181 @@ + +# Audio Device Configuration + +This document outlines the steps on how to configure an audio interface with Engine Core. + +Following three audio drivers & servers are supported: + +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. + +<!-- TOC --> + +- [Audio Device Configuration](#audio-device-configuration) + - [ALSA](#alsa) + - [Defining the default audio device](#defining-the-default-audio-device) + - [Setting the output device](#setting-the-output-device) + - [Setting the input device](#setting-the-input-device) + - [Detecting the correct frame-size](#detecting-the-correct-frame-size) + - [Pulse Audio](#pulse-audio) + - [JACK](#jack) + +<!-- /TOC --> + +## ALSA + +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. 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. 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 + +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. + +<u>Documentation:</u> 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. + +### 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) + +### Setting the output device + +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 periods 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" +alsa_buffer="8192" +``` + +> #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. + +#### 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_default_live.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_default_live.liq` +2. This causes plenty buffer underruns. +3. Liquidsoap reports the "correct" frame-size of e.g. 1881 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 `1881`. +5. This may have caused buffer underruns too +6. Now try to set the frame size to a multiple of "1881". For example frame size to 2 x 1881 = 3762. Run the script again. +7. Liquidsoap logs another mismatch in the logs: `[analog_input:3] Could not set buffer size to 'frame.size' (3762 samples), got 3763.` +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 3762 + 1 = 3763 +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 3763 = 7526. +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_size` in the `engine-core.ini` config. Then start the engine and double-check the logs there. + +## Pulse Audio + +> *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 + +<u>Documentation:</u> Find more information in the [*PulseAudio*](https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/) documentation. + + + +## JACK + +> *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.* + +<u>Documentation:</u> Find more information in the [*JACK Audio Connection Kit*](https://jackaudio.org/) documentation. diff --git a/docs/frequently-asked-questions.md b/docs/frequently-asked-questions.md index b240ef972218832cf6dcb631cd0a0df93f51eba6..5684fce0157f6975a47aee164a49abd1a332fc09 100644 --- a/docs/frequently-asked-questions.md +++ b/docs/frequently-asked-questions.md @@ -22,51 +22,12 @@ Basically any audio device which is supported by Linux Debian/Ubuntu and has ALS ## How can I find the audio device IDs, required for settings in engine-core.ini? -**ALSA**: If your system has a default ALSA device configured you just need to enter the device id "`default`". 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: [alsa-project.org/wiki/Asoundrc](https://www.alsa-project.org/wiki/Asoundrc). But if you want some specific device, there is a varienty of commands to obtain the device ids: - - 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` -For example if the last command results in: - -```ini -default:CARD=PCH -sysdefault:CARD=PCH -default:CARD=Device -sysdefault:CARD=Device -``` - -It means there are two sound cards here, the onboard sound (PCH) and a USB one (Device). - -Now, in `engine-core.ini` use: - -`output_device_0="default:CARD=PCH"` - -or just: - -`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 has 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 periods. 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:0" -alsa_buffer="8192" -``` - -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. - -**Pulse Audio**: You might not need this for Pulse Audio as the `default` device might be sufficient. To choose a specific one its ID can be found using `pactl list` - -**JACK**: Please check out the [JACK Documentation](https://jackaudio.org/). - +Check out the [Audio Device Configuration](docs/audio-device-configuration.md) page for more details on the input/output settings. ## I have configured an audio device in my `engine-core.ini` but still hear no sound To test if you device is able to output audio at all, independently from Engine Core, try executing `speaker-test`. Also checkout out the `-D` argument to test specific devices. If you system doesn't provided `speaker-test` you have to install or use your preferred way of testing also audio. diff --git a/tests/test_alsa_default_live.liq b/tests/test_alsa_default_live.liq index 5c802124295c53a122521b6d14f1329e2e278386..5c16083f85d13d8d7a8080115239879c571688a6 100644 --- a/tests/test_alsa_default_live.liq +++ b/tests/test_alsa_default_live.liq @@ -20,12 +20,12 @@ set("init.allow_root", true) set("init.catch_exn", false) -set("init.trace", true) set("log.file.path", "../logs/<script>.log") set("log.level", 5) set("ffmpeg.log.level", 5) -set("frame.audio.size", 7526) +set("frame.audio.size", 0) +# set("frame.audio.size", 7526) set("frame.video.framerate", 0) input_analog = input.alsa(id="analog_input", device="default", bufferize=false, start=true, fallible=true) output.alsa(id="lineout", device="default", input_analog, bufferize=false, fallible=true) \ No newline at end of file diff --git a/tests/test_framesize.liq b/tests/test_framesize.liq index dc6c7fda9c2411b61435604c7c718ed14e80bd28..95042b709b82f24ace8022f3348a9c14ef3fedce 100755 --- a/tests/test_framesize.liq +++ b/tests/test_framesize.liq @@ -23,4 +23,4 @@ set("log.file.path", "../logs/<script>.log") set("frame.audio.size", 0) set("frame.video.framerate", 0) -input.alsa(bufferize=false) \ No newline at end of file +input.alsa(device="default", bufferize=false) \ No newline at end of file