Full Code of hifiberry/hifiberry-dsp for AI

master 377fdb51faf1 cached
145 files
4.8 MB
1.3M tokens
460 symbols
1 requests
Download .txt
Showing preview only (5,014K chars total). Download the full file or copy to clipboard to get everything.
Repository: hifiberry/hifiberry-dsp
Branch: master
Commit: 377fdb51faf1
Files: 145
Total size: 4.8 MB

Directory structure:
gitextract_7qv9da6w/

├── .ai-config.json
├── .ai-guidelines
├── .gitattributes
├── .gitignore
├── .settings/
│   └── .gitignore
├── LICENSE
├── README.md
├── build.sh
├── contrib/
│   ├── Readme.md
│   ├── hifiberry_config.toml
│   ├── install_hbdsp.sh
│   └── set-loudness
├── create-profiles.sh
├── debian/
│   ├── changelog
│   ├── control
│   ├── copyright
│   ├── dirs
│   ├── hifiberry-dsp.docs
│   ├── hifiberry-dsp.examples
│   ├── hifiberry-dsp.install
│   ├── hifiberry-dsp.manpages
│   ├── hifiberry-sigmatcp.nginx
│   ├── postrm
│   ├── rules
│   └── source/
│       └── format
├── doc/
│   ├── adaptexistingprofiles.md
│   ├── asrc.md
│   ├── checksum.md
│   ├── crossovers.md
│   ├── debug.md
│   ├── dspprofiles.md
│   ├── dspreset.md
│   ├── dspsettings.md
│   ├── dsptoolkit.md
│   ├── restapi.md
│   ├── reverse-engineering-lg.md
│   ├── rew-basics.md
│   ├── settingsfiles.md
│   └── sigmatcpserver.md
├── man/
│   └── man1/
│       ├── dsp-get-profile.1
│       ├── dsp-install-profile.1
│       └── dsp-program-info.1
├── repair_filter_store.py
├── sample_files/
│   ├── dspproj/
│   │   ├── 4way-iir-delay-inputswitcher.dspproj
│   │   ├── 4way-iir-delay-mixer-asrccontrol.dspproj
│   │   ├── 4way-iir-delay-mixer.dspproj
│   │   ├── 4way-iir-delay.dspproj
│   │   ├── 4way-iir.dspproj
│   │   ├── 4way-mixed.dspproj
│   │   ├── dacdsp-v11.dspproj
│   │   ├── dacdsp-v12-1.dspproj
│   │   ├── dacdsp-v12-1_lg_soundsync.dspproj
│   │   ├── dsp-addon-v11.dspproj
│   │   ├── dsp192.dspproj
│   │   ├── fullrange-fir.dspproj
│   │   ├── fullrange-iir.dspproj
│   │   └── sine777.dspproj
│   ├── measurement/
│   │   └── sweep48khz.f32
│   ├── rew-filter-coefficients.txt
│   ├── rew-filter-settings.txt
│   ├── roomeq-daniel.txt
│   ├── settings/
│   │   ├── 2-way.txt
│   │   ├── 4-way.txt
│   │   ├── beocreate-default.txt
│   │   ├── filters.txt
│   │   ├── full-volume.txt
│   │   ├── fullrange.txt
│   │   ├── invert-mute.txt
│   │   ├── multiple.txt
│   │   ├── no_automute.txt
│   │   ├── no_spdif.txt
│   │   ├── subsat.txt
│   │   └── volume-limit.txt
│   └── xml/
│       ├── 4way-default.params
│       ├── 4way-default.xml
│       ├── 4way-iir-delay-mixer-asrccontrol.xml
│       ├── 4way-iir-delay-mixer.params
│       ├── 4way-iir-delay-mixer.xml
│       ├── 4way-iir-delay.params
│       ├── 4way-iir-delay.xml
│       ├── 4way-iir.params
│       ├── 4way-iir.xml
│       ├── 4way-inputswitcher.xml
│       ├── 4way-mixed.params
│       ├── 4way-mixed.xml
│       ├── beocreate-default.xml
│       ├── dacdsp-default.xml
│       ├── dacdsp-v12-1.xml
│       ├── dspdac-noautomute.xml
│       ├── fullrange-fir.xml
│       ├── fullrange-iir.xml
│       ├── fullrange-mixed.xml
│       ├── generic192.xml
│       ├── generic96.xml
│       └── sine777.xml
├── src/
│   ├── bin/
│   │   ├── dsp-get-profile
│   │   ├── dsp-install-profile
│   │   ├── dsp-program-info
│   │   ├── dspdac-reset
│   │   ├── dsptoolkit
│   │   ├── mergeparameters
│   │   ├── optimizer-client
│   │   ├── sigmatcpserver
│   │   └── spdifclockgen
│   ├── hifiberrydsp/
│   │   ├── __init__.py
│   │   ├── alsa/
│   │   │   ├── __init__.py
│   │   │   └── alsasync.py
│   │   ├── api/
│   │   │   ├── __init__.py
│   │   │   ├── filters.py
│   │   │   ├── restapi.py
│   │   │   └── settings_store.py
│   │   ├── client/
│   │   │   ├── __init__.py
│   │   │   └── sigmatcp.py
│   │   ├── conftest.py
│   │   ├── datatools.py
│   │   ├── dsptoolkit.py
│   │   ├── filtering/
│   │   │   ├── __init__.py
│   │   │   ├── biquad.py
│   │   │   ├── filtermath.py
│   │   │   ├── volume.py
│   │   │   └── volume_test.py
│   │   ├── genclocks.py
│   │   ├── hardware/
│   │   │   ├── __init__.py
│   │   │   ├── adau145x.py
│   │   │   ├── adau145x_test.py
│   │   │   └── spi.py
│   │   ├── lg/
│   │   │   ├── __init__.py
│   │   │   ├── soundsync.py
│   │   │   └── test_soundsync.py
│   │   ├── measurement/
│   │   │   ├── __init__.py
│   │   │   └── data.py
│   │   ├── parser/
│   │   │   ├── __init__.py
│   │   │   ├── biquad.py
│   │   │   ├── rew.py
│   │   │   ├── settings.py
│   │   │   ├── sigmaparams.py
│   │   │   └── xmlprofile.py
│   │   └── server/
│   │       ├── __init__.py
│   │       ├── constants.py
│   │       └── sigmatcp.py
│   └── setup.py
├── systemd/
│   └── sigmatcpserver.service
├── test-dsptoolkit.sh
├── test_autoload_filters.py
└── test_filter_store.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .ai-config.json
================================================
{
  "ai_config": {
    "style_guidelines": {
      "no_emojis": true,
      "text_only": true,
      "professional_tone": true,
      "technical_writing": true
    },
    "formatting": {
      "markdown_style": "standard",
      "warning_format": "> **WARNING**",
      "note_format": "> **NOTE**", 
      "deprecated_format": "> **DEPRECATED**",
      "bullet_points": "*",
      "max_line_length": 100
    },
    "code_style": {
      "comment_style": "technical",
      "no_decorative_chars": true,
      "descriptive_variables": true,
      "logging_format": "standard"
    },
    "documentation": {
      "api_format": "openapi",
      "example_format": "curl_commands",
      "error_descriptions": "detailed",
      "include_troubleshooting": true
    },
    "project_context": {
      "domain": "audio_dsp",
      "audience": "technical_users",
      "environment": "production",
      "reliability_focus": true
    },
    "prohibited": [
      "emojis",
      "decorative_unicode",
      "casual_language",
      "marketing_speak"
    ],
    "preferred": [
      "plain_text_symbols",
      "technical_precision",
      "clear_instructions",
      "professional_tone"
    ]
  }
}

================================================
FILE: .ai-guidelines
================================================
# AI Agent Guidelines for HiFiBerry DSP Project

## Code Style and Documentation Requirements

### Text Formatting
- **NO EMOJIS**: Do not use emojis in any code, comments, documentation, or commit messages
- Use plain text symbols instead: *, -, >, !, WARNING, NOTE, etc.
- Maintain professional, technical writing style throughout

### Documentation Standards
- Use standard Markdown formatting
- Use text-based warning indicators:
  - `> **WARNING**` instead of emoji warnings
  - `> **NOTE**` instead of emoji notes
  - `> **DEPRECATED**` instead of emoji deprecation notices
- Use bullet points (*) or numbered lists (1.) for organization

### Code Comments
- Write clear, concise technical comments
- Use standard comment formatting without decorative elements
- Focus on explaining complex logic, not obvious operations

### Commit Messages
- Follow conventional commit format
- Use imperative mood: "Add feature" not "Added feature"
- No emojis or decorative characters
- Maximum 72 characters for subject line

### Error Messages and Logging
- Use clear, descriptive error messages
- Include relevant context and suggested solutions
- Use standard logging levels (DEBUG, INFO, WARNING, ERROR)
- No decorative characters in log output

### API Documentation
- Use OpenAPI/Swagger standard formatting
- Include comprehensive examples
- Document all parameters, responses, and error conditions
- Use consistent terminology throughout

## Examples

### Good Documentation Format:
```markdown
> **DEPRECATION NOTICE**
> 
> This feature is deprecated and will be removed in version 2.0.
> Please use the new REST API instead.
```

### Good Code Comment:
```python
# Calculate SHA-1 checksum using length-based detection for better performance
# Falls back to signature-based detection if length registers are not available
```

### Good Error Message:
```python
logging.error("Failed to calculate checksum: DSP communication timeout after 5s")
```

## Project-Specific Guidelines

### HiFiBerry DSP Context
- This is a professional audio DSP control system
- Code is used in production environments
- Documentation must be clear for technical users
- Maintain consistency with existing codebase style
- Focus on functionality and reliability over visual appeal

### File Types to Follow These Guidelines
- Python source files (.py)
- Markdown documentation (.md)
- Configuration files (.json, .toml, .ini)
- Shell scripts (.sh)
- API documentation
- README files
- Changelog entries

## Enforcement
All code contributions, documentation updates, and AI-generated content must adhere to these guidelines. This ensures consistency and professionalism across the entire codebase.

================================================
FILE: .gitattributes
================================================
# Set default behavior to automatically normalize line endings
* text=auto eol=lf

# Explicitly declare text files to be normalized
*.py text eol=lf
*.sh text eol=lf
*.md text eol=lf
*.txt text eol=lf
*.ini text eol=lf
*.yaml text eol=lf
*.yml text eol=lf
*.json text eol=lf
*.xml text eol=lf
*.html text eol=lf
*.js text eol=lf
*.css text eol=lf
*.conf text eol=lf
*.service text eol=lf
debian/* text eol=lf

# Denote all files that are truly binary and should not be modified
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.zip binary
*.tar binary
*.gz binary
*.pdf binary
*.pyc binary


================================================
FILE: .gitignore
================================================
devenv.sh.settings
*.pyc
.project
.pydevproject
.metadata
hifiberrydsp.egg-info
.DS_Store
*.bak
tmp
/devenv.sh
/update
build
dist
*.tar.gz
deb_dist
debian/CONTENTS/
*.egg-info/
beocreate-universal-10.xml
update-clock
.vscode/settings.json


================================================
FILE: .settings/.gitignore
================================================
/org.eclipse.ltk.core.refactoring.prefs


================================================
FILE: LICENSE
================================================
Copyright (c) 2018 Modul 9/HiFiBerry

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

================================================
FILE: README.md
================================================
![Python package](https://github.com/hifiberry/hifiberry-dsp/workflows/Python%20package/badge.svg)
[![PyPI version](https://badge.fury.io/py/hifiberrydsp.svg)](https://badge.fury.io/py/hifiberrydsp)
[![PyPI license](https://img.shields.io/pypi/l/ansicolortags.svg)](https://pypi.python.org/pypi/hifiberrydsp/)
[![PyPI download month](https://img.shields.io/pypi/dm/hifiberrydsp.svg)](https://pypi.python.org/pypi/hifiberrydsp/)
[![GitHub contributors](https://img.shields.io/github/contributors/hifiberry/hifiberry-dsp.svg)](https://gitHub.com/hifiberry/hifiberry-dsp/graphs/contributors/)

# HiFiberry DSP

Software for HiFiBerry boards equipped with DSP. This package can be 
used to read/write data to HiFiBerry DSP boards using the Beocreate TCP 
server.

The software comes "as-is". There is no individual support for this software. Feel free to post in the [HiFiBerry forum](https://support.hifiberry.com/hc/en-us/community/topics/115000377385-DSP-boards-and-Beocreate) for questions. 

## sigmatcpserver

This server runs in background and provides a TCP interface (port 8089) 
to access DSP functions. It is compatible with SigmaStudio. That means 
you can directly deploy DSP programs from SigmaStudio and change 
parameters online.

You can also enable the REST API with this server:

```bash
sigmatcpserver --enable-rest
```

## REST API (Recommended)

The DSP REST API provides a RESTful interface to access metadata, memory, registers, and more from the currently loaded DSP profile. It runs by default on localhost port 13141.

The REST API can be enabled with the sigmatcpserver:

```bash
sigmatcpserver --enable-rest
```

Read the detailed documentation in [doc/restapi.md](/doc/restapi.md).

**Note:** The REST API is the recommended interface for all new development. It provides a more modern, flexible, and powerful way to interact with the DSP.

## Command line utility (Deprecated)

> **DEPRECATED:** The dsptoolkit command line interface is now considered deprecated. For new development, please use the REST API instead, which provides more functionality and better integration options.

The dsptoolkit command is the legacy command line tool to communicate 
with the DSP TCP server. The command line parameters are documented
in [doc/dsptoolkit.md](doc/dsptoolkit.md).

We are no longer adding new features to dsptoolkit and it will eventually be phased out. All new development should use the REST API instead.

## REW integration

The software can be used to push filters created by Room Equalisation 
Wizard (REW) to the DSP.
Have a look at the guide in [doc/rew-basic.md](doc/rew-basics.md)

## DSP profile format

DSP profiles can be generated directly in SigmaStudio. However, to 
enable the full potential of DSP Profiles and allow DSPToolkit to 
directly control the DSP program, you need to add some additional 
metadata to the XML file.
The process to create a DSP profile is documented in [doc/dspprofiles.md](/doc/dspprofiles.md)

## Contributing

When contributing to this project, please follow the AI and style guidelines in `.ai-guidelines` and `.ai-config.json`. This ensures consistent, professional documentation without decorative elements like emojis.



================================================
FILE: build.sh
================================================
#!/bin/bash
set -e

export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8

# Parse command-line arguments for version suffix
VERSION_SUFFIX=""
while [[ $# -gt 0 ]]; do
  case $1 in
    --version-suffix=*)
      VERSION_SUFFIX="${1#*=}"
      shift
      ;;
    *)
      echo "Unknown option $1"
      shift
      ;;
  esac
done

echo "Building HiFiBerry DSP package..."
if [ -n "$VERSION_SUFFIX" ]; then
  echo "Using version suffix: $VERSION_SUFFIX"
fi

# Step 1: Clean up any previous builds
echo "Cleaning up previous builds..."
rm -rf build/ dist/ *.egg-info/
rm -rf debian/CONTENTS
mkdir -p debian/CONTENTS

# Step 2: Build Python package
echo "Building Python package..."
cd src
python3 setup.py sdist
python3 setup.py egg_info
cd ..

# Step 3: Prepare for Debian packaging
echo "Preparing for Debian packaging..."
mkdir -p debian/CONTENTS/python3-hifiberry-dsp/usr/share/hifiberry-dsp/systemd
mkdir -p debian/CONTENTS/python3-hifiberry-dsp/DEBIAN
mkdir -p debian/CONTENTS/python3-hifiberry-dsp/lib/systemd/system

# Step 4: Install Python package into Debian structure
echo "Installing Python package..."
cd src
python3 setup.py install --root=../debian/CONTENTS/python3-hifiberry-dsp --install-layout=deb
cd ..

# Step 5: Copy systemd service file
echo "Copying systemd service file..."
if [ ! -f systemd/sigmatcpserver.service ]; then
    echo "ERROR: systemd/sigmatcpserver.service not found!"
    exit 1
fi

# Ensure target directories exist
mkdir -p debian/CONTENTS/python3-hifiberry-dsp/usr/share/hifiberry-dsp/systemd
mkdir -p debian/CONTENTS/python3-hifiberry-dsp/lib/systemd/system

# Copy the service file
cp systemd/sigmatcpserver.service debian/CONTENTS/python3-hifiberry-dsp/usr/share/hifiberry-dsp/systemd/
cp systemd/sigmatcpserver.service debian/CONTENTS/python3-hifiberry-dsp/lib/systemd/system/

# Set proper permissions for systemd service file
chmod 644 debian/CONTENTS/python3-hifiberry-dsp/lib/systemd/system/sigmatcpserver.service

# Verify the service file was copied correctly
if [ -f debian/CONTENTS/python3-hifiberry-dsp/lib/systemd/system/sigmatcpserver.service ]; then
    echo "✓ Systemd service file copied to package"
    ls -la debian/CONTENTS/python3-hifiberry-dsp/lib/systemd/system/sigmatcpserver.service
    echo "Content check:"
    head -5 debian/CONTENTS/python3-hifiberry-dsp/lib/systemd/system/sigmatcpserver.service
else
    echo "ERROR: Failed to copy systemd service file to package!"
    exit 1
fi

# Step 6: Copy Debian control files with proper formatting
echo "Copying and preparing Debian control files..."
# Ensure control file has Unix line endings
sed -i 's/\r$//' debian/control
cp debian/control debian/CONTENTS/python3-hifiberry-dsp/DEBIAN/

# Process script files with special care
for script in postinst prerm; do
  echo "Processing $script script..."
  # First, ensure Unix line endings (remove any Windows CR characters)
  sed -i 's/\r$//' debian/$script
  
  # Ensure first line is a proper shebang
  if ! grep -q "^#!/bin/sh" debian/$script; then
    echo "Adding shebang to $script"
    sed -i '1s/^/#!/bin/sh\n/' debian/$script
  fi
  
  # Copy to package directory
  cp debian/$script debian/CONTENTS/python3-hifiberry-dsp/DEBIAN/
  
  # Ensure script has executable permissions (0755)
  chmod 755 debian/CONTENTS/python3-hifiberry-dsp/DEBIAN/$script
  
  # Extra verification
  echo "Verifying $script is executable"
  if [ ! -x debian/CONTENTS/python3-hifiberry-dsp/DEBIAN/$script ]; then
    echo "Warning: $script is not marked as executable!"
    ls -la debian/CONTENTS/python3-hifiberry-dsp/DEBIAN/$script
  else
    echo "✓ $script is properly executable"
  fi
done

# Verify all required files are in place for systemd service installation
echo "Verifying package contents for systemd service..."
echo "Checking for systemd service file:"
ls -la debian/CONTENTS/python3-hifiberry-dsp/lib/systemd/system/sigmatcpserver.service || echo "ERROR: systemd service file missing!"
echo "Checking for postinst script:"
ls -la debian/CONTENTS/python3-hifiberry-dsp/DEBIAN/postinst || echo "ERROR: postinst script missing!"

# Step 7: Update version in control file
VERSION=$(cd src && python3 -c 'from hifiberrydsp import __version__; print(__version__)')
if [ -n "$VERSION_SUFFIX" ]; then
  VERSION="${VERSION}${VERSION_SUFFIX}"
fi
sed -i "s/^Version:.*/Version: $VERSION/" debian/CONTENTS/python3-hifiberry-dsp/DEBIAN/control

# Step 8: Build the Debian package
echo "Building Debian package..."
dpkg-deb --build debian/CONTENTS/python3-hifiberry-dsp .

# Verify the package contains the systemd service file
echo "Verifying package contents..."
if command -v dpkg-deb >/dev/null 2>&1; then
    echo "Checking if systemd service file is in the package:"
    dpkg-deb -c python3-hifiberry-dsp_*.deb | grep sigmatcpserver.service || echo "WARNING: systemd service file not found in package!"
fi

echo "Done! The Debian package has been created."



================================================
FILE: contrib/Readme.md
================================================
# Hifiberry DSP External Conributions

## What is this?

This directory contains external contributions (like useful scripts, snippets, etc.) for Hifiberry DSP.

## Disclaimer

This is not an official part of Hifiberry Products. The code included here wasn't thoroughly reviewed and may contain security issues. Use at your own risk!

# Overview

* install_hbdsp
  install Hifiberry Dsp on piCorePlayer

* set-loudness
  for profiles that do not support loudness this script 'fakes' loudness by using tonecontrol.

* hifiberry_config.toml
  `cp hifiberry_config.toml ~/.config/hifiberry_config.toml`
  This config file allows to customise the filterdefinitions

** Please do not report any issues with these scripts to hifiberry! *+
issues can be reported here https://github.com/rawdlite/hifiberry-dsp/issues


================================================
FILE: contrib/hifiberry_config.toml
================================================
[contrib]
loudness="{'1': {'hs': {'freq': '7000Hz', 'vol': '3dB'},'ls': {'freq': '100Hz', 'vol': '3dB'}},'2': {'hs': {'freq': '7000Hz', 'vol': '4dB'},'ls': {'freq': '150Hz', 'vol': '6dB'}},'3': {'hs': {'freq': '7000Hz', 'vol': '6dB'},'ls': {'freq': '200Hz', 'vol': '9dB'}}}"


================================================
FILE: contrib/install_hbdsp.sh
================================================
#!/bin/sh -e

### Exit, if not enough free space
requiredSpaceInMB=25
availableSpaceInMB=$(/bin/df -m /dev/mmcblk0p2 | awk 'NR==2 { print $4 }')
if [[ $availableSpaceInMB -le $requiredSpaceInMB ]]; then
    >&2 echo "Not enough free space"
    >&2 echo "Increase SD-Card size: Main Page > Additional functions > Resize FS"
    exit 1
fi

### Abort, if piCoreCDSP extension is already installed
if [ -f "/etc/sysconfig/tcedir/optional/HifiBerryDSP.tcz" ]; then
    >&2 echo "Uninstall the HifiBerryDSP Extension and reboot, before installing it again"
    >&2 echo "In Main Page > Extensions > Installed > select 'HifiBerry.tcz' and press 'Delete'"
    exit 1
fi


if [ -d "/tmp/hbdsp" ]; then
    #>&2 echo "Reboot before running the script again."
    #exit 1
    rm -rf /tmp/hbdsp
fi
mkdir -p /tmp/hbdsp

# Installs a module from the piCorePlayer repository - if not already installed.
# Call like this: install_if_missing module_name
install_if_missing(){
  if ! tce-status -i | grep -q "$1" ; then
    pcp-load -wil "$1"
  fi
}

# Installs a module from the piCorePlayer repository, at least until the next reboot - if not already installed.
# Call like this: install_temporarily_if_missing module_name
install_temporarily_if_missing(){
  if ! tce-status -i | grep -q "$1" ; then
    pcp-load -wil -t /tmp "$1" # Downloads to /tmp/optional and loads extensions temporarily
  fi
}

set -v

### Create hifiberry data folder

cd /mnt/mmcblk0p2/tce
[ -d hifiberry ] || mkdir hifiberry
mkdir -p /tmp/hbdsp/var/lib
ln -s /mnt/mmcblk0p2/tce/hifiberry /tmp/hbdsp/var/lib/hifiberry

install_if_missing python3.11
install_if_missing libxslt-dev
install_if_missing libxml2-dev
install_temporarily_if_missing python3.11-pip
install_temporarily_if_missing python3.11-wheel
install_temporarily_if_missing python3.11-dev
install_temporarily_if_missing binutils
install_temporarily_if_missing git
install_temporarily_if_missing compiletc
install_temporarily_if_missing libasound-dev

cd /tmp

### Install HifiBerryDSP
mkdir -p /usr/local/hifiberry
python3.11 -m venv /usr/local/hifiberry/environment
cd /usr/local/hifiberry/
(tr -d '\r' < environment/bin/activate) > environment/bin/activate_new # Create fixed version of the activate script. See https://stackoverflow.com/a/44446239
mv -f environment/bin/activate_new environment/bin/activate
source environment/bin/activate # activate custom python environment
python3 -m pip install --upgrade pip
# pypi versions are yanked, installing from git repository
git clone https://github.com/hifiberry/hifiberry-dsp.git /tmp/hifiberry-dsp
cd /tmp/hifiberry-dsp
python3.11 -m pip install .
deactivate # deactivate custom python environment
mkdir -p /tmp/hbdsp/usr/local/bin
cp -Rv /usr/local/hifiberry /tmp/hbdsp/usr/local
#create executables
ln -s /usr/local/hifiberry/environment/bin/dsptoolkit /tmp/hbdsp/usr/local/bin
ln -s /usr/local/hifiberry/environment/bin/sigmatcpserver /tmp/hbdsp/usr/local/bin

mkdir -p /tmp/hbdsp/usr/local/etc/init.d
echo "#!/bin/sh
# Version: 1.1.0

PNAME='sigmatcpserver'
DESC='SigmaTCP Server for HiFiBerry DSP'
PIDFILE=/var/run/sigmatcpserver/sigmatcpserver.pid

# Set DAEMON to the actual binary
DAEMON=\"/usr/local/hifiberry/environment/bin/sigmatcpserver\"

case \"\$1\" in
        start)
                echo \"Starting \$DESC...\"
                if [ -e \$PIDFILE ]; then
                        rm \$PIDFILE
                fi

                start-stop-daemon --start --quiet --exec \$DAEMON \
                        -- --daemon 
        ;;
        stop)
                echo \"Stopping \$DESC...\"
                start-stop-daemon --stop --quiet --exec \$DAEMON

        ;;
        restart)
                echo \"Restarting \$DESC...\"
                \$0 stop
                sleep 1
                \$0 start
        ;;
        status)
                # Check if sigmatcpserver daemon is running
                PID=\$(pgrep \$DAEMON)
                if [ 0\$PID -gt 0 ]; then
                        echo \"\$PNAME is running.\"
                        exit 0
                else
                        echo \"\$PNAME not running.\"
                        exit 1
                fi
        ;;
        *)
                echo
                echo -e \"Usage: \$0 [start|stop|restart|status]\"
                echo
                exit 1
        ;;
esac

exit 0" > /tmp/hbdsp/usr/local/etc/init.d/sigmatcpserver
chmod 755 /tmp/hbdsp/usr/local/etc/init.d/sigmatcpserver

mkdir -p /tmp/hbdsp/usr/local/tce.installed
echo "#!/bin/sh

/usr/local/etc.init.d/sigmatcpserver start
" >> /tmp/hbdsp/usr/local/tce.installed/HifiBerryDSP
### Create and install HifiBerryDSP.tcz

install_temporarily_if_missing squashfs-tools
mksquashfs /tmp/hbdsp /etc/sysconfig/tcedir/optional/HifiBerryDSP.tcz
echo "python3.11.tcz" > /etc/sysconfig/tcedir/optional/HifiBerryDSP.tcz.dep
echo "libxslt-dev.tcz" > /etc/sysconfig/tcedir/optional/HifiBerryDSP.tcz.dep
echo "libxml2-dev.tcz" > /etc/sysconfig/tcedir/optional/HifiBerryDSP.tcz.dep
echo HifiBerryDSP.tcz >> /etc/sysconfig/tcedir/onboot.lst

### Save Changes

pcp backup
pcp reboot


================================================
FILE: contrib/set-loudness
================================================
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Author: rawdlite@gmail.com
# Created: 2024-12-21
# License: MIT License
from hifiberrydsp.dsptoolkit import DSPToolkit,CommandLine
from hifiberrydsp.filtering.biquad import Biquad
from hifiberrydsp.datatools import parse_int, parse_frequency, parse_decibel
import tomllib
from pathlib import Path
import argparse


try:
    with open(Path.home() / ".config" / "hifiberry_config.toml", mode="rb") as fp:
        settings = tomllib.load(fp)
    print(settings)
    LOUDNESS = eval(settings['contrib']['loudness'])
except:
    LOUDNESS = {
            '1': {'hs': {'freq': '7000Hz', 'vol': '3dB'},
                'ls': {'freq': '100Hz', 'vol': '3dB'}},
            '2': {'hs': {'freq': '7000Hz', 'vol': '4dB'},
                'ls': {'freq': '150Hz', 'vol': '6dB'}},
            '3': {'hs': {'freq': '7000Hz', 'vol': '6dB'},
                'ls': {'freq': '200Hz', 'vol': '9dB'}}}

parser = argparse.ArgumentParser(description='set loudness via tonecontrol')
parser.add_argument("-v", "--verbose", action="store_true",
                    help="be verbose about  whats going on")
parser.add_argument('loudness_value', choices=LOUDNESS.keys(),help="loudness intensity value")
args = parser.parse_args()
loudness = LOUDNESS[args.loudness_value]
hs_cmd = f"dsptoolkit tone-control hs {loudness['hs']['freq']} {loudness['hs']['vol']}"
ls_cmd = f"dsptoolkit tone-control hs {loudness['ls']['freq']} {loudness['ls']['vol']}"


if args.verbose:
    print(f"got loudness defined as {loudness}")
    print(f"hs-cmd: {hs_cmd}")
    print(f"ls-cmd: {ls_cmd}")

dsptoolkit = DSPToolkit()
cmd = CommandLine()

hs_frequency = parse_frequency(loudness['hs']['freq'])
hs_dbgain    = parse_decibel(loudness['hs']['vol'])
ls_frequency = parse_frequency(loudness['ls']['freq'])
ls_dbgain    = parse_decibel(loudness['ls']['vol'])
hs_filterdef = f"hs:{hs_frequency}:{hs_dbgain}"
ls_filterdef = f"ls:{ls_frequency}:{ls_dbgain}"
lowshelffilter = Biquad.create_filter(ls_filterdef,dsptoolkit.get_samplerate())
highshelffilter = Biquad.create_filter(hs_filterdef,dsptoolkit.get_samplerate())
dsptoolkit.hibernate()
try:
    dsptoolkit.set_tonecontrol_filters(lowshelf=lowshelffilter, highshelf=highshelffilter)
except Exception:
    print("check filerdefinition")
    exit
finally:
    dsptoolkit.hibernate(False)



================================================
FILE: create-profiles.sh
================================================
#!/bin/bash
#
# Script to create different profiles from a standard profile 
# and settings files
#
cd `dirname $0`
BASEDIR=`pwd`
cd sample_files/xml

DEFAULTPROFILE=4way-iir-delay-mixer.xml
PATH=$BASEDIR/bin:$PATH
PYTHONPATH=$BASEDIR:$PYTHONPATH

for f in dacdsp-default.xml dacdsp-noautomute.xml beocreate-default.xml; do 
 cp $DEFAULTPROFILE $f
done

dsptoolkit store-settings ../settings/invert-mute.txt dacdsp-default.xml
dsptoolkit store-settings ../settings/no_automute.txt dacdsp-noautomute.xml
dsptoolkit store-settings ../settings/beocreate-default.txt beocreate-default.xml

dsptoolkit store-settings ../settings/full-volume.txt dacdsp-default.xml
dsptoolkit store-settings ../settings/full-volume.txt dacdsp-noautomute.xml



================================================
FILE: debian/changelog
================================================
hifiberry-dsp (1.3.11) stable; urgency=medium

  * systemd: launch sigmatcpserver with --store --restore so DSP data
    memory (including the volume register) is dumped on graceful stop
    and re-applied on next start. Audio level set via the DSPVolume
    ALSA control now survives reboots instead of resetting to the
    firmware's quiet default (~-39 dB on Beocreate).
  * systemd: KillSignal=SIGINT + TimeoutStopSec=15 so the --store path
    (which only runs from the KeyboardInterrupt handler) actually
    executes during `systemctl stop` / reboot.

 -- HiFiBerry <support@hifiberry.com>  Mon, 11 May 2026 14:00:00 +0000

hifiberry-dsp (1.3.10) stable; urgency=medium

  * sigmatcpserver: compare each XML checksum field against the matching
    algorithm — "checksum" (signature MD5) vs DSP signature-mode MD5,
    "checksum_sha1" (length SHA-1) vs DSP length-mode SHA-1. Either
    match is sufficient. Pairs with hifiberry-dspprofiles 1.1.1 which
    now ships both metadata entries. Profiles that still carry only the
    old "checksum" entry continue to work via the MD5 path.

 -- HiFiBerry <support@hifiberry.com>  Mon, 11 May 2026 13:00:00 +0000

hifiberry-dsp (1.3.9) stable; urgency=medium

  * sigmatcpserver: fix profile-vs-DSP checksum comparison. XML profiles
    store signature-based MD5/SHA-1 under <metadata type="checksum">, but
    the server was reading the DSP's length-based checksums and comparing
    against them. Two different algorithms over the same firmware never
    match, so every healthy boot was logging "checksums do not match,
    aborting" and refusing to wire alsasync to the volume control
    register. Result: the DSPVolume ALSA control had no effect on the
    actual DSP volume register, which boots at a near-mute default
    value, and speakers stayed silent. Fix is to compare signature ↔
    signature (with length as a fallback only). Length-mode is still
    used for filter-store indexing where the algorithm difference is
    intentional.

 -- HiFiBerry <support@hifiberry.com>  Mon, 11 May 2026 12:00:00 +0000

hifiberry-dsp (1.3.8) stable; urgency=medium

  * Fix critical bug: Biquad.from_parameters() replaced with correct Biquad() constructor
  * Fix duplicate _group_filters_by_bank() method in settings_store.py
  * Fix wrong import in test_filter_store.py (FilterStore → SettingsStore)
  * Fix @classmethod methods using self instead of cls in biquad.py
  * Change debug-level messages from logging.info to logging.debug in adau145x.py
  * Replace bare except clauses with specific exception types across 11 files

 -- HiFiBerry <support@hifiberry.com>  Mon, 02 Mar 2026 12:00:00 +0000

hifiberry-dsp (1.3.7) stable; urgency=medium

  * Add nginx include file for DSP Toolkit API proxy (/etc/nginx/hifiberry-api.d/)

 -- HiFiBerry <support@hifiberry.com>  Sat, 28 Feb 2026 12:00:00 +0000

hifiberry-dsp (1.3.6) stable; urgency=medium

  * Fixed ALSA volume sync to ignore ALSA changes when no DSP volume register
  * ALSA volume automatically resets to 100% when DSP volume register unavailable
  * Added --alsa option to sigmatcpserver systemd service
  * Enables automatic synchronization between DSP and ALSA volume controls
  * Simplified Debian packaging: removed postinst and prerm scripts
  * Streamlined debian/rules with simplified build configuration
  * Added postrm script for proper cleanup on package removal
  * Organized package documentation with .docs, .examples, and .manpages files
  * Simplified sigmatcpserver systemd service configuration
  * Code cleanup in api/filters.py, api/restapi.py, measurement/data.py, setup.py
  * Removed obsolete requirements.txt and dspparamreader documentation images
  
 -- HiFiBerry <info@hifiberry.com>  Fri, 06 Feb 2026 15:35:00 +0000

hifiberry-dsp (1.3.3) stable; urgency=medium

  * Added /version endpoint to REST API for toolkit version information

 -- HiFiBerry <info@hifiberry.com>  Tue, 02 Oct 2025 16:00:00 +0000

hifiberry-dsp (1.3.2) stable; urgency=medium

  * Enhanced checksum caching system with program length validation
  * Added START_PULSE_REGISTER constant for DSP sample rate detection
  * Refactored checksum functions into separate get_current_program_checksum() 
    and get_current_program_checksum_sha1()
  * Removed legacy cache fields for cleaner, more maintainable code
  * Improved cache invalidation based on DSP program length changes
  * Enhanced /cache endpoint with detailed checksum and validation status
  * Fixed checksum cache synchronization between REST API and SigmaTCP server
  * Added new dsp-install-profile command-line tool using REST API
  * Added new dsp-program-info command-line tool using REST API
  * Added new dsp-get-profile command-line tool using REST API
  * Added comprehensive man pages for all new command-line tools
  * Enhanced /dspprofile endpoint to accept raw XML content in addition to JSON
  * Improved XML profile validation logic for better reliability

 -- HiFiBerry <info@hifiberry.com>  Tue, 30 Sep 2025 16:00:00 +0000

hifiberry-dsp (1.3.1) stable; urgency=medium

  * Added XML profile support for checksum_sha1 attribute
  * Enhanced profile matching to prioritize SHA-1 over MD5 checksums
  * Updated SigmaTCP server to validate both MD5 and SHA-1 checksums
  * Added comprehensive /program-info API endpoint
  * Added deprecation notices to dsptoolkit command-line utility
  * Updated documentation to guide users to REST API
  * Fixed Debian packaging issues (aliased locations, removed unused binaries)
  * Added AI agent configuration to maintain code style consistency

 -- HiFiBerry <info@hifiberry.com>  Tue, 30 Sep 2025 15:00:00 +0000

hifiberry-dsp (1.3) stable; urgency=medium

  * Enhanced checksum API with dual MD5/SHA-1 algorithm support
  * Added intelligent checksum mode selection (signature-based vs length-based)
  * Implemented efficient checksum caching system to minimize DSP memory access
  * Added program memory subset functionality for optimized checksum calculation
  * Enhanced program length API with max parameter for maximum length retrieval
  * Enhanced program memory API with multiple end detection modes 
    (signature/full/len)
  * Added checksum priority system: SHA-1 (length-based) over MD5 
    (signature-based)
  * Added comprehensive checksum documentation (doc/checksum.md)
  * Improved performance with multi-level caching for memory and checksums
  * Enhanced REST API with detailed checksum response including mode and 
    length info

 -- HiFiBerry <info@hifiberry.com>  Mon, 29 Sep 2025 15:00:00 +0000

hifiberry-dsp (1.2.1) stable; urgency=medium

  * Fix logging bug
  * Added REST API endpoint to retrieve DSP program length (/program-length)
  * Added REST API endpoint to retrieve DSP program memory (/program-memory)
  * Enhanced program memory API with multiple output formats (hex, raw, base64)
  * Updated REST API documentation with new program memory endpoints

 -- HiFiBerry <info@hifiberry.com>  Sun, 29 Sep 2025 12:00:00 +0000

hifiberry-dsp (1.2) stable; urgency=medium

  * Major architecture refactoring: Filter Store to Settings Store
  * Renamed FilterStore class to SettingsStore for generic settings support
  * Renamed filters.json to dspsettings.json for consistent naming
  * Added dedicated memory settings storage with store parameter in memory API
  * Enhanced JSON structure to support both filters and memory settings
  * Added automatic migration from old filter-only format to new structure
  * Enhanced sigmatcp server with memory settings autoloading support
  * Fixed memory API address parsing bug (hex vs decimal inconsistency)
  * Added concurrent write protection with file locking for settings store
  * Added checksum normalization to prevent duplicate profile entries
  * Enhanced REST API consistency across memory and register endpoints
  * Added comprehensive backward compatibility for existing filter APIs
  * Improved error handling and validation throughout settings system
  * Enhanced debug logging with memory write tracing capabilities
  * Added comprehensive documentation for new settings store architecture

 -- HiFiBerry <info@hifiberry.com>  Thu, 08 Aug 2025 12:00:00 +0000

hifiberry-dsp (1.1) stable; urgency=medium

  * Added comprehensive Filter Store API with JSON persistence
  * Added filter storage organized by DSP profile checksum
  * Added automatic filter loading and persistence via REST API
  * Added sigmatcp server autoloading of stored filters on DSP updates
  * Added REST API endpoints for filter management (/filters)
  * Added DSP program checksum endpoint (/checksum)
  * Added cache management and status endpoint (/cache)
  * Added bulk profile metadata endpoint (/profiles/metadata)
  * Added checksum caching for improved REST API performance
  * Added debug mode with --debug flag for memory write logging
  * Added systemd configuration support via /etc/default/sigmatcpserver
  * Added Bypass/PassThrough filter type for signal pass-through
  * Added comprehensive debug logging for all memory writes
  * Enhanced REST API documentation with detailed examples
  * Fixed memory write debug logging bug in sigmatcp server
  * Enhanced filter store with offset-aware addressing
  * Enhanced biquad filter support with coefficient calculation
  * Moved filter storage to /var/lib/hifiberry/filters.json
  * Improved error handling and validation throughout system

 -- HiFiBerry <info@hifiberry.com>  Wed, 07 Aug 2025 14:00:00 +0000

hifiberry-dsp (1.0.3) stable; urgency=low

  * Changed distribution from unstable to stable
  * Improved package stability and compatibility

 -- HiFiBerry <info@hifiberry.com>  Mon, 30 Jun 2025 15:30:00 +0000

hifiberry-dsp (1.0.2) stable; urgency=low

  * Package renamed from python3-hifiberry-dsp to hifiberry-dsp

 -- HiFiBerry <info@hifiberry.com>  Mon, 30 Jun 2025 12:00:00 +0000

hifiberry-dsp (1.0.1) stable; urgency=low

  * Changed packaging to debian sbuild

 -- HiFiBerry <info@hifiberry.com>  Thu, 26 Jun 2025 12:00:00 +0000

hifiberry-dsp (1.0) stable; urgency=low

  * Initial Debian package release
  * Collection of tools to configure HiFiBerry DSP boards
  * Program DSP boards from SigmaStudio
  * Support for SigmaTCP server
  * ALSA volume control integration
  * REW filter support
  * DSP profile management
  * EEPROM programming capabilities
  * Zeroconf network discovery
  * Web interface support
  * Command line utilities for DSP configuration

 -- HiFiBerry <info@hifiberry.com>  Thu, 24 Jun 2025 12:00:00 +0000


================================================
FILE: debian/control
================================================
Source: hifiberry-dsp
Section: utils
Priority: optional
Maintainer: HiFiBerry <info@hifiberry.com>
Build-Depends: debhelper-compat (= 13),
               dh-sequence-python3,
               pybuild-plugin-pyproject,
               python3-all,
               python3-setuptools,
Standards-Version: 4.7.2
Homepage: https://github.com/hifiberry/hifiberry-dsp
Vcs-Git: https://github.com/hifiberry/hifiberry-dsp.git
Vcs-Browser: https://github.com/hifiberry/hifiberry-dsp

Package: hifiberry-dsp
Architecture: all
Depends: ${misc:Depends},
         ${python3:Depends}
Description: HiFiBerry DSP toolkit
 Tools to configure HiFiBerry DSP boards and program them from SigmaStudio.


================================================
FILE: debian/copyright
================================================
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: hifiberry-dsp
Upstream-Contact: HiFiBerry <info@hifiberry.com>
Source: https://github.com/hifiberry/hifiberry-dsp

Files: *
Copyright: 2018-2025 HiFiBerry
License: MIT

Files: debian/*
Copyright: 2025 HiFiBerry <info@hifiberry.com>
License: MIT

License: MIT
 Permission is hereby granted, free of charge, to any person obtaining a
 copy of this software and associated documentation files (the "Software"),
 to deal in the Software without restriction, including without limitation
 the rights to use, copy, modify, merge, publish, distribute, sublicense,
 and/or sell copies of the Software, and to permit persons to whom the
 Software is furnished to do so, subject to the following conditions:
 .
 The above copyright notice and this permission notice shall be included
 in all copies or substantial portions of the Software.
 .
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: debian/dirs
================================================
etc/nginx/hifiberry-api.d


================================================
FILE: debian/hifiberry-dsp.docs
================================================
doc/*


================================================
FILE: debian/hifiberry-dsp.examples
================================================
sample_files/*


================================================
FILE: debian/hifiberry-dsp.install
================================================
systemd/sigmatcpserver.service usr/lib/systemd/system/
debian/hifiberry-sigmatcp.nginx etc/nginx/hifiberry-api.d/


================================================
FILE: debian/hifiberry-dsp.manpages
================================================
man/man1/dsp-install-profile.1
man/man1/dsp-program-info.1
man/man1/dsp-get-profile.1


================================================
FILE: debian/hifiberry-sigmatcp.nginx
================================================
# HiFiBerry DSP Toolkit API proxy configuration
# This file should be included in the main nginx server block

# Proxy DSP Toolkit API requests to the backend service
location /api/dsptoolkit/ {
    rewrite ^/api/dsptoolkit/(.*) /$1 break;
    proxy_pass http://localhost:13141;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    
    # WebSocket support for real-time features
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    
    # POST request support
    proxy_request_buffering off;
    proxy_buffering off;
    proxy_redirect off;
    
    # Increase buffer sizes for larger requests
    proxy_buffer_size 4k;
    proxy_buffers 8 4k;
    proxy_busy_buffers_size 8k;
    client_max_body_size 10M;
    
    # Timeout settings
    proxy_connect_timeout 60s;
    proxy_send_timeout 60s;
    proxy_read_timeout 60s;
}


================================================
FILE: debian/postrm
================================================
#!/bin/sh

set -e

if [ "$1" = "purge" ]; then
	rm -rf /var/lib/hifiberry
fi

#DEBHELPER#

exit 0


================================================
FILE: debian/rules
================================================
#!/usr/bin/make -f

export PYBUILD_DIR=src

%:
	dh $@ --buildsystem=pybuild

override_dh_auto_test:
	# Skip tests due to hardware dependencies (spidev, pyalsaaudio)
	@echo "Skipping tests due to hardware-specific dependencies"


================================================
FILE: debian/source/format
================================================
1.0

================================================
FILE: doc/adaptexistingprofiles.md
================================================
# Adapting existing profiles

While we provide pre-configured profiles, you might want to add more functionalities or simply remove some blocks. 
This document shows how this can be done easily. It's recommended to start with a working project as creating one from scratch can
be quite complicated.

## Open and edit the project

## Connect to the Pi

In the Hardware configuration/TCPIP block, right click and set the IP address of your Pi. Then press "Open connection"
![tcpip](img/tcpip.png)

## Test

Use the Action/Link Compile Download menu to push the DSP program to the Pi. 
![linkcompiledownload](img/linkcompiledownload.png)

## Create a DSP profile

First, make sure that the "Capture" window is empty. If it's not, press "Clear all output data".
Now right-click on the ADAUxxxx component and select "Self-Boot Memory/Write latest compilation through DSP"

![writeeeprom](img/writeeeprom.png)

This will take some time. All communication with the DSP is being recorded in the Capture windows. Now select all entries in the Capture window and select "Add to Sequence".

![addtosequence](img/addtosequence.png)

Now save the sequence to an XML file

![savesequence](img/savesequence.png)

That's it. You have created a new DSP Profile. 

## Add metadata

While you can already deploy the DSP profile that you created, you won't be able to control parameters e.g. using the GUI in HiFiBerryOS. For these features the software on the Pi requires additional metadata to known how to control parameters of this profile. To add these metadata, first export system files for this project:

![exportsystemfiles](img/exportsystemfiles.png)

This will create a lot of file, but you only need the .params file. It includes data of all controls and their adresses. Based on this, you could now create metadata by yourself, but there's an easier way in HiFiBerryOS. 
Point your browser to http://hifiberry.local/misc/dspparamreader (replace the hifiberry.local by the name or IP address of your Pi)

![dspparamreader](img/dspparamreader.png)

Drag and drop the params file to this web page.

![dspparamreader2](img/dspparamreader2.png)

No click on Metadata/Show or Hide XML.

![dspparamreader3](img/dspparamreader3.png)

Copy the metadata.

Open the DSP profile that you have created before and copy the metadata into the file just starting after the "<ROM>..." line
  
![xmledit1](img/xmledit1.png)
  
You might want to edit some data liek sample rate, profile name or model name.

Last thing you need to add is the checksum of the profile. This isn't included in the params file. To get the checksum, make sure your program is deployed on the Pi and display it using dsp-toolkit:

```
# dsptoolkit get-checksum
CB71C7D437125A4CE066798726B1D25D
```

After adding this, the profile is ready. You can just copy it onto your Pi and either deploy it directly using

```
dsptoolkit install-profile profile.xml
```

If you're using HiFiBerryOS, copy it to /opt/beocreate/beo-dsp-programs. After a restart, you will find the new DSP profile in the selection of available profiles in the HiFiBerryOS sound settings.

![hifiberryos](img/hbosdspprofile.png)


================================================
FILE: doc/asrc.md
================================================
# Usage of ASRCSs

The ADAU14xx models wer'e using on the DAC+ DSP, Beocreate 4CA and the DSP add-on board provide 8 asynchrounous sample rate converter 
that can be used to convert external I2S signals to the internal sample rate of the DSP or vice-versa.

While you're completely free how to use these, this is how we do it:

|ASRC|channels|usage|
|---|---|---|
|0|0,1|Raspberry Pi audio input|
|1|2,3|Analog audio input|
|2|||
|3|||
|4|8,9|DSP channel 4,5 output|
|5|10,11|DSP channel 2,3 output|
|6|12,13|DSP channel 0,1 output|
|7|14,15|SPDIF input|

We try to keep this consistent on different profiles. However, not every profile might use all of these


================================================
FILE: doc/checksum.md
================================================
# DSP Program Checksums

## Overview

The HiFiBerry DSP toolkit provides checksum functionality to verify the integrity of DSP programs loaded into the ADAU145x processor. Checksums are essential for:

- **Program Verification**: Ensuring the DSP program has been loaded correctly without corruption
- **Change Detection**: Detecting when a different program has been loaded
- **Debugging**: Identifying communication issues or memory corruption
- **Quality Assurance**: Validating program integrity in production environments

## Checksum Algorithms

The system supports two cryptographic hash algorithms:

- **MD5**: Fast 128-bit hash, suitable for basic integrity checking
- **SHA-1**: More secure 160-bit hash, recommended for production use

## Program Memory Detection Methods

The DSP toolkit uses two different approaches to determine the extent of the program memory to checksum:

### 1. Signature-Based Detection

This is the traditional method that searches for a specific end-of-program signature in memory.

**How it works:**
- Reads the entire program memory space (0xC000-0xDFFF)
- Searches for the program end signature: `0x02 0xC2 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00`
- Includes the signature itself in the checksum
- If no signature is found but memory contains data, uses the full program space

**Advantages:**
- Works with any DSP program regardless of register configuration
- Historical compatibility with existing programs
- Fallback to full memory if signature is missing

**Disadvantages:**
- Must read entire program memory space
- Slower for large programs
- Includes potentially unused memory areas, enf of program signature could be missing sometimes

### 2. Length-Based Detection

This newer method uses the DSP's program length registers to determine the exact program size.

**How it works:**
- Reads program length from DSP registers (0xF463/0xF464)
- Only reads the exact amount of memory specified by the length registers
- More efficient as it avoids reading unused memory
- Does not depend on detecting an signature at the end of the program (that might be missing)

**Advantages:**
- More precise (exact program boundary)
- Consistent results regardless of memory padding

**Disadvantages:**
- Incompatible with old signature-based approach

## Checksum Types and Defaults

The system automatically determines which detection method to use based on the checksum algorithm:

### MD5 Checksums (Legacy)
- **Default Detection**: Signature-based
- **Rationale**: Maintains compatibility with existing systems and programs
- **Use Case**: Legacy applications, backward compatibility

### SHA-1 Checksums (Recommended)
- **Default Detection**: Length-based
- **Rationale**: More efficient and precise for modern DSP programs
- **Use Case**: New applications, production systems

## Priority System

When multiple checksums are available for a DSP profile, the system uses this priority order:

1. **SHA-1 (length-based)** - Highest priority
2. **MD5 (signature-based)** - Fallback option

This ensures that modern, efficient checksums are preferred while maintaining backward compatibility.

## XML Profile Integration

DSP profiles stored in XML format can include checksum attributes for validation:

### Checksum Attributes

- **`checksum`**: MD5 checksum (legacy, signature-based detection)
- **`checksum_sha1`**: SHA-1 checksum (modern, length-based detection)

### XML Profile Example

```xml
<ROM>
  <page>
    <!-- DSP program data -->
  </page>
  <metadata type="checksum">A1B2C3D4E5F6789012345678901234EF</metadata>
  <metadata type="checksum_sha1">FEDCBA0987654321ABCDEF1234567890A1B2C3D4</metadata>
  <metadata type="profileName">My DSP Profile</metadata>
</ROM>
```

### Profile Matching Priority

When the system searches for matching DSP profiles (e.g., during startup), it uses this priority:

1. **SHA-1 checksum match** (`checksum_sha1` attribute)
2. **MD5 checksum match** (`checksum` attribute)

This ensures that profiles with modern SHA-1 checksums are preferred while maintaining compatibility with legacy MD5-only profiles.

## API Usage

### Getting Checksums

```bash
# Get both MD5 and SHA-1 checksums (default modes)
curl http://localhost:8080/api/checksum

# Get specific algorithm with custom mode
curl "http://localhost:8080/api/checksum?algorithm=sha1&mode=signature"

# Get multiple algorithms
curl "http://localhost:8080/api/checksum?algorithm=md5,sha1"
```

### Response Format

```json
{
    "checksums": {
        "md5": {
            "digest": "A1B2C3D4E5F6789012345678901234EF",
            "mode": "signature",
            "length": 8192
        },
        "sha1": {
            "digest": "A1B2C3D4E5F6789012345678901234567890ABCDEF",
            "mode": "length", 
            "length": 6144
        }
    },
    "status": "success"
}
```

## Performance Considerations

### Caching

The system implements intelligent caching to minimize DSP memory access:

- **Memory Caching**: Program memory is cached per detection mode
- **Checksum Caching**: Calculated checksums are cached per algorithm and mode
- **Cache Invalidation**: Cache is cleared when new programs are loaded

### Efficiency Tips

1. **Use SHA-1 for new projects**: More efficient length-based detection
2. **Cache Results**: The API automatically caches results for repeated requests
3. **Batch Requests**: Request multiple algorithms in one API call when possible
4. **Avoid Full Memory**: Use length-based detection when registers are properly configured

## Troubleshooting

### Common Issues

**"No program memory found"**
- Ensure DSP is properly initialized
- Check SPI communication
- Verify DSP program is loaded

**"Length registers not set"**
- DSP program may not configure length registers
- Fall back to signature-based detection
- Use MD5 checksum which defaults to signature mode

**"Checksum mismatch"**
- Program may have been corrupted during loading
- Different detection modes may yield different results (this is normal)
- Ensure consistent checksum algorithm and mode for comparisons

### Debug Information

Enable debug logging to see detailed checksum calculation information:

```python
import logging
logging.basicConfig(level=logging.DEBUG)
```

This will show:
- Memory reading operations
- Cache hits/misses
- Detection mode selection
- Checksum calculation details

## Best Practices

1. **Choose Appropriate Algorithm**: Use SHA-1 for new projects, MD5 for legacy compatibility
2. **Consistent Comparison**: Always compare checksums using the same algorithm and detection mode
3. **Store Checksums**: Save checksums with DSP profiles for later verification
4. **Monitor Performance**: Use caching effectively to minimize DSP access
5. **Handle Errors**: Implement proper error handling for checksum calculation failures

## Example Use Cases

### Program Verification After Loading
```bash
# Load program
curl -X POST http://localhost:8080/api/program -d @program.xml

# Verify with checksum
CHECKSUM=$(curl -s http://localhost:8080/api/checksum | jq -r '.checksums.sha1.digest')
echo "Program loaded with SHA-1: $CHECKSUM"
```

### Comparing Different Programs
```bash
# Get checksum of current program
CHECKSUM1=$(curl -s http://localhost:8080/api/checksum?algorithm=sha1)

# Load different program
curl -X POST http://localhost:8080/api/program -d @other_program.xml

# Compare checksums
CHECKSUM2=$(curl -s http://localhost:8080/api/checksum?algorithm=sha1)
```

### Legacy Compatibility Check
```bash
# Get MD5 checksum (signature-based) for compatibility
curl "http://localhost:8080/api/checksum?algorithm=md5&mode=signature"
```

================================================
FILE: doc/crossovers.md
================================================
# Creating speaker crossovers with dsptoolkit

While you can always use SigmaStudio to design your individual DSP program for HiFiBerry DSP boards, for simple use cases, this might be overkill.

Therefore, we provide a simple way to create your own n-way crossovers using a configuration file

## What you need

### DSP toolkit

First you need to have the DSP toolkit in at least version 0.10 installed.
Get it at https://github.com/hifiberry/hifiberry-dsp

### A DSP profile that supports a mixing/crossover matrix

A mixing/crossover matrix allows you to mix each input channel onto each output channel and also apply filtering.
In SigmaStudio it looks like this:

![crossover matrix](img/crossover-matrix.png)

We provide an example profile here:
https://raw.githubusercontent.com/hifiberry/hifiberry-dsp/master/sample_files/xml/4way-iir.xml

## Installing the DSP profile

First, you need to install the profile onto the DSP:

```bash
dsptoolkit install-profile 4way-iir.xml
```

You don't even have to download the profile by yourself as dsptoolkit directly accepts URLs:

```bash
dsptoolkit install-profile https://raw.githubusercontent.com/hifiberry/hifiberry-dsp/master/sample_files/xml/4way-iir.xml
```

## Create a crossover settings file

The settings files defines the filters used on each channel of the mixing/crossover matrix

A very simply example looks like this:

```
IIR_L1: pass
IIR_L2: mute
IIR_L3: mute
IIR_L4: mute
IIR_R1: mute
IIR_R2: pass
IIR_R3: mute
IIR_R4: mute
```

This settings will pass the left channel to output 1 of the DSP board
and the right channel to output 2 without any processing. This is basically a normal stereo full range configuration.

For a crossover, you need to use low-pass and high-pass filters. Let's do a simple 2 way setup with a crossover at 2kHz.
The connection to the DSP board is as follows:

- woofer left:   channel 1
- woofer right:  channel 2
- tweeter left:  channel 3
- tweeter right: channel 4

On the Beocreate 4 channel amplifier it is recommended to connect woofers to channels 1 and 2 as these can provide twice the power of channels 3 and 4

```
IIR_L1: lp:2000Hz
IIR_L2: mute
IIR_L3: hp:2000Hz
IIR_L4: mute
IIR_R1: mute
IIR_R2: lp: 2000Hz
IIR_R3: mute
IIR_R4: hp: 2000Hz
```

With this settings configuration,

- output 1 receives a signal from the left channel filtered with a 2kHz low-pass filter
- output 2 receives a signal from the right channel filtered with a 2kHz low-pass filter
- output 3 receives a signal from the left channel filtered with a 2kHz high-pass filter
- output 4 receives a signal from the right channel filtered with a 2kHz high-pass filter

## Applying the crossover

Save you crossover file as a file, e.g. crossover.txt. Then use dsptoolkit to apply the settings on the DSP.

```bash
dsptoolkit apply-settings crossover.txt
```

This will apply the settings just in the DSP RAM, not store them permanently. This is recommended especially when you develop crossovers as it is the fastest way to apply settings and fix potential problems.
Sometimes things can go wrong, e.g. if you have mixed up channels.
In this case, just edit the file and apply the settings again.

In rare cases it can happen that something is completely wrong and you fear that your speakers might be damaged (e.g. if you have accidentally applied a huge volume increase). In these cases, the fastest way to return to the default settings is to reset the DSP:

```bash
dsptoolkit reset
```

This will load the standard settings from the DSP's EEPROM.

## Optimizing the crossover

In most cases a crossover like this won't work perfectly as this would only be correct if woofers and tweeters have exactly the same efficiency.
Usually the tweeters will be some decibels too loud. You can correct this with an additional "vol" filter:

```
IIR_L1: lp:2000Hz
IIR_L2: mute
IIR_L3: hp:2000Hz,vol:-3dB
IIR_L4: mute
IIR_R1: mute
IIR_R2: lp: 2000Hz
IIR_R3: mute
IIR_R4: hp: 2000Hz, vol:-3dB
```

This would reduce the volume of the tweeters by 3dB.

## Further optimizations

There are a lot more optimisations you can do here:

### Adding a subsonic filter

Filtering low frequencies that the speaker can't really handle is often a good idea:

```
IIR_L1: lp:2000Hz,hp:30Hz,hp:30Hz
```

This adds a 4th order high-pass filter to the woofer channel that removes very low frequencies. Depending on your speaker a value between 20 and 100Hz might be used

### Filtering specific frequencies

The frequency response of almost any loudspeakers isn't really flat.
So you might add some filters to increase or decrease the volume at a specific frequency:

```
IIR_R4: hp: 2000Hz, vol:-3dB, eq:5000Hz:2:+2dB
```

Note that you will need measurement equipment to correctly design these filters.

### Delays for specific channels

It might be necessary to delay a channel a bit (often the tweeter). If the profile supports delays, you can configure them also with settings:

```
delay1: 100
```

Note that the delay is defined in samples. At 48kHz the lengths of a sample is roughly 0.02ms. So a delay 100 means approximately 2ms delay. If your profile is using a different sample rate, you need to do the calculations according to your sample rate (which is the internal DSP sample rate, NOT the sample rate of music you want to play back).

## Write the settings to the EEPROM

If your crossover is working as expected, you should save it to the EEPROM of the DSP board. This ensures that the crossover is still correctly configured after a reboot.

```bash
dsptoolkit store-settings crossover.txt
```

Check if is stored correctly by resetting the DSP:

```bash
dsptoolkit reset
```

## Merge the settings into an existing DSP profile

If you want to share your settings or apply the profile including these settings on another system, it can help to merge the settings into an existing XML DSP profile.
This can also be done with dsptoolkit by just adding the file name of the XML profile file:

```bash
dsptoolkit store-settings crossover.txt profile.xml
```

Note that this will NOT apply the settings directly to the DSP, but only to the XML profile file.


================================================
FILE: doc/debug.md
================================================
# HiFiBerry DSP Debug Configuration

## Enabling Debug Mode

To enable debug logging of all DSP memory writes (including REST API and SigmaStudio TCP server):

1. Edit the configuration file:
   ```bash
   sudo nano /etc/default/sigmatcpserver
   ```

2. Uncomment the DEBUG_OPTIONS line:
   ```bash
   DEBUG_OPTIONS="--debug"
   ```

3. Restart the service:
   ```bash
   sudo systemctl restart sigmatcpserver
   ```

## Viewing Debug Logs

To view the debug output:
```bash
sudo journalctl -u sigmatcpserver -f
```

## Debug Output Format

When debug mode is enabled, you'll see log entries for all memory writes including:
- Direct memory writes via REST API (`/memory` endpoint)
- Biquad filter writes via REST API (`/biquad` endpoint) 
- Register writes via REST API (`/register` endpoint)
- Memory writes from SigmaStudio via TCP server

Example debug output:
```
DEBUG: Memory write to address 0x1234 (4660), length: 20 bytes
DEBUG: Write data: 01 00 00 00 FF FE 12 34 ...
```

## Coverage

Debug logging captures all DSP memory writes regardless of the source:
- **REST API**: All endpoints that write to DSP memory (`/memory`, `/biquad`, `/register`)
- **TCP Server**: All writes from SigmaStudio or other TCP clients
- **Internal Operations**: Profile loading, filter application, etc.

## Available Options

You can also add other options in `/etc/default/sigmatcpserver`:

- `--debug` - Log all DSP memory writes
- `--verbose` - Enable verbose logging  
- `--alsa` - Enable ALSA volume control
- `--lgsoundsync` - Enable LG Sound Sync
- `--no-autoload-filters` - Disable filter autoloading

## Disabling Debug Mode

To disable debug logging:

1. Edit `/etc/default/sigmatcpserver`
2. Comment out or remove the DEBUG_OPTIONS line:
   ```bash
   #DEBUG_OPTIONS="--debug"
   ```
3. Restart the service:
   ```bash
   sudo systemctl restart sigmatcpserver
   ```


================================================
FILE: doc/dspprofiles.md
================================================
# DSP Profiles

Our DSP toolkit uses so-called DSP profiles to describe the DSP program. They basically consist of a collection of instructions that write a DSP program to the DSP.

The process to create these profiles consists of multiple steps that are described here.

## Create the DSP program

Firs you have to create you DSP program in SigmaStudio. You can use all available controls and functions.

However, it is recommended to use an existing project and adapt it to your needs. This is usually much easier than creating a new DSP program from scratch.

There are some specific functions that can be controlled later by dsptoolkit:

- Volume - controls the output volume
- VolumeLimit - controls the maximum volume
- Balance - a DC source with a value of 0-2
- Mute - a switch to mute the output
- IIR_L, IIR_R - 2 IIR filter banks to apply equalisations to left and
 right channels
- IIR_L1,IIR_L2,IIR_L3,IIR_L4, IIR_R1,IIR_R2,IIR_R3,IIR_R4 - a mixer/equalisation matrix to implement crossovers
- Delay1 - Delay9 - up to 9 delays for individual channels
  ![crossover matrix](img/crossover-matrix.png)

It is recommended to implement at least the Volume and VolumeLimit controls.

Feel free to add more controls to the DSP programs.

## Write the program to the DSP

Select the Hardware configuration tab on top and config tab on the bottom and you should see a TCP control. Right click onto it to change the TCP/IP settings.

![SigmaStudio TCP/IP](img/ss-tcpip.png)

Enter the IP address of your system here, click "Open connection" and close the settings again.

Now select "Action/Link Compile Download" in the menu. This will push the DSP program onto the DSP.

You can now test your program and check if everything performs as expected.

## Write the program to the EEPROM

Until now, the program only resides in the DSP memory. It will be deleted of you reset the DSP (e.g. on power loss). Therefore, you should write it to the EEPROM. You can also use this step already to create a DSP profile.

First open a capture window using the "View/Capture window menu".
You should now see an additional "Capture window". This will record all transactions send to the DSP.

![SigmaStudio Capture window](img/ss-capture.png)

Also make sure that the sequence window is unhidden. This is the window that will ultimately contain the sequences to be written to the xml profile.

![UnhideSequenceWindow](https://user-images.githubusercontent.com/4656964/205437033-703254fb-9356-4d19-ba86-7a31ec4fc290.png)

The "Capture Window" should be empty. If it isn't click on the "Clear all output data" button in the top-left of this window.
The "Sequence Window" should also be empty. If it isn't click on the "New Sequence" button in the top-left of this window.

![HowToClear](https://user-images.githubusercontent.com/4656964/205437049-9bd8835c-ec91-4099-aa8c-3e34e8f21534.png)

Right-click onto the ADAU1451 and select "Write latest compilation through DSP".

![SigmaStudio Write EEPROM](img/ss-write-eeprom.png)

Configure the properties as follows and click "OK".

![SigmaStudio EEPROM settings](img/ss-eeprom-settings.png)

This will take some time and you should now see the transactions in the
capture window.

## Export the DSP profile

Now mark all transactions in the capture window and right click on
"Add to sequence"

![SigmaStudio Add to sequence](img/ss-add-sequence.png)
  
A new subwindow should open with the recorded transactions. Use the save button in this window to export the sequence file.

You now have created an XML file that can be used as a DSP profile.

It can be downloaded using dsptoolkit.

```bash
dsptoolkit install-profile filename
```

## Metadata

While the program can be already written to the DSP, you can't control any settings directly from dsptoolkit. The reason is simple: dsptoolkit doesn't have any information about this program except the program itself.
It doesn't know what controls are implemented and how they can be controlled.
To support this, you have to add metadata to the DSP profile.

The first step is to export more data from SigmaStudio. Select "Export system files" from the action menu.

![SigmaStudio Export system files](img/ss-export-system.png)

This will create a lot of files.
Note if you used the project filename also for the XML file, exporting the system files will overwrite this file, as it will also create a projectname.xml that will overwrite the profile that you've just created.
Therefore you should rename the profile file before exporting the system
files.

The only file that is really needed for the metadata is the .params file. This file contains a description of all controls,
their addresses in memory and their settings.

It looks like this (but much longer)

```
Cell Name         = SPDIF output.Nx2-2
Parameter Name    = stereomuxSigma300ns2index
Parameter Address = 547
Parameter Value   = 0
Parameter Data :
0x00, 0x00, 0x00, 0x00,



Cell Name         = Balance.Balance
Parameter Name    = DCInpAlg145X1value
Parameter Address = 525
Parameter Value   = 1
Parameter Data :
0x01, 0x00, 0x00, 0x00,



Cell Name         = Balance.DC2
Parameter Name    = DCInpAlg145X2value
Parameter Address = 526
Parameter Value   = 2
Parameter Data :
0x02, 0x00, 0x00, 0x00,



Cell Name         = Mute.Mute
Parameter Name    = SwitchAlg321ison
Parameter Address = 527
Parameter Value   = 0
Parameter Data :
0x00, 0x00, 0x00, 0x00,
```

Based on these information you could create the metadata records by yourself.

A  metadata record is basically a name with an associated address

```xml
<metadata type="balanceRegister">525</metadata>
```

This declares that the balance setting is stored at the memory address 525. You also see this address in the parameters file.

These memory locations are not static and they will change if you modify your DSP program. This means the process of creating metadata has to be repeated each time you add or remove controls in your DSP program or change connection between function blocks.

As the process of creating metadata records takes quite a lot of time, there is a tool that can automatically create the metadata. The tool has the name "mergeparameters". It accepts the XML file and params file as command line argument.

It will read known parameter names from the params file and add the metadata records to the DSP program:

```bash
mergeparameters 4way-iir.xml 4way-iir.params
added parameters to XML profile:
  IIR_L
  IIR_L1
  IIR_L2
  IIR_L3
  IIR_L4
  IIR_R
  IIR_R1
  IIR_R2
  IIR_R3
  IIR_R4
  balanceRegister
  channelSelectRegister
  muteRegister
  volumeControlRegister
  volumeLimitRegister
```

One metadata record that isn't generated is the checksum. It is used to identify a program. While it is optional, it is **strongly recommended** to add a checksum. To calculate the checksum, push the DSP profile to the dsp and then use the "get-checksum" command.

Why is it important to have the checksum? If you're experimenting with different profile, there might be a situation where the DSP server thinks a specific program is installed, but there is really another program running on the DSP.
Changing settings based on the wrong profile might result in all kinds of unwanted behavior. In worst case the DSP program might generate a high-level output signal that can damage your speakers.

```bash
dsptoolkit install-profile 4way-iir.xml
dsptoolkit get-checksum
 8B924F2C2210B903CB4226C12C56EE44
```

Now add metadata records to the XML profile. For maximum compatibility and performance, add both MD5 and SHA-1 checksums:

```xml
<metadata type="checksum">8B924F2C2210B903CB4226C12C56EE44</metadata>
<metadata type="checksum_sha1">FEDCBA0987654321ABCDEF1234567890A1B2C3D4</metadata>
```

The system will prefer the SHA-1 checksum (`checksum_sha1`) when available, falling back to MD5 (`checksum`) for backward compatibility.

To get both checksums:

```bash
# Get both MD5 and SHA-1 checksums
curl "http://localhost:8080/api/checksum"
```

Push the profile to the DSP again

```bash
dsptoolkit install-profile 4way-iir.xml
```


================================================
FILE: doc/dspreset.md
================================================
# Resetting the DSP

The DSP's reset is connected to Pi's GPIO 17. To reset the DSP, you need to first pull this to LOW, then to HIGH:

```
echo 17 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio17/direction
echo 0 > /sys/class/gpio/gpio17/value
echo 1 > /sys/class/gpio/gpio17/value
```


================================================
FILE: doc/dspsettings.md
================================================
# DSP Settings Store

The DSP settings store persists filter and memory configurations across reboots. It is managed by the DSP REST server (`sigmatcpserver`) and stored as a JSON file on disk.

## File Location

```
/var/lib/hifiberry/dspsettings.json
```

Previously named `filters.json` (renamed in 1.3.0).

## How It Works

1. When filters are set via the `/biquad` REST endpoint, they are automatically written to the settings store.
2. Memory settings written via `/memory` with `store=true` are also persisted.
3. On startup, the DSP server restores all stored settings for the currently active DSP profile.
4. Settings are organized by DSP profile checksum, so different profiles maintain independent filter/memory configurations.

## JSON Structure

```json
{
  "PROFILE_CHECKSUM": {
    "filters": {
      "filterKey_offset": {
        "address": "customFilterRegisterBankLeft",
        "offset": 0,
        "filter": {
          "type": "PeakingEq",
          "f": 1000,
          "db": -3.0,
          "q": 1.0
        },
        "timestamp": 1699564123.456,
        "bypassed": false
      }
    },
    "memory": {
      "memoryAddress": {
        "address": "4744",
        "values": [1.0, 0.5],
        "timestamp": 1699564567.89
      }
    }
  }
}
```

### Top-level keys

Each top-level key is a DSP profile checksum (uppercase hex string, e.g. `0A33FEBFD64AC92B1EED630B1499E8E29C06E598`). This allows multiple profile configurations to coexist in the same file.

### Filter entries

Each filter entry key follows the pattern `{address}_{offset}`, e.g. `customFilterRegisterBankLeft_3`.

| Field | Description |
|-------|-------------|
| `address` | DSP metadata register name (e.g. `customFilterRegisterBankLeft`, `eq1_band1`) |
| `offset` | Position within the filter bank (0-based index) |
| `filter` | Filter parameters — either named (type/f/db/q/gain/slope) or raw biquad coefficients (a0/a1/a2/b0/b1/b2) |
| `timestamp` | Unix timestamp of when the filter was last written |
| `bypassed` | Whether the filter is currently bypassed (original coefficients preserved, unity written to DSP) |

### Filter types

Named filters use a `type` field:

| Type | Parameters |
|------|-----------|
| `PeakingEq` | `f`, `db`, `q` |
| `HighShelf` | `f`, `db`/`gain`, `slope` |
| `LowShelf` | `f`, `db`/`gain`, `slope` |
| `Highpass` | `f`, `q` |
| `Lowpass` | `f`, `q` |

Unity/passthrough filters are stored as raw biquad coefficients with `b0=1, b1=0, b2=0, a0=1, a1=0, a2=0`.

### Memory entries

Memory entries store raw DSP memory values at specific addresses. These are used for non-filter settings like volume limits or custom DSP parameters.

## Filter Bank Addresses

Common filter bank addresses defined in DSP profile metadata:

| Address | Description |
|---------|-------------|
| `customFilterRegisterBankLeft` | Left channel custom EQ filters |
| `customFilterRegisterBankRight` | Right channel custom EQ filters |
| `eq1_band1` ... `eq1_bandN` | Individual EQ band registers |

The exact addresses depend on the DSP profile loaded on the device.

## Data Integrity

The settings store includes corruption recovery:

- Corrupted files are backed up with a `.corrupted.{timestamp}` suffix before being repaired
- Common JSON corruption (truncation, encoding issues) is auto-fixed on load
- Checksum keys are normalized to uppercase to prevent duplicates
- Legacy filter-only format (pre-memory support) is auto-migrated

## Related API Endpoints

| Endpoint | Description |
|----------|-------------|
| `GET /filters?current=true` | Get stored filters for the active DSP profile |
| `GET /filters?checksum=...` | Get stored filters for a specific profile |
| `POST /filters` | Manually store filters without applying to DSP |
| `DELETE /filters?checksum=...` | Delete stored filters |
| `DELETE /filters?all=true` | Delete all stored filters |

See [restapi.md](restapi.md) for full API documentation.

## Implementation

The settings store is implemented in `SettingsStore` class at:
```
src/hifiberrydsp/api/settings_store.py
```


================================================
FILE: doc/dsptoolkit.md
================================================
# Command Line Utility (DEPRECATED)

> **⚠️ DEPRECATION NOTICE**
> 
> The `dsptoolkit` command-line utility is **DEPRECATED** and will be removed in a future version.
> 
> **Please migrate to the REST API instead:**
> - **Start server**: `sigmatcpserver --rest`
> - **API documentation**: [http://localhost:8080/api/docs](http://localhost:8080/api/docs)
> - **Migration guide**: See [restapi.md](restapi.md)
> 
> **Benefits of the REST API:**
> - Better performance with intelligent caching
> - Modern JSON responses
> - Enhanced checksum support (MD5 + SHA-1)
> - Web-based interface
> - Comprehensive documentation
> - Better error handling and validation
> 
> **Quick migration examples:**
> ```bash
> # Old: dsptoolkit get-checksum
> curl http://localhost:8080/api/checksum
> 
> # Old: dsptoolkit get-volume
> curl http://localhost:8080/api/volume
> 
> # Old: dsptoolkit install-profile profile.xml
> curl -X POST -F "file=@profile.xml" http://localhost:8080/api/dspprofile
> ```

## Legacy Documentation

dsptoolkit is a tool that is used to directly access functions of the DSP via the TCP server. This means it can run on another system.

The general usage pattern is

```bash
dsptoolkit command parameter
```

The following commands are supported. Note that some command need specific parameters in the DSP profile. If the DSP profile does not support these, the command won't have any effect.

* `install-profile`

  writes a DSP profile to the DSP EEPROM and activates it. A profile installed with this command will be automatically started after a reset.
  
* `set-volume volume`

  set the volume. Volume values can be defined in real values (0-1), percent (0% to 100%) or decibels (you need to use negative values to reduce the volume)
  For negative db values, you need to prefix these with `--`, e.g.  
    `dsptoolkit set-volume -- -3db`

* `adjust-volume volume`

  adjust the volume. Volume adjustment values can be defined just as for `set-volume`. With `adjust-volume`, the current volume is adjusted by the chosen amount, instead of setting it to a fixed level.
  For negative db values, you need to prefix these with `--`, e.g.  
    `dsptoolkit adjust-volume -- -3db`

* `get-volume`

  gets the current setting of the volume control register.

* `set-limit`

  sets the volume limit. The effect is the same as setting volume. The idea of this setting is having a volume control that can be changed between 0 and 100% (or -inf dB to 0dB) and the limit setting to set the maximum volume of the system.
  For negative db values, you need to prefix these with `--`, e.g.  
    `dsptoolkit set-limit -- -3db`

* `apply-rew-filters|apply-rew-filters-left|apply-rew-filters-right filename`

  Deploys parametric equaliser settings calculated by REW to the equaliser filter banks (left, right or both).
  Not all DSP profiles will support this setting.
  To make sure the filters are still active after a system reboot, make sure you use the store command.

* `apply-fir-filters|apply-fir-filters-left|apply-fir-filters-right`

  Deploys a FIR (finite impulse response) filter to the left, right or both FIR filter banks.
  A FIR filter file is a simple text file with one real number per line.
  Not all DSP profiles will support this setting.
  To make sure the filters are still active after a system reboot, make sure you use the store command.

* `clear-iir-filters`

  Resets the IIR filter banks to default values. This is helpful if you deployed filters to the DSP that do not perform as expected

* `read-dec|red-int|read-hex address`

  Reads a memory word from the given address and interprets it as a decimal value, integer value or just displays it as a HEX value.
  Addresses are 2byte long and they can be defined as integers or hex values.
  Hex values are defined by the prefix `0x` (e.g. `0x01aa`)

* `loop-read-dec|loop-read-int|loop-read-hex address`
  
  Works exactly like the read-xxx command. However, it reads the values in a loop. This is often useful when debugging DSP programs as you can easily see if and how parameters change

* `write-reg address value`

  Writes a value to a 2-byte register. This command should be used to write the DSP register addresses. While it will also accept DSP RAM addresses, these are 4 bytes long and the command will only set the first 2 bytes of a RAM cell.

* `write-mem address value`

  Writes a 4 byte value to a memory cell.
  The value can be given as an integer or hex value.
  When using this command on register addresses, the command will write to 2 consecutive register addresses as addresses have a length of only 2 bytes.
  
* `mute|unmute`

  Mutes/unmutes the output. This only works if the profile supports a mute register.

* `servers`

  Find all servers on the local network using Zeroconf.
  
* `apply-settings settings-file`

  Apply the parameter settings from the given parameter file to the running program.
  
* `store-settings settings-file [xml-file]`

  Apply the parameter from the given parameter file to the running program. Also store them into the given DSP profile.
  This means, the default settings of this DSP Profile will be changed.
  There are 2 possible ways to merge this into a DSP profile:
  1. If an XML file is given in the command line, the settings will be applied to this DSP profile. The profile file will be edited.  
     A backup version of teh DSP profile will be stored.
  2. If no xml-file parameter is given, dsptoolkit retrieves the currently running DSP program directly from the server, applies the settings and pushed the profile back to the server. In this case, the server not only activated this, but also stores the changed settings to the EEPROM. They will then be automatically activated after a reset of the DSP board.

* `save`

  saves the current parameter RAM to the file system. This is recommended if you have deployed new filters or changed other settings that should be re-activated later.  
  This does NOT save anything to EEPROM.

* `load`

  restores the parameter RAM from the file system.

* `store-filters`

  Store filters currently deployed in the IIR and FIR filter banks to the EEPROM.
  
* `store`

  Store all known parameter settings (filters, volume, balance) that are currently active on the DSP to the DSP's EEPROM.
  Resetting the EEPROM will than recover these settings.
  
* `reset`

  Resets the DSP. The program will be loaded from the EEPROM. The parameter RAM won't be stored and/or recovered from the file system.

## Migration to REST API

The REST API provides a modern, more efficient alternative to the dsptoolkit command-line utility. Here's a comparison and migration guide:

### Starting the Server

```bash
# Start the SigmaTCP server with REST API support
sigmatcpserver --rest

# The API will be available at http://localhost:8080/api/
# Documentation at http://localhost:8080/api/docs
```

### Command Migration Examples

| dsptoolkit Command | REST API Equivalent |
|-------------------|-------------------|
| `dsptoolkit get-checksum` | `curl http://localhost:8080/api/checksum` |
| `dsptoolkit get-volume` | `curl http://localhost:8080/api/volume` |
| `dsptoolkit set-volume 50%` | `curl -X POST -d "volume=50%" http://localhost:8080/api/volume` |
| `dsptoolkit get-meta profileName` | `curl http://localhost:8080/api/profile/metadata` |
| `dsptoolkit install-profile file.xml` | `curl -X POST -F "file=@file.xml" http://localhost:8080/api/dspprofile` |
| `dsptoolkit store` | `curl -X POST http://localhost:8080/api/store` |
| `dsptoolkit reset` | `curl -X POST http://localhost:8080/api/reset` |

### REST API Advantages

- **Performance**: Intelligent caching reduces DSP memory access
- **Modern**: JSON responses, standard HTTP methods
- **Enhanced Features**: 
  - Dual checksum support (MD5 + SHA-1)
  - Comprehensive program information via `/program-info`
  - Better error handling and validation
- **Documentation**: Interactive API documentation
- **Integration**: Easy integration with web applications and scripts
- **Future-Proof**: Active development and new features

### Getting Started with REST API

1. **Start the server**:
   ```bash
   sigmatcpserver --rest
   ```

2. **Explore the API**:
   - Visit http://localhost:8080/api/docs for interactive documentation
   - Try basic endpoints like `/api/checksum` or `/api/volume`

3. **Read the documentation**:
   - See [restapi.md](restapi.md) for comprehensive API documentation
   - Check [checksum.md](checksum.md) for enhanced checksum features

For more information and detailed examples, see the [REST API Documentation](restapi.md).


================================================
FILE: doc/restapi.md
================================================
# HiFiBerry DSP REST API Documentation

This document describes the REST API provided by the HiFiBerry DSP service for interacting with DSP profiles and memory.

## Base URL

The API server runs by default on:
```
http://localhost:13141
```

## Endpoints

### Version API

#### Get Version Information

Retrieves version information about the HiFiBerry DSP toolkit.

```
GET /version
```

**Example Request:**
```bash
curl -X GET http://localhost:13141/version
```

**Example Response:**
```json
{
  "version": "1.3.2",
  "name": "hifiberry-dsp",
  "description": "HiFiBerry DSP toolkit"
}
```

**Response Properties:**

- `version`: The version string of the HiFiBerry DSP toolkit
- `name`: The package name
- `description`: Brief description of the toolkit

### Hardware Detection API

#### Get Detected DSP Hardware

Retrieves information about the DSP hardware detected by the sigmatcpserver. This endpoint provides the same information as the `dsptoolkit get-meta detected_dsp` command.

```
GET /hardware/dsp
```

**Example Request:**
```bash
curl -X GET http://localhost:13141/hardware/dsp
```

**Example Response (DSP Detected):**
```json
{
  "detected_dsp": "ADAU14xx",
  "status": "detected"
}
```

**Example Response (No DSP Detected):**
```json
{
  "detected_dsp": "",
  "status": "not_detected"
}
```

**Response Properties:**

- `detected_dsp`: String identifying the detected DSP chip (e.g., "ADAU14xx"), or empty string if no DSP detected
- `status`: Either "detected" or "not_detected" indicating whether a DSP was successfully detected

### DSP Profiles API

#### List Available DSP Profiles

Retrieves a list of all available DSP profile files from the profiles directory.

```
GET /profiles
```

**Example Request:**
```bash
curl -X GET http://localhost:13141/profiles
```

**Example Response:**
```json
{
  "profiles": [
    "beocreate-universal-11.xml",
    "dacdsp-15.xml",
    "dsp-addon-96-14.xml"
  ],
  "count": 3,
  "directory": "/usr/share/hifiberry/dspprofiles"
}
```

**Response Properties:**

- `profiles`: Array of XML profile filenames
- `count`: Number of available profiles
- `directory`: Path to the profiles directory

#### Get All Profiles Metadata

Retrieves metadata for all available DSP profiles.

```
GET /profiles/metadata
```

**Example Request:**
```bash
curl -X GET http://localhost:13141/profiles/metadata
```

**Example Response:**
```json
{
  "profiles": {
    "beocreate-universal-11.xml": {
      "checksum": "A1B2C3D4E5F6...",
      "profileName": "Beocreate Universal",
      "profileVersion": "11.0",
      "volumeControlRegister": "1234",
      "_system": {
        "profileName": "Beocreate Universal",
        "profileVersion": "11.0",
        "sampleRate": 48000,
        "filename": "beocreate-universal-11.xml",
        "filepath": "/usr/share/hifiberry/dspprofiles/beocreate-universal-11.xml"
      }
    },
    "dacdsp-15.xml": {
      "checksum": "F6E5D4C3B2A1...",
      "profileName": "DAC+ DSP",
      "profileVersion": "15.0",
      "_system": {
        "profileName": "DAC+ DSP",
        "profileVersion": "15.0",
        "sampleRate": 48000,
        "filename": "dacdsp-15.xml",
        "filepath": "/usr/share/hifiberry/dspprofiles/dacdsp-15.xml"
      }
    }
  },
  "count": 2,
  "directory": "/usr/share/hifiberry/dspprofiles"
}
```

**Response Properties:**

- `profiles`: Dictionary with filename as key and profile metadata as value
- `count`: Number of profiles processed
- `directory`: Path to the profiles directory

**Notes:**
- Profiles that cannot be parsed will include an `error` field in their metadata
- Each profile includes a `_system` section with filename, filepath, and parsed system information

### Metadata API

#### Get Profile Metadata

Retrieves metadata from the currently loaded DSP profile.

```
GET /metadata
```

**Query Parameters:**

- `start` (optional): Filter metadata keys that start with the specified string
- `filter` (optional): Filter metadata by type. Supported values:
  - `biquad`: Only return metadata entries that represent biquad filters (format: xxx/yy where yy is a multiple of 5)

**Example Requests:**

Get all metadata:
```
GET /metadata
```

```bash
curl -X GET http://localhost:13141/metadata
```

Get metadata with keys starting with "eq1_":
```
GET /metadata?start=eq1_
```

```bash
curl -X GET "http://localhost:13141/metadata?start=eq1_"
```

Get only biquad filter metadata:
```
GET /metadata?filter=biquad
```

```bash
curl -X GET "http://localhost:13141/metadata?filter=biquad"
```

Get biquad filters with keys starting with "eq1_":
```
GET /metadata?filter=biquad&start=eq1_
```

```bash
curl -X GET "http://localhost:13141/metadata?filter=biquad&start=eq1_"
```

**Example Response:**
```json
{
  "checksum": "12345abcde",
  "eq1_band1": "1234/5",
  "eq1_band2": "5678/10",
  "_system": {
    "profileName": "Example Profile",
    "profileVersion": "1.0",
    "sampleRate": 48000
  }
}
```

### Program Checksum API

#### Get Current DSP Program Checksum

Retrieves multiple checksums (MD5 and SHA-1) of the currently loaded DSP program in memory using both signature-based and length-based methods. These checksums can be used to verify program integrity and compare with profile checksums.

```
GET /checksum
```

**Example Request:**
```bash
curl -X GET http://localhost:13141/checksum
```

**Example Response:**
```json
{
  "checksum": "97C9C5A88582888D111259BF70D6D79E",
  "format": "checksums",
  "signature": {
    "md5": "97C9C5A88582888D111259BF70D6D79E",
    "sha1": "A1B2C3D4E5F67890ABCDEF1234567890FEDCBA09"
  },
  "length": {
    "md5": "1234567890ABCDEF1234567890ABCDEF",
    "sha1": "FEDCBA0987654321ABCDEF1234567890A1B2C3D4"
  }
}
```

**Response Properties:**

- `checksum`: MD5 checksum using signature-based detection (for backward compatibility)
- `format`: Always "checksums" indicating multiple checksum algorithms are provided
- `signature`: Object containing signature-based checksums
  - `md5`: MD5 checksum using program end signature detection
  - `sha1`: SHA-1 checksum using program end signature detection
- `length`: Object containing length-based checksums
  - `md5`: MD5 checksum using program length registers
  - `sha1`: SHA-1 checksum using program length registers

**Notes:**
- **Signature checksums**: Use program end signature detection (matches XML profile checksums)
- **Length checksums**: Use program length registers to determine program boundaries
- **Efficient caching**: Memory is read only once per mode, and all checksums are calculated and cached
- **Multiple algorithms**: Both MD5 and SHA-1 checksums are provided for enhanced security
- The `checksum` field maintains backward compatibility and contains the signature-based MD5
- **Smart caching**: Checksums are cached per mode and algorithm to avoid recalculation
- Cache is automatically cleared when a new DSP program is installed
- Different methods may produce different checksums for the same program due to different end detection
- Signature-based checksums are compatible with existing XML profile checksums
- XML profiles can include both `checksum` (MD5) and `checksum_sha1` (SHA-1) attributes
- Profile validation prioritizes SHA-1 over MD5 when both are available
- Length-based checksums provide precise register-based program verification
- If one method fails, the other may still succeed (failed checksums return `null`)
- Useful for debugging profile loading issues and ensuring program integrity

#### Get Comprehensive Program Information

Retrieves comprehensive information about the currently loaded DSP program, including checksums calculated with different methods and program length.

```
GET /program-info
```

**Example Request:**

```bash
curl http://localhost:8080/api/program-info
```

**Response Format:**

```json
{
  "program_length": 1536,
  "checksums": {
    "signature": {
      "md5": "A1B2C3D4E5F6789012345678901234EF",
      "sha1": "FEDCBA0987654321ABCDEF1234567890A1B2C3D4"
    },
    "length": {
      "md5": "1234567890ABCDEF1234567890ABCDEF",
      "sha1": "ABCDEF1234567890FEDCBA0987654321A1B2C3D4"
    }
  }
}
```

**Response Properties:**

- `program_length`: Length of the current DSP program in words (from length registers)
- `checksums`: Object containing checksums calculated with different detection methods
  - `signature`: Checksums using program end signature detection
    - `md5`: MD5 checksum (compatible with XML profile `checksum` attribute)
    - `sha1`: SHA-1 checksum
  - `length`: Checksums using program length registers
    - `md5`: MD5 checksum using precise length detection
    - `sha1`: SHA-1 checksum (compatible with XML profile `checksum_sha1` attribute)

**Notes:**
- Provides all checksum variants in a single API call for comprehensive program verification
- Signature-based checksums match those stored in XML profiles for validation
- Length-based checksums provide more precise program boundary detection
- Useful for debugging, profile validation, and program integrity verification
- All checksums are cached for performance

#### Get Current DSP Program Length

Retrieves the length of the currently loaded DSP program in memory. This information is read from the DSP's program length registers.

```
GET /program-length[?max={true|false}]
```

**Query Parameters:**

- `max` (optional, default: `false`): If `true`, returns the maximum program length instead of current length

**Example Request (Current Length):**
```bash
curl -X GET http://localhost:13141/program-length
```

**Example Request (Maximum Length):**
```bash
curl -X GET "http://localhost:13141/program-length?max=true"
```

**Example Response (Current Length):**
```json
{
  "length": 2048,
  "unit": "words",
  "bytes": 8192,
  "type": "current"
}
```

**Example Response (Maximum Length):**
```json
{
  "length": 8192,
  "unit": "words", 
  "bytes": 32768,
  "type": "maximum"
}
```

**Response Properties:**

- `length`: Length of the DSP program in words
- `unit`: Always "words" indicating the unit of measurement
- `bytes`: Length converted to bytes (length × 4)
- `type`: Either "current" or "maximum" depending on the `max` parameter

**Notes:**
- Current length is read from DSP registers 0xf463 and 0xf464
- Maximum length is read from DSP registers 0xf465 and 0xf466
- Current length shows how much program memory is currently in use
- Maximum length shows the total available program memory space
- Useful for debugging and monitoring DSP program size and available space
- Returns null/error if the DSP is not accessible or the registers cannot be read

#### Get Current DSP Program Memory

Retrieves the complete program memory content from the DSP. This endpoint provides access to the actual program code running on the DSP with different end detection modes.

```
GET /program-memory[?format={hex|raw|base64}&end={signature|full|len}]
```

**Query Parameters:**

- `format` (optional, default: `hex`): Output format for the program memory data. Supported values:
  - `hex`: Return data as hexadecimal string (uppercase)
  - `raw`: Return data as array of integers (0-255)
  - `base64`: Return data as base64-encoded string

- `end` (optional, default: `signature`): End detection mode for program memory. Supported values:
  - `signature`: Find program end signature (default, stops at program end marker)
  - `full`: Dump full program memory space (entire allocated memory region)
  - `len`: Use program length registers to determine end (stops at current program length)

**Example Request (Default - Signature End):**
```bash
curl -X GET http://localhost:13141/program-memory
```

**Example Request (Full Memory Dump):**
```bash
curl -X GET "http://localhost:13141/program-memory?end=full"
```

**Example Request (Length-based with Base64 Format):**
```bash
curl -X GET "http://localhost:13141/program-memory?end=len&format=base64"
```

**Example Response (Hex Format - Signature End):**
```json
{
  "memory": "02C20000000000000000000000000000A1B2C3D4...",
  "length": 8192,
  "format": "hex",
  "end_mode": "signature"
}
```

**Example Response (Base64 Format - Full Memory):**
```json
{
  "memory": "AsIAAAAAAAAAAAAAAAAAobLD1A==...",
  "length": 32768,
  "format": "base64",
  "end_mode": "full"
}
```

**Example Response (Raw Format - Length-based):**
```json
{
  "memory": [2, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 178, 195, 212, ...],
  "length": 8192,
  "format": "raw",
  "end_mode": "len"
}
```

**Response Properties:**

- `memory`: Program memory content in the requested format
- `length`: Length of the program memory in bytes
- `format`: Format of the returned data
- `end_mode`: End detection mode used ("signature", "full", or "len")

**Notes:**
- The DSP core is temporarily stopped during memory read and automatically restarted
- **Signature mode**: Stops at program end signature marker (default, most efficient)
- **Full mode**: Dumps entire program memory space (largest output, includes unused memory)
- **Length mode**: Uses program length registers to determine end (precise, based on DSP registers)
- Large program memory may result in substantial response sizes, especially with `raw` format and `full` mode
- Use `base64` format for efficient binary data transfer
- Use `hex` format for human-readable debugging
- Use `signature` mode for normal program analysis and backup
- Use `full` mode for complete memory forensics or debugging
- Use `len` mode for precise program content based on DSP registers
- Useful for program backup, analysis, and verification

### Memory Access API

#### Read Memory

Read 32-bit memory cells from the DSP.

```
GET /memory/{address}[/{length}]
```

**Path Parameters:**

- `address`: Memory address in decimal or hexadecimal (with 0x prefix)
- `length` (optional, default: 1): Number of 32-bit memory cells to read

**Query Parameters:**

- `format` (optional, default: `hex`): Output format for the memory values. Supported values:
  - `hex`: Return values as hexadecimal strings (e.g., "0x12345678")
  - `int`: Return values as integers
  - `float`: Return values as floating-point numbers (converted from 32-bit fixed-point representation)

**Example Requests:**

Read 4 memory cells starting at address 0x100 in hexadecimal format:
```
GET /memory/0x100/4
```

```bash
curl -X GET http://localhost:13141/memory/0x100/4
```

Read 2 memory cells starting at address 0x200 in integer format:
```
GET /memory/0x200/2?format=int
```

```bash
curl -X GET "http://localhost:13141/memory/0x200/2?format=int"
```

Read 1 memory cell at address 0x300 in floating-point format:
```
GET /memory/0x300?format=float
```

```bash
curl -X GET "http://localhost:13141/memory/0x300?format=float"
```

**Example Response (Hexadecimal Format):**
```json
{
  "address": "0x100",
  "values": ["0x12345678", "0xabcdef01", "0x87654321", "0x10abcdef"]
}
```

**Example Response (Integer Format):**
```json
{
  "address": "0x200",
  "values": [305419896, 2882400001]
}
```

**Example Response (Float Format):**
```json
{
  "address": "0x300",
  "values": [1.23, -0.45, 0.0078125]
}
```

#### Write Memory

Write 32-bit memory cells to the DSP.

```
POST /memory
```

**Request Body:**

You can write values in different formats:

1. Hexadecimal strings:
```json
{
  "address": "0x100",
  "value": ["0x12345678", "0xabcdef01"]
}
```

```bash
curl -X POST http://localhost:13141/memory \
  -H "Content-Type: application/json" \
  -d '{"address": "0x100", "value": ["0x12345678", "0xabcdef01"]}'
```

2. Floating-point values (automatically converted to DSP fixed-point format):
```json
{
  "address": "0x100",
  "value": [1.23, -0.45, 0.0078125]
}
```

```bash
curl -X POST http://localhost:13141/memory \
  -H "Content-Type: application/json" \
  -d '{"address": "0x100", "value": [1.23, -0.45, 0.0078125]}'
```

3. Mix of formats:
```json
{
  "address": "0x100",
  "value": ["0x12345678", 1.23, -0.45]
}
```

```bash
curl -X POST http://localhost:13141/memory \
  -H "Content-Type: application/json" \
  -d '{"address": "0x100", "value": ["0x12345678", 1.23, -0.45]}'
```

4. Single value:
```json
{
  "address": "0x100",
  "value": "0x12345678"
}
```

```bash
curl -X POST http://localhost:13141/memory \
  -H "Content-Type: application/json" \
  -d '{"address": "0x100", "value": "0x12345678"}'
```

or

```json
{
  "address": "0x100",
  "value": 1.23
}
```

```bash
curl -X POST http://localhost:13141/memory \
  -H "Content-Type: application/json" \
  -d '{"address": "0x100", "value": 1.23}'
```

5. Store memory setting for auto-loading:
```json
{
  "address": "4744",
  "value": [1.0, 0.5],
  "store": true
}
```

```bash
curl -X POST http://localhost:13141/memory \
  -H "Content-Type: application/json" \
  -d '{"address": "4744", "value": [1.0, 0.5], "store": true}'
```

**Parameters:**

- `address` (required): Memory address in decimal or hexadecimal format
- `value` (required): Single value or array of values to write
- `store` (optional, default: false): If true, store this memory setting in the filter store for automatic loading on startup

**Example Response:**
```json
{
  "address": "0x100",
  "values": ["0x12345678", 1.23, -0.45],
  "status": "success"
}
```

**Example Response (with store=true):**
```json
{
  "address": "0x1288", 
  "values": [1.0, 0.5],
  "status": "success",
  "stored": true
}
```

**Note on Float Values:**
When using floating-point values, they must be within the valid range for the SigmaDSP fixed-point representation (approximately -256 to 256). Values will be automatically converted to the appropriate 32-bit fixed-point representation understood by the DSP.

**Note on Stored Memory Settings:**
When `store` is set to true, the memory setting will be saved in the filter store organized by the current DSP profile checksum. These settings will be automatically restored when the DSP profile is loaded on system startup, similar to how stored filters work.

### Biquad Filter API

#### Set Biquad Filter

Write biquad filter coefficients to DSP memory.

```
POST /biquad
```

**Request Body:**

You can specify biquad filters in different ways:

1. Direct coefficients:
```json
{
  "address": "0x100",
  "offset": 0,
  "sampleRate": 96000,
  "filter": {
    "a0": 1.0,
    "a1": -1.8,
    "a2": 0.81,
    "b0": 0.5,
    "b1": 0.0,
    "b2": -0.5
  }
}
```

```bash
curl -X POST http://localhost:13141/biquad \
  -H "Content-Type: application/json" \
  -d '{
  "address": "0x100",
  "offset": 0,
  "sampleRate": 96000,
  "filter": {
    "a0": 1.0,
    "a1": -1.8,
    "a2": 0.81,
    "b0": 0.5,
    "b1": 0.0,
    "b2": -0.5
  }
}'
```

2. Using filter specification:
```json
{
  "address": "0x100",
  "offset": 1,
  "sampleRate": 48000,
  "filter": {
    "type": "PeakingEq",
    "f": 1000,
    "db": -3.0,
    "q": 1.0
  }
}
```

```bash
curl -X POST http://localhost:13141/biquad \
  -H "Content-Type: application/json" \
  -d '{
  "address": "0x100",
  "offset": 1,
  "sampleRate": 48000,
  "filter": {
    "type": "PeakingEq",
    "f": 1000,
    "db": -3.0,
    "q": 1.0
  }
}'
```

3. Using a metadata key as address:
```json
{
  "address": "eq1_band1",
  "offset": 0,
  "filter": {
    "type": "LowShelf",
    "f": 100,
    "db": 3.0,
    "slope": 1.0
  }
}
```

```bash
curl -X POST http://localhost:13141/biquad \
  -H "Content-Type: application/json" \
  -d '{
  "address": "eq1_band1",
  "offset": 0,
  "filter": {
    "type": "LowShelf",
    "f": 100,
    "db": 3.0,
    "slope": 1.0
  }
}'
```

**Parameters:**

- `address`: Memory address (hexadecimal or decimal), or a metadata key that resolves to a memory address
- `offset` (optional, default: 0): Offset from the base address, will be multiplied by 5 (as each biquad filter requires 5 memory cells)
- `sampleRate` (optional): Override the sample rate used for filter calculations. If not provided, the system will use the sample rate from the profile metadata or try to guess it.
- `filter`: Either direct biquad coefficients or a filter specification object

**Example Response (Direct Coefficients):**
```json
{
  "status": "success",
  "address": "0x100",
  "sampleRate": 48000,
  "coefficients": {
    "a0": 1.0,
    "a1": -1.8,
    "a2": 0.81,
    "b0": 0.5,
    "b1": 0.0,
    "b2": -0.5
  }
}
```

**Example Response (Filter Specification):**
```json
{
  "status": "success",
  "address": "0x100",
  "sampleRate": 96000,
  "filter": {
    "type": "PeakingEq",
    "f": 1000,
    "db": -3.0,
    "q": 1.0
  },
  "coefficients": {
    "a0": 1.0,
    "a1": -1.8969,
    "a2": 0.9025,
    "b0": 0.9513,
    "b1": -1.8969,
    "b2": 0.8538
  }
}
```

**Notes:**

1. When using a metadata key as the address, the system will look up the key in the metadata and extract the base address from it.
2. The offset parameter is useful when you have multiple filters starting at a base address. For example, with offset=1, the filter will be written 5 memory cells after the base address.
3. Filter coefficients are automatically normalized to ensure a0 = 1.0 before being written to the DSP.
4. The sample rate is important for calculating the correct filter coefficients. Specify it explicitly when you know your system is running at a non-standard rate.
5. Filters set via the `/biquad` endpoint are automatically stored in the filter store using the current DSP profile checksum.

### Filter Store API

The filter store allows you to save and retrieve filter configurations for different DSP profiles. Filters are automatically stored when set via the `/biquad` endpoint and are organized by profile checksum.

#### Get Stored Filters

Retrieve stored filters from the filter store.

```
GET /filters
```

**Query Parameters:**

- `checksum` (optional): DSP profile checksum to get filters for. If not specified, returns filters for all profiles.
- `current` (optional): Set to `true` to get filters for the currently active DSP profile. This automatically determines the current checksum and returns filters for that profile.

**Example Requests:**

Get all stored filters:
```bash
curl -X GET http://localhost:13141/filters
```

Get filters for a specific profile by checksum:
```bash
curl -X GET "http://localhost:13141/filters?checksum=8B924F2C2210B903CB4226C12C56EE44"
```

Get filters for the currently active profile:
```bash
curl -X GET "http://localhost:13141/filters?current=true"
```

**Example Response (All Profiles):**
```json
{
  "profiles": {
    "8B924F2C2210B903CB4226C12C56EE44": {
      "eq1_band1_0": {
        "address": "eq1_band1",
        "offset": 0,
        "filter": {
          "type": "PeakingEq",
          "f": 1000,
          "db": -3.0,
          "q": 1.0
        },
        "timestamp": 1699564123.456
      },
      "0x100_1": {
        "address": "0x100",
        "offset": 1,
        "filter": {
          "a0": 1.0,
          "a1": -1.8,
          "a2": 0.81,
          "b0": 0.5,
          "b1": 0.0,
          "b2": -0.5
        },
        "timestamp": 1699564156.789
      }
    },
    "A1B2C3D4E5F6789012345678ABCDEF01": {
      ...
    }
  }
}
```

**Example Response (Single Profile by Checksum):**
```json
{
  "checksum": "8B924F2C2210B903CB4226C12C56EE44",
  "filters": {
    "eq1_band1_0": {
      "address": "eq1_band1",
      "offset": 0,
      "filter": {
        "type": "PeakingEq",
        "f": 1000,
        "db": -3.0,
        "q": 1.0
      },
      "timestamp": 1699564123.456
    }
  }
}
```

**Example Response (Current Profile):**
```json
{
  "checksum": "8B924F2C2210B903CB4226C12C56EE44",
  "current": true,
  "filters": {
    "customFilterRegisterBankLeft": {
      "address": "customFilterRegisterBankLeft",
      "offset": 0,
      "filter": {
        "type": "PeakingEq",
        "f": 1000,
        "db": 10.0,
        "q": 1.0
      },
      "timestamp": 1699564789.123
    }
  }
}
  }
}
```

#### Store Filters Manually

Manually store filters in the filter store without applying them to the DSP.

```
POST /filters
```

**Request Body:**

```json
{
  "checksum": "8B924F2C2210B903CB4226C12C56EE44",
  "filters": [
    {
      "address": "eq1_band1",
      "offset": 0,
      "filter": {
        "type": "PeakingEq",
        "f": 1000,
        "db": -3.0,
        "q": 1.0
      }
    },
    {
      "address": "0x200",
      "offset": 2,
      "filter": {
        "a0": 1.0,
        "a1": -1.5,
        "a2": 0.5,
        "b0": 0.8,
        "b1": 0.0,
        "b2": -0.8
      }
    }
  ]
}
```

**Parameters:**

- `checksum` (optional): DSP profile checksum. If not provided, uses the current active profile checksum.
- `filters`: Array of filter objects to store.

Each filter object should contain:
- `address`: Memory address or metadata key
- `offset` (optional, default: 0): Offset value
- `filter`: Filter specification (same format as `/biquad` endpoint)

**Example Response:**
```json
{
  "status": "success",
  "checksum": "8B924F2C2210B903CB4226C12C56EE44",
  "stored": 2,
  "total": 2
}
```

#### Delete Stored Filters

Delete stored filters from the filter store.

```
DELETE /filters
```

**Query Parameters:**

- `checksum`: DSP profile checksum to delete filters for
- `address` (optional): Specific address to delete. If not provided, deletes all filters for the profile.
- `all` (optional): Set to `true` to delete all filters for all profiles

**Example Requests:**

Delete all filters for a specific profile by checksum:
```bash
curl -X DELETE "http://localhost:13141/filters?checksum=8B924F2C2210B903CB4226C12C56EE44"
```

Delete a specific filter:
```bash
curl -X DELETE "http://localhost:13141/filters?checksum=8B924F2C2210B903CB4226C12C56EE44&address=eq1_band1"
```

Delete all filters for all profiles:
```bash
curl -X DELETE "http://localhost:13141/filters?all=true"
```

**Example Response:**
```json
{
  "status": "success",
  "message": "All filters deleted for profile checksum '8B924F2C2210B903CB4226C12C56EE44'"
}
```

**Notes:**

1. The filter store is saved as `filters.json` at `/var/lib/hifiberry/filters.json`.
2. Filters are automatically stored when set via the `/biquad` endpoint using the current profile checksum.
3. Filter keys are generated as `{address}_{offset}` or just `{address}` if offset is 0.
4. Each stored filter includes a timestamp indicating when it was last modified.
5. The filter store persists across system restarts and profile changes.
6. Profiles are organized by their MD5 checksum for better reliability and uniqueness.
7. Profile names are stored for display purposes but checksums are used as the primary identifier.
8. Legacy support is provided for accessing filters by profile name, but checksum-based access is recommended.
9. Each filter can be individually bypassed without losing its configuration using the bypass API endpoints.

### Filter Bypass API

The filter bypass API allows you to temporarily disable filters without losing their configuration. When a filter is bypassed, its original coefficients are preserved in the filter store, but a bypass filter (unity coefficients) is written to the DSP instead.

The bypass API supports both **individual filter** operations and **filter bank** operations (all filters sharing the same base address).

#### Get Filter Bypass State

Retrieve the bypass state of a specific filter or entire filter bank.

```
GET /filters/bypass?address={address}&offset={offset}&checksum={checksum}&bank={bank}
```

**Query Parameters:**

- `address` (required): Memory address or metadata key
- `offset` (optional): Offset value. Omit or set `bank=true` for entire bank operations
- `checksum` (optional): DSP profile checksum. If not provided, uses the current active profile
- `bank` (optional): Set to `true` to get bypass state of entire filter bank

**Example Requests:**

Get bypass state for a single filter:
```bash
curl -X GET "http://localhost:13141/filters/bypass?address=eq1_band1&offset=0"
```

Get bypass state for entire filter bank:
```bash
curl -X GET "http://localhost:13141/filters/bypass?address=eq1_band1&bank=true"
```

**Example Response (Single Filter):**
```json
{
  "checksum": "8B924F2C2210B903CB4226C12C56EE44",
  "address": "eq1_band1",
  "offset": 0,
  "bank_mode": false,
  "bypassed": false
}
```

**Example Response (Filter Bank):**
```json
{
  "checksum": "8B924F2C2210B903CB4226C12C56EE44",
  "address": "eq1_band1",
  "bank_mode": true,
  "total_filters": 5,
  "filters": [
    {
      "offset": 0,
      "bypassed": false,
      "filter_key": "eq1_band1_0"
    },
    {
      "offset": 1,
      "bypassed": true,
      "filter_key": "eq1_band1_1"
    }
  ]
}
```

#### Set Filter Bypass State

Set the bypass state of a filter or entire filter bank and apply the change to the DSP immediately.

```
POST /filters/bypass
```

**Request Body (Single Filter):**
```json
{
  "address": "eq1_band1",
  "offset": 0,
  "bypassed": true,
  "checksum": "8B924F2C2210B903CB4226C12C56EE44"
}
```

**Request Body (Filter Bank):**
```json
{
  "address": "eq1_band1",
  "bank": true,
  "bypassed": true,
  "checksum": "8B924F2C2210B903CB4226C12C56EE44"
}
```

**Parameters:**

- `address` (required): Memory address or metadata key
- `bypassed` (required): `true` to bypass the filter(s), `false` to enable them
- `offset` (optional, default: 0): Offset value for single filter operations
- `bank` (optional, default: false): Set to `true` to operate on entire filter bank
- `checksum` (optional): DSP profile checksum. If not provided, uses the current active profile

**Example Requests:**

Bypass a single filter:
```bash
curl -X POST http://localhost:13141/filters/bypass \
  -H "Content-Type: application/json" \
  -d '{
    "address": "eq1_band1",
    "offset": 0,
    "bypassed": true
  }'
```

Bypass entire filter bank:
```bash
curl -X POST http://localhost:13141/filters/bypass \
  -H "Content-Type: application/json" \
  -d '{
    "address": "eq1_band1",
    "bank": true,
    "bypassed": true
  }'
```

Enable entire filter bank:
```bash
curl -X POST http://localhost:13141/filters/bypass \
  -H "Content-Type: application/json" \
  -d '{
    "address": "eq1_band1",
    "bank": true,
    "bypassed": false
  }'
```

**Example Response (Single Filter):**
```json
{
  "status": "success",
  "message": "Filter at eq1_band1+0 bypassed",
  "checksum": "8B924F2C2210B903CB4226C12C56EE44",
  "address": "eq1_band1",
  "offset": 0,
  "bank_mode": false,
  "bypassed": true
}
```

**Example Response (Filter Bank):**
```json
{
  "status": "success",
  "message": "All 5 filters in bank bypassed",
  "checksum": "8B924F2C2210B903CB4226C12C56EE44",
  "address": "eq1_band1",
  "bank_mode": true,
  "bypassed": true,
  "total_filters": 5,
  "successful": 5
}
```

#### Toggle Filter Bypass State

Toggle the bypass state of a filter or entire filter bank between enabled and bypassed.

```
PUT /filters/bypass
```

**Request Body (Single Filter):**
```json
{
  "address": "eq1_band1",
  "offset": 0,
  "checksum": "8B924F2C2210B903CB4226C12C56EE44"
}
```

**Request Body (Filter Bank):**
```json
{
  "address": "eq1_band1",
  "bank": true,
  "checksum": "8B924F2C2210B903CB4226C12C56EE44"
}
```

**Parameters:**

- `address` (required): Memory address or metadata key
- `offset` (optional, default: 0): Offset value for single filter operations
- `bank` (optional, default: false): Set to `true` to toggle entire filter bank
- `checksum` (optional): DSP profile checksum. If not provided, uses the current active profile

**Toggle Logic:**

- **Single Filter**: Toggles the current bypass state (enabled ↔ bypassed)
- **Filter Bank**: If any filter in the bank is enabled, all filters are bypassed. If all filters are bypassed, all filters are enabled.

**Example Requests:**

Toggle single filter:
```bash
curl -X PUT http://localhost:13141/filters/bypass \
  -H "Content-Type: application/json" \
  -d '{
    "address": "eq1_band1",
    "offset": 0
  }'
```

Toggle entire filter bank:
```bash
curl -X PUT http://localhost:13141/filters/bypass \
  -H "Content-Type: application/json" \
  -d '{
    "address": "eq1_band1",
    "bank": true
  }'
```

**Example Response (Single Filter):**
```json
{
  "status": "success", 
  "message": "Filter at eq1_band1+0 enabled",
  "checksum": "8B924F2C2210B903CB4226C12C56EE44",
  "address": "eq1_band1",
  "offset": 0,
  "bank_mode": false,
  "bypassed": false
}
```

**Example Response (Filter Bank):**
```json
{
  "status": "success",
  "message": "All 5 filters in bank toggled to enabled",
  "checksum": "8B924F2C2210B903CB4226C12C56EE44",
  "address": "eq1_band1",
  "bank_mode": true,
  "bypassed": false,
  "total_filters": 5,
  "successful": 5
}
```

**Bypass API Notes:**

1. **Immediate DSP Application**: All bypass operations immediately update the DSP hardware
2. **Coefficient Preservation**: Original filter coefficients are always preserved in the filter store
3. **Bypass Implementation**: Bypassed filters use unity coefficients (b0=1, b1=0, b2=0, a0=1, a1=0, a2=0)
4. **Automatic Loading**: Bypass states are preserved and restored during DSP profile changes
5. **Address Resolution**: Both direct memory addresses and metadata keys are supported
6. **Error Handling**: Invalid addresses or missing filters return appropriate error responses
7. **Filter Bank Operations**: Operate on all filters sharing the same base address
8. **Partial Failures**: For bank operations, individual filter failures are reported in the response
9. **Smart Toggle Logic**: Bank toggle considers the state of all filters to determine the new state
10. **Performance**: Bank operations are atomic and efficient for managing multiple related filters

### Register Access API

#### Read Register

Read 16-bit registers from the DSP.

```
GET /register/{address}[/{length}]
```

**Path Parameters:**

- `address`: Register address in decimal or hexadecimal (with 0x prefix)
- `length` (optional, default: 1): Number of 16-bit registers to read

**Example Request:**
```
GET /register/0x200/2
```

```bash
curl -X GET http://localhost:13141/register/0x200/2
```

**Example Response:**
```json
{
  "address": "0x200",
  "values": ["0x1234", "0x5678"]
}
```

#### Write Register

Write a 16-bit register to the DSP.

```
POST /register
```

**Request Body:**
```json
{
  "address": "0x200",
  "value": "0x1234"
}
```

```bash
curl -X POST http://localhost:13141/register \
  -H "Content-Type: application/json" \
  -d '{"address": "0x200", "value": "0x1234"}'
```

**Example Response:**
```json
{
  "address": "0x200",
  "value": "0x1234",
  "status": "success"
}
```

### Frequency Response API

#### Calculate Frequency Response

Calculate the frequency response of one or more filters.

```
POST /frequency-response
```

**Request Body:**

```json
{
  "filters": [
    {
      "type": "PeakingEq",
      "f": 1000,
      "db": -3.0,
      "q": 1.0
    },
    {
      "type": "HighPass",
      "f": 80,
      "db": 0.0,
      "q": 0.707
    }
  ],
  "frequencies": [20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000],
  "pointsPerOctave": 8
}
```

```bash
curl -X POST http://localhost:13141/frequency-response \
  -H "Content-Type: application/json" \
  -d '{
  "filters": [
    {
      "type": "PeakingEq",
      "f": 1000,
      "db": -3.0,
      "q": 1.0
    },
    {
      "type": "HighPass",
      "f": 80,
      "db": 0.0,
      "q": 0.707
    }
  ],
  "frequencies": [20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000],
  "pointsPerOctave": 8
}'
```

**Parameters:**

- `filters`: An array of filter objects (required)
- `frequencies`: Optional array of specific frequencies (in Hz) to calculate the response at
- `pointsPerOctave`: Optional number of points per octave for automatically generated frequencies (default: 8)

If `frequencies` is not provided, the response will be calculated using a logarithmic scale from 20Hz to 20kHz with the specified number of points per octave.

**Example Response:**

```json
{
  "frequencies": [20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000],
  "response": [-18.06, -12.04, -6.02, -1.87, 0.0, -3.01, -0.97, 0.0, 0.0, 0.0]
}
```

**Response Properties:**

- `frequencies`: Array of frequencies (in Hz) at which the response was calculated
- `response`: Array of corresponding gain values (in dB)

### Cache Management API

#### Get Cache Status

Get information about the current cache status, including whether the XML profile, metadata, and program checksum are cached.

```
GET /cache
```

```bash
curl -X GET http://localhost:13141/cache
```

**Example Response:**
```json
{
  "profile": {
    "cached": true,
    "path": "/etc/hifiberry/dspprofile.xml",
    "name": "4-Way IIR Crossover"
  },
  "metadata": {
    "cached": true,
    "keyCount": 24,
    "system": {
      "profileName": "4-Way IIR Crossover",
      "profileVersion": "1.0",
      "sampleRate": 48000
    }
  },
  "checksum": {
    "cached": true,
    "value": "8B924F2C2210B903CB4226C12C56EE44"
  }
}
}
```

#### Clear Cache

Clear the internal XML profile cache and program checksum cache. This is useful if the DSP profile file has been updated externally. Note that the checksum cache is automatically cleared when a new DSP program is installed via the API.

```
POST /cache/clear
```

```bash
curl -X POST http://localhost:13141/cache/clear
```

#### Get DSP Profile

Retrieve the full DSP profile configuration in XML format.

```
GET /dspprofile
```

```bash
curl -X GET http://localhost:13141/dspprofile
```

#### Update DSP Profile

Upload a new DSP profile to the device. The profile can be provided in one of three ways:
- Direct XML content in the request body
- A path to a local file on the server
- A URL pointing to a remote XML profile

The new profile will be written to the DSP's EEPROM and also cached in the standard location.

```
POST /dspprofile
```

**Request Body Options:**

1. Direct XML content:
```json
{
  "xml": "<XML content of DSP profile>"
}
```

```bash
curl -X POST http://localhost:13141/dspprofile \
  -H "Content-Type: application/json" \
  -d '{"xml": "<XML content of DSP profile>"}'
```

2. Local file path on the server:
```json
{
  "file": "/path/to/dspprofile.xml"
}
```

```bash
curl -X POST http://localhost:13141/dspprofile \
  -H "Content-Type: application/json" \
  -d '{"file": "/path/to/dspprofile.xml"}'
```

3. URL to a remote file:
```json
{
  "url": "https://example.com/profiles/dspprofile.xml"
}
```

```bash
curl -X POST http://localhost:13141/dspprofile \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/profiles/dspprofile.xml"}'
```

4. Direct file upload (multipart/form-data):
```bash
curl -X POST http://localhost:13141/dspprofile \
  -F "file=@/path/to/local/dspprofile.xml"
```

**Response:**

```json
{
  "status": "success",
  "message": "Profile from direct successfully written to EEPROM",
  "checksum": {
    "memory": "1a2b3c4d5e6f7890...",
    "profile": "1a2b3c4d5e6f7890...",
    "match": true
  }
}
```

**Notes:**
1. After writing the DSP profile, the system will verify if the checksum in memory matches the one in the profile.
2. The profile will be saved to the standard location and the cache will be updated.
3. The API requires sufficient permissions to write to the DSP EEPROM.
4. For security reasons, when using the `file` option, the file must be accessible on the server running the REST API.

## Filter Operations

### Filter JSON Syntax

Filters are defined using JSON format. Each filter has a specific type and parameters depending on the filter type.

#### Common Filter Parameters

All filters share these common parameters:

- `type`: The type of filter (required)
- Additional parameters specific to each filter type

#### Supported Filter Types

##### PeakingEq Filter

Used for creating peaking equalization filters.

```json
{
  "type": "PeakingEq",
  "f": 1000,
  "db": -3.0,
  "q": 1.0
}
```

**Parameters:**
- `f`: Center frequency in Hz
- `db`: Gain in decibels
- `q`: Q factor (bandwidth)

##### GenericBiquad Filter

Used for creating custom biquad filters with direct coefficient specification. This is useful for advanced filter design or when importing filter coefficients from external applications.

```json
{
  "type": "GenericBiquad",
  "a0": 1.0,
  "a1": -1.8,
  "a2": 0.81,
  "b0": 0.5,
  "b1": 0.0,
  "b2": -0.5
}
```

**Parameters:**
- `a0`: Denominator coefficient (typically normalized to 1.0)
- `a1`: Denominator coefficient
- `a2`: Denominator coefficient
- `b0`: Numerator coefficient
- `b1`: Numerator coefficient
- `b2`: Numerator coefficient

All coefficients default to neutral values (a0=1.0, b0=1.0, others=0.0) if not specified.

##### LowPass Filter

Used for creating low pass filters that attenuate high frequencies.

```json
{
  "type": "LowPass",
  "f": 5000,
  "db": 0.0,
  "q": 0.707
}
```

**Parameters:**
- `f`: Cutoff frequency in Hz
- `db`: Gain in decibels
- `q`: Q factor (determines steepness of roll-off)

##### HighPass Filter

Used for creating high pass filters that attenuate low frequencies.

```json
{
  "type": "HighPass",
  "f": 100,
  "db": 0.0,
  "q": 0.707
}
```

**Parameters:**
- `f`: Cutoff frequency in Hz
- `db`: Gain in decibels
- `q`: Q factor (determines steepness of roll-off)

##### LowShelf Filter

Used for boosting or cutting frequencies below a specified frequency.

```json
{
  "type": "LowShelf",
  "f": 300,
  "db": 6.0,
  "slope": 1.0,
  "gain": 6.0
}
```

**Parameters:**
- `f`: Cutoff frequency in Hz
- `db`: Gain in decibels
- `slope`: Shelf slope parameter
- `gain`: Shelf gain in decibels

##### HighShelf Filter

Used for boosting or cutting frequencies above a specified frequency.

```json
{
  "type": "HighShelf",
  "f": 8000,
  "db": 4.0,
  "slope": 1.0,
  "gain": 4.0
}
```

**Parameters:**
- `f`: Cutoff frequency in Hz
- `db`: Gain in decibels
- `slope`: Shelf slope parameter
- `gain`: Shelf gain in decibels

##### Volume Filter

Used for controlling overall volume.

```json
{
  "type": "Volume",
  "db": -6.0
}
```

**Parameters:**
- `db`: Volume level in decibels

##### Bypass Filter

Used for creating a pass-through filter that does not modify the audio signal. This is useful for temporarily disabling a filter slot without removing the filter configuration, or for creating placeholder filters.

```json
{
  "type": "Bypass"
}
```

**Parameters:**
- No parameters required

**Alternative name:** You can also use `"type": "PassThrough"` which is equivalent to `"type": "Bypass"`.

**Technical details:** The Bypass filter creates a unity biquad filter with coefficients b0=1, b1=0, b2=0, a0=1, a1=0, a2=0, resulting in a transfer function H(z) = 1 (unity gain, no filtering).

### Frequency Response Calculation

The API can calculate the frequency response of a filter or chain of filters at specified frequencies. The response is calculated in decibels, where 0 dB represents unity gain (no change in amplitude).

For complex filter chains, the individual filter responses are added together to produce the combined response.

**Example Request:**
```json
{
  "filters": [
    {"type": "LowShelf", "f": 100, "db": 3.0, "slope": 1.0, "gain": 3.0},
    {"type": "HighShelf", "f": 10000, "db": -2.0, "slope": 1.0, "gain": -2.0}
  ]
}
```

This would calculate the combined frequency response of a low shelf filter at 100Hz with +3dB gain and a high shelf filter at 10kHz with -2dB gain.

## Error Responses

All endpoints can return the following error responses:

### 400 Bad Request

Returned when the request is invalid.

```json
{
  "error": "Error message explaining the issue"
}
```

### 500 Internal Server Error

Returned when there's a server-side error.

```json
{
  "error": "Error message explaining the issue"
}
```

## Utility Functions

### Biquad Filter Detection

The API can identify metadata entries that represent biquad filters. A biquad filter follows the format "xxx/yy" where:

- xxx is any integer
- yy is an integer that is a multiple of 5

Examples of valid biquad filter values:
- "100/5"
- "1234/10"
- "5000/15"

This format detection is used by the `filter=biquad` query parameter in the metadata endpoint.

================================================
FILE: doc/reverse-engineering-lg.md
================================================
# Reverse engineering LG Sound Sync

LG TVs have a feature called "Sound Sync (optical)" that allows the TV to control the volume of a sound bar or speaker that is connected via SPDIF.
As this might be useful, let's see if we can find out how this works.

## Basics

SPDIF is a one-way protocol. There is no feedback from the receiver to the sender.
Therefore no negotiation between sender and receiver is possible. SPDIF sends a left/right data stream. In addition to the PCM data, additional status and user bits can be set. Unfortunately there is no common standard to encode control information into these bits.

I would expected that LG uses some of these bits to send additional control information.
Let's have a look.

## Status of the SPDIF registers with no active SPDIF

```
0xf61: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 02 00 8C 04
0xf62: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 8C 04
```

## Status of the SPDIF registers with active SPDIF

```
0xf61: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 02 00 8C 04
0xf62: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 8C 04
```

no change yet

## Status of the SPDIF registers with LG Sound Sync optical

```
0xf61: 00 00 00 00 00 00 00 00 00 00 01 E0 00 00 00 10 1F 04 8A 62 02 00 8C 04
0xf62: 00 00 00 00 00 00 00 00 00 00 01 E0 00 00 00 10 1F 04 8A 60 02 00 8C 04
```

Now, we see additional channel status bits set

## Changing the volume

```
0xf61: 00 00 00 00 00 00 00 00 00 00 00 60 00 00 00 11 9F 04 8A 62 02 00 8C 04
0xf62: 00 00 00 00 00 00 00 00 00 00 00 60 00 00 00 11 9F 04 8A 60 02 00 8C 04
```

Looks like this changes some status bits - cool :-)

## Setting volume to 0

```
0xf61: 00 00 00 00 00 00 00 00 00 00 01 F0 00 00 00 10 0F 04 8A 62 02 00 8C 04
0xf62: 00 00 00 00 00 00 00 00 00 00 01 F0 00 00 00 10 0F 04 8A 60 02 00 8C 04
```

## Setting volume to max

```
0xf61: 00 00 00 00 00 00 00 00 00 00 07 B0 00 00 00 16 4F 04 8A 62 02 00 8C 04
0xf62: 00 00 00 00 00 00 00 00 00 00 07 B0 00 00 00 16 4F 04 8A 60 02 00 8C 04
```

## Setting volume to 50%

```
0xf61: 00 00 00 00 00 00 00 00 00 00 02 D0 00 00 00 13 2F 04 8A 62 02 00 8C 04
0xf62: 00 00 00 00 00 00 00 00 00 00 02 D0 00 00 00 13 2F 04 8A 60 02 00 8C 04
```

## Setting volume to 51%

```
0xf61: 00 00 00 00 00 00 00 00 00 00 02 C0 00 00 00 13 3F 04 8A 62 02 00 8C 04
0xf62: 00 00 00 00 00 00 00 00 00 00 02 C0 00 00 00 13 3F 04 8A 60 02 00 8C 04
```

## Setting volume to 52%

```
0xf61: 00 00 00 00 00 00 00 00 00 00 02 B0 00 00 00 13 4F 04 8A 62 02 00 8C 04
0xf62: 00 00 00 00 00 00 00 00 00 00 02 B0 00 00 00 13 4F 04 8A 60 02 00 8C 04
```

## Setting volume to 53%

```
0xf61: 00 00 00 00 00 00 00 00 00 00 02 A0 00 00 00 13 5F 04 8A 62 02 00 8C 04
0xf62: 00 00 00 00 00 00 00 00 00 00 02 A0 00 00 00 13 5F 04 8A 60 02 00 8C 04
```

### Corresponding status when connected to a LG OLED55C9

```
0xf61: 00 00 00 00 00 00 00 00 00 00 02 B0 00 00 00 03 5F 04 8A 60 02 00 0C 04
0xf62: 00 00 00 00 00 00 00 00 00 00 02 B0 00 00 00 03 5F 04 8A 60 02 00 0C 04
```

## Muting

Pressing the mute button on the remote toggles two bits:

```
0xf61: 00 00 00 00 00 00 00 00 00 00 04 E0 00 00 00 05 0F 04 8A 60 02 00 0C 04
                                      |              |
0xf61: 00 00 00 00 00 00 00 00 00 00 0C E0 00 00 00 0D 0F 04 8A 60 02 00 0C 04
```

More visible at the bit level:

```
                                      4: 0100        5: 0101
                                      |  |           |  |
                                      C: 1100        D: 1101
```

(Data collected using a LG OLED55C9 with volume set to 80%.)

## Conclusions

It seems the volume information is encoded multiple times.

It might be the easiest way to use byte 16.5 (half of byte 16 and 17) that gives the volume as 0-100 when unmuted.
When muted, the first bit in that byte is set.

Checking bytes 17.5/19 for 0xF048A seems to indicate that Sound Sync is active.

## Other

- More about channel status bits 
https://www.av-iq.com/avcat/images/documents/pdfs/digaudiochannelstatusbits.pdf


================================================
FILE: doc/rew-basics.md
================================================
# Optimizing acoustics performance with DSPToolkit and REW

While many people try improving the performance of their audio systems with higher-quality components, there is one component that most people miss: the listening room.

Normal listening rooms at home are rarely optimised for best sound reproduction. The best way would be to really optimise room acoustics.
However, this often doesn't work well as it would mean adding a lot of absorbers and diffusors to your listening room. The worst thing about it: To perform well at low frequencies, these devices have to be very large.

But there's another way to deal with problems in room acoustics - corrections using specifically designed electronic filters. This won't be a full replacement for optimised room acoustics, but it will definitely improve the performance of you audio system.

## What do you need?

* Raspberry Pi
* DSP equipped HiFiBerry board - the DAC+ DSP or the Beocreate 4 channel amplifier
* a measurement microphone
* a PC with an SPDIF output
* [REW](https://www.roomeqwizard.com/)
* HiFiBerry DSP toolkit

![equipment](img/roomeq-equipment.jpg)

While REW can run directly on the Raspberry Pi, we don't recommend it. The Raspberry Pi is quite slow for this kinds of software which makes the usability quite bad.

## Sound card configuration

For this guide, we assume that your HiFiBerry sound card is already configured correctly. If you need more information how to do this, have a look at www.hifiberry.com

## Software installation

If the DSP toolkit isn't already installed, you can install it with a simple script:

```bash
bash <(curl https://raw.githubusercontent.com/hifiberry/hifiberry-dsp/master/install-dsptoolkit)
```

Check if it is installed correctly by running "dsptoolkit"

```bash
dsptoolkit
```

## Install the DSP program

Install a DSP program with equalisation support. For the start it is recommended to use a pre-configured profile as the 4-way profile (that can be also used for 1-,2- and 3-way speakers).

```bash
dsptoolkit install-profile https://raw.githubusercontent.com/hifiberry/hifiberry-dsp/master/sample_files/xml/4way-iir.xml
```

If you're using the DAC+ DSP, you should use another profile

```bash
dsptoolkit install-profile https://raw.githubusercontent.com/hifiberry/hifiberry-dsp/master/sample_files/xml/dacdsp-default.xml
```

If you want to create your own DSP profiles, have a look at our [guide](dspprofiles.md).

## Install REW

Download and install REW on your PC. While it also runs on the Raspberry Pi, we don't recommend to install and run it on the RPi. The experience on the PC is much better as the program runs much smoother on a PC than on the Raspberry Pi.

## Connect and position the microphone

If you use an USB measurement microphone (we recommend this), just connect it to an USB port of your PC. If you use an XLR measurement microphone, you will need an external microphone preamplifier to connect it to an input of your sound card.
Don't try to use cheap electret microphones with the onboard sound input from your PC. Most likely, linearity of both will be quite bad.

The microphone should be positioned vertically at your listening position. The height should be about the height of your head when you sit at this position.  We recommend to use a microphone stand to position the microphone.

![microphone](img/mic.jpg)

You might require an USB extension cable. Just note that for long extensions you will need an active USB extension cable. You can get these at your favorite computer shop.

## Connect the DSP board

Connect the optical output of your PC or sound card to the optical input of the HiFiBerry DSP/DAC or 4-channel amplifier.

![TOSLink input](img/toslink-input.jpg)

## Configure REW

Make sure, you select your measurement microphone as the input device for REW in the setting dialogue. If your microphone comes with a calibration file, you can configure it under the "Mic/Meter" tab.

![REW preferences](img/rew-prefs.png)

While you can configure the equalisation option later, we recommend also to set the correct equalisation options. You should select the Generic equalisation type:

![REW EQ preferences](img/rew-eq.png)

## Measure the frequency response on your listening position

Now create a new measurement by clicking the Measure button.

![REW start measurement](img/rew-start.png)

Make sure the frequency range is 20-20.000 Hz. During the measurement REW shows you the headroom of the mesurement. Ideally it should be between 3 and 10dB. If it's more, increase the volume using the "Level (dbFS)" setting. If it is less than 3 or even 0dB, you need to reduce the output level.

When the measurement is finished, REW will show you the frequency response of your system:

![REW frequency response](img/rew-fr.png)

Note that this the the frequency response at the position of your microphone. It will look differently if you move the microphone around. You can do multiple measurements at multiple positions and calculate an average to optimise the system for a broader range of listening positions.

In this measurement you can see that it is not linear. The biggest problem is the peak at 45Hz. This is looks like a so-called "room mode".  
In general there are 2 reasons for a non-linear frequency response:

* Non-linearities of the speaker
* Interactions with the room

With a far-field measurement as we did it here, you can't distinguish between both, but that's not a problem. REW will correct both.

## Calculate optimisation filters

Select the optimisation dialog by clicking on the EQ button.

![REW optimisations](img/rew-opti.png)

Under "Equalizer" select "Generic". Make sure speaker type is "Full range".

Depending on your speakers, you can add a subsonic filter at a given frequency using the "Bass limited" setting. This is especially helpful with small speakers that can't If you're not sure what do do, leave it at 40Hz.

You might notice that the target isn't perfectly linear. There is a slight increase of frequencies above 100Hz and a falling slope starting at  1kHz. The reason for this is again room acoustics. As the measurement took both direct and reflected sound into account, we need to reduce the high frequencies a bit. These frequencies are absorbed much more than lower frequencies. Therefore the measurement will measure less reflected sound here. A falling slope compensates for this effect.

First select the best matching "Target level" by clicking on "Set target level". Sometimes this doesn't work perfectly. In this case just set the target level by yourself.

Then start the optimisation by clicking "Match response to target". REW will now do it's "magic" and calculate correction filters for your setup.

![REW optimisations](img/rew-opti-result.png)

In the top-left diagram you will see the process, the correction filters and the expected frequency response.

## Write the filters to the DSP

Now you only have to transfer the correction filters to your Raspberry Pi. First save these using the "Export filter settings as text" menu item. REW will now create a text file with the definition of the filters. It looks like this:

```
Filter Settings file

Room EQ V5.18
Dated: Jul 5, 2018 12:03:08 PM

Notes:

Equaliser: Generic
Jul 5 12:01:46
Filter  1: ON  PK       Fc    7515 Hz  Gain  -9.7 dB  Q  1.00
Filter  2: ON  PK       Fc    1911 Hz  Gain  -3.1 dB  Q  1.00
Filter  3: ON  PK       Fc    50.4 Hz  Gain  -6.0 dB  Q  2.58
Filter  4: ON  PK       Fc    58.9 Hz  Gain   2.5 dB  Q  2.00
Filter  5: ON  PK       Fc    43.4 Hz  Gain  -3.8 dB  Q  3.74
Filter  6: ON  PK       Fc     352 Hz  Gain  -2.9 dB  Q  2.98
Filter  7: ON  PK       Fc     156 Hz  Gain  -4.2 dB  Q  4.49
Filter  8: ON  PK       Fc    7193 Hz  Gain   9.0 dB  Q  2.09
Filter  9: ON  PK       Fc    3388 Hz  Gain   3.8 dB  Q  2.47
Filter 10: ON  PK       Fc   13666 Hz  Gain  -3.2 dB  Q  4.98
Filter 11: ON  PK       Fc     706 Hz  Gain  -2.8 dB  Q  1.50
Filter 12: ON  PK       Fc     675 Hz  Gain   3.8 dB  Q  5.00
Filter 13: ON  PK       Fc     590 Hz  Gain   3.0 dB  Q  5.00
Filter 14: ON  None
Filter 15: ON  None
Filter 16: ON  None
Filter 17: ON  None
Filter 18: ON  None
Filter 19: ON  None
Filter 20: ON  None
```

Transfer this file to your Raspberry Pi (I recommend scp for this), e.g.

```bash
scp filters.txt pi@ip-of-your-pi
```

Login to your Raspberry Pi and write these filters to the DSP using the DSP Toolkit:

```bash
dsptoolkit apply-rew-filters filters.txt
```

## Run another measurement

If you run another measurement now, the frequency response should the target response quite well. It won't be perfectly flat, but that's fine.

![REW frequency response](img/rew-fr2.png)

## Save the settings onto the DSP's EEPROM

You just downloaded the settings to the DSP, but these will be lost after a reboot. Therefore, you should save the DSP settings to the DSP.

```bash
dsptoolkit store-filters
```

## Remove the filters

Not happy with the results and you want to start with a new measurement and another optimisation? You can remove all filter settings using the DSP toolkit

```bash
dsptoolkit clear-iir-filters
```

## Tips & tricks

### Run the optimization with a signal on both speakers

If your speakers are identical, you should apply the same filters to both speakers, especially if you use the full frequency range (20-20.000Hz).

### Use equalisations wisely

Most problems will be in the low frequencies (0-200Hz). If you're speakers frequency response is reasonably flat (it doesn't need to be perfect!), optimise only the low frequencies. Slight peaks of 2-3dB in the frequency response are not a problem. You will see these with practically every speaker in a normal listening environment.

Don't over-optimise!

### Low frequency vs. full range optimisations

The following pictures shows 2 equalisation setting: One full-range optimisation and one only in the range of 20-200Hz.

![REW optimisations](img/rew-opti-compare.png)

Which one sound better? In both cases you will still hear the "personality" of your speakers, but they will sound a bit different. Try different profiles and listen to them. There is no simple right or wrong - at the end your personal preference is important.


================================================
FILE: doc/settingsfiles.md
================================================
Settings file format
====================

A settings file is a text file that consists of lines of attribute:value pairs. Attributes are register names defined in the profile metadata.  
Values can be

- float values
- integer values
- decibel values (in format +xdb, -xdb)
- percent values (for volume, will be converted to a -60db-0dB volume control range)
- IIR filter definitions (see above)

Example
-------

Let's assume the following DSP profile:

```xml
<ROM>
  <beometa>
    <metadata type="IIR_L">37/80</metadata>
    <metadata type="IIR_R">117/80</metadata>
    <metadata type="IIR_L1">197/40</metadata>
    <metadata type="IIR_R1">237/40</metadata>
    <metadata type="IIR_L2">277/40</metadata>
    <metadata type="IIR_R2">317/40</metadata>
    <metadata type="IIR_L3">357/40</metadata>
    <metadata type="IIR_R3">397/40</metadata>
    <metadata type="IIR_L4">437/40</metadata>
    <metadata type="IIR_R4">477/40</metadata>
    <metadata type="balanceRegister">525</metadata>
    <metadata type="channelSelectRegister">546</metadata>
    <metadata type="volumeControlRegister">541</metadata>
    <metadata type="volumeLimitRegister">542</metadata>
  </beometa>
  ....
</ROM>
```

A simple settings file for this DSP profile could look like this:

```
volumeLimitRegister: -10dB
```

Applying these settings would set the the volumeLimit to -10dB.

You can check this by running the command

```bash
dsptoolkit get-limit
```

A more complex file:

```
volumeControlRegister: -3dB
volumeLimitRegister: 90%
mute: 0x1
balanceRegister: 0.8
IIR_L: lp:1500Hz, hp:300Hz:0.6, eq: 1200Hz:2:+3dB, vol:-1dB
IIR_R1: vol: +3dB
IIR_R2: vol: -3dB
IIR_R3: vol: +0dB
```

In this case, the mute setting would be ignored as no mute attribute is available in the DSP profile.


================================================
FILE: doc/sigmatcpserver.md
================================================
# SigmaTCP Server Documentation

The `sigmatcpserver` is a daemon that provides a TCP interface for communication with HiFiBerry DSP boards. It implements the SigmaTCP protocol used by Analog Devices SigmaStudio to interact with DSP devices.

## Overview

The SigmaTCP server runs in the background and provides the following features:

- Compatible with SigmaStudio for DSP programming
- Provides a REST API for modern integration (optional)
- Supports ALSA volume control synchronization
- Supports LG Sound Sync
- Handles DSP program updates and parameter persistence

## Command-Line Options

```
sigmatcpserver [OPTIONS]
```

### Options

| Option | Description |
|--------|-------------|
| `--enable-rest` | Enable the REST API server (port 13141) |
| `--disable-tcp` | Disable the SigmaTCP server (only useful with --enable-rest) |
| `--alsa` | Enable ALSA volume control synchronization |
| `--lgsoundsync` | Enable LG Sound Sync functionality |
| `--restore` | Restore saved DSP parameters on startup |
| `--store` | Store DSP data memory to a file on exit |
| `--localhost` | Bind services to localhost only (more secure) |
| `--bind-address ADDRESS` | Specify IP address to bind to |
| `--no-autoload-filters` | Disable automatic loading of stored filters on startup |
| `-v, --verbose` | Enable verbose logging |

## Configuration

The server can be configured through a configuration file located at `/etc/sigmatcp.conf`.

Example configuration:

```ini
[server]
command_after_startup=/path/to/some/script.sh
notify_on_updates=http://localhost:8080/dsp-updated
```

### Configuration Options

- `command_after_startup`: A command to execute after the server has started
- `notify_on_updates`: A URL to send a POST request to when DSP program updates occur

## Usage Examples

### Basic Usage

Start the server with default options:

```bash
sigmatcpserver
```

### With REST API Enabled

Start the server with REST API enabled:

```bash
sigmatcpserver --enable-rest
```

### REST API Only Mode

Run only the REST API without the SigmaTCP server:

```bash
sigmatcpserver --enable-rest --disable-tcp
```

### Local-Only Mode

Run the server in local-only mode for better security:

```bash
sigmatcpserver --localhost
```

### With ALSA Volume Control

Enable ALSA volume control:

```bash
sigmatcpserver --alsa
```

### With All Features

Enable all available features:

```bash
sigmatcpserver --enable-rest --alsa --lgsoundsync --restore
```

## Filter Autoloading

The SigmaTCP server automatically loads and applies stored filters from the filter store when starting up or after a DSP program update. This ensures that your custom filter settings persist across reboots and program changes.

### How It Works

1. **On Startup**: The server calculates the checksum of the current DSP program and looks up any stored filters for that checksum in the filter store.

2. **After Updates**: When a new DSP program is loaded (e.g., via SigmaStudio or the REST API), the server automatically reloads filters for the new program checksum.

3. **Automatic Application**: Found filters are automatically applied to their respective memory addresses using the same logic as the `/biquad` REST API endpoint.

### Disabling Autoloading

If you want to disable automatic filter loading, use the `--no-autoload-filters` option:

```bash
sigmatcpserver --no-autoload-filters
```

This can be useful for:
- Debugging filter issues
- Starting with a clean slate
- Performance testing without filters
- Development scenarios where you want manual control

### Filter Resolution

The autoloader supports both direct memory addresses and metadata key resolution:

- **Direct addresses**: Filters stored with hex addresses (e.g., `0x1000`) are applied directly
- **Metadata keys**: Filters stored with metadata keys (e.g., `eq1_band1`) are resolved using the current DSP profile's metadata

### Error Handling

The autoloader is designed to be robust:
- Invalid filters are skipped with warnings
- Missing metadata keys don't prevent other filters from loading
- Address validation ensures memory safety
- Errors are logged but don't prevent server startup

## Systemd Integration

The server is typically run as a systemd service. You can control the service with the following commands:

```bash
# Start the service
sudo systemctl start sigmatcpserver

# Stop the service
sudo systemctl stop sigmatcpserver

# Enable at boot
sudo systemctl enable sigmatcpserver

# Disable at boot
sudo systemctl disable sigmatcpserver

# Check status
sudo systemctl status sigmatcpserver
```

## SigmaStudio Integration

The SigmaTCP server allows direct deployment of DSP programs from SigmaStudio. To connect SigmaStudio to the server:

1. Open SigmaStudio and your DSP project
2. Go to "Hardware Configuration"
3. Under "TCP/IP Settings", enter the IP address of your device
4. Use port 8089 (the default SigmaTCP port)
5. Click "Connect"

Once connected, you can download programs to the DSP and adjust parameters in real-time using SigmaStudio's interface.

## REST API Integration

When enabled with the `--enable-rest` option, the server also provides a RESTful API for interacting with the DSP. This API runs on port 13141 by default.

See [restapi.md](restapi.md) for detailed documentation on the REST API.


================================================
FILE: man/man1/dsp-get-profile.1
================================================
.TH DSP-GET-PROFILE 1 "September 2025" "HiFiBerry DSP 1.3.2" "HiFiBerry DSP Tools"
.SH NAME
dsp-get-profile \- retrieve DSP profile from HiFiBerry DSP using REST API
.SH SYNOPSIS
.B dsp-get-profile
[\fIOPTIONS\fR] [\fIoutput_file\fR]
.SH DESCRIPTION
.B dsp-get-profile
retrieves the current DSP profile from a HiFiBerry DSP device using the REST API.
The profile is returned in XML format and can be saved to a file or displayed on stdout.
This tool is useful for backing up current DSP configurations or examining the active profile.

The tool connects to the DSP via the REST API server (sigmatcpserver) and retrieves
the currently active DSP profile. The profile contains all DSP configuration data
including filters, parameters, and metadata.

.SH ARGUMENTS
.TP
.I output_file
Optional file path where the retrieved profile should be saved. If not specified,
the profile is written to stdout. The output file will contain the complete XML
profile data.

.SH OPTIONS
.TP
.BR \-h ", " \-\-host " " \fIHOST\fR
Specify the DSP server hostname or IP address.
.br
Default: localhost
.TP
.BR \-p ", " \-\-port " " \fIPORT\fR
Specify the DSP server port number.
.br
Default: 13141
.TP
.BR \-t ", " \-\-timeout " " \fISECONDS\fR
Set the connection timeout in seconds.
.br
Default: 30
.TP
.BR \-v ", " \-\-verbose
Enable verbose output showing detailed operation information.
.TP
.BR \-q ", " \-\-quiet
Suppress all non-error output. Only error messages will be displayed.
.TP
.BR \-\-help
Display help message and exit.
.TP
.BR \-\-version
Display version information and exit.

.SH EXIT STATUS
The program exits with one of the following status codes:
.TP
.B 0
Success - profile retrieved successfully
.TP
.B 1
General error - unexpected failure
.TP
.B 2
Invalid arguments - check command line parameters
.TP
.B 3
File I/O error - cannot write to output file
.TP
.B 4
Connection error - cannot connect to DSP API server
.TP
.B 5
API error - server error or no profile found

.SH EXAMPLES
.TP
.B dsp-get-profile current-profile.xml
Retrieve the current profile and save it to 'current-profile.xml'.
.TP
.B dsp-get-profile -h 192.168.1.100 backup.xml
Retrieve profile from a remote DSP at IP 192.168.1.100 and save to 'backup.xml'.
.TP
.B dsp-get-profile
Retrieve the current profile and display it on stdout.
.TP
.B dsp-get-profile -q profile-backup.xml
Quietly retrieve the profile and save to 'profile-backup.xml' with minimal output.
.TP
.B dsp-get-profile -v | grep metadata
Retrieve profile with verbose output and filter for metadata lines.

.SH DEPENDENCIES
This tool requires:
.TP
.B curl
Used for HTTP communication with the REST API server
.TP
.B sigmatcpserver
The HiFiBerry DSP REST API server must be running and accessible

.SH FILES
The tool retrieves profiles from the DSP via the REST API. The profile data
is typically stored at:
.TP
.I /var/lib/hifiberry/dspprogram.xml
Default location for the active DSP profile (server-side)

.SH TROUBLESHOOTING
.TP
.B Connection refused
Ensure sigmatcpserver is running:
.br
sudo systemctl status sigmatcpserver
.TP
.B No profile found (exit code 5)
The DSP may not have a profile loaded, or the profile file may be missing.
Check the server logs:
.br
journalctl -u sigmatcpserver
.TP
.B Permission denied writing file
Ensure you have write permissions to the output directory.

.SH SEE ALSO
.BR dsp-install-profile (1),
.BR dsp-program-info (1),
.BR sigmatcpserver (1)

.SH AUTHOR
Written by the HiFiBerry team.

.SH REPORTING BUGS
Report bugs to the HiFiBerry support team or GitHub issues.

.SH COPYRIGHT
This is free software; see the source for copying conditions.

================================================
FILE: man/man1/dsp-install-profile.1
================================================
.TH DSP-INSTALL-PROFILE 1 "30 September 2025" "HiFiBerry DSP toolkit 1.3.2" "User Commands"
.SH NAME
dsp-install-profile \- install DSP profile using REST API
.SH SYNOPSIS
.B dsp-install-profile
[\fIOPTIONS\fR] \fIPROFILE_FILE\fR
.SH DESCRIPTION
.B dsp-install-profile
installs a DSP profile XML file to a HiFiBerry DSP using the REST API.
This tool provides a simple command-line interface to upload and activate
DSP profiles without requiring direct access to SigmaStudio or complex
API calls.

The tool connects to the DSP's REST API server (sigmatcpserver), uploads
the specified XML profile file, and verifies the installation. The profile
is written to the DSP's EEPROM and becomes active immediately.

.SH ARGUMENTS
.TP
.BR PROFILE_FILE
Path to the XML profile file to install. The file must be a valid
SigmaStudio-exported XML profile compatible with the target DSP hardware.

.SH OPTIONS
.TP
.BR \-h ", " \-\-host " " \fIHOST\fR
DSP server hostname or IP address (default: localhost)
.TP
.BR \-p ", " \-\-port " " \fIPORT\fR
DSP server port (default: 13141)
.TP
.BR \-t ", " \-\-timeout " " \fISECONDS\fR
Connection timeout in seconds (default: 30)
.TP
.BR \-v ", " \-\-verbose
Enable verbose output for debugging and detailed progress information
.TP
.BR \-q ", " \-\-quiet
Suppress non-error output messages
.TP
.BR \-\-help
Show help message and exit
.TP
.BR \-\-version
Show version information and exit

.SH EXAMPLES
.TP
Install profile to local DSP:
.B dsp-install-profile /path/to/profile.xml

.TP
Install profile to remote DSP:
.B dsp-install-profile -h 192.168.1.100 /path/to/profile.xml

.TP
Install with custom port and verbose output:
.B dsp-install-profile -h dsp.local -p 8080 -v /path/to/profile.xml

.TP
Quiet installation with timeout:
.B dsp-install-profile -q -t 60 /usr/share/profiles/my-profile.xml

.SH EXIT STATUS
.TP
.B 0
Success
.TP
.B 1
General error
.TP
.B 2
Invalid arguments or command-line options
.TP
.B 3
Profile file not found or not readable
.TP
.B 4
Connection error - cannot reach DSP API server
.TP
.B 5
API error - server rejected the profile or returned an error

.SH FILES
.TP
.B /usr/share/hifiberry/dspprofiles/
Default location for DSP profile XML files
.TP
.B /etc/sigmatcp.conf
SigmaTCP server configuration file

.SH ENVIRONMENT
.TP
.B HTTP_PROXY, HTTPS_PROXY
Proxy settings for curl (if needed for network access)

.SH DEPENDENCIES
.TP
.B curl
Required for making HTTP requests to the DSP API server

.SH NOTES
.PP
This tool requires the sigmatcpserver to be running on the target DSP
system with the REST API enabled. The default configuration listens on
localhost:13141.

.PP
The XML profile file should be exported from SigmaStudio and be compatible
with the target DSP hardware (typically ADAU145x series).

.PP
Profile installation writes to the DSP's EEPROM, making the change
persistent across reboots. The new profile becomes active immediately
upon successful installation.

.PP
For security reasons, ensure that the DSP API server is properly
configured and access-controlled in production environments.

.SH SEE ALSO
.BR dsptoolkit (1),
.BR sigmatcpserver (1),
.BR curl (1)

.PP
HiFiBerry DSP documentation:
.I https://www.hifiberry.com/docs/

.PP
REST API documentation:
.I /usr/share/doc/hifiberry-dsp/restapi.md

.SH BUGS
Report bugs to: https://github.com/hifiberry/hifiberry-dsp/issues

.SH AUTHOR
HiFiBerry team <info@hifiberry.com>

.SH COPYRIGHT
Copyright \(co 2025 HiFiBerry. This is free software; see the source
for copying conditions. There is NO warranty; not even for MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.

================================================
FILE: man/man1/dsp-program-info.1
================================================
.TH DSP-PROGRAM-INFO 1 "30 September 2025" "HiFiBerry DSP toolkit 1.3.2" "User Commands"
.SH NAME
dsp-program-info \- get DSP program information using REST API
.SH SYNOPSIS
.B dsp-program-info
[\fIOPTIONS\fR]
.SH DESCRIPTION
.B dsp-program-info
retrieves comprehensive information about the currently loaded DSP program
from a HiFiBerry DSP using the REST API. This tool provides details including
program length and checksums, which are useful for verification and debugging.

The tool connects to the DSP's REST API server (sigmatcpserver) and queries
the /program-info endpoint to obtain current program information.

.SH OPTIONS
.TP
.BR \-h ", " \-\-host " " \fIHOST\fR
DSP server hostname or IP address (default: localhost)
.TP
.BR \-p ", " \-\-port " " \fIPORT\fR
DSP server port (default: 13141)
.TP
.BR \-t ", " \-\-timeout " " \fISECONDS\fR
Connection timeout in seconds (default: 30)
.TP
.BR \-f ", " \-\-format " " \fIFORMAT\fR
Output format: json, text, or brief (default: text)
.TP
.BR \-v ", " \-\-verbose
Enable verbose output for debugging and detailed progress information
.TP
.BR \-q ", " \-\-quiet
Suppress non-error output messages (only show program info)
.TP
.BR \-\-help
Show help message and exit
.TP
.BR \-\-version
Show version information and exit

.SH OUTPUT FORMATS
.TP
.B json
Raw JSON response from the API, suitable for parsing by other tools
.TP
.B text
Human-readable formatted output with labeled fields
.TP
.B brief
Compact single-line output showing program length and SHA-1 checksum

.SH EXAMPLES
.TP
Get program info from local DSP:
.B dsp-program-info

.TP
Get program info from remote DSP in JSON format:
.B dsp-program-info -h 192.168.1.100 -f json

.TP
Get brief info quietly (suitable for scripts):
.B dsp-program-info -q -f brief

.TP
Get program info with verbose output:
.B dsp-program-info -v

.TP
Monitor program length in a script:
.B LENGTH=$(dsp-program-info -q -f brief | cut -d' ' -f1)

.SH EXIT STATUS
.TP
.B 0
Success
.TP
.B 1
General error
.TP
.B 2
Invalid arguments or command-line options
.TP
.B 4
Connection error - cannot reach DSP API server
.TP
.B 5
API error - server returned an error

.SH OUTPUT FIELDS
The program information includes the following fields:

.TP
.B Program Length
The size of the currently loaded DSP program in words (32-bit). Also 
displayed in human-readable format (KB/MB).

.TP
.B MD5 Checksum
MD5 checksum of the DSP program calculated using signature-based detection.
Used for compatibility with legacy systems.

.TP
.B SHA-1 Checksum
SHA-1 checksum of the DSP program calculated using length-based detection.
Preferred for modern applications due to better performance.

.SH FILES
.TP
.B /etc/sigmatcp.conf
SigmaTCP server configuration file

.SH ENVIRONMENT
.TP
.B HTTP_PROXY, HTTPS_PROXY
Proxy settings for curl (if needed for network access)

.SH DEPENDENCIES
.TP
.B curl
Required for making HTTP requests to the DSP API server

.SH NOTES
.PP
This tool requires the sigmatcpserver to be running on the target DSP
system with the REST API enabled. The default configuration listens on
localhost:13141.

.PP
The checksums are calculated from the currently loaded DSP program in
memory, not from any stored profile files.

.PP
Program length is reported in DSP words (32-bit units). To convert to
bytes, multiply by 4.

.PP
Different checksum algorithms may return different values for the same
program due to their calculation methods (signature-based vs length-based).

.SH SEE ALSO
.BR dsp-install-profile (1),
.BR dsptoolkit (1),
.BR sigmatcpserver (1),
.BR curl (1)

.PP
HiFiBerry DSP documentation:
.I https://www.hifiberry.com/docs/

.PP
REST API documentation:
.I /usr/share/doc/hifiberry-dsp/restapi.md

.SH BUGS
Report bugs to: https://github.com/hifiberry/hifiberry-dsp/issues

.SH AUTHOR
HiFiBerry team <info@hifiberry.com>

.SH COPYRIGHT
Copyright \(co 2025 HiFiBerry. This is free software; see the source
for copying conditions. There is NO warranty; not even for MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.

================================================
FILE: repair_filter_store.py
================================================
#!/usr/bin/env python3
"""
Filter Store Repair Utility

This utility repairs corrupted filter store JSON files by:
1. Detecting and fixing extra braces
2. Normalizing checksum keys to uppercase
3. Merging duplicate entries with different case
4. Validating JSON structure
"""

import os
import json
import time
import sys
import logging
import re

logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')

def fix_json_corruption(content):
    """Fix common JSON corruption issues"""
    # Count opening and closing braces
    open_braces = content.count('{')
    close_braces = content.count('}')
    
    if close_braces > open_braces:
        # Remove extra closing braces from the end
        extra_braces = close_braces - open_braces
        logging.info(f"Detected {extra_braces} extra closing braces, fixing...")
        
        # Remove trailing braces and whitespace
        content = content.rstrip()
        for _ in range(extra_braces):
            if content.endswith('}'):
                content = content[:-1].rstrip()
    
    # Remove trailing commas before closing braces/brackets
    content = re.sub(r',\s*}', '}', content)
    content = re.sub(r',\s*]', ']', content)
    
    return content

def normalize_checksums(data):
    """Normalize checksum keys to uppercase and merge duplicates"""
    normalized_data = {}
    
    for checksum, filters in data.items():
        normalized_checksum = checksum.upper()
        
        if normalized_checksum in normalized_data:
            # Merge duplicate checksums
            logging.info(f"Merging duplicate checksum: {checksum} -> {normalized_checksum}")
            for filter_key, filter_data in filters.items():
                if filter_key not in normalized_data[normalized_checksum]:
                    normalized_data[normalized_checksum][filter_key] = filter_data
                else:
                    # Keep the newer one based on timestamp
                    existing_timestamp = normalized_data[normalized_checksum][filter_key].get("timestamp", 0)
                    new_timestamp = filter_data.get("timestamp", 0)
                    if new_timestamp > existing_timestamp:
                        logging.info(f"Keeping newer version of filter {filter_key}")
                        normalized_data[normalized_checksum][filter_key] = filter_data
                    else:
                        logging.info(f"Keeping existing version of filter {filter_key}")
        else:
            normalized_data[normalized_checksum] = filters
    
    return normalized_data

def repair_filter_store(file_path):
    """Repair a corrupted filter store file"""
    if not os.path.exists(file_path):
        logging.error(f"File does not exist: {file_path}")
        return False
    
    # Create backup
    backup_file = f"{file_path}.backup.{int(time.time())}"
    try:
        with open(file_path, 'r') as src, open(backup_file, 'w') as dst:
            dst.write(src.read())
        logging.info(f"Created backup: {backup_file}")
    except Exception as e:
        logging.error(f"Failed to create backup: {e}")
        return False
    
    # Read and attempt to repair the file
    try:
        with open(file_path, 'r') as f:
            content = f.read().strip()
        
        if not content:
            logging.warning("File is empty")
            return True
        
        logging.info(f"Original file size: {len(content)} characters")
        
        # Fix JSON corruption
        fixed_content = fix_json_corruption(content)
        
        if fixed_content != content:
            logging.info("Applied JSON corruption fixes")
        
        # Try to parse the JSON
        try:
            data = json.loads(fixed_content)
        except json.JSONDecodeError as e:
            logging.error(f"JSON is still invalid after basic repairs: {e}")
            return False
        
        # Normalize checksums
        normalized_data = normalize_checksums(data)
        
        changes_made = (normalized_data != data) or (fixed_content != content)
        
        if changes_made:
            # Write the repaired data
            with open(file_path, 'w') as f:
                json.dump(normalized_data, f, indent=2, ensure_ascii=False)
            
            logging.info(f"Repaired filter store saved to: {file_path}")
            
            # Validate the repaired file
            try:
                with open(file_path, 'r') as f:
                    json.load(f)
                logging.info("Repair validation successful - JSON is now valid")
            except json.JSONDecodeError as e:
                logging.error(f"Repair validation failed: {e}")
                return False
        else:
            logging.info("No repairs needed - file is already valid")
        
        # Show summary
        profile_count = len(normalized_data)
        total_filters = sum(len(filters) for filters in normalized_data.values())
        logging.info(f"Summary: {profile_count} profiles, {total_filters} total filters")
        
        return True
        
    except Exception as e:
        logging.error(f"Error during repair: {e}")
        return False

def main():
    if len(sys.argv) != 2:
        print("Usage: python3 repair_filter_store.py <path_to_filters.json>")
        print("Example: python3 repair_filter_store.py /var/lib/hifiberry/filters.json")
        sys.exit(1)
    
    file_path = sys.argv[1]
    
    logging.info(f"Repairing filter store: {file_path}")
    
    if repair_filter_store(file_path):
        logging.info("Repair completed successfully")
        sys.exit(0)
    else:
        logging.error("Repair failed")
        sys.exit(1)

if __name__ == "__main__":
    main()


================================================
FILE: sample_files/rew-filter-coefficients.txt
================================================
biquad1,
b0=0.9971434794400773,
b1=-1.992564782301403,
b2=0.9954708988160471,
a1=1.992564782301403,
a2=-0.9926143782561245,
biquad2,
b0=0.9971980210178277,
b1=-1.9916729886811797,
b2=0.9945622031593789,
a1=1.9916729886811797,
a2=-0.9917602241772067,
biquad3,
b0=0.9908924296651285,
b1=-1.969660992321457,
b2=0.9803188377230254,
a1=1.969660992321457,
a2=-0.971211267388154,
biquad4,
b0=0.9966391858982099,
b1=-1.9881477678870783,
b2=0.9917378025802783,
a1=1.9881477678870783,
a2=-0.9883769884784883,
biquad5,
b0=0.9243747547954926,
b1=-0.833994305740652,
b2=0.4491279741771851,
a1=0.833994305740652,
a2=-0.3735027289726776,
biquad6,
b0=0.979734465405361,
b1=-1.7683824029708475,
b2=0.8231987707880306,
a1=1.7683824029708475,
a2=-0.8029332361933915,
biquad7,
b0=0.9933592054320635,
b1=-1.9456358617387361,
b2=0.9598510084092484,
a1=1.9456358617387361,
a2=-0.9532102138413121,
biquad8,
b0=0.9928376977020587,
b1=-1.9148753029143437,
b2=0.9606793554599762,
a1=1.9148753029143437,
a2=-0.9535170531620349,
biquad9,
b0=1.0101644452619554,
b1=-1.8548273235488608,
b2=0.9385476808276387,
a1=1.8548273235488608,
a2=-0.9487121260895943,
biquad10,
b0=1.0006552096621963,
b1=-1.9976444130187114,
b2=0.9975194608837485,
a1=1.9976444130187114,
a2=-0.9981746705459446,
biquad11,
b0=1.0,
b1=0.0,
b2=0.0,
a1=0.0,
a2=0.0,
biquad12,
b0=1.0,
b1=0.0,
b2=0.0,
a1=0.0,
a2=0.0,
biquad13,
b0=1.0,
b1=0.0,
b2=0.0,
a1=0.0,
a2=0.0,
biquad14,
b0=1.0,
b1=0.0,
b2=0.0,
a1=0.0,
a2=0.0,
biquad15,
b0=1.0,
b1=0.0,
b2=0.0,
a1=0.0,
a2=0.0,
biquad16,
b0=1.0,
b1=0.0,
b2=0.0,
a1=0.0,
a2=0.0,
biquad17,
b0=1.0,
b1=0.0,
b2=0.0,
a1=0.0,
a2=0.0,
biquad18,
b0=1.0,
b1=0.0,
b2=0.0,
a1=0.0,
a2=0.0,
biquad19,
b0=1.0,
b1=0.0,
b2=0.0,
a1=0.0,
a2=0.0,
biquad20,
b0=1.0,
b1=0.0,
b2=0.0,
a1=0.0,
a2=0.0


================================================
FILE: sample_files/rew-filter-settings.txt
================================================
Filter Settings file

Room EQ V5.18
Dated: Jun 24, 2018 10:44:32 PM

Notes:

Equaliser: Generic
Jun 24 21:41:10
Filter  1: ON  PK       Fc    56.0 Hz  Gain -14.7 dB  Q  2.00
Filter  2: ON  PK       Fc    77.3 Hz  Gain  -7.5 dB  Q  2.00
Filter  3: ON  PK       Fc     303 Hz  Gain  -8.0 dB  Q  2.54
Filter  4: ON  PK       Fc     122 Hz  Gain  -6.0 dB  Q  2.00
Filter  5: ON  PK       Fc    7453 Hz  Gain  -1.8 dB  Q  1.00
Filter  6: ON  PK       Fc    1525 Hz  Gain  -4.2 dB  Q  3.08
Filter  7: ON  PK       Fc     675 Hz  Gain  -2.5 dB  Q  2.47
Filter  8: ON  PK       Fc    2411 Hz  Gain   2.8 dB  Q  3.36
Filter  9: ON  PK       Fc     175 Hz  Gain   5.2 dB  Q  7.53
Filter 10: ON  None   
Filter 11: ON  None   
Filter 12: ON  None   
Filter 13: ON  None   
Filter 14: ON  None   
Filter 15: ON  None   
Filter 16: ON  None   
Filter 17: ON  None   
Filter 18: ON  None   
Filter 19: ON  None   
Filter 20: ON  None   



================================================
FILE: sample_files/roomeq-daniel.txt
================================================
Filter Settings file

Room EQ V5.18
Dated: Jun 24, 2018 9:48:25 PM

Notes:RoomEq Daniel

Equaliser: Generic
Jun 24 21:41:10
Filter  1: ON  PK       Fc    58.1 Hz  Gain -14.6 dB  Q  2.00
Filter  2: ON  PK       Fc     140 Hz  Gain  -6.9 dB  Q  2.00
Filter  3: ON  PK       Fc    6484 Hz  Gain  -3.0 dB  Q  1.00
Filter  4: ON  PK       Fc    85.7 Hz  Gain  -5.6 dB  Q  2.00
Filter  5: ON  PK       Fc     164 Hz  Gain   6.4 dB  Q  2.35
Filter  6: ON  PK       Fc    9526 Hz  Gain  -3.2 dB  Q  1.36
Filter  7: ON  PK       Fc     302 Hz  Gain  -6.5 dB  Q  3.26
Filter  8: ON  PK       Fc    1524 Hz  Gain  -3.2 dB  Q  4.96
Filter  9: ON  None   
Filter 10: ON  None   
Filter 11: ON  None   
Filter 12: ON  None   
Filter 13: ON  None   
Filter 14: ON  None   
Filter 15: ON  None   
Filter 16: ON  None   
Filter 17: ON  None   
Filter 18: ON  None   
Filter 19: ON  None   
Filter 20: ON  None   



================================================
FILE: sample_files/settings/2-way.txt
================================================
# Sample settings for a sub/sat setup with the subwoofer connected to outputs 1 and 2 and
# the satellites connected to 3 and 4
# Tune crossover freqency and volume to your setup
IIR_L1: lp:2500Hz
IIR_L2: mute
IIR_L3: hp:2500Hz
IIR_L4: mute
IIR_R1: mute
IIR_R2: lp:2500Hz
IIR_R3: mute
IIR_R4: hp:2500Hz




================================================
FILE: sample_files/settings/4-way.txt
================================================
# Sample settings for a sub/sat setup with the subwoofer connected to outputs 1 and 2 and
# the satellites connected to 3 and 4
# Tune crossover freqency and volume to your setup
IIR_L1: lp:200Hz
IIR_L2: hp:200Hz,lp:1000Hz
IIR_L3: hp:1000Hz,lp:4000Hz
IIR_L4: hp:4000Hz
IIR_R1: mute
IIR_R2: mute
IIR_R3: mute
IIR_R4: mute




================================================
FILE: sample_files/settings/beocreate-default.txt
================================================
# Sample settings for a sub/sat setup with the subwoofer connected to outputs 1 and 2 and
# the satellites connected to 3 and 4
# Tune crossover freqency and volume to your setup
IIR_L1: pass
IIR_L2: mute
IIR_L3: pass
IIR_L4: mute
IIR_R1: mute
IIR_R2: pass
IIR_R3: mute
IIR_R4: pass
volumeLimitRegister: 0.005




================================================
FILE: sample_files/settings/filters.txt
================================================
# Simple example file showing how to define filter coefficients with a settings file
IIR_L1: lp:200Hz
IIR_L2: hp:200Hz,lp:1000Hz
IIR_L3: hp:1000Hz,lp:4000Hz
IIR_L4: hp:4000Hz
IIR_R1: coeff:1:2:3:4:5
IIR_R2: coeff:0.1:0.2:0.3:0.4:0.5:0.6
IIR_R3: mute
IIR_R4: mute




================================================
FILE: sample_files/settings/full-volume.txt
================================================
volumeControlRegister: 1.0
volumeLimitRegister: 0.5



================================================
FILE: sample_files/settings/fullrange.txt
================================================
# Sample settings for a sub/sat setup with the subwoofer connected to outputs 1 and 2 and
# the satellites connected to 3 and 4
# Tune crossover freqency and volume to your setup
IIR_L1: pass
IIR_L2: mute
IIR_L3: pass
IIR_L4: mute
IIR_R1: mute
IIR_R2: pass
IIR_R3: mute
IIR_R4: mute




================================================
FILE: sample_files/settings/invert-mute.txt
================================================
invertMute: 0x01


================================================
FILE: sample_files/settings/multiple.txt
================================================
volumeControlRegister: -3dB
volumeLimitRegister: 50%
mute: 0x1
balanceRegister: 0.8
IIR_L: lp:1500Hz, hp:300Hz:0.6, eq: 1200Hz:2:+3dB, vol:-1dB
IIR_R1: vol: +3dB
IIR_R2: vol: -3dB
IIR_R3: vol: +0dB


================================================
FILE: sample_files/settings/no_automute.txt
================================================
automute: 0


================================================
FILE: sample_files/settings/no_spdif.txt
================================================
enableSPDIFRegister: 0


================================================
FILE: sample_files/settings/subsat.txt
================================================
# Sample settings for a sub/sat setup with the subwoofer connected to outputs 1 and 2 and
# the satellites connected to 3 and 4
# Tune crossover freqency and volume to your setup
IIR_L1: lp:100Hz,vol:+1db
IIR_L2: mute
IIR_L3: hp:100Hz
IIR_L4: mute
IIR_R1: mute
IIR_R2: lp:100Hz,vol:+1db
IIR_R3: mute
IIR_R4: hp:100Hz




================================================
FILE: sample_files/settings/volume-limit.txt
================================================
volumeLimitRegister: -24db


================================================
FILE: sample_files/xml/4way-default.params
================================================
Cell Name         = SPDIF output.SpdifSource
Parameter Name    = stereomuxSigma300ns2index
Parameter Address = 549
Parameter Value   = 0
Parameter Data :
0x00, 0x00, 0x00, 0x00, 



Cell Name         = Balance.BalanceValue
Parameter Name    = DCInpAlg145X1value
Parameter Address = 526
Parameter Value   = 1
Parameter Data :
0x01, 0x00, 0x00, 0x00, 



Cell Name         = Balance.DC2
Parameter Name    = DCInpAlg145X2value
Parameter Address = 527
Parameter Value   = 2
Parameter Data :
0x02, 0x00, 0x00, 0x00, 



Cell Name         = Mute.Mute
Parameter Name    = SwitchAlg321ison
Parameter Address = 528
Parameter Value   = 0
Parameter Data :
0x00, 0x00, 0x00, 0x00, 



Cell Name         = Mute.PeakEnv1
Parameter Name    = MonoEnvelopePeakAlgS3001hold
Parameter Address = 534
Parameter Value   = 24000
Parameter Data :
0x00 ,	0x00 ,	0x5D ,	0xC0 ,	



Cell Name         = Mute.PeakEnv1
Parameter Name    = MonoEnvelopePeakAlgS3001decay
Parameter Address = 535
Parameter Value   = 2.16960906982422E-05
Parameter Data :
0x00 ,	0x00 ,	0x01 ,	0x6C ,	



Cell Name         = Mute.PeakEnv1_2
Parameter Name    = MonoEnvelopePeakAlgS3002hold
Parameter Address = 538
Parameter Value   = 24000
Parameter Data :
0x00 ,	0x00 ,	0x5D ,	0xC0 ,	



Cell Name         = Mute.PeakEnv1_2
Parameter Name    = MonoEnvelopePeakAlgS3002decay
Parameter Address = 539
Parameter Value   = 2.16960906982422E-05
Parameter Data :
0x00 ,	0x00 ,	0x01 ,	0x6C ,	



Cell Name         = Mute.MuteLimit
Parameter Name    = DCInpAlg145X3value
Parameter Address = 529
Parameter Value   = 0.0009765625
Parameter Data :
0x00, 0x00, 0x40, 0x00, 



Cell Name         = Mute.False
Parameter Name    = DCInpAlg145X4value
Parameter Address = 530
Parameter Value   = 0
Parameter Data :
0x00, 0x00, 0x00, 0x00, 



Cell Name         = Mute.True
Parameter Name    = DCInpAlg145X5value
Parameter Address = 531
Parameter Value   = 17.066666662693
Parameter Data :
0x11, 0x11, 0x11, 0x11, 



Cell Name         = Mute.DCB1
Parameter Name    = DCBlockAlgDblPrecS3001pole
Parameter Address = 23
Parameter Value   = 0.999899983406067
Parameter Data :
0x00, 0xFF, 0xF9, 0x72, 



Cell Name         = Mute.DCB1_2
Parameter Name    = DCBlockAlgDblPrecS3002pole
Parameter Address = 26
Parameter Value   = 0.999899983406067
Parameter Data :
0x00, 0xFF, 0xF9, 0x72, 



Cell Name         = Mute.DC1
Parameter Name    = DCInpAlg145X6value
Parameter Address = 532
Parameter Value   = 0.000244081020355225
Parameter Data :
0x00, 0x00, 0x0F, 0xFF, 



Cell Name         = Mute.ZeroComp1
Parameter Name    = ZeroCompareAlgSigma3001output
Parameter Address = 28
Parameter Value   = 1
Parameter Data :
0x00, 0x00, 0x00, 0x01, 



Cell Name         = Mute.ZeroComp2
Parameter Name    = ZeroCompareAlgSigma3002output
Parameter Address = 27
Parameter Value   = 1
Parameter Data :
0x00, 0x00, 0x00, 0x01, 



Cell Name         = Mute.RegRead1
Parameter Name    = RegisterReadAlg1address0
Parameter Address = 533
Parameter Value   = 62848
Parameter Data :
0x00, 0x00, 0xF5, 0x80, 



Cell Name         = Mute.ZeroComp2_2
Parameter Name    = ZeroCompareAlgSigma3003output
Parameter Address = 20
Parameter Value   = 1
Parameter Data :
0x00, 0x00, 0x00, 0x01, 



Cell Name         = Mute.ZeroComp2_3
Parameter Name    = ZeroCompareAlgSigma3004output
Parameter Address = 37
Parameter Value   = 1
Parameter Data :
0x00, 0x00, 0x00, 0x01, 



Cell Name         = Mute.InvertMute
Parameter Name    = monomuxSigma300ns1index
Parameter Address = 548
Parameter Value   = 0
Parameter Data :
0x00, 0x00, 0x00, 0x00, 



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B2_1
Parameter Address = 38
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B1_1
Parameter Address = 39
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B0_1
Parameter Address = 40
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A2_1
Parameter Address = 41
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A1_1
Parameter Address = 42
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B2_2
Parameter Address = 43
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B1_2
Parameter Address = 44
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B0_2
Parameter Address = 45
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A2_2
Parameter Address = 46
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A1_2
Parameter Address = 47
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B2_3
Parameter Address = 48
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B1_3
Parameter Address = 49
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B0_3
Parameter Address = 50
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A2_3
Parameter Address = 51
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A1_3
Parameter Address = 52
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B2_4
Parameter Address = 53
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B1_4
Parameter Address = 54
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B0_4
Parameter Address = 55
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A2_4
Parameter Address = 56
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A1_4
Parameter Address = 57
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B2_5
Parameter Address = 58
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B1_5
Parameter Address = 59
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B0_5
Parameter Address = 60
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A2_5
Parameter Address = 61
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A1_5
Parameter Address = 62
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B2_6
Parameter Address = 63
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B1_6
Parameter Address = 64
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B0_6
Parameter Address = 65
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A2_6
Parameter Address = 66
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A1_6
Parameter Address = 67
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B2_7
Parameter Address = 68
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B1_7
Parameter Address = 69
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B0_7
Parameter Address = 70
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A2_7
Parameter Address = 71
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A1_7
Parameter Address = 72
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B2_8
Parameter Address = 73
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B1_8
Parameter Address = 74
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B0_8
Parameter Address = 75
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A2_8
Parameter Address = 76
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A1_8
Parameter Address = 77
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B2_9
Parameter Address = 78
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B1_9
Parameter Address = 79
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B0_9
Parameter Address = 80
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A2_9
Parameter Address = 81
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A1_9
Parameter Address = 82
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B2_10
Parameter Address = 83
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B1_10
Parameter Address = 84
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B0_10
Parameter Address = 85
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A2_10
Parameter Address = 86
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A1_10
Parameter Address = 87
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B2_11
Parameter Address = 88
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B1_11
Parameter Address = 89
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B0_11
Parameter Address = 90
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A2_11
Parameter Address = 91
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A1_11
Parameter Address = 92
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B2_12
Parameter Address = 93
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B1_12
Parameter Address = 94
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B0_12
Parameter Address = 95
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A2_12
Parameter Address = 96
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A1_12
Parameter Address = 97
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B2_13
Parameter Address = 98
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B1_13
Parameter Address = 99
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B0_13
Parameter Address = 100
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A2_13
Parameter Address = 101
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A1_13
Parameter Address = 102
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B2_14
Parameter Address = 103
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B1_14
Parameter Address = 104
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B0_14
Parameter Address = 105
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A2_14
Parameter Address = 106
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A1_14
Parameter Address = 107
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B2_15
Parameter Address = 108
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B1_15
Parameter Address = 109
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B0_15
Parameter Address = 110
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A2_15
Parameter Address = 111
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A1_15
Parameter Address = 112
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B2_16
Parameter Address = 113
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B1_16
Parameter Address = 114
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1B0_16
Parameter Address = 115
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A2_16
Parameter Address = 116
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_L
Parameter Name    = EQS300MultiS1A1_16
Parameter Address = 117
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B2_1
Parameter Address = 118
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B1_1
Parameter Address = 119
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B0_1
Parameter Address = 120
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2A2_1
Parameter Address = 121
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2A1_1
Parameter Address = 122
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B2_2
Parameter Address = 123
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B1_2
Parameter Address = 124
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B0_2
Parameter Address = 125
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2A2_2
Parameter Address = 126
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2A1_2
Parameter Address = 127
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B2_3
Parameter Address = 128
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B1_3
Parameter Address = 129
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B0_3
Parameter Address = 130
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2A2_3
Parameter Address = 131
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2A1_3
Parameter Address = 132
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B2_4
Parameter Address = 133
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B1_4
Parameter Address = 134
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B0_4
Parameter Address = 135
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2A2_4
Parameter Address = 136
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2A1_4
Parameter Address = 137
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B2_5
Parameter Address = 138
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B1_5
Parameter Address = 139
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B0_5
Parameter Address = 140
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2A2_5
Parameter Address = 141
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2A1_5
Parameter Address = 142
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B2_6
Parameter Address = 143
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B1_6
Parameter Address = 144
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B0_6
Parameter Address = 145
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2A2_6
Parameter Address = 146
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2A1_6
Parameter Address = 147
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B2_7
Parameter Address = 148
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B1_7
Parameter Address = 149
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B0_7
Parameter Address = 150
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2A2_7
Parameter Address = 151
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2A1_7
Parameter Address = 152
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B2_8
Parameter Address = 153
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B1_8
Parameter Address = 154
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B0_8
Parameter Address = 155
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2A2_8
Parameter Address = 156
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2A1_8
Parameter Address = 157
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B2_9
Parameter Address = 158
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B1_9
Parameter Address = 159
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B0_9
Parameter Address = 160
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2A2_9
Parameter Address = 161
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2A1_9
Parameter Address = 162
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B2_10
Parameter Address = 163
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B1_10
Parameter Address = 164
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B0_10
Parameter Address = 165
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2A2_10
Parameter Address = 166
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2A1_10
Parameter Address = 167
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B2_11
Parameter Address = 168
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B1_11
Parameter Address = 169
Parameter Value   = 0
Parameter Data :
0x00 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2B0_11
Parameter Address = 170
Parameter Value   = 1
Parameter Data :
0x01 ,	0x00 ,	0x00 ,	0x00 ,	



Cell Name         = Equalisation.IIR_R
Parameter Name    = EQS300MultiS2A2_11
Parameter Address = 17
Download .txt
gitextract_7qv9da6w/

├── .ai-config.json
├── .ai-guidelines
├── .gitattributes
├── .gitignore
├── .settings/
│   └── .gitignore
├── LICENSE
├── README.md
├── build.sh
├── contrib/
│   ├── Readme.md
│   ├── hifiberry_config.toml
│   ├── install_hbdsp.sh
│   └── set-loudness
├── create-profiles.sh
├── debian/
│   ├── changelog
│   ├── control
│   ├── copyright
│   ├── dirs
│   ├── hifiberry-dsp.docs
│   ├── hifiberry-dsp.examples
│   ├── hifiberry-dsp.install
│   ├── hifiberry-dsp.manpages
│   ├── hifiberry-sigmatcp.nginx
│   ├── postrm
│   ├── rules
│   └── source/
│       └── format
├── doc/
│   ├── adaptexistingprofiles.md
│   ├── asrc.md
│   ├── checksum.md
│   ├── crossovers.md
│   ├── debug.md
│   ├── dspprofiles.md
│   ├── dspreset.md
│   ├── dspsettings.md
│   ├── dsptoolkit.md
│   ├── restapi.md
│   ├── reverse-engineering-lg.md
│   ├── rew-basics.md
│   ├── settingsfiles.md
│   └── sigmatcpserver.md
├── man/
│   └── man1/
│       ├── dsp-get-profile.1
│       ├── dsp-install-profile.1
│       └── dsp-program-info.1
├── repair_filter_store.py
├── sample_files/
│   ├── dspproj/
│   │   ├── 4way-iir-delay-inputswitcher.dspproj
│   │   ├── 4way-iir-delay-mixer-asrccontrol.dspproj
│   │   ├── 4way-iir-delay-mixer.dspproj
│   │   ├── 4way-iir-delay.dspproj
│   │   ├── 4way-iir.dspproj
│   │   ├── 4way-mixed.dspproj
│   │   ├── dacdsp-v11.dspproj
│   │   ├── dacdsp-v12-1.dspproj
│   │   ├── dacdsp-v12-1_lg_soundsync.dspproj
│   │   ├── dsp-addon-v11.dspproj
│   │   ├── dsp192.dspproj
│   │   ├── fullrange-fir.dspproj
│   │   ├── fullrange-iir.dspproj
│   │   └── sine777.dspproj
│   ├── measurement/
│   │   └── sweep48khz.f32
│   ├── rew-filter-coefficients.txt
│   ├── rew-filter-settings.txt
│   ├── roomeq-daniel.txt
│   ├── settings/
│   │   ├── 2-way.txt
│   │   ├── 4-way.txt
│   │   ├── beocreate-default.txt
│   │   ├── filters.txt
│   │   ├── full-volume.txt
│   │   ├── fullrange.txt
│   │   ├── invert-mute.txt
│   │   ├── multiple.txt
│   │   ├── no_automute.txt
│   │   ├── no_spdif.txt
│   │   ├── subsat.txt
│   │   └── volume-limit.txt
│   └── xml/
│       ├── 4way-default.params
│       ├── 4way-default.xml
│       ├── 4way-iir-delay-mixer-asrccontrol.xml
│       ├── 4way-iir-delay-mixer.params
│       ├── 4way-iir-delay-mixer.xml
│       ├── 4way-iir-delay.params
│       ├── 4way-iir-delay.xml
│       ├── 4way-iir.params
│       ├── 4way-iir.xml
│       ├── 4way-inputswitcher.xml
│       ├── 4way-mixed.params
│       ├── 4way-mixed.xml
│       ├── beocreate-default.xml
│       ├── dacdsp-default.xml
│       ├── dacdsp-v12-1.xml
│       ├── dspdac-noautomute.xml
│       ├── fullrange-fir.xml
│       ├── fullrange-iir.xml
│       ├── fullrange-mixed.xml
│       ├── generic192.xml
│       ├── generic96.xml
│       └── sine777.xml
├── src/
│   ├── bin/
│   │   ├── dsp-get-profile
│   │   ├── dsp-install-profile
│   │   ├── dsp-program-info
│   │   ├── dspdac-reset
│   │   ├── dsptoolkit
│   │   ├── mergeparameters
│   │   ├── optimizer-client
│   │   ├── sigmatcpserver
│   │   └── spdifclockgen
│   ├── hifiberrydsp/
│   │   ├── __init__.py
│   │   ├── alsa/
│   │   │   ├── __init__.py
│   │   │   └── alsasync.py
│   │   ├── api/
│   │   │   ├── __init__.py
│   │   │   ├── filters.py
│   │   │   ├── restapi.py
│   │   │   └── settings_store.py
│   │   ├── client/
│   │   │   ├── __init__.py
│   │   │   └── sigmatcp.py
│   │   ├── conftest.py
│   │   ├── datatools.py
│   │   ├── dsptoolkit.py
│   │   ├── filtering/
│   │   │   ├── __init__.py
│   │   │   ├── biquad.py
│   │   │   ├── filtermath.py
│   │   │   ├── volume.py
│   │   │   └── volume_test.py
│   │   ├── genclocks.py
│   │   ├── hardware/
│   │   │   ├── __init__.py
│   │   │   ├── adau145x.py
│   │   │   ├── adau145x_test.py
│   │   │   └── spi.py
│   │   ├── lg/
│   │   │   ├── __init__.py
│   │   │   ├── soundsync.py
│   │   │   └── test_soundsync.py
│   │   ├── measurement/
│   │   │   ├── __init__.py
│   │   │   └── data.py
│   │   ├── parser/
│   │   │   ├── __init__.py
│   │   │   ├── biquad.py
│   │   │   ├── rew.py
│   │   │   ├── settings.py
│   │   │   ├── sigmaparams.py
│   │   │   └── xmlprofile.py
│   │   └── server/
│   │       ├── __init__.py
│   │       ├── constants.py
│   │       └── sigmatcp.py
│   └── setup.py
├── systemd/
│   └── sigmatcpserver.service
├── test-dsptoolkit.sh
├── test_autoload_filters.py
└── test_filter_store.py
Download .txt
SYMBOL INDEX (460 symbols across 29 files)

FILE: repair_filter_store.py
  function fix_json_corruption (line 21) | def fix_json_corruption(content):
  function normalize_checksums (line 44) | def normalize_checksums(data):
  function repair_filter_store (line 71) | def repair_filter_store(file_path):
  function main (line 145) | def main():

FILE: src/hifiberrydsp/alsa/alsasync.py
  class AlsaSync (line 62) | class AlsaSync(Thread):
    method __init__ (line 68) | def __init__(self):
    method set_volume_register (line 85) | def set_volume_register(self, volume_register):
    method set_alsa_control (line 93) | def set_alsa_control(self, alsa_control):
    method update_alsa (line 117) | def update_alsa(self, value, mixer=None):
    method update_dsp (line 132) | def update_dsp(self, value):
    method read_alsa_data (line 154) | def read_alsa_data(self):
    method read_dsp_data (line 174) | def read_dsp_data(self):
    method get_dsp_mixer (line 202) | def get_dsp_mixer(self, mixername):
    method check_sync (line 217) | def check_sync(self):
    method run (line 237) | def run(self):
    method finish (line 267) | def finish(self):
    method create_mixer (line 271) | def create_mixer(name):

FILE: src/hifiberrydsp/api/filters.py
  class Filter (line 7) | class Filter:
    method __init__ (line 8) | def __init__(self, **kwargs):
    method toJSON (line 12) | def toJSON(self):
    method normalize_biquad (line 16) | def normalize_biquad(b0, b1, b2, a0, a1, a2):
    method biquadCoefficients (line 39) | def biquadCoefficients(self, fs):
    method frequencyResponse (line 50) | def frequencyResponse(self, f, fs):
    method frequencyResponseDb (line 89) | def frequencyResponseDb(self, f, fs):
    method getFrequencyResponse (line 110) | def getFrequencyResponse(fs, filters, frequencies=None):
    method logspace_frequencies (line 141) | def logspace_frequencies(fmin, fmax, points_per_octave):
    method fromJSON (line 179) | def fromJSON(json_string):
  class PeakingEq (line 201) | class PeakingEq(Filter):
    method __init__ (line 202) | def __init__(self, f, db, q, **kwargs):
    method biquadCoefficients (line 209) | def biquadCoefficients(self, fs):
  class LowPass (line 215) | class LowPass(Filter):
    method __init__ (line 216) | def __init__(self, f, db, q, **kwargs):
    method biquadCoefficients (line 223) | def biquadCoefficients(self, fs):
  class HighPass (line 228) | class HighPass(Filter):
    method __init__ (line 229) | def __init__(self, f, db, q, **kwargs):
    method biquadCoefficients (line 236) | def biquadCoefficients(self, fs):
  class LowShelf (line 241) | class LowShelf(Filter):
    method __init__ (line 242) | def __init__(self, f, db, slope, gain, **kwargs):
    method biquadCoefficients (line 250) | def biquadCoefficients(self, fs):
  class HighShelf (line 256) | class HighShelf(Filter):
    method __init__ (line 257) | def __init__(self, f, db, slope, gain, **kwargs):
    method biquadCoefficients (line 265) | def biquadCoefficients(self, fs):
  class Volume (line 271) | class Volume(Filter):
    method __init__ (line 272) | def __init__(self, db, **kwargs):
    method biquadCoefficients (line 277) | def biquadCoefficients(self, fs):
  class GenericBiquad (line 282) | class GenericBiquad(Filter):
    method __init__ (line 283) | def __init__(self, a0=1.0, a1=0.0, a2=0.0, b0=1.0, b1=0.0, b2=0.0, fs=...
    method biquadCoefficients (line 294) | def biquadCoefficients(self, fs):
    method from_biquad (line 316) | def from_biquad(cls, biquad, fs=48000):
  class Bypass (line 334) | class Bypass(Filter):
    method __init__ (line 335) | def __init__(self, **kwargs):
    method biquadCoefficients (line 339) | def biquadCoefficients(self, fs):

FILE: src/hifiberrydsp/api/restapi.py
  function isBiquad (line 65) | def isBiquad(value):
  function get_xml_profile (line 94) | def get_xml_profile():
  function get_profile_metadata (line 201) | def get_profile_metadata():
  function invalidate_cache (line 254) | def invalidate_cache():
  function get_or_guess_samplerate (line 267) | def get_or_guess_samplerate():
  function get_current_profile_name (line 296) | def get_current_profile_name():
  function clear_checksum_cache (line 315) | def clear_checksum_cache():
  function is_checksum_cache_valid (line 326) | def is_checksum_cache_valid():
  function get_current_program_checksum (line 355) | def get_current_program_checksum():
  function get_current_program_checksum_sha1 (line 394) | def get_current_program_checksum_sha1():
  function get_version (line 434) | def get_version():
  function get_hardware_info (line 455) | def get_hardware_info():
  function list_dsp_profiles (line 483) | def list_dsp_profiles():
  function get_all_profiles_metadata (line 521) | def get_all_profiles_metadata():
  function get_metadata (line 589) | def get_metadata():
  function split_to_bytes (line 631) | def split_to_bytes(value, byte_count):
  function memory_access (line 645) | def memory_access():
  function memory_read (line 729) | def memory_read(address, length):
  function register_read (line 778) | def register_read(address, length):
  function register_write (line 816) | def register_write():
  function get_program_checksum (line 848) | def get_program_checksum():
  function get_program_info (line 905) | def get_program_info():
  function get_program_length (line 936) | def get_program_length():
  function get_program_memory (line 969) | def get_program_memory():
  function get_frequency_response (line 1029) | def get_frequency_response():
  function clear_cache (line 1088) | def clear_cache():
  function get_cache_status (line 1099) | def get_cache_status():
  function get_xml_profile_data (line 1151) | def get_xml_profile_data():
  function resolve_address_from_metadata (line 1306) | def resolve_address_from_metadata(key):
  function set_biquad_filter (line 1332) | def set_biquad_filter():
  function get_filters (line 1468) | def get_filters():
  function set_filters (line 1514) | def set_filters():
  function delete_filters (line 1580) | def delete_filters():
  function get_filter_bypass (line 1611) | def get_filter_bypass():
  function set_filter_bypass (line 1687) | def set_filter_bypass():
  function toggle_filter_bypass (line 1824) | def toggle_filter_bypass():
  function apply_filter_bypass_to_dsp (line 1955) | def apply_filter_bypass_to_dsp(checksum, address, offset, bypassed):
  function run_api (line 2076) | def run_api(host=DEFAULT_HOST, port=DEFAULT_PORT):

FILE: src/hifiberrydsp/api/settings_store.py
  class SettingsStore (line 30) | class SettingsStore:
    method __init__ (line 60) | def __init__(self, profiles_dir="/usr/share/hifiberry/dspprofiles"):
    method load_store (line 70) | def load_store(self):
    method _migrate_legacy_format (line 153) | def _migrate_legacy_format(self, data):
    method normalize_checksum (line 190) | def normalize_checksum(self, checksum):
    method _fix_json_corruption (line 202) | def _fix_json_corruption(self, content):
    method save_store (line 236) | def save_store(self, store_data):
    method load_filters (line 291) | def load_filters(self, checksum):
    method load_memory_settings (line 306) | def load_memory_settings(self, checksum):
    method store_filter (line 321) | def store_filter(self, checksum, address, offset, filter_data, bypasse...
    method store_memory_setting (line 375) | def store_memory_setting(self, checksum, address, values):
    method get_filters (line 415) | def get_filters(self, checksum=None, group_by_bank=False):
    method load (line 460) | def load(self):
    method save (line 472) | def save(self, legacy_data):
    method _group_filters_by_bank (line 480) | def _group_filters_by_bank(self, filters):
    method delete_filters (line 513) | def delete_filters(self, checksum=None, address=None, all_profiles=Fal...
    method get_profile_filter_count (line 577) | def get_profile_filter_count(self, checksum):
    method get_all_profile_checksums (line 596) | def get_all_profile_checksums(self):
    method get_profile_info_by_checksum (line 610) | def get_profile_info_by_checksum(self, checksum):
    method clear_empty_profiles (line 629) | def clear_empty_profiles(self):
    method set_filter_bypass (line 660) | def set_filter_bypass(self, checksum, address, offset, bypassed):
    method get_filter_bypass_state (line 704) | def get_filter_bypass_state(self, checksum, address, offset):
    method toggle_filter_bypass (line 739) | def toggle_filter_bypass(self, checksum, address, offset):
    method set_filter_bank_bypass (line 769) | def set_filter_bank_bypass(self, checksum, address, bypassed):
    method get_filter_bank_bypass_states (line 819) | def get_filter_bank_bypass_states(self, checksum, address):
    method validate_and_repair (line 860) | def validate_and_repair(self):

FILE: src/hifiberrydsp/client/sigmatcp.py
  class SigmaTCPClient (line 41) | class SigmaTCPClient():
    method __init__ (line 43) | def __init__(self, dsp, ip, port=DEFAULT_PORT, autoconnect=True):
    method connect (line 50) | def connect(self):
    method disconnect (line 59) | def disconnect(self):
    method read_memory (line 64) | def read_memory(self, addr, length):
    method program_checksum (line 78) | def program_checksum(self):
    method readwrite_gpio (line 92) | def readwrite_gpio(self, rw, pin, value):
    method write_memory (line 106) | def write_memory(self, addr, data):
    method write_eeprom_from_file (line 116) | def write_eeprom_from_file(self, filename):
    method write_eeprom_from_xml (line 136) | def write_eeprom_from_xml(self, xmldata):
    method get_decimal_repr (line 153) | def get_decimal_repr(self, value):
    method write_decimal (line 157) | def write_decimal(self, addr, value):
    method read_decimal (line 160) | def read_decimal(self, addr):
    method read_data (line 164) | def read_data(self, addr, length=None):
    method write_biquad (line 169) | def write_biquad(self, start_addr, bq):
    method write_decibel (line 188) | def write_decibel(self, addr, db):
    method read_request (line 192) | def read_request(self, addr, length):
    method metadata_request (line 204) | def metadata_request(attribute):
    method gpio_request (line 214) | def gpio_request(readwrite, pin, value):
    method write_request (line 226) | def write_request(addr, data):
    method request_generic (line 243) | def request_generic(self, request_code, response_code=None):
    method request_metadata (line 271) | def request_metadata(self, attribute):
    method write_eeprom_file_request (line 299) | def write_eeprom_file_request(filename):
    method write_eeprom_content_request (line 308) | def write_eeprom_content_request(data):
    method generic_request (line 319) | def generic_request(request_type):
    method reset (line 324) | def reset(self):
    method hibernate (line 331) | def hibernate(self, onoff):
    method data_int (line 339) | def data_int(self, data):

FILE: src/hifiberrydsp/conftest.py
  function pytest_configure (line 2) | def pytest_configure(config):

FILE: src/hifiberrydsp/datatools.py
  function parse_frequency (line 26) | def parse_frequency(f_str):
  function parse_decibel (line 33) | def parse_decibel(dbstr):
  function parse_int (line 41) | def parse_int(val):
  function parse_int_length (line 51) | def parse_int_length(val):
  function parse_int_list (line 71) | def parse_int_list(val):
  function int_data (line 88) | def int_data(intval, length=4):

FILE: src/hifiberrydsp/dsptoolkit.py
  class DSPError (line 93) | class DSPError(Exception):
    method __init__ (line 95) | def __init__(self, value):
    method __str__ (line 98) | def __str__(self):
  class DSPToolkit (line 102) | class DSPToolkit():
    method __init__ (line 104) | def __init__(self,
    method set_ip (line 112) | def set_ip(self, ip):
    method set_volume (line 116) | def set_volume(self, volume):
    method set_limit (line 127) | def set_limit(self, volume):
    method set_loudness (line 138) | def set_loudness(self, volume):
    method get_volume (line 148) | def get_volume(self):
    method adjust_volume (line 161) | def adjust_volume(self, adjustment):
    method get_limit (line 177) | def get_limit(self):
    method get_loudness (line 186) | def get_loudness(self):
    method set_balance (line 195) | def set_balance(self, value):
    method write_biquad (line 210) | def write_biquad(self, addr, bq_params):
    method write_fir (line 213) | def write_fir(self, coefficients, mode=MODE_BOTH):
    method write_coefficients (line 232) | def write_coefficients(self, addr, length, coefficients):
    method get_checksum (line 251) | def get_checksum(self):
    method generic_request (line 254) | def generic_request(self, request_code, response_code=None):
    method set_tonecontrol_filters (line 257) | def set_tonecontrol_filters(self, lowshelf=None, highshelf=None, mode=...
    method set_filters (line 288) | def set_filters(self, filters, mode=MODE_BOTH, cutoff_long=False):
    method clear_iir_filters (line 338) | def clear_iir_filters(self, mode=MODE_BOTH):
    method install_profile (line 343) | def install_profile(self, xmlfile):
    method install_profile_from_content (line 346) | def install_profile_from_content(self, content):
    method mute (line 349) | def mute(self, mute=True):
    method reset (line 364) | def reset(self):
    method hibernate (line 367) | def hibernate(self, hibernate=True):
    method get_meta (line 371) | def get_meta(self, attribute):
    method get_samplerate (line 374) | def get_samplerate(self):
  class CommandLine (line 390) | class CommandLine():
    method __init__ (line 392) | def __init__(self):
    method register_file (line 496) | def register_file(self):
    method string_to_volume (line 499) | def string_to_volume(self, strval):
    method cmd_version (line 522) | def cmd_version(self):
    method cmd_adjust_volume (line 525) | def cmd_adjust_volume(self):
    method cmd_set_volume (line 540) | def cmd_set_volume(self):
    method cmd_set_limit (line 555) | def cmd_set_limit(self):
    method cmd_set_loudness (line 570) | def cmd_set_loudness(self):
    method cmd_get_volume (line 585) | def cmd_get_volume(self):
    method cmd_get_limit (line 596) | def cmd_get_limit(self):
    method cmd_get_loudness (line 607) | def cmd_get_loudness(self):
    method cmd_read (line 618) | def cmd_read(self, display=DISPLAY_FLOAT, loop=False, length=None):
    method cmd_loop_read_dec (line 647) | def cmd_loop_read_dec(self):
    method cmd_read_int (line 650) | def cmd_read_int(self):
    method cmd_loop_read_int (line 653) | def cmd_loop_read_int(self):
    method cmd_read_hex (line 656) | def cmd_read_hex(self):
    method cmd_loop_read_hex (line 659) | def cmd_loop_read_hex(self):
    method cmd_read_reg (line 662) | def cmd_read_reg(self):
    method cmd_loop_read_reg (line 667) | def cmd_loop_read_reg(self):
    method cmd_reset (line 672) | def cmd_reset(self):
    method cmd_clear_iir_filters (line 676) | def cmd_clear_iir_filters(self):
    method set_iir_filters (line 680) | def set_iir_filters(self, mode=MODE_BOTH, format=GENERIC):
    method cmd_set_balance (line 701) | def cmd_set_balance(self):
    method cmd_tonecontrol (line 713) | def cmd_tonecontrol(self):
    method cmd_set_rew_filters_left (line 750) | def cmd_set_rew_filters_left(self):
    method cmd_set_rew_filters_right (line 753) | def cmd_set_rew_filters_right(self):
    method cmd_set_rew_filters_both (line 756) | def cmd_set_rew_filters_both(self):
    method cmd_set_iir_filters_left (line 759) | def cmd_set_iir_filters_left(self):
    method cmd_set_iir_filters_right (line 762) | def cmd_set_iir_filters_right(self):
    method cmd_set_iir_filters_both (line 765) | def cmd_set_iir_filters_both(self):
    method cmd_set_fir_filters (line 768) | def cmd_set_fir_filters(self, mode=MODE_BOTH):
    method cmd_set_fir_filter_left (line 793) | def cmd_set_fir_filter_left(self):
    method cmd_set_fir_filter_right (line 796) | def cmd_set_fir_filter_right(self):
    method cmd_checksum (line 799) | def cmd_checksum(self):
    method cmd_get_xml (line 804) | def cmd_get_xml(self):
    method cmd_get_prog (line 809) | def cmd_get_prog(self):
    method cmd_get_Data (line 814) | def cmd_get_Data(self):
    method cmd_get_meta (line 819) | def cmd_get_meta(self):
    method cmd_mute (line 825) | def cmd_mute(self):
    method cmd_unmute (line 831) | def cmd_unmute(self):
    method cmd_save (line 837) | def cmd_save(self):
    method cmd_load (line 840) | def cmd_load(self):
    method cmd_samplerate (line 843) | def cmd_samplerate(self):
    method cmd_install_profile (line 846) | def cmd_install_profile(self):
    method cmd_write_reg (line 882) | def cmd_write_reg(self):
    method cmd_write_mem (line 892) | def cmd_write_mem(self):
    method cmd_check_eeprom (line 905) | def cmd_check_eeprom(self):
    method cmd_selfboot (line 918) | def cmd_selfboot(self):
    method cmd_store_settings (line 944) | def cmd_store_settings(self):
    method cmd_apply_settings (line 959) | def cmd_apply_settings(self):
    method cmd_store_filters (line 977) | def cmd_store_filters(self):
    method cmd_store (line 985) | def cmd_store(self):
    method cmd_get_memory (line 989) | def cmd_get_memory(self):
    method read_register_and_xml (line 993) | def read_register_and_xml(self, settingsfile, xmlfile):
    method write_back_xml (line 1023) | def write_back_xml(self, xmlprofile, xmlfile=None):
    method store_attributes (line 1050) | def store_attributes(self, attributes=None):
    method main (line 1091) | def main(self):
  class TimeoutThread (line 1155) | class TimeoutThread(threading.Thread):
    method __init__ (line 1157) | def __init__(self, timeout):
    method run (line 1163) | def run(self):
    method finish (line 1172) | def finish(self):

FILE: src/hifiberrydsp/filtering/biquad.py
  class Biquad (line 40) | class Biquad():
    method __init__ (line 42) | def __init__(self, a0, a1, a2, b0, b1, b2, description,
    method normalized (line 57) | def normalized(self):
    method coefficients_a (line 70) | def coefficients_a(self, a0=False):
    method coefficients_b (line 76) | def coefficients_b(self):
    method coefficients_b_a (line 79) | def coefficients_b_a(self, a0=False):
    method __str__ (line 85) | def __str__(self):
    method low_pass (line 92) | def low_pass(cls, f0, q, fs):
    method high_pass (line 106) | def high_pass(cls, f0, q, fs):
    method band_pass_peak_q (line 120) | def band_pass_peak_q(cls, f0, q, fs):
    method band_pass (line 134) | def band_pass(cls, f0, q, fs):
    method notch (line 148) | def notch(cls, f0, q, fs):
    method all_pass (line 162) | def all_pass(cls, f0, q, fs):
    method peaking_eq (line 176) | def peaking_eq(cls, f0, q, dbgain, fs):
    method low_shelf (line 191) | def low_shelf(cls, f0, q, dbgain, fs):
    method high_shelf (line 206) | def high_shelf(cls, f0, q, dbgain, fs):
    method plain (line 221) | def plain(cls):
    method low_pass_firstorder (line 230) | def low_pass_firstorder(cls, f0, q, fs):
    method high_pass_firstorder (line 241) | def high_pass_firstorder(cls, f0, q, fs):
    method volume (line 252) | def volume(cls, db):
    method mute (line 259) | def mute(cls):
    method pass_filter (line 263) | def pass_filter(cls):
    method omega (line 267) | def omega(f0, fs):
    method alpha (line 271) | def alpha(omega, q):
    method a (line 275) | def a(dbgain):
    method create_filter (line 279) | def create_filter(cls, definition, fs):

FILE: src/hifiberrydsp/filtering/filtermath.py
  function magnitude_to_db (line 25) | def magnitude_to_db(mag):
  function db_to_gain (line 29) | def db_to_gain(db):
  function db_sum (line 39) | def db_sum(db1, db2):

FILE: src/hifiberrydsp/filtering/volume.py
  function decibel2amplification (line 26) | def decibel2amplification(db):
  function amplification2decibel (line 30) | def amplification2decibel(amplification):
  function log_coefficients (line 37) | def log_coefficients(dbrange):
  function percent2amplification (line 61) | def percent2amplification(percent, dbrange=60):
  function amplification2percent (line 69) | def amplification2percent(amplification, dbrange=60):

FILE: src/hifiberrydsp/filtering/volume_test.py
  class Test (line 27) | class Test(unittest.TestCase):
    method testPercentAmplification (line 30) | def testPercentAmplification(self):
    method testDecibelAmplification (line 37) | def testDecibelAmplification(self):

FILE: src/hifiberrydsp/genclocks.py
  class LoopStateMachine (line 41) | class LoopStateMachine:
    method __init__ (line 43) | def __init__(self, sigma_tcp_client, playback_pcm='default'):
    method active (line 50) | def active(self):
    method run (line 57) | async def run(self):
    method idle (line 69) | async def idle(self):
    method play (line 74) | async def play(self):
    method hybernate (line 88) | async def hybernate(self, sig):
    method _gather (line 92) | async def _gather(self):
    method shutdown (line 100) | async def shutdown(self, sig):
  function parse_args (line 106) | def parse_args():
  function logger_config (line 118) | def logger_config(verbose):
  function main (line 125) | def main():

FILE: src/hifiberrydsp/hardware/adau145x.py
  class Adau145x (line 34) | class Adau145x():
    method decimal_repr (line 107) | def decimal_repr(f):
    method decimal_val (line 124) | def decimal_val(p):
    method cell_len (line 144) | def cell_len(addr):
    method is_valid_memory_address (line 155) | def is_valid_memory_address(addr):
    method is_valid_register_address (line 168) | def is_valid_register_address(addr):
    method int_data (line 181) | def int_data(value, length):
    method detect_dsp (line 199) | def detect_dsp():
    method kill_dsp (line 219) | def kill_dsp():
    method start_dsp (line 236) | def start_dsp():
    method read_memory (line 256) | def read_memory(addr, length):
    method write_memory (line 271) | def write_memory(addr, data):
    method get_memory_block (line 303) | def get_memory_block(addr, length):
    method get_program_len (line 338) | def get_program_len(max=False):
    method get_program_memory (line 372) | def get_program_memory(end="signature"):
    method get_data_memory (line 458) | def get_data_memory():
    method get_program_memory_subset (line 473) | def get_program_memory_subset(mode="signature", cached=True):
    method calculate_program_checksums (line 510) | def calculate_program_checksums(mode="signature", algorithms=None, cac...
    method clear_checksum_cache (line 580) | def clear_checksum_cache():
    method calculate_program_checksum (line 593) | def calculate_program_checksum(program_data=None, cached=True):
    method write_biquad (line 628) | def write_biquad(start_addr, bq):
    method write_biquad_direct (line 657) | def write_biquad_direct(start_addr, a0, a1, a2, b0, b1, b2):
    method guess_samplerate (line 679) | def guess_samplerate():
    method write_eeprom_content (line 705) | def write_eeprom_content(xmldata):

FILE: src/hifiberrydsp/hardware/adau145x_test.py
  class Test (line 25) | class Test(unittest.TestCase):
    method testConversion (line 28) | def testConversion(self):
    method testValues (line 38) | def testValues(self):

FILE: src/hifiberrydsp/hardware/spi.py
  function init_spi (line 25) | def init_spi():
  class SpiHandler (line 41) | class SpiHandler():
    method read (line 54) | def read(addr, length):
    method write (line 71) | def write(addr, data):

FILE: src/hifiberrydsp/lg/soundsync.py
  class SoundSync (line 40) | class SoundSync(Thread):
    method __init__ (line 45) | def __init__(self):
    method set_registers (line 57) | def set_registers(self, volume_register, spdif_active_register):
    method update_volume (line 63) | def update_volume(self):
    method is_spdif_active (line 79) | def is_spdif_active(self):
    method try_read_volume (line 87) | def try_read_volume(self):
    method parse_volume_from_status (line 105) | def parse_volume_from_status(data):
    method write_volume (line 116) | def write_volume(self, volume):
    method run (line 124) | def run(self):
    method finish (line 143) | def finish(self):

FILE: src/hifiberrydsp/lg/test_soundsync.py
  class TestSoundSync (line 5) | class TestSoundSync(TestCase):
    method test_parse_volume_with_missing_sound_sync_signature (line 6) | def test_parse_volume_with_missing_sound_sync_signature(self):
    method test_parse_volume_of_0 (line 9) | def test_parse_volume_of_0(self):
    method test_parse_volume_of_50 (line 12) | def test_parse_volume_of_50(self):
    method test_parse_volume_of_100 (line 15) | def test_parse_volume_of_100(self):
    method test_parse_volume_of_100_on_another_tv (line 18) | def test_parse_volume_of_100_on_another_tv(self):
    method test_parse_volume_of_muted_tv (line 22) | def test_parse_volume_of_muted_tv(self):

FILE: src/hifiberrydsp/measurement/data.py
  function read_sample_file_float32 (line 26) | def read_sample_file_float32(filename):

FILE: src/hifiberrydsp/parser/biquad.py
  class BiquadParser (line 27) | class BiquadParser():
    method __init__ (line 29) | def __init__(self):
    method readfilters (line 33) | def readfilters(filename, fs=48000):

FILE: src/hifiberrydsp/parser/rew.py
  class REWParser (line 27) | class REWParser():
    method __init__ (line 29) | def __init__(self):
    method readfilters (line 33) | def readfilters(filename, fs=48000):

FILE: src/hifiberrydsp/parser/settings.py
  class SettingsFile (line 35) | class SettingsFile():
    method __init__ (line 37) | def __init__(self, filename, fs=48000, dsp=Adau145x()):
    method parse_value (line 59) | def parse_value(self, value):
    method parse_biquad (line 73) | def parse_biquad(self, value):
    method get_updates (line 88) | def get_updates(self, xmlprofile):
    method update_xml_profile (line 127) | def update_xml_profile(self, xmlprofile):
    method param_to_bytes (line 132) | def param_to_bytes(self, value, max_length=1, ignore_limit=False, word...
  function demo (line 184) | def demo():

FILE: src/hifiberrydsp/parser/sigmaparams.py
  class SigmastudioParamsFile (line 102) | class SigmastudioParamsFile():
    method __init__ (line 109) | def __init__(self, filename):
    method process_cell (line 155) | def process_cell(self, cellname, paramname, address, length):
    method param_list (line 187) | def param_list(self):
    method merge_params_into_xml (line 205) | def merge_params_into_xml(self, xmlfile):
  function basefilename (line 216) | def basefilename(filename):
  function extension (line 221) | def extension(filename):
  function merge_params_main (line 226) | def merge_params_main(xmlfile=None, paramsfile=None):

FILE: src/hifiberrydsp/parser/xmlprofile.py
  function replace_in_memory_block (line 98) | def replace_in_memory_block(data, startaddr, replace_dict):
  function get_default_dspprofile_path (line 128) | def get_default_dspprofile_path():
  class XmlProfile (line 152) | class XmlProfile():
    method __init__ (line 154) | def __init__(self, filename=None, read_default_profile=False):
    method read_from_file (line 168) | def read_from_file(self, filename):
    method read_from_text (line 179) | def read_from_text(self, xmlcontent):
    method update (line 184) | def update(self):
    method replace_eeprom_cells (line 205) | def replace_eeprom_cells(self, replace_dict):
    method replace_ram_cells (line 235) | def replace_ram_cells(self, replace_dict):
    method get_meta (line 263) | def get_meta(self, name):
    method get_meta_keys (line 269) | def get_meta_keys(self):
    method get_storable_registers (line 279) | def get_storable_registers(self):
    method get_addr_length (line 294) | def get_addr_length(self, attribute):
    method update_metadata (line 298) | def update_metadata(self, metadata_dict):
    method samplerate (line 329) | def samplerate(self):
    method write_xml (line 335) | def write_xml(self, filename):
    method __str__ (line 339) | def __str__(self):
  class DummyEepromWriter (line 346) | class DummyEepromWriter():
    method __init__ (line 353) | def __init__(self, dsp):
    method write_eeprom (line 359) | def write_eeprom(self, addr, values):
    method as_bytes (line 372) | def as_bytes(self):
    method get_header (line 385) | def get_header(self):
    method first_block_addr (line 392) | def first_block_addr(self):
    method calc_checksum (line 400) | def calc_checksum(self, eeprom_content):
    method has_pattern_at_addr (line 422) | def has_pattern_at_addr(self, address, pattern):
    method find_pattern (line 440) | def find_pattern(self, pattern, start_addr = 0):
    method find_register_position (line 449) | def find_register_position(self, register_address, start_addr = 0):
    method replace_memory_data (line 480) | def replace_memory_data(self, replace_dict):
  function demo (line 547) | def demo():

FILE: src/hifiberrydsp/server/constants.py
  class SigmaTCPException (line 60) | class SigmaTCPException(IOError):
    method __init__ (line 62) | def __init__(self, message):

FILE: src/hifiberrydsp/server/sigmatcp.py
  function parameterfile (line 77) | def parameterfile():
  function dspprogramfile (line 84) | def dspprogramfile():
  function startup_notify (line 102) | def startup_notify():
  function find_and_restore_dsp_profile (line 113) | def find_and_restore_dsp_profile():
  class SigmaTCPHandler (line 269) | class SigmaTCPHandler(BaseRequestHandler):
    method __init__ (line 283) | def __init__(self, request, client_address, server):
    method setup (line 287) | def setup(self):
    method finish (line 290) | def finish(self):
    method handle (line 293) | def handle(self):
    method read_xml_profile (line 487) | def read_xml_profile():
    method get_checked_xml (line 564) | def get_checked_xml():
    method get_and_check_xml (line 575) | def get_and_check_xml():
    method get_meta (line 579) | def get_meta(attribute):
    method handle_read (line 598) | def handle_read(data):
    method handle_write (line 613) | def handle_write(data):
    method write_eeprom_content (line 659) | def write_eeprom_content(xmldata):
    method write_eeprom_file (line 671) | def write_eeprom_file(filename):
    method save_data_memory (line 681) | def save_data_memory():
    method restore_data_memory (line 689) | def restore_data_memory():
    method get_memory_block (line 714) | def get_memory_block(addr, length):
    method get_program_memory (line 718) | def get_program_memory():
    method get_data_memory (line 725) | def get_data_memory():
    method program_checksum (line 732) | def program_checksum(cached=True):
    method _list_str (line 736) | def _list_str(int_list):
    method _response_packet (line 741) | def _response_packet(command, addr, data_length):
    method _kill_dsp (line 758) | def _kill_dsp():
    method _start_dsp (line 762) | def _start_dsp():
    method store_parameters (line 766) | def store_parameters(checksum, memory):
    method restore_parameters (line 772) | def restore_parameters(checksum):
    method prepare_update (line 782) | def prepare_update():
    method finish_update (line 803) | def finish_update():
    method update_alsasync (line 812) | def update_alsasync(clear=False):
    method update_lgsoundsync (line 828) | def update_lgsoundsync(clear=False):
    method load_and_apply_filters (line 851) | def load_and_apply_filters(type="sha1"):
    method _apply_memory_setting (line 992) | def _apply_memory_setting(setting_key, setting_data):
    method _apply_memory_setting_new (line 1071) | def _apply_memory_setting_new(memory_address, memory_data):
    method _apply_filter (line 1146) | def _apply_filter(address, filter_spec):
    method _apply_bypass_filter (line 1224) | def _apply_bypass_filter(address):
  class ProgramRefresher (line 1253) | class ProgramRefresher(Thread):
    method run (line 1255) | def run(self):
  class SigmaTCPServer (line 1283) | class SigmaTCPServer(ThreadingMixIn, TCPServer):
    method __init__ (line 1285) | def __init__(self,
    method server_activate (line 1292) | def server_activate(self):
    method server_close (line 1295) | def server_close(self):
  class SigmaTCPServerMain (line 1299) | class SigmaTCPServerMain():
    method __init__ (line 1301) | def __init__(self, alsa_mixer_name="DSPVolume"):
    method parse_config (line 1364) | def parse_config(self):
    method run (line 1414) | def run(self):

FILE: test_autoload_filters.py
  class TestFilterAutoloading (line 18) | class TestFilterAutoloading(unittest.TestCase):
    method setUp (line 20) | def setUp(self):
    method tearDown (line 58) | def tearDown(self):
    method test_autoload_filters_success (line 70) | def test_autoload_filters_success(self, mock_apply_filter, mock_get_xm...
    method test_autoload_filters_no_checksum (line 113) | def test_autoload_filters_no_checksum(self, mock_filter_store_class, m...
    method test_autoload_filters_no_filters (line 128) | def test_autoload_filters_no_filters(self, mock_filter_store_class, mo...
    method test_apply_filter_direct_coefficients (line 150) | def test_apply_filter_direct_coefficients(self, mock_biquad_class, moc...

FILE: test_filter_store.py
  class TestFilterStore (line 18) | class TestFilterStore(unittest.TestCase):
    method setUp (line 20) | def setUp(self):
    method tearDown (line 25) | def tearDown(self):
    method test_empty_filter_store (line 33) | def test_empty_filter_store(self):
    method test_save_and_load_filter_store (line 38) | def test_save_and_load_filter_store(self):
    method test_store_filter (line 59) | def test_store_filter(self):
    method test_store_filter_with_offset (line 78) | def test_store_filter_with_offset(self):
    method test_get_filters_all (line 93) | def test_get_filters_all(self):
    method test_get_filters_by_checksum (line 106) | def test_get_filters_by_checksum(self):
    method test_get_profile_info_by_checksum (line 123) | def test_get_profile_info_by_checksum(self):
    method test_delete_filters_by_checksum (line 138) | def test_delete_filters_by_checksum(self):
    method test_delete_specific_filter (line 157) | def test_delete_specific_filter(self):
Condensed preview — 145 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (5,145K chars).
[
  {
    "path": ".ai-config.json",
    "chars": 1187,
    "preview": "{\n  \"ai_config\": {\n    \"style_guidelines\": {\n      \"no_emojis\": true,\n      \"text_only\": true,\n      \"professional_tone\""
  },
  {
    "path": ".ai-guidelines",
    "chars": 2679,
    "preview": "# AI Agent Guidelines for HiFiBerry DSP Project\n\n## Code Style and Documentation Requirements\n\n### Text Formatting\n- **N"
  },
  {
    "path": ".gitattributes",
    "chars": 608,
    "preview": "# Set default behavior to automatically normalize line endings\n* text=auto eol=lf\n\n# Explicitly declare text files to be"
  },
  {
    "path": ".gitignore",
    "chars": 239,
    "preview": "devenv.sh.settings\n*.pyc\n.project\n.pydevproject\n.metadata\nhifiberrydsp.egg-info\n.DS_Store\n*.bak\ntmp\n/devenv.sh\n/update\nb"
  },
  {
    "path": ".settings/.gitignore",
    "chars": 40,
    "preview": "/org.eclipse.ltk.core.refactoring.prefs\n"
  },
  {
    "path": "LICENSE",
    "chars": 1060,
    "preview": "Copyright (c) 2018 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof th"
  },
  {
    "path": "README.md",
    "chars": 3199,
    "preview": "![Python package](https://github.com/hifiberry/hifiberry-dsp/workflows/Python%20package/badge.svg)\n[![PyPI version](http"
  },
  {
    "path": "build.sh",
    "chars": 4913,
    "preview": "#!/bin/bash\nset -e\n\nexport LC_ALL=en_US.UTF-8\nexport LANG=en_US.UTF-8\n\n# Parse command-line arguments for version suffix"
  },
  {
    "path": "contrib/Readme.md",
    "chars": 810,
    "preview": "# Hifiberry DSP External Conributions\n\n## What is this?\n\nThis directory contains external contributions (like useful scr"
  },
  {
    "path": "contrib/hifiberry_config.toml",
    "chars": 275,
    "preview": "[contrib]\nloudness=\"{'1': {'hs': {'freq': '7000Hz', 'vol': '3dB'},'ls': {'freq': '100Hz', 'vol': '3dB'}},'2': {'hs': {'f"
  },
  {
    "path": "contrib/install_hbdsp.sh",
    "chars": 5097,
    "preview": "#!/bin/sh -e\n\n### Exit, if not enough free space\nrequiredSpaceInMB=25\navailableSpaceInMB=$(/bin/df -m /dev/mmcblk0p2 | a"
  },
  {
    "path": "contrib/set-loudness",
    "chars": 2338,
    "preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n# Author: rawdlite@gmail.com\n# Created: 2024-12-21\n# License: MIT License"
  },
  {
    "path": "create-profiles.sh",
    "chars": 736,
    "preview": "#!/bin/bash\n#\n# Script to create different profiles from a standard profile \n# and settings files\n#\ncd `dirname $0`\nBASE"
  },
  {
    "path": "debian/changelog",
    "chars": 10515,
    "preview": "hifiberry-dsp (1.3.11) stable; urgency=medium\n\n  * systemd: launch sigmatcpserver with --store --restore so DSP data\n   "
  },
  {
    "path": "debian/control",
    "chars": 676,
    "preview": "Source: hifiberry-dsp\nSection: utils\nPriority: optional\nMaintainer: HiFiBerry <info@hifiberry.com>\nBuild-Depends: debhel"
  },
  {
    "path": "debian/copyright",
    "chars": 1392,
    "preview": "Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/\nUpstream-Name: hifiberry-dsp\nUpstream-Contact"
  },
  {
    "path": "debian/dirs",
    "chars": 26,
    "preview": "etc/nginx/hifiberry-api.d\n"
  },
  {
    "path": "debian/hifiberry-dsp.docs",
    "chars": 6,
    "preview": "doc/*\n"
  },
  {
    "path": "debian/hifiberry-dsp.examples",
    "chars": 15,
    "preview": "sample_files/*\n"
  },
  {
    "path": "debian/hifiberry-dsp.install",
    "chars": 114,
    "preview": "systemd/sigmatcpserver.service usr/lib/systemd/system/\ndebian/hifiberry-sigmatcp.nginx etc/nginx/hifiberry-api.d/\n"
  },
  {
    "path": "debian/hifiberry-dsp.manpages",
    "chars": 86,
    "preview": "man/man1/dsp-install-profile.1\nman/man1/dsp-program-info.1\nman/man1/dsp-get-profile.1\n"
  },
  {
    "path": "debian/hifiberry-sigmatcp.nginx",
    "chars": 1033,
    "preview": "# HiFiBerry DSP Toolkit API proxy configuration\n# This file should be included in the main nginx server block\n\n# Proxy D"
  },
  {
    "path": "debian/postrm",
    "chars": 98,
    "preview": "#!/bin/sh\n\nset -e\n\nif [ \"$1\" = \"purge\" ]; then\n\trm -rf /var/lib/hifiberry\nfi\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "debian/rules",
    "chars": 227,
    "preview": "#!/usr/bin/make -f\n\nexport PYBUILD_DIR=src\n\n%:\n\tdh $@ --buildsystem=pybuild\n\noverride_dh_auto_test:\n\t# Skip tests due to"
  },
  {
    "path": "debian/source/format",
    "chars": 3,
    "preview": "1.0"
  },
  {
    "path": "doc/adaptexistingprofiles.md",
    "chars": 3147,
    "preview": "# Adapting existing profiles\n\nWhile we provide pre-configured profiles, you might want to add more functionalities or si"
  },
  {
    "path": "doc/asrc.md",
    "chars": 660,
    "preview": "# Usage of ASRCSs\n\nThe ADAU14xx models wer'e using on the DAC+ DSP, Beocreate 4CA and the DSP add-on board provide 8 asy"
  },
  {
    "path": "doc/checksum.md",
    "chars": 7622,
    "preview": "# DSP Program Checksums\n\n## Overview\n\nThe HiFiBerry DSP toolkit provides checksum functionality to verify the integrity "
  },
  {
    "path": "doc/crossovers.md",
    "chars": 6119,
    "preview": "# Creating speaker crossovers with dsptoolkit\n\nWhile you can always use SigmaStudio to design your individual DSP progra"
  },
  {
    "path": "doc/debug.md",
    "chars": 1871,
    "preview": "# HiFiBerry DSP Debug Configuration\n\n## Enabling Debug Mode\n\nTo enable debug logging of all DSP memory writes (including"
  },
  {
    "path": "doc/dspprofiles.md",
    "chars": 8064,
    "preview": "# DSP Profiles\n\nOur DSP toolkit uses so-called DSP profiles to describe the DSP program. They basically consist of a col"
  },
  {
    "path": "doc/dspreset.md",
    "chars": 297,
    "preview": "# Resetting the DSP\n\nThe DSP's reset is connected to Pi's GPIO 17. To reset the DSP, you need to first pull this to LOW,"
  },
  {
    "path": "doc/dspsettings.md",
    "chars": 4057,
    "preview": "# DSP Settings Store\n\nThe DSP settings store persists filter and memory configurations across reboots. It is managed by "
  },
  {
    "path": "doc/dsptoolkit.md",
    "chars": 8604,
    "preview": "# Command Line Utility (DEPRECATED)\n\n> **⚠️ DEPRECATION NOTICE**\n> \n> The `dsptoolkit` command-line utility is **DEPRECA"
  },
  {
    "path": "doc/restapi.md",
    "chars": 43913,
    "preview": "# HiFiBerry DSP REST API Documentation\n\nThis document describes the REST API provided by the HiFiBerry DSP service for i"
  },
  {
    "path": "doc/reverse-engineering-lg.md",
    "chars": 4101,
    "preview": "# Reverse engineering LG Sound Sync\n\nLG TVs have a feature called \"Sound Sync (optical)\" that allows the TV to control t"
  },
  {
    "path": "doc/rew-basics.md",
    "chars": 10230,
    "preview": "# Optimizing acoustics performance with DSPToolkit and REW\n\nWhile many people try improving the performance of their aud"
  },
  {
    "path": "doc/settingsfiles.md",
    "chars": 1770,
    "preview": "Settings file format\n====================\n\nA settings file is a text file that consists of lines of attribute:value pair"
  },
  {
    "path": "doc/sigmatcpserver.md",
    "chars": 5294,
    "preview": "# SigmaTCP Server Documentation\n\nThe `sigmatcpserver` is a daemon that provides a TCP interface for communication with H"
  },
  {
    "path": "man/man1/dsp-get-profile.1",
    "chars": 3621,
    "preview": ".TH DSP-GET-PROFILE 1 \"September 2025\" \"HiFiBerry DSP 1.3.2\" \"HiFiBerry DSP Tools\"\n.SH NAME\ndsp-get-profile \\- retrieve "
  },
  {
    "path": "man/man1/dsp-install-profile.1",
    "chars": 3601,
    "preview": ".TH DSP-INSTALL-PROFILE 1 \"30 September 2025\" \"HiFiBerry DSP toolkit 1.3.2\" \"User Commands\"\n.SH NAME\ndsp-install-profile"
  },
  {
    "path": "man/man1/dsp-program-info.1",
    "chars": 4023,
    "preview": ".TH DSP-PROGRAM-INFO 1 \"30 September 2025\" \"HiFiBerry DSP toolkit 1.3.2\" \"User Commands\"\n.SH NAME\ndsp-program-info \\- ge"
  },
  {
    "path": "repair_filter_store.py",
    "chars": 5741,
    "preview": "#!/usr/bin/env python3\n\"\"\"\nFilter Store Repair Utility\n\nThis utility repairs corrupted filter store JSON files by:\n1. De"
  },
  {
    "path": "sample_files/rew-filter-coefficients.txt",
    "chars": 1752,
    "preview": "biquad1,\nb0=0.9971434794400773,\nb1=-1.992564782301403,\nb2=0.9954708988160471,\na1=1.992564782301403,\na2=-0.99261437825612"
  },
  {
    "path": "sample_files/rew-filter-settings.txt",
    "chars": 924,
    "preview": "Filter Settings file\n\nRoom EQ V5.18\nDated: Jun 24, 2018 10:44:32 PM\n\nNotes:\n\nEqualiser: Generic\nJun 24 21:41:10\nFilter  "
  },
  {
    "path": "sample_files/roomeq-daniel.txt",
    "chars": 897,
    "preview": "Filter Settings file\n\nRoom EQ V5.18\nDated: Jun 24, 2018 9:48:25 PM\n\nNotes:RoomEq Daniel\n\nEqualiser: Generic\nJun 24 21:41"
  },
  {
    "path": "sample_files/settings/2-way.txt",
    "chars": 305,
    "preview": "# Sample settings for a sub/sat setup with the subwoofer connected to outputs 1 and 2 and\n# the satellites connected to "
  },
  {
    "path": "sample_files/settings/4-way.txt",
    "chars": 323,
    "preview": "# Sample settings for a sub/sat setup with the subwoofer connected to outputs 1 and 2 and\n# the satellites connected to "
  },
  {
    "path": "sample_files/settings/beocreate-default.txt",
    "chars": 312,
    "preview": "# Sample settings for a sub/sat setup with the subwoofer connected to outputs 1 and 2 and\n# the satellites connected to "
  },
  {
    "path": "sample_files/settings/filters.txt",
    "chars": 265,
    "preview": "# Simple example file showing how to define filter coefficients with a settings file\nIIR_L1: lp:200Hz\nIIR_L2: hp:200Hz,l"
  },
  {
    "path": "sample_files/settings/full-volume.txt",
    "chars": 53,
    "preview": "volumeControlRegister: 1.0\nvolumeLimitRegister: 0.5\n\n"
  },
  {
    "path": "sample_files/settings/fullrange.txt",
    "chars": 285,
    "preview": "# Sample settings for a sub/sat setup with the subwoofer connected to outputs 1 and 2 and\n# the satellites connected to "
  },
  {
    "path": "sample_files/settings/invert-mute.txt",
    "chars": 17,
    "preview": "invertMute: 0x01\n"
  },
  {
    "path": "sample_files/settings/multiple.txt",
    "chars": 198,
    "preview": "volumeControlRegister: -3dB\nvolumeLimitRegister: 50%\nmute: 0x1\nbalanceRegister: 0.8\nIIR_L: lp:1500Hz, hp:300Hz:0.6, eq: "
  },
  {
    "path": "sample_files/settings/no_automute.txt",
    "chars": 12,
    "preview": "automute: 0\n"
  },
  {
    "path": "sample_files/settings/no_spdif.txt",
    "chars": 23,
    "preview": "enableSPDIFRegister: 0\n"
  },
  {
    "path": "sample_files/settings/subsat.txt",
    "chars": 319,
    "preview": "# Sample settings for a sub/sat setup with the subwoofer connected to outputs 1 and 2 and\n# the satellites connected to "
  },
  {
    "path": "sample_files/settings/volume-limit.txt",
    "chars": 27,
    "preview": "volumeLimitRegister: -24db\n"
  },
  {
    "path": "sample_files/xml/4way-default.params",
    "chars": 87186,
    "preview": "Cell Name         = SPDIF output.SpdifSource\nParameter Name    = stereomuxSigma300ns2index\nParameter Address = 549\nParam"
  },
  {
    "path": "sample_files/xml/4way-default.xml",
    "chars": 107874,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ROM IC=\"ADAU1451\" IC_Address=\"1\" Address_byte_length=\"2\">\n\t<beometa>\n\t\t<metadata"
  },
  {
    "path": "sample_files/xml/4way-iir-delay-mixer-asrccontrol.xml",
    "chars": 204863,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ROM IC=\"ADAU1451\" IC_Address=\"1\" Address_byte_length=\"2\">\n\t<beometa>\n\t\t<metadata"
  },
  {
    "path": "sample_files/xml/4way-iir-delay-mixer.params",
    "chars": 89882,
    "preview": "Cell Name         = InputSelector.VolumeLimitPi\nParameter Name    = SWGainADAU145XAlg3target\nParameter Address = 4559\nPa"
  },
  {
    "path": "sample_files/xml/4way-iir-delay-mixer.xml",
    "chars": 210086,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ROM IC=\"ADAU1451\" IC_Address=\"1\" Address_byte_length=\"2\">\n\t<beometa>\n\t\t<metadata"
  },
  {
    "path": "sample_files/xml/4way-iir-delay.params",
    "chars": 87869,
    "preview": "Cell Name         = SPDIF output.SpdifSource\nParameter Name    = stereomuxSigma300ns2index\nParameter Address = 4561\nPara"
  },
  {
    "path": "sample_files/xml/4way-iir-delay.xml",
    "chars": 206385,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ROM IC=\"ADAU1451\" IC_Address=\"1\" Address_byte_length=\"2\">\n\t<beometa>\n\t\t<metadata"
  },
  {
    "path": "sample_files/xml/4way-iir.params",
    "chars": 87186,
    "preview": "Cell Name         = SPDIF output.SpdifSource\nParameter Name    = stereomuxSigma300ns2index\nParameter Address = 549\nParam"
  },
  {
    "path": "sample_files/xml/4way-iir.xml",
    "chars": 107812,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ROM IC=\"ADAU1451\" IC_Address=\"1\" Address_byte_length=\"2\">\n\t<beometa>\n\t\t<metadata"
  },
  {
    "path": "sample_files/xml/4way-inputswitcher.xml",
    "chars": 210373,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ROM IC=\"ADAU1451\" IC_Address=\"1\" Address_byte_length=\"2\">\n\t<beometa>\n\t\t<metadata"
  },
  {
    "path": "sample_files/xml/4way-mixed.params",
    "chars": 277417,
    "preview": "Cell Name         = SPDIF output.Nx2-2\nParameter Name    = stereomuxSigma300ns2index\nParameter Address = 8147\nParameter "
  },
  {
    "path": "sample_files/xml/4way-mixed.xml",
    "chars": 427766,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ROM IC=\"ADAU1451\" IC_Address=\"1\" Address_byte_length=\"2\">\n\t<beometa>\n\t\t<metadata"
  },
  {
    "path": "sample_files/xml/beocreate-default.xml",
    "chars": 210071,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ROM IC=\"ADAU1451\" IC_Address=\"1\" Address_byte_length=\"2\">\n\t<beometa>\n\t\t<metadata"
  },
  {
    "path": "sample_files/xml/dacdsp-default.xml",
    "chars": 210071,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ROM IC=\"ADAU1451\" IC_Address=\"1\" Address_byte_length=\"2\">\n\t<beometa>\n\t\t<metadata"
  },
  {
    "path": "sample_files/xml/dacdsp-v12-1.xml",
    "chars": 219456,
    "preview": "<?xml version=\"1.0\" standalone=\"no\"?>\n<ROM IC=\"ADAU1451\" IC_Address=\"1\" Address_byte_length=\"2\">\n<beometa>\n\t<metadata ty"
  },
  {
    "path": "sample_files/xml/dspdac-noautomute.xml",
    "chars": 204223,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ROM IC=\"ADAU1451\" IC_Address=\"1\" Address_byte_length=\"2\">\n\t<beometa>\n\t\t<metadata"
  },
  {
    "path": "sample_files/xml/fullrange-fir.xml",
    "chars": 419274,
    "preview": "<?xml version=\"1.0\" standalone=\"no\"?>\n<ROM IC=\"ADAU1451\" IC_Address=\"1\" Address_byte_length=\"2\">\n  <beometa>\n    <metada"
  },
  {
    "path": "sample_files/xml/fullrange-iir.xml",
    "chars": 89464,
    "preview": "<?xml version=\"1.0\" standalone=\"no\"?>\n<ROM IC=\"ADAU1451\" IC_Address=\"1\" Address_byte_length=\"2\">\n  <beometa>\n    <metada"
  },
  {
    "path": "sample_files/xml/fullrange-mixed.xml",
    "chars": 418097,
    "preview": "<?xml version=\"1.0\" standalone=\"no\"?>\n<ROM IC=\"ADAU1451\" IC_Address=\"1\" Address_byte_length=\"2\">\n  <beometa>\n    <metada"
  },
  {
    "path": "sample_files/xml/generic192.xml",
    "chars": 221817,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ROM IC=\"ADAU1451\" IC_Address=\"1\" Address_byte_length=\"2\">\n\t<beometa>\n           "
  },
  {
    "path": "sample_files/xml/generic96.xml",
    "chars": 221642,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ROM IC=\"ADAU1451\" IC_Address=\"1\" Address_byte_length=\"2\">\n\t<beometa>\n           "
  },
  {
    "path": "sample_files/xml/sine777.xml",
    "chars": 74628,
    "preview": "<?xml version=\"1.0\" standalone=\"no\"?>\n<ROM IC=\"ADAU1451\" IC_Address=\"1\" Address_byte_length=\"2\">\n  <dateTime>2019-04-09T"
  },
  {
    "path": "src/bin/dsp-get-profile",
    "chars": 9391,
    "preview": "#!/bin/bash\n#\n# dsp-get-profile - Retrieve DSP profile from HiFiBerry DSP using REST API\n#\n# This script connects to a H"
  },
  {
    "path": "src/bin/dsp-install-profile",
    "chars": 8691,
    "preview": "#!/bin/bash\n\n# dsp-install-profile - Install DSP profile using REST API\n# Copyright (c) 2025 HiFiBerry\n\nset -e\n\nSCRIPT_N"
  },
  {
    "path": "src/bin/dsp-program-info",
    "chars": 9806,
    "preview": "#!/bin/bash\n\n# dsp-program-info - Get DSP program information using REST API\n# Copyright (c) 2025 HiFiBerry\n\nset -e\n\nSCR"
  },
  {
    "path": "src/bin/dspdac-reset",
    "chars": 73,
    "preview": "#!/bin/bash\ngpio mode 0 out\ngpio write 0 0\ngpio write 0 1\ngpio mode 0 in\n"
  },
  {
    "path": "src/bin/dsptoolkit",
    "chars": 1224,
    "preview": "#!/usr/bin/env python3\n\n'''\nCopyright (c) 2019 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any p"
  },
  {
    "path": "src/bin/mergeparameters",
    "chars": 1208,
    "preview": "#!/usr/bin/env python3\n\n'''\nCopyright (c) 2019 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any p"
  },
  {
    "path": "src/bin/optimizer-client",
    "chars": 5520,
    "preview": "#!/usr/bin/env python3\n\n'''\nCopyright (c) 2018 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any p"
  },
  {
    "path": "src/bin/sigmatcpserver",
    "chars": 1099,
    "preview": "#!/usr/bin/env python3\n\"\"\"\nCopyright (c) 2018 HiFiBerry\n\nAll Rights Reserved.\n\nThis program is free software: you can re"
  },
  {
    "path": "src/bin/spdifclockgen",
    "chars": 1173,
    "preview": "#!/usr/bin/env python3\n\n'''\nCopyright (c) 2020 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any p"
  },
  {
    "path": "src/hifiberrydsp/__init__.py",
    "chars": 79,
    "preview": "\"\"\"\nHiFiBerry DSP toolkit\n\"\"\"\n__version__ = \"1.3.11\"\n_called_from_test = False\n"
  },
  {
    "path": "src/hifiberrydsp/alsa/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/hifiberrydsp/alsa/alsasync.py",
    "chars": 9509,
    "preview": "'''\nCopyright (c) 2018 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "src/hifiberrydsp/api/__init__.py",
    "chars": 117,
    "preview": "'''\nAPI module for HiFiBerry DSP tools\n'''\n\nfrom hifiberrydsp.api.restapi import run_api, DEFAULT_HOST, DEFAULT_PORT\n"
  },
  {
    "path": "src/hifiberrydsp/api/filters.py",
    "chars": 11811,
    "preview": "import json\nimport math\nimport cmath\n\nfrom hifiberrydsp.filtering.biquad import Biquad\n\nclass Filter:\n    def __init__(s"
  },
  {
    "path": "src/hifiberrydsp/api/restapi.py",
    "chars": 85562,
    "preview": "'''\nCopyright (c) 2023 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "src/hifiberrydsp/api/settings_store.py",
    "chars": 41472,
    "preview": "'''\nCopyright (c) 2023 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "src/hifiberrydsp/client/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/hifiberrydsp/client/sigmatcp.py",
    "chars": 11049,
    "preview": "'''\nCopyright (c) 2018 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "src/hifiberrydsp/conftest.py",
    "chars": 96,
    "preview": "\ndef pytest_configure(config):\n    import hifiberrydsp\n    hifiberrydsp._called_from_test = True"
  },
  {
    "path": "src/hifiberrydsp/datatools.py",
    "chars": 2575,
    "preview": "'''\nCopyright (c) 2018 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "src/hifiberrydsp/dsptoolkit.py",
    "chars": 42002,
    "preview": "#!/usr/bin/env python3\n\n'''\nCopyright (c) 2018 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any p"
  },
  {
    "path": "src/hifiberrydsp/filtering/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/hifiberrydsp/filtering/biquad.py",
    "chars": 12901,
    "preview": "'''\nCopyright (c) 2019 Modul 9/HiFiBerry\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof"
  },
  {
    "path": "src/hifiberrydsp/filtering/filtermath.py",
    "chars": 1422,
    "preview": "'''\nCopyright (c) 2018 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "src/hifiberrydsp/filtering/volume.py",
    "chars": 2470,
    "preview": "'''\nCopyright (c) 2018 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "src/hifiberrydsp/filtering/volume_test.py",
    "chars": 2015,
    "preview": "'''\nCopyright (c) 2019 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "src/hifiberrydsp/genclocks.py",
    "chars": 5223,
    "preview": "#!/usr/bin/env python\n'''\nCopyright (c) 2020 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any per"
  },
  {
    "path": "src/hifiberrydsp/hardware/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/hifiberrydsp/hardware/adau145x.py",
    "chars": 28026,
    "preview": "'''\nCopyright (c) 2018 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "src/hifiberrydsp/hardware/adau145x_test.py",
    "chars": 2284,
    "preview": "'''\nCopyright (c) 2019 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "src/hifiberrydsp/hardware/spi.py",
    "chars": 3829,
    "preview": "'''\nCopyright (c) 2018 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "src/hifiberrydsp/lg/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/hifiberrydsp/lg/soundsync.py",
    "chars": 4865,
    "preview": "'''\nCopyright (c) 2018 Modul 9/HiFiBerry\n              2020 Christoffer Sawicki\n\nPermission is hereby granted, free of c"
  },
  {
    "path": "src/hifiberrydsp/lg/test_soundsync.py",
    "chars": 927,
    "preview": "from unittest import TestCase\n\nfrom hifiberrydsp.lg.soundsync import SoundSync\n\nclass TestSoundSync(TestCase):\n    def t"
  },
  {
    "path": "src/hifiberrydsp/measurement/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/hifiberrydsp/measurement/data.py",
    "chars": 1420,
    "preview": "'''\nCopyright (c) 2018 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "src/hifiberrydsp/parser/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/hifiberrydsp/parser/biquad.py",
    "chars": 1807,
    "preview": "'''\nCopyright (c) 2018 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "src/hifiberrydsp/parser/rew.py",
    "chars": 5698,
    "preview": "'''\nCopyright (c) 2018 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "src/hifiberrydsp/parser/settings.py",
    "chars": 6995,
    "preview": "'''\nCopyright (c) 2018 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "src/hifiberrydsp/parser/sigmaparams.py",
    "chars": 9376,
    "preview": "'''\nCopyright (c) 2018 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "src/hifiberrydsp/parser/xmlprofile.py",
    "chars": 18577,
    "preview": "'''\nCopyright (c) 2018 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "src/hifiberrydsp/server/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/hifiberrydsp/server/constants.py",
    "chars": 1929,
    "preview": "'''\nCopyright (c) 2018 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "src/hifiberrydsp/server/sigmatcp.py",
    "chars": 62596,
    "preview": "'''\nCopyright (c) 2018 Modul 9/HiFiBerry\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "src/setup.py",
    "chars": 1759,
    "preview": "import sys\nfrom setuptools import setup, find_packages\nfrom hifiberrydsp import __version__ as hifiberrydsp_version\nimpo"
  },
  {
    "path": "systemd/sigmatcpserver.service",
    "chars": 749,
    "preview": "[Unit]\nDescription=HiFiBerry DSP TCP/REST API service\nAfter=network.target\n\n[Service]\n# --store: dump DSP data memory on"
  },
  {
    "path": "test-dsptoolkit.sh",
    "chars": 309,
    "preview": "#!/bin/bash\n#\n# Some simple tests\n#\ncd `dirname $0`\nBASEDIR=`pwd`\nPATH=$BASEDIR/bin:$PATH\nexport $PATH\nPYTHONPATH=$BASED"
  },
  {
    "path": "test_autoload_filters.py",
    "chars": 6631,
    "preview": "#!/usr/bin/env python3\n\"\"\"\nTest script for the filter autoloading functionality\n\"\"\"\n\nimport os\nimport sys\nimport tempfil"
  },
  {
    "path": "test_filter_store.py",
    "chars": 6684,
    "preview": "#!/usr/bin/env python3\n\"\"\"\nTest script for the filter store functionality using checksums\n\"\"\"\n\nimport json\nimport os\nimp"
  }
]

// ... and 15 more files (download for full content)

About this extraction

This page contains the full source code of the hifiberry/hifiberry-dsp GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 145 files (4.8 MB), approximately 1.3M tokens, and a symbol index with 460 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!