{"id":13603563,"url":"https://github.com/HEnquist/camilladsp","last_synced_at":"2025-04-11T22:31:38.705Z","repository":{"id":37543658,"uuid":"224718305","full_name":"HEnquist/camilladsp","owner":"HEnquist","description":"A flexible cross-platform IIR and FIR engine for crossovers, room correction etc.","archived":false,"fork":false,"pushed_at":"2025-04-09T21:21:21.000Z","size":83831,"stargazers_count":643,"open_issues_count":22,"forks_count":54,"subscribers_count":26,"default_branch":"master","last_synced_at":"2025-04-09T21:37:52.620Z","etag":null,"topics":["alsa","audio","coreaudio","dsp","fir","iir-filters","pulseaudio","wasapi"],"latest_commit_sha":null,"homepage":"https://henquist.github.io/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/HEnquist.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-11-28T19:40:03.000Z","updated_at":"2025-04-08T11:28:20.000Z","dependencies_parsed_at":"2023-10-15T10:03:01.235Z","dependency_job_id":"73ac6fda-3f16-431c-945d-b6b18536ea8e","html_url":"https://github.com/HEnquist/camilladsp","commit_stats":null,"previous_names":[],"tags_count":71,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HEnquist%2Fcamilladsp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HEnquist%2Fcamilladsp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HEnquist%2Fcamilladsp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HEnquist%2Fcamilladsp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/HEnquist","download_url":"https://codeload.github.com/HEnquist/camilladsp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248489667,"owners_count":21112617,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alsa","audio","coreaudio","dsp","fir","iir-filters","pulseaudio","wasapi"],"created_at":"2024-08-01T19:00:25.308Z","updated_at":"2025-04-11T22:31:38.676Z","avatar_url":"https://github.com/HEnquist.png","language":"Rust","readme":"# CamillaDSP v3.0\n![CI test and lint](https://github.com/HEnquist/camilladsp/workflows/CI%20test%20and%20lint/badge.svg)\n\nA tool to create audio processing pipelines for applications such as active crossovers or room correction.\nIt is written in Rust to benefit from the safety and elegant handling of threading that this language provides.\n\nSupported platforms: Linux, macOS, Windows.\n\nAudio data is captured from a capture device and sent to a playback device.\nAlsa, PulseAudio, Jack, Wasapi and CoreAudio are currently supported for both capture and playback.\n\nThe processing pipeline consists of any number of filters and mixers.\nMixers are used to route audio between channels and to change the number of channels in the stream.\nFilters can be both IIR and FIR. IIR filters are implemented as biquads, while FIR use convolution via FFT/IFFT.\nA filter can be applied to any number of channels. All processing is done in chunks of a fixed number of samples.\nA small number of samples gives a small in-out latency while a larger number is required for long FIR filters.\nThe full configuration is given in a YAML file.\n\n# Disclaimer\n\nCamillaDSP is distributed under the [GNU GENERAL PUBLIC LICENSE Version 3](LICENSE.txt).\n\nThis includes the following disclaimer:\n\u003e  15. Disclaimer of Warranty.\n\u003e\n\u003e  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\n\u003eAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\n\u003eHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\n\u003eOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\n\u003eTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n\u003ePURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\n\u003eIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\n\u003eALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\u003e\n\u003e  16. Limitation of Liability.\n\u003e\n\u003e  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n\u003eWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\n\u003eTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\n\u003eGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\n\u003eUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\n\u003eDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\n\u003ePARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\n\u003eEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\n\u003eSUCH DAMAGES.\n\nIn short this means that the user is responsible for any damage resulting from using this program.\nIt does not matter if the damage is caused by incorrect usage or a bug in the software.\n\n# Table of Contents\n**[Introduction](#introduction)**\n- **[Background](#background)**\n- **[How it works](#how-it-works)**\n- **[System requirements](#system-requirements)**\n- **[Usage example: crossover for 2-way speakers](#usage-example-crossover-for-2-way-speakers)**\n- **[Dependencies](#dependencies)**\n- **[Companion libraries and tools](#companion-libraries-and-tools)**\n- **[GUI](#gui)**\n\n**[Installing](#installing)**\n\n**[Building](#building)**\n- **[Build with standard features](#building-in-linux-with-standard-features)**\n- **[Customized build](#customized-build)**\n- **[Optimize for your system](#optimize-for-your-system)**\n- **[Building on Windows and macOS](#building-on-windows-and-macos)**\n\n**[How to run](#how-to-run)**\n- **[Command line options](#command-line-options)**\n- **[Reloading the configuration](#reloading-the-configuration)**\n- **[Controlling via websocket](#controlling-via-websocket)**\n\n**[Processing audio](#processing-audio)**\n- **[Cross-platform](#cross-platform)**\n  - **[Jack](#jack)**\n  - **[File or pipe](#file-or-pipe)**\n- **[Windows](#windows)**\n- **[MacOS (CoreAudio)](#macos-coreaudio)**\n- **[Linux](#linux)**\n  - **[Alsa](#alsa)**\n  - **[PulseAudio](#pulseaudio)**\n  - **[Pipewire](#pipewire)**\n\n**[Configuration](#configuration)**\n- **[The YAML format](#the-yaml-format)**\n- **[Title and description](#title-and-description)**\n- **[Volume control](#volume-control)**\n- **[Devices](#devices)**\n- **[Resampling](#resampling)**\n- **[Mixers](#mixers)**\n- **[Filters](#filters)**\n   - **[Gain](#gain)**\n   - **[Volume](#volume)**\n   - **[Loudness](#loudness)**\n   - **[Delay](#delay)**\n   - **[FIR](#fir)**\n   - **[IIR](#iir)**\n   - **[Dither](#dither)**\n   - **[Limiter](#limiter)**\n   - **[Difference equation](#difference-equation)**\n- **[Processors](#processors)**\n   - **[Compressor](#compressor)**\n   - **[NoiseGate](#noise-gate)**\n- **[Pipeline](#pipeline)**\n   - **[Filter step](#filter-step)**\n   - **[Mixer and Processor step](#mixer-and-processor-step)**\n   - **[Tokens in names](#tokens-in-names)**\n   - **[Bypassing steps](#bypassing-steps)**\n- **[Using filters from REW](#using-filters-from-rew)**\n- **[Visualizing the config](#visualizing-the-config)**\n\n**[Related projects](#related-projects)**\n\n**[Getting help](#getting-help)**\n- **[FAQ](#faq)**\n- **[Troubleshooting](#troubleshooting)**\n\n\n\n# Introduction\n\n## Background\nThe purpose of CamillaDSP is to enable audio processing with combinations of FIR and IIR filters.\nThis functionality is available in EqualizerAPO, but for Windows only.\nFor Linux the best known FIR filter engine is probably BruteFIR, which works very well but doesn't support IIR filters.\nThe goal of CamillaDSP is to provide both FIR and IIR filtering for Linux, Windows and macOS, to be stable, fast and flexible, and be easy to use and configure.\n\n* BruteFIR: https://torger.se/anders/brutefir.html\n* EqualizerAPO: https://sourceforge.net/projects/equalizerapo/\n* The IIR filtering is heavily inspired by biquad-rs: https://github.com/korken89/biquad-rs\n\n## How it works\nThe audio pipeline in CamillaDSP runs in three separate threads.\nOne thread handles capturing audio, one handles the playback, and one does the processing in between.\nThe capture thread passes audio to the processing thread via a message queue.\nEach message consists of a chunk of audio with a configurable size.\nThe processing queue waits for audio messages, processes them in the order they arrive,\nand passes the processed audio via another message queue to the playback thread.\nThere is also a supervisor thread for control.\nThis chart shows the most important parts:\n\n![Overview](overview.png)\n\n### Capture\nThe capture thread reads a chunk samples from the audio device in the selected format.\nIt then converts the samples to 64-bit floats (or optionally 32-bit).\nIf resampling is enabled, the audio data is sent to the resampler.\nAt the end, the chunk of samples is packed as a message that is then posted to the input queue of the processing thread.\nAfter this the capture thread returns to reading the next chunk of samples from the device.\n\n### Processing\nThe processing thread waits for audio chunk messages to arrive in the input queue.\nOnce a message arrives, it's passed through all the defined filters and mixers of the pipeline.\nOnce all processing is done, the audio data is posted to the input queue of the playback device.\n\n### Playback\nThe playback thread simply waits for audio messages to appear in the queue.\nOnce a message arrives, the audio data is converted to the right sample format for the device, and written to the playback device.\nThe Alsa playback device supports monitoring the buffer level of the playback device.\nThis is used to send requests for adjusting the capture speed to the supervisor thread, on a separate message channel.\n\n### Supervisor\nThe supervisor monitors all threads by listening to their status messages.\nThe requests for capture rate adjust are passed on to the capture thread.\nIt's also responsible for updating the configuration when requested to do so via the websocket server or a SIGHUP signal.\n\n### Websocket server\nThe websocket server launches a separate thread to handle each connected client.\nAll commands to change the config are sent to the supervisor thread.\n\n## System requirements\nCamillaDSP runs on Linux, macOS and Windows.\nThe exact system requirements are determined by the amount of processing the application requires,\nbut even relatively weak CPUs like Intel Atom have much more processing power than most will need.\n\nIn general, a 64-bit CPU and OS will perform better.\n\nA few examples, done with CamillaDSP v0.5.0:\n\n- A Raspberry Pi 4 doing FIR filtering of 8 channels, with 262k taps per channel, at 192 kHz.\n  CPU usage about 55%.\n\n- An AMD Ryzen 7 2700u (laptop) doing FIR filtering of 96 channels, with 262k taps per channel, at 192 kHz.\n  CPU usage just under 100%.\n\n### Linux requirements\nBoth 64 and 32 bit architectures are supported. All platforms supported by the Rustc compiler should work.\n\nPre-built binaries are provided for:\n- x86_64 (almost all PCs)\n- armv6 (32-bit arm, for example a Raspberry Pi 1 and Zero)\n- armv7 (32-bit arm, for example a Raspberry Pi 2,3,4 with a 32-bit OS)\n- aarch64 (64-bit arm, for example Raspberry Pis running a 64 bit OS)\n\n### Windows requirements\nAn x86_64 CPU and the 64-bit version of Windows is recommended. Any x86_64 CPU will likely be sufficient.\n\nPre-built binaries are provided for 64-bit systems.\n\n### MacOS requirements\nCamillaDSP can run on both Intel and Apple Silicon macs. Any reasonably recent version of MacOS should work.\n\nPre-built binaries are provided for both Intel and Apple Silicon\n\n\n## Usage example: crossover for 2-way speakers\nA crossover must filter all sound being played on the system.\nThis is possible with both PulseAudio and Alsa by setting up a loopback device (Alsa) or null sink (Pulse) and setting this device as the default output device.\nCamillaDSP is then configured to capture from the output of this device and play the processed audio on the real sound card.\n\nSee the [tutorial for a step-by-step guide.](./stepbystep.md)\n\n## Dependencies\nThese are the key dependencies for CamillaDSP.\n* https://crates.io/crates/alsa - Alsa audio backend\n* https://crates.io/crates/clap - Command line argument parsing\n* https://crates.io/crates/cpal - Jack audio backend\n* https://crates.io/crates/libpulse-simple-binding - PulseAudio audio backend\n* https://crates.io/crates/realfft - Wrapper for RustFFT that speeds up FFTs of real-valued data\n* https://crates.io/crates/rustfft - FFT used for FIR filters\n* https://crates.io/crates/rubato - Sample rate conversion\n* https://crates.io/crates/serde_yaml - Config file reading\n* https://crates.io/crates/tungstenite - Websocket server\n\n\n## Companion libraries and tools\nThese projects are part of the CamillaDSP family:\n* https://github.com/HEnquist/pycamilladsp - Library for communicating with CamillaDSP over websocket.\n* https://github.com/HEnquist/pycamilladsp-plot - Plotting and visualization of configurations.\n* https://github.com/HEnquist/camilladsp-config - Example configurations for things like running CamillaDSP as a systemd service.\n\n## GUI\n[CamillaGUI](https://github.com/HEnquist/camillagui-backend) is a user interface for CamillaDSP that is accessed via a web browser.\n\n\n# Installing\n\nThe easiest way to install CamillaDSP is to download a pre-built binary.\nBinaries for each release are available for the most common systems.\nSee the [\"Releases\"](https://github.com/HEnquist/camilladsp/releases) page.\nTo see the files click \"Assets\".\n\nThese are compressed files containing a single executable file that is ready to run.\n\nThe following configurations are provided:\n\n| Filename | Description | Backends |\n|----------|-------------|----------|\n| `camilladsp-linux-amd64.tar.gz` | Linux on 64-bit Intel or AMD CPU | Alsa, Pulseaudio |\n| `camilladsp-linux-armv6.tar.gz` | Linux on Armv6 (32-bit), intended for Raspberry Pi 1 and Pi Zero but should also work on others | Alsa |\n| `camilladsp-linux-armv7.tar.gz` | Linux on Armv7 with Neon (32-bit), intended for Raspberry Pi 2 and up but should also work on others | Alsa |\n| `camilladsp-linux-aarch64.tar.gz` | Linux on Armv8 (64-bit), intended for Raspberry Pi 3 and up, but should also work on others | Alsa |\n| `camilladsp-macos-amd64.tar.gz` | macOS on 64-bit Intel CPU | CoreAudio |\n| `camilladsp-macos-aarch64.tar.gz` | macOS on Apple silicon | CoreAudio |\n| `camilladsp-windows-amd64.zip` | Windows on 64-bit Intel or AMD CPU | Wasapi |\n\nAll builds include the Websocket server.\n\nThe `.tar.gz`-files can be uncompressed with the `tar` command:\n\n```sh\ntar -xvf camilladsp-linux-amd64.tar.gz\n```\n\n## Running downloaded executables on macOS\nIf the binary was downloaded using Safari, then macOS most likely won't allow it to be executed.\nTrying will result in an error message such as:\n`\"camilladsp\" can't be opened because its integrity cannot be verified.`\n\nThe solution is to remove the \"quarantine\" attribute from the binary using the `xattr` command.\n\nOpen a a terminal and run:\n\n```sh\nxattr -d com.apple.quarantine /path/to/camilladsp\n```\n\n# Building\n\nUse recent stable versions of rustc and cargo. The minimum rustc version is 1.61.0.\n\nThe recommended way to install rustc and cargo is by using the \"rustup\" tool.\nThis tool works on all supported platforms (Linux, macOS and Windows). Get it here: https://rustup.rs/\n\nFor Windows you also need the \"Build Tools for Visual Studio\". Get them from here: https://aka.ms/buildtools\n\nWhen building on Linux the Alsa backend is always enabled.\nSimilarly, building on Windows always enables the Wasapi backend.\nAnd building on macOS always enables the CoreAudio backend.\n\nBy default both the PulseAudio and Jack backends are disabled, but they can be enabled if desired.\nLeaving them disabled also means that the corresponding system Jack/Pulse packages aren't needed.\n\nBy default the internal processing is done using 64-bit floats.\nThere is a possibility to switch this to 32-bit floats.\nThis might be useful for speeding up the processing when running on a 32-bit CPU (or a 64-bit CPU running in 32-bit mode),\nbut the actual speed advantage has not been evaluated.\nNote that the reduction in precision increases the numerical noise.\n\nCamillaDSP includes a Websocket server that can be used to pass commands to the running process.\nThis feature is enabled by default, but can be left out. The feature name is \"websocket\".\nFor usage see the section \"Controlling via websocket\".\n\n## Building in Linux with standard features\nThese instructions assume that the linux distribution used is one of Fedora, Debian, Ubunty or Arch.\nThey should also work also work on distributions closely related to one of these, such as Manjaro (Arch),\nor Raspberry Pi OS (Debian).\n\nThere are many others, including some specialized distributions for example targeting audio playback.\nThese often come with a slimmed down set of preinstalled packages.\nCompiling CamillaDSP on one of these may require installing several more packages than the ones listed here.\nIf possible, it's recommended to use a pre-built binary on these systems.\n\n- Install pkg-config (very likely already installed):\n- - Fedora: ```sudo dnf install pkgconf-pkg-config```\n- - Debian/Ubuntu etc: ```sudo apt-get install pkg-config```\n- - Arch: ```sudo pacman -S cargo pkg-config```\n- Install Alsa dependency:\n- - Fedora: ```sudo dnf install alsa-lib-devel```\n- - Debian/Ubuntu etc: ```sudo apt-get install libasound2-dev```\n- - Arch: ```sudo pacman -S alsa-lib```\n- Install OpenSSL dependency:\n- - Fedora: ```sudo dnf install openssl openssl-devel```\n- - Debian/Ubuntu etc: ```sudo apt-get install openssl libssl-dev```\n- - Arch:  ```sudo pacman -S openssl```\n- Clone the repository\n- Build with standard options: ```cargo build --release```\n- - see below for other options\n- The binary is now available at ./target/release/camilladsp\n- Optionally install with `cargo install --path .`\n- - Note: the `install` command takes the same options for features as the `build` command.\n\n## Customized build\nAll the available options, or \"features\" are:\n- `pulse-backend`: PulseAudio support.\n- `cpal-backend`: Used for Jack support (automatically enabled when needed).\n- `jack-backend`: Jack support (Linux only).\n- `bluez-backend`: Bluetooth support via BlueALSA (Linux only).\n- `websocket`: Websocket server for control.\n- `secure-websocket`: Enable secure websocket, also enables the `websocket` feature.\n- `32bit`: Perform all calculations with 32-bit floats (instead of 64).\n- `debug`: Enable extra logging, useful for debugging.\n- `avoid-rustc-issue-116359`: Enable a workaround for [rust issue #116359](https://github.com/rust-lang/rust/issues/116359).\n  Used to check if a performance issue is caused by this compiler bug.\n\n\nThe `websocket` feature is included in the default features, meaning it will be enabled if you don't specify anything.\n\nCargo doesn't allow disabling a single default feature,\nbut you can disable the whole group with the `--no-default-features` flag.\nThen you have to manually add all the ones you want.\n\nExample 1: You want `websocket` and `pulse-backend`. The first one is included by default so you only need to add `pulse-backend`:\n```\ncargo build --release --features pulse-backend\n(or)\ncargo install --path . --features pulse-backend\n```\n\nExample 2: You want only `32bit`. Since you don't want `websocket` you have to disable the defaults:\n```\ncargo build --release --no-default-features --features 32bit\n(or)\ncargo install --path . --no-default-features --features 32bit\n```\n\n### Additional dependencies\n\nThe `pulse-backend` feature requires PulseAudio and its development files. To install:\n- Fedora: ```sudo dnf install pulseaudio-libs-devel```\n- Debian/Ubuntu etc: ```sudo apt-get install libpulse-dev```\n- Arch:  ```sudo pacman -S libpulse```\n\nThe `jack-backend` feature requires jack and its development files. To install:\n- Fedora: ```sudo dnf install jack-audio-connection-kit jack-audio-connection-kit-devel```\n- Debian/Ubuntu etc: ```sudo apt-get install jack libjack-dev```\n- Arch:  ```sudo pacman -S jack```\n\n## Optimize for your system\nBy default Cargo builds for a generic system, meaning the resulting binary might not run as fast as possible on your system.\nThis means for example that it will not use AVX on an x86-64 CPU, or NEON on a Raspberry Pi.\n\nTo make an optimized build for your system, you can specify this in your Cargo configuration file.\nOr, just set the RUSTFLAGS environment variable by adding RUSTFLAGS='...' in from of the \"cargo build\" or \"cargo install\" command.\n\nMake an optimized build on x86-64:\n```\nRUSTFLAGS='-C target-cpu=native' cargo build --release\n```\n\nOn a Raspberry Pi also state that NEON should be enabled:\n```\nRUSTFLAGS='-C target-feature=+neon -C target-cpu=native' cargo build --release\n```\n\n## Building on Windows and macOS\nThe platform-specific backends are always enabled when building on Windows and macOS. The recommended build command is:\n\nmacOS:\n```\nRUSTFLAGS='-C target-cpu=native' cargo build --release\n```\n\nWindows (cmd.exe command prompt):\n```\nset RUSTFLAGS=-C target-cpu=native\ncargo build --release\n```\n\nWindows (PowerShell):\n```\n$env:RUSTFLAGS=\"-C target-cpu=native\"\ncargo build --release\n```\n\nThe PulseAudio backend can be used on macOS.\nThe necessary dependencies can be installed with brew:\n```\nbrew install pkg-config\nbrew install pulseaudio\n```\n\n\n# How to run\n\nThe command is simply:\n```\ncamilladsp /path/to/config.yml\n```\nThis starts the processing defined in the specified config file.\nThe config is first parsed and checked for errors.\nThis first checks that the YAML syntax is correct, and then checks that the configuration is complete and valid.\nWhen an error is found it displays an error message describing the problem.\nSee more about the configuration file below.\n\n## Command line options\nStarting with the --help flag prints a short help message:\n```\n\u003e camilladsp --help\nCamillaDSP v3.0.0\nHenrik Enquist \u003chenrik.enquist@gmail.com\u003e\nA flexible tool for processing audio\n\nBuilt with features: websocket\n\nSupported device types:\nCapture: RawFile, WavFile, Stdin, SignalGenerator, CoreAudio\nPlayback: File, Stdout, CoreAudio\n\nUsage: camilladsp [OPTIONS] [CONFIGFILE]\n\nArguments:\n  [CONFIGFILE]  The configuration file to use\n\nOptions:\n  -c, --check                          Check config file and exit\n  -s, --statefile \u003cSTATEFILE\u003e          Use the given file to persist the state\n  -v...                                Increase message verbosity\n  -l, --loglevel \u003cLOGLEVEL\u003e            Set log level [possible values: trace, debug, info, warn, error, off]\n  -o, --logfile \u003cLOGFILE\u003e              Write logs to the given file path\n      --log_rotate_size \u003cROTATE_SIZE\u003e  Rotate log file when the size in bytes exceeds this value\n      --log_keep_nbr \u003cKEEP_NBR\u003e        Number of previous log files to keep\n  -a, --address \u003cADDRESS\u003e              IP address to bind websocket server to\n  -p, --port \u003cPORT\u003e                    Port for websocket server\n  -w, --wait                           Wait for config from websocket\n  -g, --gain \u003cGAIN\u003e                    Initial gain in dB for main volume control\n      --gain1 \u003cGAIN1\u003e                  Initial gain in dB for Aux1 fader\n      --gain2 \u003cGAIN2\u003e                  Initial gain in dB for Aux2 fader\n      --gain3 \u003cGAIN3\u003e                  Initial gain in dB for Aux3 fader\n      --gain4 \u003cGAIN4\u003e                  Initial gain in dB for Aux4 fader\n  -m, --mute                           Start with main volume control muted\n      --mute1                          Start with Aux1 fader muted\n      --mute2                          Start with Aux2 fader muted\n      --mute3                          Start with Aux3 fader muted\n      --mute4                          Start with Aux4 fader muted\n  -e, --extra_samples \u003cEXTRA_SAMPLES\u003e  Override number of extra samples in config\n  -n, --channels \u003cCHANNELS\u003e            Override number of channels of capture device in config\n  -r, --samplerate \u003cSAMPLERATE\u003e        Override samplerate in config\n  -f, --format \u003cFORMAT\u003e                Override sample format of capture device in config [possible values: S16LE, S24LE, S24LE3, S32LE, FLOAT32LE, FLOAT64LE]\n  -h, --help                           Print help\n  -V, --version                        Print version\n```\n\nMost flags and options have a long and a short form. For example `--port 1234` and `-p1234` are equivalent.\n\nIf the `--check` flag is given, the program will exit after checking the configuration file.\nUse this if you only want to verify that the configuration is ok, and not start any processing.\n\n### Logging\n\nThe default logging setting prints messages of levels \"error\", \"warn\" and \"info\".\nThis can be changed with the `loglevel` option.\nSetting this to for example `warn` will print messages of level `warn` and above, but suppress the lower levels of `info`, `debug` and `trace`.\nAlternatively, the log level can be changed with the verbosity flag.\nBy passing the verbosity flag once, `-v`, `debug` messages are enabled.\nIf it's given twice, `-vv`, it also prints `trace` messages.\n\nThe log messages are normally written to the terminal via stderr,\nbut they can instead be written to a file by giving the `--logfile` option.\nThe argument should be the path to the logfile.\nIf this file is not writable, CamillaDSP will panic and exit.\n\nLog rotation can be enabled by the `--log_rotate_size` option.\nThis creates a new log file whenever the log fize size exceeds the given size in bytes.\nWhen rotation is enabled the current log file gets an added infix of `_rCURRENT`,\nso for example `logfile.log` becomes `logfile_rCURRENT.log`.\nWhen the file is rotated, the old logs are kept with a timestamp as infix,\nfor example `logfile_r2023-01-29_12-59-00.log`.\nThe default is to keep all previous log files,\nbut this can be limited by setting the `--log_keep_nbr` option to the desired number.\n\n### Persistent storage of state\n\nThe `--statefile` option is used to give a path to a file where CamillaDSP will save the config file path, and the volume and mute settings.\nOn startup, these values will be read from the statefile if the file exists and is valid.\nThe values in the file will then be kept updated whenever they change.\nIf the file doesn't exist, it will be created on the first write.\n\nIf the `configfile` argument is given, then this will be used instead of the value from the statefile.\nSimilarly, the `--gain` and `--mute` options also override the values in the statefile for the main fader\nwhile the `--gain1` to `--gain4` and `--mute1` to `--mute4` do the same for the Aux faders.\n\n**Use this feature with caution! The volume setting given in the statefile will be applied immediately when CamillaDSP starts processing.**\nIn systems that have a gain structure such that a too high volume setting can damage equipment or ears,\nit is recommended to always use the `--gain` and `--gain1..4` options to set the volume to start at a safe value.\n\n#### Example statefile\nThe statefile is a small YAML file that holds the path to the active config file,\nas well as mute and volume settings for the five faders (`Main` and `Aux1` to `Aux4`)\n```\n---\nconfig_path: /path/to/config.yml\nmute:\n  - false\n  - false\n  - false\n  - false\n  - false\nvolume:\n  - 0.0\n  - 0.0\n  - 0.0\n  - 0.0\n  - 0.0\n```\n\n### Websocket\n\nTo enable the websocket server, provide a port number with the `--port` option. Leave it out, or give 0 to disable.\n\nBy default the websocket server binds to the address 127.0.0.1 which means it's only accessible locally (to clients running on the same machine).\nIf it should be also available to remote machines, give the IP address of the interface where it should be available with the `--address` option.\nGiving 0.0.0.0 will bind to all interfaces.\nIf CamillaDSP was built with the \"secure-websocket\" feature, it has two additional options `--cert` and `--pass`.\nThese are used to provide an identity, to enable secure websocket connections.\nSee the [websocket readme for more details.](./websocket.md)\n\nIf the \"wait\" flag, `--wait` is given, CamillaDSP will start the websocket server and wait for a configuration to be uploaded.\nThen the config file argument must be left out.\n\n### Overriding config values\n\nThere are a few options to override values in the loaded config file.\nGiving these options means the provided values will be used instead of the values in any loaded configuration.\nTo change the values, CamillaDSP has to be restarted.\nIf the config file has resampling disabled, then overriding the samplerate will change the `samplerate` parameter.\nBut if resampling is enabled, it will instead change the `capture_samplerate` parameter.\nIf then `enable_rate_adjust` is false and `capture_samplerate`=`samplerate`, then resampling will be disabled.\nWhen overriding the samplerate, two other parameters are scaled as well.\nFirstly, the `chunksize` is multiplied or divided by integer factors to try to keep the pipeline running at a constant number of chunks per second.\nSecondly, the value of `extra_samples` is scaled to give the extra samples the same duration at the new samplerate.\nBut if the `extra_samples` override is used, the given value is used without scaling it.\n\n\n### Initial volume\n\nThe `--gain` and `--gain1..4` options can accept negative values,\nbut this requires a little care since the minus sign can be misinterpreted as another option.\nIt works as long as there is no space in front of the minus sign.\n\nThese all work for positive values (with 12.3 dB used as an example):\n```\n-g12.3\n--gain=12.3\n-g 12.3\n--gain 12.3\n```\n\nThese work for negative values (note that there is no space before the minus sign):\n```\n-g-12.3\n--gain=-12.3\n```\n\nThese have a space before the minus sign and do __NOT__ work:\n```\n-g -12.3\n--gain -12.3\n```\n\n\n## Exit codes\nThese are the exit codes CamillaDSP will give:\n\n| Exit code | Meaning |\n| --------- | ------- |\n| 0         | Normal exit, no error |\n| 101       | Invalid config file, see the error message for details |\n| 102       | Error from DSP process, see the error message for details |\n| 103       | Forced exit by a second SIGINT before before a normal exit was completed |\n\n\n## Reloading the configuration\nThe configuration can be reloaded without restarting by sending a SIGHUP to the camilladsp process.\nThis will reload the config and if possible apply the new settings without interrupting the processing.\nNote that for this to update the coefficients for a FIR filter, the filename of the coefficients file needs to change.\n\n## Controlling via websocket\nSee the [separate readme for the websocket server](./websocket.md)\n\n\n# Processing audio\nThe goal is to insert CamillaDSP between applications and the sound card.\nThe details of how this is achieved depends on which operating system and which audio API is being used.\nIt is also possible to use pipes for apps that support reading or writing audio data from/to stdout.\n\n## Cross-platform\nThese backends are supported on all platforms.\n\n### File or pipe\nAudio can be read from a file or a pipe using the `RawFile` device type.\nThis can read raw interleaved samples in most common formats.\n\nTo instead read from stdin, use the `Stdin` type.\nThis makes it possible to pipe raw samples from some applications directly to CamillaDSP,\nwithout going via a virtual soundcard.\n\nWav files can be read using the `WavFile` device type.\nSee [the capture device section](#file-rawfile-wavfile-stdin-stdout) for more details.\n\n### Jack\nJack is most commonly used with Linux, but can also be used with both Windows and MacOS.\nThe Jack support of CamillaDSP version should be considered experimental.\nIt is implemented using the CPAL library, which currently only supports Jack on Linux.\n\n#### Using Jack\nThe Jack server must be running.\n\nSet `device` to \"default\" for both capture and playback.\nThe sample format is fixed at 32-bit float (FLOAT32LE).\n\nThe samplerate must match the samplerate configured for the Jack server.\n\nCamillaDSP will show up in Jack as \"cpal_client_in\" and \"cpal_client_out\".\n\n\n## Windows\nSee the [separate readme for Wasapi](./backend_wasapi.md).\n\n## MacOS (CoreAudio)\nSee the [separate readme for CoreAudio](./backend_coreaudio.md).\n\n## Linux\nLinux offers several audio APIs that CamillaDSP can use.\n\n### Alsa\nSee the [separate readme for ALSA](./backend_alsa.md).\n\n### PulseAudio\nPulseAudio provides a null-sink that can be used to capture audio from applications. To create a null sink type:\n```\npacmd load-module module-null-sink sink_name=MySink\n```\nThis device can be set as the default output, meaning any application using PulseAudio will use it.\nThe audio sent to this device can then be captured from the monitor output named \"MySink.monitor\".\n\nAll available sinks and sources can be listed with the commands:\n```\npacmd list-sinks\npacmd list-sources\n```\n\n### Pipewire\nPipewire implements both the PulseAudio and Jack APIs.\nIt is therefore supported both via the Pulse and the Jack backends, and there is no need for a specific Pipewire backend.\n\nPipewire supports creating null-sink like PulseAudio. Create it with:\n```\npactl load-module module-null-sink sink_name=MySink object.linger=1 media.class=Audio/Sink\n```\n\nList sources and sinks with:\n```\npw-cli ls Node\n```\n\nThis will list all devices, and the null-sink should be included like this:\n```\n\tid 75, type PipeWire:Interface:Node/3\n \t\tfactory.id = \"18\"\n \t\tnode.description = \"MySink Audio/Sink sink\"\n \t\tnode.name = \"MySink\"\n \t\tmedia.class = \"Audio/Sink\"\n```\nThis device can be set as the default output in the Gnome sound settings, meaning all desktop audio will use it.\nThe audio sent to this device can then be captured from the monitor output named \"MySink.monitor\" using the PulseAudio backend.\n\nPipewire can also be configured to output to an ALSA Loopback.\nThis is done by adding an ALSA sink in the Pipewire configuration.\nThis sink then becomes available as an output device in the Gnome sound settings.\nSee the \"camilladsp-config\" repository under [Related projects](#related-projects) for an example Pipewire configuration.\n\nTODO test with Jack.\n\n### BlueALSA\nBlueALSA ([bluez-alsa](https://github.com/Arkq/bluez-alsa)) is a project to receive or send audio through Bluetooth A2DP.\nThe `Bluez` source will connect to BlueALSA via D-Bus to get a file descriptor.\nIt will then read the audio directly from there, avoiding the need to go via ALSA.\nCurrently only capture (a2dp-sink) is supported.\nBlueALSA is supported on Linux only, and requires building CamillaDSP with the `bluez-backend` Cargo feature.\n\n#### Prerequisites\nStart by installing `bluez-alsa`.\nBoth Pipewire and PulseAudio will interfere with BlueALSA and must be disabled.\nThe source device should be paired after disabling Pipewire or PulseAudio and enabling BlueALSA.\n\n#### Configuration\n\nExample configuration:\n```\ndevices:\n  samplerate: 44100\n  chunksize: 4096\n  target_level: 8000\n  adjust_period: 3\n  resampler:\n    type: AsyncSinc\n    profile: Balanced\n  enable_rate_adjust: true\n  capture:\n    type: Bluez\n    format: S16LE\n    channels: 2\n    dbus_path: /org/bluealsa/hci0/dev_A0_B1_C2_D3_E4_F5/a2dpsnk/source\n    service: org.bluealsa (*)\n```\n\nAfter connecting an A2DP device, for example a mobile phone, the D-Bus path can be found with this command:\n```\ngdbus call -y --dest org.bluealsa -o /org/bluealsa -m org.freedesktop.DBus.ObjectManager.GetManagedObjects\n```\nThis should produce output similar to this:\n```\n({objectpath '/org/bluealsa/hci0/dev_A0_B1_C2_D3_E4_F5/a2dpsnk/source': {'org.bluealsa.PCM1': {'Device': \u003cobjectpath '/org/bluez/hci0/dev_A0_B1_C2_D3_E4_F5'\u003e, 'Sequence': \u003cuint32 0\u003e, 'Transport': \u003c'A2DP-sink'\u003e, 'Mode': \u003c'source'\u003e, 'Format': \u003cuint16 33296\u003e, 'Channels': \u003cbyte 0x02\u003e, 'Sampling': \u003cuint32 44100\u003e, 'Codec': \u003c'AAC'\u003e, 'CodecConfiguration': \u003c[byte 0x80, 0x01, 0x04, 0x03, 0x5b, 0x60]\u003e, 'Delay': \u003cuint16 150\u003e, 'SoftVolume': \u003ctrue\u003e, 'Volume': \u003cuint16 32639\u003e}}},)\n```\nThe wanted path is the string after `objectpath`.\nIf the output is looking like `(@a{oa{sa{sv}}} {},)`, then no A2DP source is connected or detected.\nConnect an A2DP device and try again. If a device is already connected, try removing and pairing the device again.\n\nThe `service` property can be left out to get the default. This only needs changing if there is more than one instance of BlueALSA running.\n\nYou have to specify correct capture sample rate, number of channel and sample format.\nThese parameters can be found with `bluealsa-aplay`:\n```\n\u003e bluealsa-aplay -L\n\nbluealsa:DEV=A0:B1:C2:D3:E4:F5,PROFILE=a2dp,SRV=org.bluealsa\n    MyPhone, trusted phone, capture\n    A2DP (AAC): S16_LE 2 channels 44100 Hz\n```\n\nNote that Bluetooth transfers data in chunks, and the time between chunks can vary.\nTo avoid underruns, use a large chunksize and a large target_level.\nThe values in the example above are a good starting point.\nRate adjust should also be enabled.\n\n# Configuration\n\n## The YAML format\nCamillaDSP is using the YAML format for the configuration file.\nIt is a standard format that was chosen because of its nice readable syntax.\n\nThis section is a very brief introduction to the YAML format\nthat is intended to cover only what is needed to read and write CamillaDSP config files.\nPlease see the full [YAML specification](https://yaml.org/) for more details.\n\nThere are a few things to keep in mind with YAML.\nThe configuration is a tree, and the level is determined by the indentation level.\nFor YAML the indentation is as important as opening and closing brackets in other formats.\nIf it's wrong, Serde might not be able to give a good description of what the error is, only that the file is invalid.\nIf you get strange errors, first check that the indentation is correct.\nAlso check that you only use spaces and no tabs.\nMany text editors can help by highlighting syntax errors in the file.\n\nThe items at each level of the tree can be placed in any order. Consider the following example:\n```\nfilters:\n  example_fir_a:\n    type: Conv\n    parameters:\n      filename: path/to/filter.txt  \u003c\n      format: TEXT                  \u003c-- \"filename\", \"format\" and \"type\" can be in any order as long as they are properly indented to be part of the \"parameters\" block.\n      type: Raw                     \u003c\n  example_fir_b:\n    parameters:                     \u003c-- \"parameters\" can be placed before or after \"type\".\n      type: Wav\n      filename: path/to/filter.wav\n    type: Conv\n\nmixers:\n  mono:\n    mapping:\n      - dest: 0\n        sources:\n          - channel: 0\n            gain: -6\n          - gain: -6                \u003c-- The order of \"gain\" and \"channel\" can be reversed.\n            channel: 1              \u003c\n    channels:\n      out: 1\n      in: 2\n```\nOn the root level it contains `filters` and `mixers`. The `mixers` section could just as well be placed before the `filters`.\nLooking at `filters`, the second filter swaps the order of `parameters` and `type`. Both variants are valid.\nThe mixer example shows that the `gain` and `channel` properties can be ordered freely.\n\n### Variable types\nCamillaDSP uses values of several different types. The most basic are string, number and boolean.\n| Expression           | Type                                                           |\n| -------------------- | -------------------------------------------------------------- |\n| `value: 123`         | an integer, also acceptable for a parameter expecting a float  |\n| `value: \"123\"`       | a string, because of the added quotes                          |\n| `value: 123.0`       | a float                                                        |\n| `value: 1.23e2`      | a float in scientific notation, also uppercase `E` is accepted |\n| `value: true`        | a boolean true, also accepts `True` and `TRUE`                 |\n| `value: false`       | a boolean false, also accepts `False` and `FALSE`              |\n| `value: Some text`   | a string, written without quotes                               |\n| `value: \"Some text\"` | a string, written with quotes                                  |\n| `value: null`        | a null value, also accepts `Null`, `NULL`, `~` and empty       |\n\nSome parameters expect a list. These can be written inline or on multiple rows:\n```yaml\n---\nvalues_a: [ 1, 2, 3, 4, 5 ]\n\nvalues_b:\n  - 1\n  - 2\n  - 3\n  - 4\n  - 5\n```\n\n## Title and description\n\nThere are two properties that are used to name and describe the configuration file. They are both optional.\n\n```\ntitle: \"Example\"\ndescription: \"Example description of a configuration\"\n```\n\nBoth these properties are optional and can be set to `null` or left out.\nThe `title` property is intended for a short title, while `description` can be longer and more descriptive.\n\n## Volume control\nThere is a volume control that is enabled regardless of what configuration file is loaded.\n\nCamillaDSP defines a total of five control \"channels\" for volume called \"faders\".\nThe default volume control reacts to the `Main` fader.\nWhen the volume or mute setting is changed, the gain is smoothly ramped to the new setting.\nThe duration of this ramp can be customized via the `volume_ramp_time` parameter\nin the `devices` section.\nThe value must not be negative. If left out or set to `null`, it defaults to 400 ms.\n\nThe range of the volume control can be limited.\nSet the `volume_limit` to the desired maximum volume value.\nThis setting is optional. If left out or set to `null`, it defaults to +50 dB.\n\nIn addition to this, there are four additional control channels, named `Aux1` to `Aux4`.\nThese can be used to implement for example a separate volume control for a headphone output,\nor crossfading between different input channels.\n\n## Devices\nExample config:\n```\ndevices:\n  samplerate: 96000\n  chunksize: 2048\n  queuelimit: 4 (*)\n  silence_threshold: -60 (*)\n  silence_timeout: 3.0 (*)\n  target_level: 500 (*)\n  adjust_period: 10 (*)\n  enable_rate_adjust: true (*)\n  resampler: null (*)\n  capture_samplerate: 44100 (*)\n  stop_on_rate_change: false (*)\n  rate_measure_interval: 1.0 (*)\n  volume_ramp_time: 400.0 (*)\n  volume_limit: -12.0 (*)\n  multithreaded: false (*)\n  worker_threads: 4 (*)\n  capture:\n    type: Pulse\n    channels: 2\n    device: \"MySink.monitor\"\n    format: S16LE\n    labels: [\"L\", \"R\"] (*)\n  playback:\n    type: Alsa\n    channels: 2\n    device: \"hw:Generic_1\"\n    format: S32LE\n```\nA parameter marked (*) in any example is optional. If they are left out from the configuration, or set to `null`, their default values will be used.\n\n* `samplerate`\n\n  The `samplerate` setting decides the sample rate that everything will run at.\n  This rate must be supported by both the capture and  playback device.\n\n* `chunksize`\n\n  All processing is done in chunks of data.\n  The `chunksize` is the number of samples each chunk will have per channel.\n\n  Suggested starting points for different sample rates:\n  - 44.1 or 48 kHz: 1024\n  - 88.2 or 96 kHz: 2048\n  - 176.4 or 192 kHz: 4096\n\n  The duration in seconds of a chunk is `chunksize/samplerate`,\n  so the suggested values corresponds to about 22 ms per chunk.\n  This is a reasonable value.\n\n  A larger chunk size generally reduces CPU usage,\n  but since the entire chunk must be captured before processing,\n  it can cause unacceptably long delays.\n  Conversely, using a smaller chunk size can reduce latency\n  but will increase CPU usage.\n  Additionally, the shorter duration of each chunk makes CamillaDSP\n  more vulnerable to disruptions from other system activities,\n  potentially causing buffer underruns.\n\n  __Choosing chunk size for best performance__\n\n  FIR filters are automatically padded as needed,\n  so there is no need match chunk size and filter length.\n\n  CamillaDSP uses FFT for convolution, with an FFT length of `2 * chunksize`.\n  Therefore, the chunk size should be chosen for optimal FFT performance.\n\n  Using a power of two for the chunk size is ideal for best performance.\n  The FFT also works well with numbers that can be expressed as products\n  of small primes, like `2^4 * 3^3 = 1296`.\n\n  Avoid using prime numbers, such as 1297,\n  or numbers with large prime factors, like `29 * 43 = 1247`.\n\n  __Long FIR filters__\n\n  When a FIR filter is longer than the chunk size, the convolver uses segmented convolution.\n  The number of segments is calculated as `filter_length / chunk size`,\n  and rounded up to the nearest integer.\n\n  Using a smaller chunk size (i.e. more segments) reduces latency\n  but makes the convoultion process less efficient and thus needs more processing power.\n  Although a smaller chunk size leads to increased CPU usage for all filters,\n  the difference is larger for FIR filters than the other types.\n\n  If you have long FIR filters, try different chunk sizes\n  to find the best balance between latency and processing power.\n\n  When increasing the chunk size, try doubling it, like going from 1024 to 2048 or 4096 to 8192.\n\n\n* `queuelimit` (optional, defaults to 4)\n\n  The field `queuelimit` should normally be left out to use the default of 4.\n  It sets the limit for the length of the queues between the capture device and the processing thread,\n  as well as between the processing thread and the playback device.\n  The total queue size limit will be `2*chunksize*queuelimit` samples per channel.\n\n  The value should only be changed if the capture device can provide data faster\n  than the playback device can play it, like when using the Alsa \"cdsp\" plugin.\n  If this case, set `queuelimit` to a low value like 1.\n\n* `enable_rate_adjust` (optional, defaults to false)\n\n  This enables the playback device to control the rate of the capture device,\n  in order to avoid buffer underruns or a slowly increasing latency.\n  This is currently supported when using an Alsa, Wasapi or CoreAudio playback device (and any capture device).\n  Setting the rate can be done in two ways.\n  * Some capture devices provide a way to adjust the speed of their virtual sample clock (also called pitch adjust).\n    This is available with the Alsa Loopback and USB Audio gadget devices on Linux,\n    as well as BlackHole version 0.5.0 and later on macOS.\n    When capturing from any of these devices, the adjustment can be done by tuning the virtual sample clock of the device.\n    This avoids the need for asynchronous resampling.\n  * If asynchronous resampling is enabled, the adjustment can be done by tuning the resampling ratio.\n    Then `resampler` must be set to one of the \"Async\" types. This is supported for all capture devices.\n\n  With Alsa capture devices, the first option is used whenever it's available.\n  If not, and when not using an Alsa capture device, then the second option is used.\n\n* `target_level` (optional, defaults to the `chunksize` value)\n\n  The value is the number of samples that should be left in the buffer of the playback device\n  when the next chunk arrives. Only applies when `enable_rate_adjust` is set to `true`.\n  It will take some experimentation to find the right number.\n  If it's too small there will be buffer underruns from time to time,\n  and making it too large might lead to a longer input-output delay than what is acceptable.\n  Suitable values are in the range 1/2 to 1 times the `chunksize`.\n\n* `adjust_period` (optional, defaults to 10)\n\n  The `adjust_period` parameter is used to set the interval between corrections, in seconds.\n  The default is 10 seconds. Only applies when `enable_rate_adjust` is set to `true`.\n  A smaller value will make for a faster reaction time, which may be useful if there are occasional\n  buffer underruns when running with a small `target_level` to minimize latency.\n\n* `silence_threshold` \u0026 `silence_timeout` (optional)\n  The fields `silence_threshold` and `silence_timeout` are optional\n  and used to pause processing if the input is silent.\n  The threshold is the threshold level in dB, and the level is calculated as the difference\n  between the minimum and maximum sample values for all channels in the capture buffer.\n  0 dB is full level. Some experimentation might be needed to find the right threshold.\n\n  The `silence_timeout` (in seconds) is for how long the signal should be silent before pausing processing.\n  Set this to zero, or leave it out, to never pause.\n\n* `resampler` (optional, defaults to `null`)\n\n  Use this to configure a resampler. Setting it to `null` or leaving it out disables resampling .\n  Configure a resampler to enable resampling of the input signal.\n  In addition to resampling the input to a different sample rate,\n  this can be useful for rate-matching capture and playback devices with independent clocks.\n  See the [Resampling section](#resampling) for more details.\n\n* `capture_samplerate` (optional, defaults to `null`)\n\n  The capture samplerate. Setting it to `null` sets the capture samplerate to the same value as `samplerate`.\n  If the resampler is only used for rate-matching, then the capture samplerate\n  is the same as the overall samplerate, and this setting can be left out.\n\n* `stop_on_rate_change` and `rate_measure_interval` (both optional)\n\n  Setting `stop_on_rate_change` to `true` makes CamillaDSP stop the processing\n  if the measured capture sample rate changes.\n  Default is `false`.\n  The `rate_measure_interval` setting is used for adjusting the measurement period.\n  A longer period gives a more accurate measurement of the rate, at the cost of slower response when the rate changes.\n  The default is 1.0 seconds.\n  Processing will stop after 3 measurements in a row are more than 4% off from the configured rate.\n  The value of 4% is chosen to allow some variation, while still catching changes between for example 44.1 to 48 kHz.\n\n* `volume_ramp_time` (optional, defaults to 400 ms)\n  This setting controls the duration of this ramp when changing volume of the default volume control.\n  The value must not be negative. If left out or set to `null`, it defaults to 400 ms.\n\n* `multithreaded` and `worker_threads` (optional, defaults to `false` and automatic)\n  Setting `multithreaded` to `true` enables multithreaded processing.\n  When this is enabled, CamillaDSP creates several filtering tasks by grouping the filters for each channel.\n  These tasks are then sent to a thread pool, where multiple threads are ready to pick up the work.\n  On a machine with multiple CPU cores, this allows filters to be processed in parallel,\n  potentially boosting performance.\n  Once all tasks are completed, the results are returned to the main processing thread.\n\n  However, Mixers and Processors, which work on all channels in the pipeline,\n  cannot be parallelized and are processed in the main thread.\n  Therefore, only the filters between mixers and/or processors can be parallelized.\n\n  Multithreaded processing is beneficial for configurations that require significant processing power,\n  such as using very long FIR filters, high sample rates, or a large number of channels.\n  It should only be enabled if necessary, as it typically should remain disabled.\n  Synchronizing with worker threads adds some overhead, increasing overall CPU usage.\n  It also makes CamillaDSP more susceptible to other processes using the CPU,\n  which may cause buffer underruns.\n\n  An exception to this recommendation is when both the input and output are files on disk,\n  allowing processing to run faster than real time.\n  In this scenario, multithreading is likely to improve throughput and should usually be enabled.\n\n  The number of worker threads can be set manually using the `worker_threads` setting.\n  If left out or set to zero, it defaults to one worker thread per hardware thread of the machine.\n\n* `capture` and `playback`\n  Input and output devices are defined in the same way.\n  A device needs:\n  * `type`:\n    The available types depend on which features that were included when compiling. All possible types are:\n    * `RawFile` (capture only)\n    * `WavFile` (capture only)\n    * `File` (playback only)\n    * `SignalGenerator` (capture only)\n    * `Stdin` (capture only)\n    * `Stdout` (playback only)\n    * `Bluez` (capture only)\n    * `Jack`\n    * `Wasapi`\n    * `CoreAudio`\n    * `Alsa`\n    * `Pulse`\n  * `channels`: number of channels\n  * `device`: device name (for `Alsa`, `Pulse`, `Wasapi`, `CoreAudio`). For `CoreAudio` and `Wasapi`, `null` will give the default device.\n  * `filename` path to the file (for `File`, `RawFile` and `WavFile`)\n  * `format`: sample format (for all except `Jack`).\n\n    Currently supported sample formats are signed little-endian integers of 16, 24 and 32 bits as well as floats of 32 and 64 bits:\n    * S16LE - Signed 16-bit int, stored as two bytes\n    * S24LE - Signed 24-bit int, stored as four bytes (three bytes of data, one padding byte)\n    * S24LE3 - Signed 24-bit int, stored as three bytes (with no padding)\n    * S32LE - Signed 32-bit int, stored as four bytes\n    * FLOAT32LE - 32-bit float, stored as four bytes\n    * FLOAT64LE - 64-bit float, stored as eight bytes\n\n    __Note that there are two 24-bit formats! Make sure to select the correct one.__\n\n    ### Supported formats\n\n    |            | Alsa | Pulse | Wasapi | CoreAudio | Jack | File/Stdin/Stdout |\n    |------------|:----:|:-----:|:------:|:---------:|:----:|:-----------------:|\n    | S16LE      | Yes  | Yes   | Yes    | Yes       | No   | Yes               |\n    | S24LE      | Yes  | Yes   | Yes    | Yes       | No   | Yes               |\n    | S24LE3     | Yes  | Yes   | Yes    | Yes       | No   | Yes               |\n    | S32LE      | Yes  | Yes   | Yes    | Yes       | No   | Yes               |\n    | FLOAT32LE  | Yes  | Yes   | Yes    | Yes       | Yes  | Yes               |\n    | FLOAT64LE  | Yes  | No    | No     | No        | No   | Yes               |\n\n\n    ### Equivalent formats\n\n    This table shows which formats in the different APIs are equivalent.\n\n    | CamillaDSP | Alsa       | Pulse     |\n    |------------|------------|-----------|\n    | S16LE      | S16_LE     | S16LE     |\n    | S24LE      | S24_LE     | S24_32LE  |\n    | S24LE3     | S24_3LE    | S24LE     |\n    | S32LE      | S32_LE     | S32LE     |\n    | FLOAT32LE  | FLOAT_LE   | FLOAT32LE |\n    | FLOAT64LE  | FLOAT64_LE | -         |\n\n  ### File, RawFile, WavFile, Stdin, Stdout\n  The `RawFile` device type reads from a file, while `Stdin` reads from stdin.\n  `File` and `Stdout` writes to a file and stdout, respectively.\n  The format is raw interleaved samples, in the selected sample format.\n\n  If the capture device reaches the end of a file, the program will exit once all chunks have been played.\n  That delayed sound that would end up in a later chunk will be cut off.\n  To avoid this, set the optional parameter `extra_samples` for the File capture device.\n  This causes the capture device to yield the given number of samples (per channel) after reaching end of file,\n  allowing any delayed sound to be played back.\n\n  The `Stdin` capture device and `Stdout` playback device use stdin and stdout, so it's possible\n  to easily pipe audio between applications:\n  ```\n  \u003e camilladsp stdio_capt.yml \u003e rawfile.dat\n  \u003e cat rawfile.dat | camilladsp stdio_pb.yml\n  ```\n  Note: On Unix-like systems it's also possible to use the File device\n  and set the filename to `/dev/stdin` for capture, or `/dev/stdout` for playback.\n\n  The `File` and `Stdout` playback devices can write a wav-header to the output.\n  Enable this by setting `wav_header` to `true`.\n  Setting it to `false`, `null`, or leaving it out disables the wav header.\n  This is a _streaming_ header, meaning it contains a dummy value for the file length.\n  Most applications ignore this and calculate the correct length from the file size.\n\n  To read from a wav file, use the `WavFile` capture device.\n  The samplerate and numnber of channels of the file is used to override the values in the config,\n  similar to how these values can be [overriden from the command line](#overriding-config-values).\n  Note that `WavFile` only supports reading from files. Reading from a pipe is not supported.\n\n  Example config for raw files:\n  ```yaml\n    capture:\n      type: RawFile\n      channels: 2\n      filename: \"/path/to/inputfile.raw\"\n      format: S16LE\n      extra_samples: 123 (*)\n      skip_bytes: 0 (*)\n      read_bytes: 0 (*)\n    playback:\n      type: File\n      channels: 2\n      filename: \"/path/to/outputfile.raw\"\n      format: S32LE\n  ```\n\n  Example config for Stdin/Stdout:\n  ```yaml\n    capture:\n      type: Stdin\n      channels: 2\n      format: S16LE\n      extra_samples: 123 (*)\n      skip_bytes: 0 (*)\n      read_bytes: 0 (*)\n    playback:\n      type: Stdout\n      channels: 2\n      format: S32LE\n  ```\n\n  Example config for wav input and output:\n  ```yaml\n    capture:\n      type: WavFile\n      filename: \"/path/to/inputfile.wav\"\n    playback:\n      type: File\n      channels: 2\n      format: S32LE\n      wav_header: true\n      filename: \"/path/to/outputfile.wav\"\n  ```\n\n\n  The `RawFile` and `Stdin` capture devices support two additional optional parameters,\n  for advanced handling of raw files and testing:\n  * `skip_bytes`: Number of bytes to skip at the beginning of the file or stream.\n    This can be used to skip over the header of some formats like .wav\n    (which often has a 44-byte header).\n    Leaving it out or setting to zero means no bytes are skipped.\n  * `read_bytes`: Read only up until the specified number of bytes.\n    Leave it out or set it to zero to read until the end of the file or stream.\n\n  * Example, this will skip the first 50 bytes of the file (index 0-49)\n    and then read the following 200 bytes (index 50-249).\n    ```\n    skip_bytes: 50\n    read_bytes: 200\n    ```\n\n  The `SignalGenerator` capture device is intended for testing.\n  It accepts the number of channels as `channels`.\n  It also requires a block defining the signal properties, called `signal`.\n\n  The signal shape is give by `type`, which accepts `Sine`, `Square` and `WhiteNoise`.\n  All types require the signal level, which is given in dB in the `level` parameter.\n  `Sine` and `Square` also require a frequency, defined by the `freq` parameter.\n\n  When using the `SignalGenerator`, the resampler config and capture samplerate are ignored.\n  The same signal is generated on every channel.\n\n  Example config for sine wave at 440 Hz and -20 dB:\n  ```\n    capture:\n      type: SignalGenerator\n      channels: 2\n      signal: \n        type: Sine\n        freq: 440\n        level: -20.0\n  ```\n\n  Example config for white noise ad -10 dB:\n  ```\n    capture:\n      type: SignalGenerator\n      channels: 2\n      signal: \n        type: WhiteNoise\n        level: -10.0\n  ```\n\n  ### Wasapi\n  See the [separate readme for Wasapi](./backend_wasapi.md#configuration-of-devices).\n\n  ### Alsa\n  See the [separate readme for ALSA](./backend_alsa.md#configuration-of-devices).\n\n  ### CoreAudio\n  See the [separate readme for CoreAudio](./backend_coreaudio.md#configuration-of-devices).\n\n  ### Pulse\n  The `Pulse` capture and playback devices have no advanced options.\n\n  Example config for Pulse:\n  ```\n    capture:\n      type: Pulse\n      channels: 2\n      device: \"MySink.monitor\"\n      format: S16LE\n    playback:\n      type: Pulse\n      channels: 2\n      device: \"alsa_output.pci-0000_03_00.6.analog-stereo\"\n      format: S32LE\n  ```\n\n  ### Jack\n  The `Jack` capture and playback devices do not have a `format` parameter, since they always uses the FLOAT32LE format.\n  It seems that the `device` property should always be set to \"default\".\n  This parameter may be removed in a future version.\n\n  Example config for Jack:\n  ```\n    capture:\n      type: Jack\n      channels: 2\n      device: \"default\"\n    playback:\n      type: Jack\n      channels: 2\n      device: \"default\"\n  ```\n\n  ### Channel labels\n  All capture device types have an optional `labels` property.\n  This accepts a list of strings, and is meant to be used by a GUI\n  to display meaningful channel names.\n  CamillaDSP itself does not use these labels.\n\n## Resampling\n\nResampling is provided by the [Rubato library.](https://github.com/HEnquist/rubato)\n\nThis library does asynchronous and synchronous resampling with adjustable parameters.\nAsynchronous resampling can be done with or without anti-aliasing.\n\n### Resampler configuration\n\nThe `resampler` section under `devices` is used to specify the resampler.\n\nExample:\n```\n  resampler:\n    type: AsyncSinc\n    profile: Balanced\n```\n\nThe resampler type is given by `type`, and the available options are:\n* AsyncSinc\n* AsyncPoly\n* Synchronous\n\nThe types `AsyncPoly` and `AsyncSinc` need additional parameters, see each type below for details.\n\n### `AsyncSinc`: Asynchronous resampling with anti-aliasing\n\nFor asynchronous resampling with anti-aliasing, the overall strategy is to use a sinc interpolation filter\nwith a fixed oversampling factor,\nand then use polynomial interpolation to get values for arbitrary times between those fixed points.\n\nThe AsyncSinc resampler takes an additional parameter `profile`.\nThis is used to select a pre-defined profile.\nThe `Balanced` profile is the best choice in most cases.\nIt provides good resampling quality with a noise threshold in the range\nof -170 dB along with reasonable CPU usage.\nAs -170 dB is way beyond the resolution limit of even the best commercial DACs,\nthis preset is thus sufficient for all audio use.\nThe `Fast` and `VeryFast` profiles are faster but have a little more high-frequency roll-off\nand give a bit higher resampling artefacts.\nThe `Accurate` profile provides the highest quality result,\nwith all resampling artefacts below -200dB, at the expense of higher CPU usage.\n\nExample:\n```\n  resampler:\n    type: AsyncSinc\n    profile: VeryFast\n```\n\nIt is also possible to specify all parameters of the resampler instead of using the pre-defined profiles.\n\nExample:\n```\n  resampler:\n    type: AsyncSinc\n    sinc_len: 128\n    oversampling_factor: 256\n    interpolation: Cubic\n    window: Hann2\n    f_cutoff: null\n```\nNote that these two ways of defining the resampler cannot be mixed.\nWhen using `profile` the other parameters must not be present and vice versa.\nThe `f_cutoff` parameter is the relative cutoff frequency of the anti-aliasing filter.\nA value of 1.0 means the Nyquist limit. Useful values are in the range 0.9 - 0.99.\nIt can also be calculated automatically by setting `f_cutoff` to `null`.\n\nAvailable interpolation types:\n\n| Interpolation  | Polynomial degree | Samples fitted |\n|----------------|:-----------------:|:--------------:|\n| Nearest        | 0                 | 1              |\n| Linear         | 1                 | 2              |\n| Quadratic      | 2                 | 3              |\n| Cubic          | 3                 | 4              |\n\nSee the [Rubato documentation](https://docs.rs/rubato/latest/rubato/index.html)\nfor a desciption of the other parameters.\n\nFor reference, the profiles are defined according to this table:\n\n|                    | VeryFast     | Fast             | Balanced           | Accurate           |\n|--------------------|:------------:|:----------------:|:------------------:|:------------------:|\n|sinc_len            | 64           | 128              | 192                | 256                |\n|oversampling_factor | 1024         | 1024             | 512                | 256                |\n|interpolation       | Linear       | Linear           | Quadratic          | Cubic              |\n|window              | Hann2        | Blackman2        | BlackmanHarris2    | BlackmanHarris2    |\n|f_cutoff            | 0.91 (#)     | 0.92 (#)         | 0.93 (#)           | 0.95 (#)           |\n\n(#) These cutoff values are approximate. The actual values used are calculated automatically\nat runtime for the combination of sinc length and window.\n\n### `AsyncPoly`: Asynchronous resampling without anti-aliasing\n\nAsynchronous resampling without anti-aliasing works by performing polynomial interpolation between the sample points.\nThis skips the computationally expensive sinc interpolation filter and is therefore considerably faster.\nThis method produces a result that isn't as clean as with anti-aliasing, but the difference is small and often inaudible.\n\nThe polynomial interpolation uses the _N_ nearest samples,\nwhere the number of samples depends on the selected `interpolation`.\n\nExample:\n```\n  resampler:\n    type: AsyncPoly\n    interpolation: Cubic\n```\n\nAvailable interpolation types:\n\n| Interpolation  | Polynomial degree | Samples fitted |\n|----------------|:-----------------:|:--------------:|\n| Linear         | 1                 | 2              |\n| Cubic          | 3                 | 4              |\n| Quintic        | 5                 | 6              |\n| Septic         | 7                 | 8              |\n\nHigher polynomial degrees produce higher quality results but use more processing power.\nAll are however considerably faster than the `AsyncSinc` type.\nIn theory these produce inferior quality compared to the `AsyncSinc` type with anti-aliasing,\nhowever in practice the difference is small.\nUse the `AsyncPoly` type to save processing power, with little or no perceived quality loss.\n\n### `Synchronous`: Synchronous resampling with anti-aliasing\n\nFor performing fixed ratio resampling, like resampling\nfrom 44.1kHz to 96kHz (which corresponds to a precise ratio of 147/320)\nchoose the `Synchronous` type.\n\nThis works by transforming the waveform with FFT, modifying the spectrum, and then\ngetting the resampled waveform by inverse FFT.\n\nThis is considerably faster than the asynchronous variants, but does not support rate adjust.\n\nThe resampling quality is similar to the `AsyncSinc` type with the `Accurate` profile.\n\nThe `Synchronous` type takes no additional parameters:\n```\n  resampler:\n    type: Synchronous\n```\n\n### Rate adjust via resampling\nWhen using the rate adjust feature to match capture and playback devices,\none of the \"Async\" types must be used.\nThese asynchronous resamplers do not rely on a fixed resampling ratio.\nWhen rate adjust is enabled the resampling ratio is dynamically adjusted in order to compensate\nfor drifts and mismatches between the input and output sample clocks.\nUsing the \"Synchronous\" type with rate adjust enabled will print warnings,\nand any rate adjust request will be ignored.\n\n\n## Mixers\nA mixer is used to route audio between channels, and to increase or decrease the number of channels in the pipeline.\nExample for a mixer that copies two channels into four:\n```\nmixers:\n  ExampleMixer:\n    description: \"Example mixer to convert two channels to four\" (*)\n    labels: [\"L_LF\", \"R_LF\", \"L_HF\", \"R_HF\"] (*)\n    channels:\n      in: 2\n      out: 4\n    mapping:\n      - dest: 0\n        mute: false (*)\n        sources:\n          - channel: 0\n            gain: 0 (*)\n            inverted: false (*)\n            scale: dB (*)\n      - dest: 1\n        mute: false (*)\n        sources:\n          - channel: 1\n            gain: 0 (*)\n            inverted: false (*)\n            scale: dB (*)\n      - dest: 2\n        sources:\n          - channel: 0\n            gain: 0 (*)\n            inverted: false (*)\n            scale: dB (*)\n      - dest: 3\n        sources:\n          - channel: 1\n            gain: 0 (*)\n            inverted: false (*)\n            scale: dB (*)\n```\nParameters marked with (*) are optional. Set to `null` or leave out to use the default value.\n\nThe \"channels\" group define the number of input and output channels for the mixer. The mapping section then decides how to route the audio.\nThis is a list of the output channels, and for each channel there is a \"sources\" list that gives the sources for this particular channel.\nEach source has a `channel` number, a `gain` value, a `scale` for the gain (`dB` or `linear`) and if it should be `inverted` (`true`/`false`).\nA channel that has no sources will be filled with silence.\nThe `mute` option determines if an output channel of the mixer should be muted.\nThe `mute`, `gain`, `scale` and `inverted` parameters are optional, and defaults to not muted, a gain of 0 in dB, and not inverted.\n\nThe optional `description` property is intended for the user and is not used by CamillaDSP itself.\n\nSimilar to [capture devices](#channel-labels), the mixer also has a `labels` property.\nThis is meant to define labels for the output channels from the mixer.\nThe labels are intended to be used by GUIs and are not used by CamillaDSP.\n\nAnother example, a simple stereo to mono mixer:\n```\nmixers:\n  mono:\n    channels:\n      in: 2\n      out: 1\n    mapping:\n      - dest: 0\n        sources:\n          - channel: 0\n            gain: -6\n          - channel: 1\n            gain: -6\n```\n\n### Skip processing of unused channels\nSome audio interfaces bundle all their inputs together, meaning that it might be necessary to capture a large number of channels to get access to a particular input.\nTo reduce the CPU load, CamillaDSP will try to avoid processing of any channel that is captured but not used in the pipeline.\n\nLet's say we have an interface with one analog input, and one SPDIF.\nThese are presented as a single 4-channel input where channels 0 and 1 are analog, 2 and 3 SPDIF.\nThen, setting the number of capture channels to 4 will enable both inputs.\nIn this case we are only interested in the SPDIF input.\nThis is then done by adding a mixer that reduces the number of channels to 2.\nIn this mixer, input channels 0 and 1 are not mapped to anything.\nThis is then detected, and no format conversion, resampling or processing will be done on these two channels.\n\n## Filters\nThe filters section defines the filter configurations to use in the pipeline.\nIt's enough to define each filter once even if it should be applied on several channels.\nThe supported filter types are Biquad, BiquadCombo and DiffEq for IIR and Conv for FIR.\nThere are also filters just providing gain and delay.\nThe last filter type is Dither, which is used to add dither when quantizing the output.\n\nAll filters take an optional `description` property.\nThis is intended for the user and is not used by CamillaDSP itself.\n\n### Gain\nThe gain filter simply changes the amplitude of the signal.\nThe `inverted` parameter simply inverts the signal.\nThis parameter is optional and the default is to not invert.\nThe `gain` value is given in either dB or as a linear factor, depending on the `scale` parameter.\nThis can be set to `dB` or `linear`.\nIf set to `null` or left out it defaults to dB.\n\nWhen the dB scale is used (`scale: dB`), a positive gain value means the signal will be amplified\nwhile a negative values attenuates.\nThe gain value must be in the range -150 to +150 dB.\n\nIf linear gain is used (`scale: linear`), the gain value is treated as a simple multiplication factor.\nA factor 0.5 attenuates by a factor two (equivalent to a gain of -6.02 dB).\nA negative value inverts the signal.\nNote that the `invert` setting also inverts, so a gain of -0.5 with invert set to true\nbecomes inverted twice and the result is non-inverted.\nThe linear gain is limited to a range of -10.0 to +10.0.\n\nThe `mute` parameter determines if the the signal should be muted.\nThis is optional and defaults to not mute.\n\nExample Gain filter:\n```\nfilters:\n  gainexample_dB:\n    type: Gain\n    parameters:\n      gain: -6.0\n      inverted: false (*)\n      mute: false (*)\n      scale: dB (*)\n  gainexample_linear:\n    type: Gain\n    parameters:\n      gain: 0.5\n      inverted: false (*)\n      mute: false (*)\n      scale: linear (*)\n```\n\n### Volume\nThe Volume filter is intended to be used as an additional volume control.\n\nNote that the pipeline includes a volume control for the `Main` fader per default,\nand it's not possible to select this fader for Volume filters.\n\nVolume filters may use the four additional faders, named `Aux1`, `Aux2`,`Aux3` and `Aux4`.\n\nA Volume filter is configured to react to one of these faders.\nThe volume can then be changed via the websocket, by changing the corresponding fader.\nA request to set the volume will be applied to all Volume filters listening to the affected `fader`.\n\nWhen the volume or mute state is changed, the gain is ramped smoothly to the new value.\nThe duration of this ramp is set by the `ramp_time` parameter (unit milliseconds).\nThe value must not be negative. If left out or set to `null`, it defaults to 400 ms.\nThe value will be rounded to the nearest number of chunks.\n\nThe range of the volume control can be limited via the optional `limit` parameter.\nThis sets a limit for the maximum value of the volume.\nIf left out or set to `null`, it defaults to +50 dB.\n\nExample Volume filter:\n```\nfilters:\n  volumeexample:\n    type: Volume\n    parameters:\n      ramp_time: 200 (*)\n      limit: 10.0 (*)\n      fader: Aux1\n```\n\n### Loudness\nThe Loudness filter performs loudness compensation and is intended to be used in combination with a volume control.\nSimilar to a Volume filter, it reacts to the configured `fader`.\nThe available choices for `fader` are `Main`, `Aux1`, `Aux2`,`Aux3` and `Aux4`.\nSetting fader to `Main` adds loudness compensation to the default volume control.\n\nBy setting `fader` to one of the Aux faders it can instead work with a Volume filter\nreacting to the same fader.\nWhen used like this, there should only be a single Volume filter assigned to the chosed fader.\n\nIt can also be used with a volume control external to CamillaDSP.\nThe fader should then be set to one of the Aux faders, and the external volume control should update\nthis fader when the volume setting changes.\nA special websocket command is provided for this, see the [websocket command documentation](websocket.md).\nIf the external volume control is placed after CamillaDSP in the audio chain,\nthen the boost applied at high and low frequencies may cause clipping.\nTo avoid this, set `attenuate_mid` to `true`.\nThat makes the loudness filter attenuate the midband instead of boosting the extremes.\n\n\nThe method is the same as the one implemented by the [RME ADI-2 DAC FS](https://www.rme-audio.de/adi-2-dac.html).\nThe loudness correction is done as shelving filters that boost the high (above 3500 Hz) and low (below 70 Hz) frequencies.\nThe amount of boost is adjustable with the `high_boost` and `low_boost` parameters. If left out, they default to 10 dB.\n- When the volume is above the `reference_level`, only gain is applied.\n- When the volume is below `reference_level` - 20, the full correction is applied.\n- In the range between `reference_level` and `reference_level`-20, the boost value is scaled linearly.\n\n![Loudness](loudness.png)\n\nIn this figure, the `reference_level` was set to -5 dB, and `high_boost` = `low_boost` = 10 dB.\nAt a gain of 0 and -5, the curve is flat. Below that the boost increases.\nAt -15 dB half of the boost, and at -25 the full boost is applied.\nBelow -25 dB, the boost value stays constant.\n\nExample Loudness filter, configured to work together with the default volume control:\n```\nfilters:\n  loudness:\n    type: Loudness\n    parameters:\n      fader: Main (*)\n      reference_level: -25.0\n      high_boost: 7.0 (*)\n      low_boost: 7.0 (*)\n      attenuate_mid: false (*)\n```\nAllowed ranges:\n- reference_level: -100 to +20\n- high_boost: 0 to 20\n- low_boost: 0 to 20\n\n### Delay\nThe delay filter provides a delay in milliseconds, millimetres or samples.\nThe `unit` can be `ms`, `mm` or `samples`, and if left out it defaults to `ms`.\nWhen giving the delay in millimetres, the speed of sound of is assumed to be 343 m/s (dry air at 20 degrees Celsius).\n\nIf the `subsample` parameter is set to `true`, then it will use use an IIR filter to achieve subsample delay precision.\nIf set to `false`, the value will instead be rounded to the nearest number of full samples.\nThis is a little faster and should be used if subsample precision is not required.\n\n\nThe delay value must be positive or zero.\n\nExample Delay filter:\n```\nfilters:\n  delayexample:\n    type: Delay\n    parameters:\n      delay: 12.3\n      unit: ms\n      subsample: false\n```\n\n### FIR\nA FIR filter is given by an impulse response provided as a list of coefficients.\nThe coefficients are preferably given in a separate file, but can be included directly in the config file.\nIf the number of coefficients (or taps) is larger than the chunksize setting it will use segmented convolution.\nThe number of segments is the filter length divided by the chunksize, rounded up.\n\nExample FIR filters:\n```\nfilters:\n  example_fir_a:\n    type: Conv\n    parameters:\n      type: Raw\n      filename: path/to/filter.txt\n      format: TEXT\n      skip_bytes_lines: 0 (*)\n      read_bytes_lines: 0 (*)\n  example_fir_b:\n    type: Conv\n    parameters:\n      type: Wav\n      filename: path/to/filter.wav\n      channel: 0 (*)\n```\nThe `type` can be `Raw`, `Wav` or `Values`.\nUse `Wav` to load a standard .wav file, `Raw` to load a raw file (see list of allowed raw formats below),\nand `Values` for giving the coefficients directly in the configuration file.\nThe `filename` field should hold the path to the coefficient file.\nUsing the absolute path is recommended in most cases.\n\nIf a relative path is given it will first try to find the file relative to the config file path.\nIf it's not found there, the path is assumed to be relative to the current working directory.\nNote that this only applies when the config is loaded from a file.\nWhen a config is supplied via the websocket server only the current working dir of the CamillaDSP process will be searched.\n\nIf the filename includes the tokens `$samplerate$` or `$channels$`,\nthese will be replaced by the corresponding values from the config.\nFor example, if samplerate is 44100,\nthe filename `/path/to/filter_$samplerate$.raw` will be updated to `/path/to/filter_44100.raw`.\n\n#### Generating FIR coefficients\nThere are many ways to generate impulse responses for FIR filters.\nTypically they are generated by some dedicated application.\nSee also [Measurement and filter generation tools](#measurement-and-filter-generation-tools).\n\n[rePhase](#rephase) is a popular choice that is free to use.\nIt allows building fully linear-phase active crossovers with arbitrary slopes.\nIt also supports compensating the phase shifts of loudspeakers and existing crossovers.\nIn the Impulse Settings box configure the rate to the same as used in CamillaDSP\nand the format to 64 bits IEEE-754 (.dbl).\nThis corresponds to raw samples in FLOAT64LE format in CamillaDSP.\n\n#### Values directly in config file\n\nExample for giving values:\n```\nfilters:\n  lowpass_fir:\n    type: Conv\n    parameters:\n      type: Values\n      values: [0.0, 0.1, 0.2, 0.3]\n```\n\n#### Dummy impulse response for testing\n\nSetting the type to `Dummy` creates a dummy impulse response:\n```\nfilters:\n  lowpass_fir:\n    type: Conv\n    parameters:\n      type: Dummy\n      length: 65536\n```\nThis creates a dummy minumum-phase allpass filter of length `length` (that must be at least 1).\nThe first point has a value of one, and all the rest are zero: `[1.0, 0.0, 0.0, ..., 0.0]`.\nThis is intended to provide an easy way to evaluate the CPU load for different filter lengths.\n\n#### Coefficients from Wav-file\n\nSupplying the coefficients as `.wav` file is the most convenient method.\nThe `Wav` type takes only one parameter `channel`.\nThis is used to select which channel of a multi-channel file to load.\nFor a standard stereo file, the left track is channel 0, and the right is channel 1.\nThis parameter is optional and defaults to 0 if left out.\nThe sample rate of the file is ignored.\n\n#### Coefficient Raw (headerless) data file\n\nTo load coefficients from a raw file, use the `Raw` type. This is also used to load coefficients from text files.\nRaw files are often saved with a `.dbl`, `.raw`, or `.pcm` ending.\nThe lack of a header means that the files doesn't contain any information about data format etc.\nCamillaDSP supports loading coefficients from such files that contain a single channel only\n(stereo files are not supported), in all the most common sample formats.\nThe `Raw` type supports two additional optional parameters, for advanced handling of raw files and text files with headers:\n* `skip_bytes_lines`: Number of bytes (for raw files) or lines (for text) to skip at the beginning of the file.\n  This can be used to skip over a header. Leaving it out or setting to zero means no bytes or lines are skipped.\n* `read_bytes_lines`: Read only up until the specified number of bytes (for raw files) or lines (for text).\n  Leave it out or set it to zero to read until the end of the file.\n\nThe filter coefficients can be provided either as text, or as raw samples. Each file can only hold one channel.\nThe \"format\" parameter can be omitted, in which case it's assumed that the format is TEXT.\nThis format is a simple text file with one value per row:\n```\n-0.000021\n-0.000020\n-0.000018\n...\n-0.000012\n```\nThe other possible formats are raw data:\n- S16LE: signed 16-bit little-endian integers\n- S24LE: signed 24-bit little-endian integers stored as 32 bits (with the data in the low 24)\n- S24LE3: signed 24-bit little-endian integers stored as 24 bits\n- S32LE: signed 32-bit little-endian integers\n- FLOAT32LE: 32-bit little endian float\n- FLOAT64LE: 64-bit little endian float\n\n\n### IIR\nIIR filters are implemented as Biquad filters.\nCamillaDSP can calculate the coefficients for a number of standard filters,\nor you can provide the coefficients directly.\n\nExamples:\n```\nfilters:\n  free_nbr1:\n    type: Biquad\n    parameters:\n      type: Free\n      a1: 1.0\n      a2: 1.0\n      b0: 1.0\n      b1: 1.0\n      b2: 1.0\n  hp_80:\n    type: Biquad\n    parameters:\n      type: Highpass\n      freq: 80\n      q: 0.5\n  peak_100:\n    type: Biquad\n    parameters:\n      type: Peaking\n      freq: 100\n      gain: -7.3\n      q: 0.5\n  peak_100_bw:\n    type: Biquad\n    parameters:\n      type: Peaking\n      freq: 100\n      gain: -7.3\n      bandwidth: 0.7\n  exampleshelf:\n    type: Biquad\n    parameters:\n      type: Highshelf\n      freq: 1000\n      gain: -12\n      slope: 6\n  exampleshelf_q:\n    type: Biquad\n    parameters:\n      type: Highshelf\n      freq: 1000\n      gain: -12\n      q: 1.5\n  LR_highpass:\n    type: BiquadCombo\n    parameters:\n      type: LinkwitzRileyHighpass\n      freq: 1000\n      order: 4\n```\n\nSingle Biquads are defined using the type \"Biquad\". The available filter types are:\n* Free\n\n  Given by normalized coefficients `a1`, `a2`, `b0`, `b1`, `b2`.\n\n* Highpass \u0026 Lowpass\n\n  Second order high/lowpass filters (12dB/oct)\n\n  Defined by cutoff frequency `freq` and Q-value `q`.\n\n* HighpassFO \u0026 LowpassFO\n\n  First order high/lowpass filters (6dB/oct)\n\n  Defined by cutoff frequency `freq`.\n\n* Highshelf \u0026 Lowshelf\n\n  High / Low uniformly affects the high / low frequencies respectively while leaving the low / high part unaffected. In between there is a slope of variable steepness.\n\n  Parameters:\n  * `freq` is the center frequency of the sloping section.\n  * `gain` gives the gain of the filter\n  * `slope` is the steepness in dB/octave. Values up to around +-12 are usable.\n  * `q` is the Q-value and can be used instead of `slope` to define the steepness of the filter.\n    Only one of `q` and `slope` can be given.\n\n* HighshelfFO \u0026 LowshelfFO\n\n  First order (6dB/oct) versions of the shelving functions.\n\n  Parameters:\n  * `freq` is the center frequency of the sloping section.\n  * `gain` gives the gain of the filter\n\n* Peaking\n\n  A parametric peaking filter with selectable gain `gain` at a given frequency `freq`\n  with a bandwidth given either by the Q-value `q` or bandwidth in octaves `bandwidth`.\n  Note that bandwidth and Q-value are inversely related, a small bandwidth corresponds to a large Q-value etc.\n  Use positive gain values to boost, and negative values to attenuate.\n\n* Notch\n\n  A notch filter to attenuate a given frequency `freq` with a bandwidth\n  given either by the Q-value `q` or bandwidth in octaves `bandwidth`.\n  The notch filter is similar to a Peaking filter configured with a large negative gain.\n\n* GeneralNotch\n\n  The general notch is a notch where the pole and zero can be placed at different frequencies.\n  It is defined by its zero frequency `freq_z`, pole frequency `freq_p`,\n  pole Q `q_p`, and an optional parameter `normalize_at_dc`.\n\n  When pole and zero frequencies are different, the low-frequency gain is changed\n  and the shape (peakiness) at the `freq_p` side of the notch can be controlled by `q_p`.\n  The response is similar to an adjustable Q 2nd order shelf between `freq_p` and `freq_z` plus a notch at `freq_z`.\n\n  The highpass-notch form is obtained when `freq_p` \u003e `freq_z`.\n  In this form the LF (stopband) gain decreases to -X dB while the HF (passband) gain remains unchanged at 0 dB.\n\n  The lowpass-notch form is obtained when `freq_p` \u003c `freq_z`.\n  In this form, the LF (e.g. DC or passband) gain increases to X dB while the HF (e.g. stopband) gain remains at 0dB.\n\n  The larger the difference between `freq_p` and `freq_z` the larger is X.\n\n  To automatically swap these levels, so that the LF gain remains at 0dB while the HF gain takes on the value of ±X dB,\n  set the parameter `normalize_at_dc` to `true` (the default for this parameter is `false`).\n  Note that when the pole and zero frequencies are set to the same value the common (symmetrical) notch is obtained.\n\n* Bandpass\n\n  A second order bandpass filter for a given frequency `freq` with a bandwidth given either by the Q-value `q` or bandwidth in octaves `bandwidth`.\n\n* Allpass\n\n  A second order allpass filter for a given frequency `freq` with a steepness given\n  either by the Q-value `q` or bandwidth in octaves `bandwidth`\n\n* AllpassFO\n\n  A first order allpass filter for a given frequency `freq`.\n\n* LinkwitzTransform\n\n  A normal sealed-box speaker has a second order high-pass frequency response given by a resonance frequency and a Q-value.\n  A [Linkwitz transform](https://linkwitzlab.com/filters.htm#9) can be used to apply a tailored filter\n  that modifies the actual frequency response to a new target response.\n  The target is also a second order high-pass function, given by the target resonance frequency and Q-value.\n\n  Parameters:\n  * `freq_act`: actual resonance frequency of the speaker.\n  * `q_act`: actual Q-value of the speaker.\n  * `freq_target`: target resonance frequency.\n  * `q_target`: target Q-value.\n\nTo build more complex filters, use the type \"BiquadCombo\".\nThis automatically adds several Biquads to build other filter types.\nThe available types are:\n* ButterworthHighpass \u0026 ButterworthLowpass\n\n  Defined by frequency, `freq` and filter `order`.\n\n* LinkwitzRileyHighpass \u0026 LinkwitzRileyLowpass\n\n  Defined by frequency, `freq` and filter `order`.\n\n  Note, the order must be even\n\n* Tilt\n\n  The \"Tilt\" filter applies a tilt across the entire audible spectrum.\n  It takes a single parameter `gain`.\n  A positive value gives a positive tilt, that boosts the high end of the spectrum and attenuates the low.\n  A negative value gives the opposite result.\n\n  The `gain` value is the difference in gain between the highest and lowest frequencies.\n  It's applied symmetrically, so a value of +10 dB will result in 5 dB of boost at high frequencies,\n  and 5 dB of attenuation at low frequencies.\n  In between the gain changes linearly, with a midpoint at about 600 Hz.\n\n  The `gain` value is limited to +- 100 dB.\n\n* FivePointPeq\n\n  This filter combo is mainly meant to be created by guis.\n  It defines a 5-point (or band) parametric equalizer by combining a Lowshelf, a Highshelf and three Peaking filters.\n\n  Each individual filter is defined by frequency, gain and q. The parameter names are:\n  * Lowshelf: `fls`, `gls`, `qls`\n  * Peaking 1: `fp1`, `gp1`, `qp1`\n  * Peaking 2: `fp2`, `gp2`, `qp2`\n  * Peaking 3: `fp3`, `gp3`, `qp3`\n  * Highshelf: `fhs`, `ghs`, `qhs`\n\n  All 15 parameters must be included in the config.\n\n\nOther types such as Bessel filters can be built by combining several Biquads.\n[See the separate readme for more filter functions.](./filterfunctions.md)\n\n* GraphicEqualizer\n\n  This creates a graphic equalizer with an arbitrary number of bands.\n  It uses one Peaking biquad filter per band.\n\n  The range of the equalizer can be selected with the optional `freq_min` and `freq_max` parameters.\n  If left out, the range defaults to 20 Hz to 20 kHz.\n\n  The number of bands, and the gain for each band is given by the `gains` parameter.\n  This accepts a list of gains in dB. The number of values determines the number of bands.\n  The gains are limited to +- 40 dB.\n\n  The band frequencies are distributed evenly on the logarithmic frequency scale, and each band has the same relative bandwidth.\n\n  For example a 31-band equalizer on the default range gets a 1/3 octave bandwith,\n  with the first three bands centered at 22.4, 27.9, 34.9 Hz, and the last two at 14.3 and 17.9 kHz.\n\n  Example:\n  ```\n  filters:\n    5band_graphic:\n      type: BiquadCombo\n      parameters:\n        type: GraphicEqualizer\n        freq_min: 20 (*)\n        freq_max: 20000 (*)\n        gains: [0.0, 1.0, 2.0, 1.0, 0.0]\n  ```\n  The gain values are limited to the range +- 20 dB.\n  Only the bands that have non-zero gain values are included in the processing, the ones with zero gain are skipped.\n\n\n### Dither\nThe \"Dither\" filter should only be added at the very end of the pipeline for each channel, and adds noise shaped dither to the output.\nThis is intended for 16-bit output, but can be used also for higher bit depth if desired. There are several subtypes:\n\n| Subtype             | kHz  | Noise shaping | Comments                                                       |\n| ------------------- | ---- | ------------- | -------------------------------------------------------------- |\n| None                | Any  | -             | Bit depth reduction without dither, for testing purposes       |\n| Flat                | Any  | -             | Triangular: objectively optimal non-shaped dither              |\n| Highpass            | Any  | 2 taps        | Wannamaker highpassed, violet noise                            |\n| Fweighted441        | 44.1 | 9 taps        | Wannamaker, modeled after early ISO curve                      |\n| - FweightedShort441 | 44.1 | 3 taps        | - Lower cpu load, less noise but also less noise reduction     |\n| - FweightedLong441  | 44.1 | 24 taps       | - Higher cpu load, less noise and nearly equal noise reduction |\n| Gesemann441         | 44.1 | 8 taps        | Modeled after LAME ATH curves with flattening                  |\n| Gesemann48          | 48   | 8 taps        | Modeled after LAME ATH curves with flattening                  |\n| Lipshitz441         | 44.1 | 5 taps        | Superseded by Fweighted441                                     |\n| - LipshitzLong441   | 44.1 | 9 taps        | - Superseded by FweightedLong441                               |\n| Shibata441          | 44.1 | 24 taps       | Modeled after LAME ATH type 1                                  |\n| - ShibataHigh441    | 44.1 | 20 taps       | - High intensity (quieter noise)                               |\n| - ShibataLow441     | 44.1 | 12 taps       | - Low intensity (louder noise)                                 |\n| Shibata48           | 48   | 16 taps       | Modeled after LAME ATH type 1                                  |\n| - ShibataHigh48     | 48   | 28 taps       | - High intensity (quieter noise)                               |\n| - ShibataLow48      | 48   | 16 taps       | - Low intensity (louder noise)                                 |\n| Shibata882          | 88.2 | 20 taps       | Modeled after LAME ATH type 1                                  |\n| - ShibataLow882     | 88.2 | 24 taps       | - Low intensity (louder noise)                                 |\n| Shibata96           | 96   | 31 taps       | Modeled after LAME ATH type 1                                  |\n| - ShibataLow96      | 96   | 32 taps       | - Low intensity (louder noise)                                 |\n| Shibata192          | 192  | 54 taps       | Modeled after LAME ATH type 1                                  |\n| - ShibataLow192     | 192  | 20 taps       | - Low intensity (louder noise)                                 |\n\nThe Shibata filters are the new filters from [SSRC 1.32](https://shibatch.sourceforge.net/ssrc/).\n\nFilters with more taps are typically more precise, always at the expense of higher cpu load.\nHighpass is an exception, which is about as fast as Flat.\n\nThe parameter \"bits\" sets the target bit depth.\nFor most oversampling delta-sigma DACs, this should match the bit depth of the playback device for best results.\nFor true non-oversampling DACs, this should match the number of bits over which the DAC is linear\n(or the playback bit depth, whichever is lower).\nSetting it to a higher value is not useful since then the applied dither will be lost.\n\nFor the \"Flat\" subtype, the parameter \"amplitude\" sets the number of LSB to be dithered.\nTo linearize the samples, this should be 2.\nLower amplitudes produce less noise but also linearize less; higher numbers produce more noise but do not linearize more.\n\nSome comparisons between the noise shapers are available from [SoX](http://sox.sourceforge.net/SoX/NoiseShaping),\n[SSRC](https://shibatch.sourceforge.net/ssrc/)\nand [ReSampler](https://github.com/jniemann66/ReSampler/blob/master/ditherProfiles.md).\nTo test the different types, set the target bit depth to something very small\nlike 5 or 6 bits (the minimum allowed value is 2) and try them all.\nNote that on \"None\" this may well mean there is no or unintelligible audio -- this is to experiment with\nand show what the other ditherers actually do.\n\nFor sample rates above 48 kHz there is no need for anything more advanced than the \"Highpass\" subtype.\nFor the low sample rates there is no spare bandwidth and the dither noise must use the audible range,\nwith shaping to makes it less audible.\nBut at 96 or 192 kHz there is all the bandwidth from 20 kHz up to 48 or 96 kHz where the noise can be placed without issues.\nThe Highpass ditherer will place almost all of it there.\nOf course, the high-resolution Shibata filters provide some icing on the cake.\n\nSelecting a noise shaping ditherer for a different sample rate than it was designed for,\nwill cause the frequency response curve of the noise shaper to be fitted to the playback rate.\nThis means that the curve no longer matches its design points to be minimally audible.\nYou may experiment which shaper still sounds good,\nor use the Flat or Highpass subtypes which work well at any sample rate.\n\nExample:\n```\n  dither_fancy:\n    type: Dither\n    parameters:\n      type: Shibata441\n      bits: 16\n```\n\n### Limiter\nThe \"Limiter\" filter is used to limit the signal to a given level. It can use hard or soft clipping.\nNote that soft clipping introduces some harmonic distortion to the signal.\n\nExample:\n```\n  example_limiter:\n    type: Limiter\n    parameters:\n      soft_clip: false (*)\n      clip_limit: -10.0\n```\n\nParameters:\n  * `soft_clip`: enable soft clipping. Set to `false` to use hard clipping. Optional, defaults to `false`.\n  * `clip_limit`: the level in dB to clip at.\n\n### Difference equation\nThe \"DiffEq\" filter implements a generic difference equation filter with transfer function:\nH(z) = (b0 + b1*z^-1 + .. + bn*z^-n)/(a0 + a1*z^-1 + .. + an*z^-n).\nThe coefficients are given as a list a0..an in that order. Example:\n```\n  example_diffeq:\n    type: DiffEq\n    parameters:\n      a: [1.0, -0.1462978543780541, 0.005350765548905586]\n      b: [0.21476322779271284, 0.4295264555854257, 0.21476322779271284]\n```\nThis example implements a Biquad lowpass, but for a Biquad the Free Biquad type is faster and should be preferred.\nBoth a and b are optional. If left out, they default to [1.0].\n\n\n## Processors\nThe `processors` section contains the definitions for the Processors.\nThese are special \"filters\" that work on several channels at the same time.\n\nProcessors take an optional `description` property.\nThis is intended for the user and is not used by CamillaDSP itself.\n\n### Compressor\nThe \"Compressor\" processor implements a standard dynamic range compressor.\nIt is configured using the most common parameters.\n\nExample:\n```\nprocessors:\n  democompressor:\n    type: Compressor\n    parameters:\n      channels: 2\n      attack: 0.025\n      release: 1.0\n      threshold: -25\n      factor: 5.0\n      makeup_gain: 15 (*)\n      clip_limit: 0.0 (*)\n      soft_clip: true (*)\n      monitor_channels: [0, 1] (*)\n      process_channels: [0, 1] (*)\n\npipeline:\n  - type: Processor\n    name: democompressor\n```\n\n  Parameters:\n  * `channels`: number of channels, must match the number of channels of the pipeline where the compressor is inserted.\n  * `attack`: time constant in seconds for attack, how fast the compressor reacts to an increase of the loudness.\n  * `release`: time constant in seconds for release, how fast the compressor scales back the compression when the loudness decreases.\n  * `threshold`: the loudness threshold in dB where compression sets in.\n  * `factor`: the compression factor, giving the amount of compression over the threshold.\n    A factor of 4 means a sound that is 4 dB over the threshold will be attenuated to 1 dB over the threshold.\n  * `makeup_gain`: amount of fixed gain in dB to apply after compression. Optional, defaults to 0 dB.\n  * `clip_limit`: the level in dB to clip at. Providing a value enables clipping of the signal after compression. Leave out or set to `null` to disable clipping.\n  * `soft_clip`: enable soft clipping. Set to `false` to use hard clipping. This setting is ignored when clipping is disabled.\n    Note that soft clipping introduces some harmonic distortion to the signal.\n    This setting is ignored if `enable_clip = false`. Optional, defaults to `false`.\n  * `monitor_channels`: a list of channels used when estimating the loudness. Optional, defaults to all channels.\n  * `process_channels`: a list of channels to be compressed. Optional, defaults to all channels.\n\n### Noise Gate\nThe \"NoiseGate\" processor implements a simple noise gate.\nIt monitors the given channels to estimate the current loudness,\nusing the same algorithm as the compressor.\nWhen the loudness is above the threshold,\nthe gate \"opens\" and the sound is passed through unaltered.\nWhen it is below, the gate \"closes\" and attenuates the selected channels by the given amount.\n\nExample:\n```\nprocessors:\n  demogate:\n    type: NoiseGate\n    parameters:\n      channels: 2\n      attack: 0.025\n      release: 1.0\n      threshold: -25\n      attenuation: 50.0\n      monitor_channels: [0, 1] (*)\n      process_channels: [0, 1] (*)\n\npipeline:\n  - type: Processor\n    name: demogate\n```\n\n  Parameters:\n  * `channels`: number of channels, must match the number of channels of the pipeline where the compressor is inserted.\n  * `attack`: time constant in seconds for attack, how fast the gate reacts to an increase of the loudness.\n  * `release`: time constant in seconds for release, how fast the gate reacts when the loudness decreases.\n  * `threshold`: the loudness threshold in dB where gate \"opens\".\n  * `attenuation`: the amount of attenuation in dB to apply when the gate is \"closed\".\n  * `monitor_channels`: a list of channels used when estimating the loudness. Optional, defaults to all channels.\n  * `process_channels`: a list of channels to be gated. Optional, defaults to all channels.\n\n\n## Pipeline\nThe pipeline section defines the processing steps between input and output.\nThe input and output devices are automatically added to the start and end.\nThe pipeline section of the config is a list of processing steps.\nThis determines both what processing steps that are applied, and in which order they are applied.\nA step can be a filter, a mixer or a processor.\nThe filters, mixers and processors must be defined in the corresponding section of the configuration, and the pipeline refers to them by their name.\nDuring processing, the steps are applied in the listed order.\nFor each mixer and for the output device the number of channels from the previous step must match the number of input channels.\nFor filter steps, the channel numbers must exist at that point of the pipeline.\nChannels are numbered starting from zero.\nApart from this, there are no rules for ordering of the steps or how many are added.\n\nEach step take an optional `description` property. This is intended for the user and is not used by CamillaDSP itself.\n\nExample:\n```\npipeline:\n  - type: Mixer\n    description: \"Expand to 4 channels\"\n    name: to4channels\n    bypassed: false (*)\n  - type: Filter\n    description: \"Left and right woofer channels\"\n    channels: [0, 1] (*)\n    bypassed: false (*)\n    names:\n      - lowpass_fir\n      - peak1\n  - type: Filter\n    description: \"Left and right tweeter channels\"\n    channels: [2, 3]\n    bypassed: false (*)\n    names:\n      - highpass_fir\n  - type: Processor\n    description: \"Compressor for protecting the drivers\"\n    name: my_compressor\n    bypassed: false (*)\n```\nIn this config first a mixer is used to copy a stereo input to four channels.\nBefore the mixer, only channels 0 and 1 exist.\nAfter the mixer, four channels are available, with numbers 0 to 3.\nThe mixer is followed by a filter step for each pair of channels.\nFinally a compressor is added as the last step.\n\n### Filter step\nA filter step, `type: Filter`, can contain one or several filters.\nThe chosen filters are given in the `names` property, which is an list of filter names.\nThe filters must be defined in the `Filters` section.\n\nThe chosen filters will be applied to the channels listed in the `channels` property.\nThis property is optional. If it is left out or set to `null`,\nthe filters are applied to all the channels at that point in the pipeline.\nAn empty list means the filters will not be applied to any channel.\n\nIn the example above, channels 0 and 1 get filtered by `lowpass_fir` and `peak1`,\nwhile 2 and 3 get filtered by just `highpass_fir`.\n\nIf several filters are to be applied to a channel, it is recommended to put them in a single filter step.\nThis makes the config easier to overview and gives a minor performance benefit,\ncompared to adding each filter in a separate step.\n\n### Mixer and Processor step\nMixer steps, `type: Mixer`, and processor steps, `type: Processor`, are defined in a similar way.\nThese steps take just the the name of a mixer of processor defined in the `Mixers` or `Processors` section.\n\n### Tokens in names\nIf the name of a mixer, processor or filter includes the tokens `$samplerate$` or `$channels$`,\nthese will be replaced by the corresponding values from the config.\nFor example, if the samplerate is 44100, the filter name `fir_$samplerate$` will be updated to `fir_44100`.\n\n### Bypassing steps\nEach pipeline step has an optional `bypassed` property. Setting this to `true` removes this step from the pipeline.\nTake care when bypassing mixers. If a mixer is used to change the number of channels (like the one in the example above),\nthen bypassing it will make the pipeline output the wrong number of channels.\nIn this case, the bypass may be used to switch between mixers with different settings.\n\n## Using filters from REW\n[REW](#rew) can automatically generate a set of filters for correcting the frequency response of a system.\nREW V5.20.14 and later is able to export the filters in the CamillaDSP YAML format.\n\n- Go to the \"EQ Filters\" screen. Expand the \"Equalizer\" section in the list on the right side.\n- Select \"CamillaDSP\" as Manufacturer and \"Filters\" as Model.\n- Expand the \"Filter Task\" section and click \"Save filter settings to YAML file\".\n  - This opens a popup with the the text \"Enter the label to use for each filter, the filter number will be appended to the label\".\n    This allows identification of the filter set.\n\nNote that the generated YAML file is not a complete CamillaDSP configuration.\nIt contains only filter definitions and pipeline steps, that can be pasted into a CamillaDSP config file.\nIf using [CamillaGUI](#gui), it is also possible to import the filters into an existing configuration.\n\n# Related projects\n## Other projects using CamillaDSP\n* https://github.com/scripple/alsa_cdsp - ALSA CamillaDSP \"I/O\" plugin, automatic config updates at changes of samplerate, sample format or number of channels.\n* https://github.com/raptorlightning/I2S-Hat - An SPDIF Hat for the Raspberry Pi 2-X for SPDIF Communication, see also [this thread at diyAudio.com](https://www.diyaudio.com/forums/pc-based/375834-i2s-hat-raspberry-pi-hat-spdif-i2s-communication-dsp.html).\n* https://github.com/daverz/camilla-remote-control - Interface for remote control of CamillaDSP using a FLIRC USB infrared receiver or remote keyboard.\n* https://github.com/Wang-Yue/CamillaDSP-Monitor - A script that provides a DSP pipeline and a spectral analyzer similar to those of the RME ADI-2 DAC/Pro.\n\n## Music players\n* https://moodeaudio.org/ - moOde audio player, audiophile-quality music playback for Raspberry Pi.\n* https://github.com/thoelf/Linux-Stream-Player - Play local files or streamed music with room EQ on Linux.\n* https://github.com/Lykkedk/SuperPlayer-v8.0.0---SamplerateChanger-v1.0.0 - Automatic filter switching at sample rate change for squeezelite, see also [this thread at diyAudio.com](https://www.diyaudio.com/forums/pc-based/361429-superplayer-dsp_engine-camilladsp-samplerate-switching-esp32-remote-control.html).\n* https://github.com/JWahle/piCoreCDSP - Installs CamillaDSP and GUI on piCorePlayer\n* [FusionDsp](https://docs.google.com/document/d/e/2PACX-1vRhU4i830YaaUlB6-FiDAdvl69T3Iej_9oSbNTeSpiW0DlsyuTLSv5IsVSYMmkwbFvNbdAT0Tj6Yjjh/pub) a plugin based on CamillaDsp for [Volumio](https://volumio.com), the music player, with graphic equalizer, parametric equalizer, FIR filters, Loudness, AutoEq profile for headphone and more!\n\n## Guides and example configs\n* https://github.com/ynot123/CamillaDSP-Cfgs-FIR-Examples - Example Filter Configuration and Convolver Coefficients.\n* https://github.com/hughpyle/raspot - Hugh's raspotify config\n* https://github.com/Wang-Yue/camilladsp-crossfeed - Bauer stereophonic-to-binaural crossfeed for headphones\n* https://github.com/jensgk/akg_k702_camilladsp_eq - Headphone EQ and Crossfeed for the AKG K702 headphones\n* https://github.com/phelluy/room_eq_mac_m1 - Room Equalization HowTo with REW and Apple Silicon\n\n## Projects of general nature which can be useful together with CamillaDSP\n* https://github.com/scripple/alsa_hook_hwparams - Alsa hooks for reacting to sample rate and format changes.\n* https://github.com/HEnquist/cpal-listdevices - List audio devices with names and supported formats under Windows and macOS.\n\n## Measurement and filter generation tools\n### rePhase \nhttps://rephase.org/ - rePhase is a free FIR generation tool for building\nfully linear-phase active crossovers with arbitrary slopes.\n### REW\nhttps://www.roomeqwizard.com/ - REW is free software for room acoustic measurement,\nloudspeaker measurement and audio device measurement.\n### DRC\nhttps://drc-fir.sourceforge.net/ -  DRC is a program used to generate correction filters\nfor acoustic compensation of HiFi and audio systems in general,\nincluding listening room compensation.\n\n# Getting help\n\n## FAQ\nSee the [list of frequently asked questions.](./FAQ.md)\n\n## Troubleshooting\nSee the trouble [troubleshooting guide](./troubleshooting.md) for explanations of most error messages.\n\n","funding_links":[],"categories":["Rust"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FHEnquist%2Fcamilladsp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FHEnquist%2Fcamilladsp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FHEnquist%2Fcamilladsp/lists"}