matchpatch 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- matchpatch-0.4.0/.gitattributes +18 -0
- matchpatch-0.4.0/.github/dependabot.yml +17 -0
- matchpatch-0.4.0/.github/workflows/quality.yml +134 -0
- matchpatch-0.4.0/.github/workflows/release.yml +128 -0
- matchpatch-0.4.0/.gitignore +20 -0
- matchpatch-0.4.0/.pre-commit-config.yaml +66 -0
- matchpatch-0.4.0/.python-version +1 -0
- matchpatch-0.4.0/AGENTS.md +35 -0
- matchpatch-0.4.0/LICENSE +21 -0
- matchpatch-0.4.0/PKG-INFO +134 -0
- matchpatch-0.4.0/Python/adjust_gain.py +20 -0
- matchpatch-0.4.0/Python/decrypt_hls.py +76 -0
- matchpatch-0.4.0/Python/encrypt_hls.py +85 -0
- matchpatch-0.4.0/Python/list_cab_presets.py +114 -0
- matchpatch-0.4.0/Python/preset_handling.py +1853 -0
- matchpatch-0.4.0/Python/remove_inactive_blocks.py +278 -0
- matchpatch-0.4.0/Python/replace_amp.py +127 -0
- matchpatch-0.4.0/Python/reset_output_levels.py +189 -0
- matchpatch-0.4.0/Python/stereofy.py +254 -0
- matchpatch-0.4.0/README.md +121 -0
- matchpatch-0.4.0/audio/reference-di/DI_Strandberg_Boden_Fusion_Bridge_Humbucker.wav +0 -0
- matchpatch-0.4.0/docs/_static/matchpatch-docs.css +8 -0
- matchpatch-0.4.0/docs/assets/matchmatch-icon-512.png +0 -0
- matchpatch-0.4.0/docs/assets/matchmatch-icon.png +0 -0
- matchpatch-0.4.0/docs/assets/matchmatch-logo.png +0 -0
- matchpatch-0.4.0/docs/assets/screenshots/backend-selector.png +0 -0
- matchpatch-0.4.0/docs/assets/screenshots/completed-results-table.png +0 -0
- matchpatch-0.4.0/docs/assets/screenshots/failed-measurement-row.png +0 -0
- matchpatch-0.4.0/docs/assets/screenshots/hardware-routing.png +0 -0
- matchpatch-0.4.0/docs/assets/screenshots/loaded-setlist.png +0 -0
- matchpatch-0.4.0/docs/assets/screenshots/normalization-ongoing.png +0 -0
- matchpatch-0.4.0/docs/assets/screenshots/optimization-dialog.png +0 -0
- matchpatch-0.4.0/docs/assets/screenshots/parameter-study-setup.png +0 -0
- matchpatch-0.4.0/docs/assets/screenshots/timing-tab.png +0 -0
- matchpatch-0.4.0/docs/concepts/backends.md +73 -0
- matchpatch-0.4.0/docs/concepts/crest-factor.md +36 -0
- matchpatch-0.4.0/docs/concepts/lufs-and-loudness.md +54 -0
- matchpatch-0.4.0/docs/concepts/measurement-and-adjusted-files.md +75 -0
- matchpatch-0.4.0/docs/concepts/reading-results.md +102 -0
- matchpatch-0.4.0/docs/concepts/reference-di.md +113 -0
- matchpatch-0.4.0/docs/concepts/routing-and-levels.md +59 -0
- matchpatch-0.4.0/docs/concepts/snapshots-solos-and-ignored.md +80 -0
- matchpatch-0.4.0/docs/concepts/timing.md +81 -0
- matchpatch-0.4.0/docs/conf.py +28 -0
- matchpatch-0.4.0/docs/dev/architecture.md +275 -0
- matchpatch-0.4.0/docs/dev/commands.md +364 -0
- matchpatch-0.4.0/docs/dev/file-formats.md +226 -0
- matchpatch-0.4.0/docs/dev/release.md +202 -0
- matchpatch-0.4.0/docs/developer-notes.md +235 -0
- matchpatch-0.4.0/docs/faq.md +192 -0
- matchpatch-0.4.0/docs/glossary.md +205 -0
- matchpatch-0.4.0/docs/index.md +112 -0
- matchpatch-0.4.0/docs/musician-guide.md +271 -0
- matchpatch-0.4.0/docs/quick-start.md +102 -0
- matchpatch-0.4.0/docs/troubleshooting.md +431 -0
- matchpatch-0.4.0/docs/workflows/custom-adjustments.md +86 -0
- matchpatch-0.4.0/docs/workflows/hardware-measurement.md +116 -0
- matchpatch-0.4.0/docs/workflows/manual-editing-and-csv.md +106 -0
- matchpatch-0.4.0/docs/workflows/normalize-setlist.md +115 -0
- matchpatch-0.4.0/docs/workflows/normalize-single-preset.md +84 -0
- matchpatch-0.4.0/docs/workflows/optimize-timing.md +97 -0
- matchpatch-0.4.0/docs/workflows/save-and-import.md +97 -0
- matchpatch-0.4.0/docs/workflows/select-changed-presets.md +73 -0
- matchpatch-0.4.0/docs/workflows/test-without-hardware.md +75 -0
- matchpatch-0.4.0/installer/README.md +91 -0
- matchpatch-0.4.0/installer/matchpatch.iss +53 -0
- matchpatch-0.4.0/installer/pyinstaller/build_support.py +125 -0
- matchpatch-0.4.0/installer/pyinstaller/matchpatch-gui.spec +69 -0
- matchpatch-0.4.0/installer/smoke/smoke_installed.ps1 +121 -0
- matchpatch-0.4.0/installer/smoke/smoke_payload.ps1 +71 -0
- matchpatch-0.4.0/pyproject.toml +97 -0
- matchpatch-0.4.0/scripts/build-docs.sh +15 -0
- matchpatch-0.4.0/scripts/build-windows-installer-from-wsl.sh +43 -0
- matchpatch-0.4.0/scripts/build-windows-installer.cmd +101 -0
- matchpatch-0.4.0/scripts/build-windows-payload.cmd +66 -0
- matchpatch-0.4.0/scripts/check_commit_msg.py +88 -0
- matchpatch-0.4.0/scripts/measure-windows-from-wsl.sh +15 -0
- matchpatch-0.4.0/scripts/release.py +666 -0
- matchpatch-0.4.0/scripts/run_hook_with_hint.py +35 -0
- matchpatch-0.4.0/scripts/stage-installer-docs.sh +36 -0
- matchpatch-0.4.0/scripts/sync-windows-from-wsl.sh +30 -0
- matchpatch-0.4.0/scripts/sync-windows.cmd +20 -0
- matchpatch-0.4.0/scripts/sync-wsl.sh +8 -0
- matchpatch-0.4.0/scripts/test-gui.sh +16 -0
- matchpatch-0.4.0/scripts/test-windows-installer-from-wsl.sh +63 -0
- matchpatch-0.4.0/scripts/test-windows-installer.cmd +95 -0
- matchpatch-0.4.0/src/matchpatch/__init__.py +20 -0
- matchpatch-0.4.0/src/matchpatch/analysis.py +97 -0
- matchpatch-0.4.0/src/matchpatch/app.py +71 -0
- matchpatch-0.4.0/src/matchpatch/audio.py +148 -0
- matchpatch-0.4.0/src/matchpatch/cli.py +70 -0
- matchpatch-0.4.0/src/matchpatch/config.py +181 -0
- matchpatch-0.4.0/src/matchpatch/custom_adjustments.py +60 -0
- matchpatch-0.4.0/src/matchpatch/devices/__init__.py +5 -0
- matchpatch-0.4.0/src/matchpatch/devices/base.py +204 -0
- matchpatch-0.4.0/src/matchpatch/devices/helix.py +447 -0
- matchpatch-0.4.0/src/matchpatch/devices/registry.py +22 -0
- matchpatch-0.4.0/src/matchpatch/gui/__init__.py +1 -0
- matchpatch-0.4.0/src/matchpatch/gui/app.py +193 -0
- matchpatch-0.4.0/src/matchpatch/gui/device_panels.py +142 -0
- matchpatch-0.4.0/src/matchpatch/gui/dialogs.py +150 -0
- matchpatch-0.4.0/src/matchpatch/gui/help.py +213 -0
- matchpatch-0.4.0/src/matchpatch/gui/main_window.py +7745 -0
- matchpatch-0.4.0/src/matchpatch/gui/snapshot_header.py +48 -0
- matchpatch-0.4.0/src/matchpatch/gui/worker.py +135 -0
- matchpatch-0.4.0/src/matchpatch/measure.py +1191 -0
- matchpatch-0.4.0/src/matchpatch/measurement_optimizer.py +646 -0
- matchpatch-0.4.0/src/matchpatch/normalize.py +874 -0
- matchpatch-0.4.0/src/matchpatch/progress.py +39 -0
- matchpatch-0.4.0/src/matchpatch/workflow.py +361 -0
- matchpatch-0.4.0/tests/README.md +117 -0
- matchpatch-0.4.0/tests/test_analysis.py +71 -0
- matchpatch-0.4.0/tests/test_app.py +81 -0
- matchpatch-0.4.0/tests/test_audio.py +162 -0
- matchpatch-0.4.0/tests/test_check_commit_msg.py +41 -0
- matchpatch-0.4.0/tests/test_cli.py +58 -0
- matchpatch-0.4.0/tests/test_config.py +77 -0
- matchpatch-0.4.0/tests/test_devices.py +51 -0
- matchpatch-0.4.0/tests/test_gui.py +5343 -0
- matchpatch-0.4.0/tests/test_gui_app.py +309 -0
- matchpatch-0.4.0/tests/test_gui_dialogs.py +95 -0
- matchpatch-0.4.0/tests/test_gui_help.py +334 -0
- matchpatch-0.4.0/tests/test_helix.py +557 -0
- matchpatch-0.4.0/tests/test_installer_metadata.py +184 -0
- matchpatch-0.4.0/tests/test_measure.py +942 -0
- matchpatch-0.4.0/tests/test_measurement_optimizer.py +585 -0
- matchpatch-0.4.0/tests/test_normalize.py +1126 -0
- matchpatch-0.4.0/tests/test_preset_handling.py +316 -0
- matchpatch-0.4.0/tests/test_progress.py +27 -0
- matchpatch-0.4.0/uv.lock +1383 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Text files
|
|
2
|
+
* text=auto eol=lf
|
|
3
|
+
|
|
4
|
+
# Windows scripts
|
|
5
|
+
*.cmd eol=crlf
|
|
6
|
+
*.bat eol=crlf
|
|
7
|
+
|
|
8
|
+
# Shell scripts
|
|
9
|
+
*.sh eol=lf
|
|
10
|
+
|
|
11
|
+
# Binary files
|
|
12
|
+
*.png binary
|
|
13
|
+
*.jpg binary
|
|
14
|
+
*.jpeg binary
|
|
15
|
+
*.gif binary
|
|
16
|
+
*.wav binary
|
|
17
|
+
*.hlx binary
|
|
18
|
+
*.hls binary
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
|
|
3
|
+
updates:
|
|
4
|
+
- package-ecosystem: "uv"
|
|
5
|
+
directory: "/"
|
|
6
|
+
schedule:
|
|
7
|
+
interval: "weekly"
|
|
8
|
+
|
|
9
|
+
- package-ecosystem: "github-actions"
|
|
10
|
+
directory: "/"
|
|
11
|
+
schedule:
|
|
12
|
+
interval: "weekly"
|
|
13
|
+
|
|
14
|
+
- package-ecosystem: "pre-commit"
|
|
15
|
+
directory: "/"
|
|
16
|
+
schedule:
|
|
17
|
+
interval: "weekly"
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
name: Quality
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
docs:
|
|
12
|
+
name: Docs / Python 3.12
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- name: Check out repository
|
|
17
|
+
uses: actions/checkout@v6
|
|
18
|
+
|
|
19
|
+
- name: Install uv and Python
|
|
20
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
21
|
+
with:
|
|
22
|
+
enable-cache: true
|
|
23
|
+
python-version: "3.12"
|
|
24
|
+
|
|
25
|
+
- name: Synchronize docs environment
|
|
26
|
+
run: uv sync --locked --no-default-groups --group docs
|
|
27
|
+
|
|
28
|
+
- name: Build docs
|
|
29
|
+
run: uv run --frozen --no-default-groups --group docs sphinx-build -W --keep-going -b html docs docs_html
|
|
30
|
+
|
|
31
|
+
native:
|
|
32
|
+
name: ${{ matrix.os }} / Python ${{ matrix.python-version }}
|
|
33
|
+
runs-on: ${{ matrix.os }}
|
|
34
|
+
strategy:
|
|
35
|
+
fail-fast: false
|
|
36
|
+
matrix:
|
|
37
|
+
os:
|
|
38
|
+
- ubuntu-latest
|
|
39
|
+
- windows-latest
|
|
40
|
+
python-version:
|
|
41
|
+
- "3.12"
|
|
42
|
+
- "3.13"
|
|
43
|
+
- "3.14"
|
|
44
|
+
|
|
45
|
+
steps:
|
|
46
|
+
- name: Check out repository
|
|
47
|
+
uses: actions/checkout@v6
|
|
48
|
+
|
|
49
|
+
- name: Install uv and Python
|
|
50
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
51
|
+
with:
|
|
52
|
+
enable-cache: ${{ runner.os != 'Windows' }}
|
|
53
|
+
python-version: ${{ matrix.python-version }}
|
|
54
|
+
|
|
55
|
+
- name: Synchronize environment
|
|
56
|
+
run: uv sync --locked --no-default-groups --group wsl --extra gui
|
|
57
|
+
|
|
58
|
+
- name: Install Qt runtime libraries
|
|
59
|
+
if: runner.os == 'Linux'
|
|
60
|
+
run: sudo apt-get update && sudo apt-get install -y libegl1
|
|
61
|
+
|
|
62
|
+
- name: Ruff lint
|
|
63
|
+
run: uv run --frozen --no-default-groups --group wsl --extra gui ruff check .
|
|
64
|
+
|
|
65
|
+
- name: Ruff format check
|
|
66
|
+
run: uv run --frozen --no-default-groups --group wsl --extra gui ruff format --check .
|
|
67
|
+
|
|
68
|
+
- name: ty
|
|
69
|
+
run: uv run --frozen --no-default-groups --group wsl --extra gui ty check
|
|
70
|
+
|
|
71
|
+
- name: pytest
|
|
72
|
+
run: uv run --frozen --no-default-groups --group wsl --extra gui pytest
|
|
73
|
+
|
|
74
|
+
wsl:
|
|
75
|
+
name: WSL / Python ${{ matrix.python-version }}
|
|
76
|
+
runs-on: windows-latest
|
|
77
|
+
strategy:
|
|
78
|
+
fail-fast: false
|
|
79
|
+
matrix:
|
|
80
|
+
python-version:
|
|
81
|
+
- "3.12"
|
|
82
|
+
- "3.13"
|
|
83
|
+
- "3.14"
|
|
84
|
+
|
|
85
|
+
steps:
|
|
86
|
+
- name: Check out repository
|
|
87
|
+
uses: actions/checkout@v6
|
|
88
|
+
|
|
89
|
+
- name: Install Ubuntu on WSL
|
|
90
|
+
uses: Vampire/setup-wsl@v7
|
|
91
|
+
with:
|
|
92
|
+
distribution: Ubuntu-24.04
|
|
93
|
+
additional-packages: curl ca-certificates
|
|
94
|
+
|
|
95
|
+
- name: Run quality checks in WSL
|
|
96
|
+
shell: wsl-bash {0}
|
|
97
|
+
run: |
|
|
98
|
+
cd "$(wslpath '${{ github.workspace }}')"
|
|
99
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
100
|
+
export PATH="$HOME/.local/bin:$PATH"
|
|
101
|
+
export UV_PYTHON="${{ matrix.python-version }}"
|
|
102
|
+
uv python install "$UV_PYTHON"
|
|
103
|
+
uv sync --locked --no-default-groups --group wsl --extra gui
|
|
104
|
+
uv run --frozen --no-default-groups --group wsl --extra gui ruff check .
|
|
105
|
+
uv run --frozen --no-default-groups --group wsl --extra gui ruff format --check .
|
|
106
|
+
uv run --frozen --no-default-groups --group wsl --extra gui ty check
|
|
107
|
+
uv run --frozen --no-default-groups --group wsl --extra gui pytest
|
|
108
|
+
|
|
109
|
+
installer:
|
|
110
|
+
name: Windows installer smoke
|
|
111
|
+
runs-on: windows-latest
|
|
112
|
+
|
|
113
|
+
steps:
|
|
114
|
+
- name: Check out repository
|
|
115
|
+
uses: actions/checkout@v6
|
|
116
|
+
|
|
117
|
+
- name: Install uv and Python
|
|
118
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
119
|
+
with:
|
|
120
|
+
python-version: "3.12"
|
|
121
|
+
|
|
122
|
+
- name: Install Inno Setup
|
|
123
|
+
run: choco install innosetup --no-progress -y
|
|
124
|
+
|
|
125
|
+
- name: Build and test installer
|
|
126
|
+
shell: cmd
|
|
127
|
+
run: scripts\test-windows-installer.cmd
|
|
128
|
+
|
|
129
|
+
- name: Upload installer artifact
|
|
130
|
+
uses: actions/upload-artifact@v4
|
|
131
|
+
with:
|
|
132
|
+
name: matchpatch-installer-smoke
|
|
133
|
+
path: dist/installer/*.exe
|
|
134
|
+
if-no-files-found: error
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
publish:
|
|
13
|
+
name: Publish to PyPI
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
environment:
|
|
16
|
+
name: pypi
|
|
17
|
+
url: https://pypi.org/p/matchpatch
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
id-token: write
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- name: Check out repository
|
|
24
|
+
uses: actions/checkout@v6
|
|
25
|
+
|
|
26
|
+
- name: Install uv and Python
|
|
27
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
28
|
+
with:
|
|
29
|
+
python-version: "3.14"
|
|
30
|
+
|
|
31
|
+
- name: Verify tag matches package version
|
|
32
|
+
shell: bash
|
|
33
|
+
run: |
|
|
34
|
+
package_version="$(python -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])')"
|
|
35
|
+
test "${GITHUB_REF_NAME}" = "v${package_version}"
|
|
36
|
+
|
|
37
|
+
- name: Build distributions
|
|
38
|
+
run: uv build --no-sources
|
|
39
|
+
|
|
40
|
+
- name: Smoke test wheel
|
|
41
|
+
shell: bash
|
|
42
|
+
run: uv run --isolated --no-project --with dist/*.whl python -c "import matchpatch"
|
|
43
|
+
|
|
44
|
+
- name: Smoke test source distribution
|
|
45
|
+
shell: bash
|
|
46
|
+
run: uv run --isolated --no-project --with dist/*.tar.gz python -c "import matchpatch"
|
|
47
|
+
|
|
48
|
+
- name: Synchronize docs environment
|
|
49
|
+
run: uv sync --locked --no-default-groups --group docs
|
|
50
|
+
|
|
51
|
+
- name: Build offline docs
|
|
52
|
+
run: uv run --frozen --no-default-groups --group docs sphinx-build -W --keep-going -b html docs docs_html
|
|
53
|
+
|
|
54
|
+
- name: Stage installer docs payload
|
|
55
|
+
shell: bash
|
|
56
|
+
run: |
|
|
57
|
+
mkdir -p installer-payload/docs_html
|
|
58
|
+
cp -a docs_html/. installer-payload/docs_html/
|
|
59
|
+
test -f installer-payload/docs_html/index.html
|
|
60
|
+
|
|
61
|
+
- name: Upload installer docs payload
|
|
62
|
+
uses: actions/upload-artifact@v4
|
|
63
|
+
with:
|
|
64
|
+
name: matchpatch-docs-html-${{ github.ref_name }}
|
|
65
|
+
path: installer-payload/
|
|
66
|
+
if-no-files-found: error
|
|
67
|
+
|
|
68
|
+
- name: Publish distributions
|
|
69
|
+
run: uv publish
|
|
70
|
+
|
|
71
|
+
windows-installer:
|
|
72
|
+
name: Windows installer
|
|
73
|
+
runs-on: windows-latest
|
|
74
|
+
permissions:
|
|
75
|
+
contents: write
|
|
76
|
+
|
|
77
|
+
steps:
|
|
78
|
+
- name: Check out repository
|
|
79
|
+
uses: actions/checkout@v6
|
|
80
|
+
|
|
81
|
+
- name: Install uv and Python
|
|
82
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
83
|
+
with:
|
|
84
|
+
python-version: "3.12"
|
|
85
|
+
|
|
86
|
+
- name: Resolve package version
|
|
87
|
+
id: version
|
|
88
|
+
shell: pwsh
|
|
89
|
+
run: |
|
|
90
|
+
$version = python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])"
|
|
91
|
+
if ($env:GITHUB_REF_NAME -ne "v$version") {
|
|
92
|
+
throw "Release tag '$env:GITHUB_REF_NAME' does not match package version 'v$version'."
|
|
93
|
+
}
|
|
94
|
+
"version=$version" >> $env:GITHUB_OUTPUT
|
|
95
|
+
"installer=dist/installer/MatchPatch-Setup-$version.exe" >> $env:GITHUB_OUTPUT
|
|
96
|
+
|
|
97
|
+
- name: Install Inno Setup
|
|
98
|
+
run: choco install innosetup --no-progress -y
|
|
99
|
+
|
|
100
|
+
- name: Build and test installer
|
|
101
|
+
shell: cmd
|
|
102
|
+
run: scripts\test-windows-installer.cmd
|
|
103
|
+
|
|
104
|
+
- name: Upload installer artifact
|
|
105
|
+
uses: actions/upload-artifact@v4
|
|
106
|
+
with:
|
|
107
|
+
name: matchpatch-installer-${{ github.ref_name }}
|
|
108
|
+
path: ${{ steps.version.outputs.installer }}
|
|
109
|
+
if-no-files-found: error
|
|
110
|
+
|
|
111
|
+
- name: Attach installer to GitHub Release
|
|
112
|
+
shell: pwsh
|
|
113
|
+
env:
|
|
114
|
+
GH_TOKEN: ${{ github.token }}
|
|
115
|
+
run: |
|
|
116
|
+
$tag = $env:GITHUB_REF_NAME
|
|
117
|
+
$installer = "${{ steps.version.outputs.installer }}"
|
|
118
|
+
if (-not (Test-Path -LiteralPath $installer)) {
|
|
119
|
+
throw "Installer artifact was not found: $installer"
|
|
120
|
+
}
|
|
121
|
+
gh release view $tag 2>$null
|
|
122
|
+
if ($LASTEXITCODE -ne 0) {
|
|
123
|
+
gh release create $tag --title $tag --notes "MatchPatch $tag"
|
|
124
|
+
if ($LASTEXITCODE -ne 0) {
|
|
125
|
+
throw "Failed to create GitHub Release for $tag."
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
gh release upload $tag $installer --clobber
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Attic
|
|
2
|
+
Backups
|
|
3
|
+
Media
|
|
4
|
+
Unused
|
|
5
|
+
__pycache__
|
|
6
|
+
.venv
|
|
7
|
+
.venv-wsl
|
|
8
|
+
.venv-windows
|
|
9
|
+
.coverage
|
|
10
|
+
htmlcov
|
|
11
|
+
/docs_html/
|
|
12
|
+
/dist/
|
|
13
|
+
/build/
|
|
14
|
+
/plans/
|
|
15
|
+
/installer-payload/
|
|
16
|
+
*.spec.bak
|
|
17
|
+
*.json
|
|
18
|
+
*.hls
|
|
19
|
+
*.hlx
|
|
20
|
+
matchpatch_normalization_*
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
default_install_hook_types:
|
|
2
|
+
- pre-commit
|
|
3
|
+
- commit-msg
|
|
4
|
+
- pre-push
|
|
5
|
+
|
|
6
|
+
repos:
|
|
7
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
8
|
+
rev: v6.0.0
|
|
9
|
+
hooks:
|
|
10
|
+
- id: trailing-whitespace
|
|
11
|
+
- id: end-of-file-fixer
|
|
12
|
+
- id: check-yaml
|
|
13
|
+
- id: check-toml
|
|
14
|
+
- id: check-added-large-files
|
|
15
|
+
exclude: ^(audio/reference-di/|doc/assets/matchmatch-logo\.png$)
|
|
16
|
+
|
|
17
|
+
- repo: local
|
|
18
|
+
hooks:
|
|
19
|
+
- id: conventional-commit
|
|
20
|
+
name: Conventional commit message
|
|
21
|
+
entry: python scripts/check_commit_msg.py
|
|
22
|
+
language: python
|
|
23
|
+
stages:
|
|
24
|
+
- commit-msg
|
|
25
|
+
|
|
26
|
+
- id: ruff-lint
|
|
27
|
+
name: Ruff lint
|
|
28
|
+
entry: >-
|
|
29
|
+
bash -c 'export UV_PROJECT_ENVIRONMENT="${XDG_DATA_HOME:-$HOME/.local/share}/matchpatch/.venv-wsl";
|
|
30
|
+
python3 scripts/run_hook_with_hint.py
|
|
31
|
+
--hint "UV_PROJECT_ENVIRONMENT=\"\${XDG_DATA_HOME:-\$HOME/.local/share}/matchpatch/.venv-wsl\" uv run --frozen --no-default-groups --group wsl ruff check --fix ."
|
|
32
|
+
-- uv run --frozen --no-default-groups --group wsl ruff check .'
|
|
33
|
+
language: system
|
|
34
|
+
pass_filenames: false
|
|
35
|
+
|
|
36
|
+
- id: ruff-format
|
|
37
|
+
name: Ruff format check
|
|
38
|
+
entry: >-
|
|
39
|
+
bash -c 'export UV_PROJECT_ENVIRONMENT="${XDG_DATA_HOME:-$HOME/.local/share}/matchpatch/.venv-wsl";
|
|
40
|
+
python3 scripts/run_hook_with_hint.py
|
|
41
|
+
--hint "UV_PROJECT_ENVIRONMENT=\"\${XDG_DATA_HOME:-\$HOME/.local/share}/matchpatch/.venv-wsl\" uv run --frozen --no-default-groups --group wsl ruff format ."
|
|
42
|
+
-- uv run --frozen --no-default-groups --group wsl ruff format --check .'
|
|
43
|
+
language: system
|
|
44
|
+
pass_filenames: false
|
|
45
|
+
|
|
46
|
+
- id: ty
|
|
47
|
+
name: ty
|
|
48
|
+
entry: >-
|
|
49
|
+
bash -c 'export UV_PROJECT_ENVIRONMENT="${XDG_DATA_HOME:-$HOME/.local/share}/matchpatch/.venv-wsl";
|
|
50
|
+
python3 scripts/run_hook_with_hint.py
|
|
51
|
+
--hint "UV_PROJECT_ENVIRONMENT=\"\${XDG_DATA_HOME:-\$HOME/.local/share}/matchpatch/.venv-wsl\" uv run --frozen --no-default-groups --group wsl ty check"
|
|
52
|
+
-- uv run --frozen --no-default-groups --group wsl ty check'
|
|
53
|
+
language: system
|
|
54
|
+
pass_filenames: false
|
|
55
|
+
|
|
56
|
+
- id: pytest
|
|
57
|
+
name: pytest
|
|
58
|
+
entry: >-
|
|
59
|
+
bash -c 'export UV_PROJECT_ENVIRONMENT="${XDG_DATA_HOME:-$HOME/.local/share}/matchpatch/.venv-wsl";
|
|
60
|
+
python3 scripts/run_hook_with_hint.py
|
|
61
|
+
--hint "UV_PROJECT_ENVIRONMENT=\"\${XDG_DATA_HOME:-\$HOME/.local/share}/matchpatch/.venv-wsl\" uv run --frozen --no-default-groups --group wsl pytest"
|
|
62
|
+
-- uv run --frozen --no-default-groups --group wsl pytest'
|
|
63
|
+
language: system
|
|
64
|
+
pass_filenames: false
|
|
65
|
+
stages:
|
|
66
|
+
- pre-push
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# MatchPatch Agent Notes
|
|
2
|
+
|
|
3
|
+
Python package in `src/matchpatch`; legacy Helix JSON/HLS utilities live in `Python/`.
|
|
4
|
+
Use existing WSL env, not bare `pytest` or a stale project `.venv`:
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
scripts/sync-wsl.sh
|
|
8
|
+
$HOME/.local/share/matchpatch/.venv-wsl/bin/pytest
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
For GUI work use:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
scripts/test-gui.sh [pytest args]
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Quality checks:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
ruff check .
|
|
21
|
+
ruff format --check .
|
|
22
|
+
ty check
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Run them from the synced WSL env, or via the pre-push hook. GUI tests use PySide6
|
|
26
|
+
with offscreen Qt. Prefer focused tests in `tests/test_gui.py` for window/widget
|
|
27
|
+
changes, and broaden only when behavior crosses workflows.
|
|
28
|
+
|
|
29
|
+
MatchPatch normalizes Helix `.hls` setlists and `.hlx` presets. Core flow:
|
|
30
|
+
`workflow.py` creates/uses measurement CSVs, `normalize.py` bridges WSL to the
|
|
31
|
+
native Windows worker, `measure.py` records/analyzes audio, device profiles adapt
|
|
32
|
+
processor files and steering. Keep new device-specific behavior behind
|
|
33
|
+
`DeviceProfile`/`PatchFileHandler`/`DeviceController`. Preserve the user’s dirty
|
|
34
|
+
worktree; do not revert unrelated edits. Prefer `rg`, focused patches, and tests
|
|
35
|
+
that mock hardware unless the user explicitly asks for real-device integration.
|
matchpatch-0.4.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MatchPatch contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: matchpatch
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Audio processor preset gain normalization and measurement tools
|
|
5
|
+
Project-URL: Homepage, https://github.com/noseglasses/MatchPatch
|
|
6
|
+
Project-URL: Issues, https://github.com/noseglasses/MatchPatch/issues
|
|
7
|
+
Project-URL: Repository, https://github.com/noseglasses/MatchPatch.git
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Python: <3.15,>=3.12
|
|
10
|
+
Provides-Extra: gui
|
|
11
|
+
Requires-Dist: pyside6>=6.8; extra == 'gui'
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# MatchPatch
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
<img src="docs/assets/matchmatch-logo.png" alt="MatchPatch: Normalize presets. Match volume." width="260">
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
[](https://github.com/noseglasses/MatchPatch/actions/workflows/quality.yml)
|
|
21
|
+
[](https://github.com/noseglasses/MatchPatch/actions/workflows/release.yml)
|
|
22
|
+
[](https://pypi.org/project/matchpatch/)
|
|
23
|
+
[](https://pypi.org/project/matchpatch/)
|
|
24
|
+
|
|
25
|
+
<p align="center">
|
|
26
|
+
<strong><a href="https://youtu.be/Dw1Kez0AnCk">Watch the demo video</a></strong>
|
|
27
|
+
·
|
|
28
|
+
<strong><a href="https://noseglasses.github.io/MatchPatch/">Read the documentation</a></strong>
|
|
29
|
+
·
|
|
30
|
+
<strong><a href="https://github.com/noseglasses/MatchPatch/releases/latest">Download MatchPatch</a></strong>
|
|
31
|
+
</p>
|
|
32
|
+
|
|
33
|
+

|
|
34
|
+
|
|
35
|
+
**No more unexpected volume jumps when switching sounds.**
|
|
36
|
+
|
|
37
|
+
MatchPatch automatically equalizes the loudness of presets and snapshots in
|
|
38
|
+
guitar processors such as the Line 6 Helix.
|
|
39
|
+
|
|
40
|
+
## Why MatchPatch?
|
|
41
|
+
|
|
42
|
+
You create a great clean sound. You create a great lead sound. Then you switch
|
|
43
|
+
between them and one is much louder than the other.
|
|
44
|
+
|
|
45
|
+
MatchPatch measures your presets and calculates the gain adjustments needed to
|
|
46
|
+
make them consistent, so your setlist feels balanced before rehearsal or stage
|
|
47
|
+
use.
|
|
48
|
+
|
|
49
|
+
## Features
|
|
50
|
+
|
|
51
|
+
- Measure preset loudness automatically.
|
|
52
|
+
- Analyze snapshots.
|
|
53
|
+
- Calculate required gain corrections.
|
|
54
|
+
- Modify Helix setlists and presets.
|
|
55
|
+
- Test the workflow without hardware.
|
|
56
|
+
- Configure normal runs from the GUI.
|
|
57
|
+
- Use CLI and worker commands for advanced scripting.
|
|
58
|
+
- Open source.
|
|
59
|
+
|
|
60
|
+
## Current Support
|
|
61
|
+
|
|
62
|
+
Current normal workflows support:
|
|
63
|
+
|
|
64
|
+
- Line 6 Helix
|
|
65
|
+
- `.hls` Helix setlists
|
|
66
|
+
- `.hlx` Helix presets
|
|
67
|
+
- GUI-first workflows
|
|
68
|
+
|
|
69
|
+
Loopback and simulated modes are available for no-hardware tests. Hardware mode
|
|
70
|
+
is for real Helix measurement.
|
|
71
|
+
|
|
72
|
+
## Documentation
|
|
73
|
+
|
|
74
|
+
- Online manual: [noseglasses.github.io/MatchPatch](https://noseglasses.github.io/MatchPatch/)
|
|
75
|
+
- Start here: [docs/index.md](docs/index.md)
|
|
76
|
+
- 10-minute guide: [docs/quick-start.md](docs/quick-start.md)
|
|
77
|
+
- Main manual: [docs/musician-guide.md](docs/musician-guide.md)
|
|
78
|
+
- Test without hardware: [docs/workflows/test-without-hardware.md](docs/workflows/test-without-hardware.md)
|
|
79
|
+
- Hardware measurement: [docs/workflows/hardware-measurement.md](docs/workflows/hardware-measurement.md)
|
|
80
|
+
- Reference DI: [docs/concepts/reference-di.md](docs/concepts/reference-di.md)
|
|
81
|
+
- Troubleshooting: [docs/troubleshooting.md](docs/troubleshooting.md)
|
|
82
|
+
- FAQ: [docs/faq.md](docs/faq.md)
|
|
83
|
+
- Glossary: [docs/glossary.md](docs/glossary.md)
|
|
84
|
+
|
|
85
|
+
## Safety Notes
|
|
86
|
+
|
|
87
|
+
> Warning:
|
|
88
|
+
> Keep backups of your original Helix files.
|
|
89
|
+
|
|
90
|
+
> Warning:
|
|
91
|
+
> Measurement files are for measuring, not for live playing.
|
|
92
|
+
|
|
93
|
+
## Install And Launch
|
|
94
|
+
|
|
95
|
+
On Windows, download the latest installer from
|
|
96
|
+
[GitHub Releases](https://github.com/noseglasses/MatchPatch/releases/latest),
|
|
97
|
+
run `MatchPatch-Setup-<version>.exe`, then launch MatchPatch from the Start
|
|
98
|
+
Menu. The installed app bundles offline Help, available from the GUI.
|
|
99
|
+
|
|
100
|
+
For source checkouts, use the verified local setup commands below and see
|
|
101
|
+
[Developer Notes](docs/developer-notes.md) and
|
|
102
|
+
[developer commands](docs/dev/commands.md) for fuller setup details.
|
|
103
|
+
|
|
104
|
+
Install the optional GUI support and launch MatchPatch:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# Linux or WSL
|
|
108
|
+
scripts/sync-wsl.sh --extra gui
|
|
109
|
+
matchpatch-gui
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
```powershell
|
|
113
|
+
# Windows PowerShell
|
|
114
|
+
cd C:\src\MatchPatch-windows
|
|
115
|
+
.\scripts\sync-windows.cmd --extra gui
|
|
116
|
+
.\.venv-windows\Scripts\matchpatch-gui.exe
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Hardware measurement from WSL needs a synced native Windows runtime. See
|
|
120
|
+
[developer commands](docs/dev/commands.md) before using real Helix hardware from
|
|
121
|
+
WSL.
|
|
122
|
+
|
|
123
|
+
## Advanced And Developer Information
|
|
124
|
+
|
|
125
|
+
Technical details live in the developer docs:
|
|
126
|
+
|
|
127
|
+
- [Developer Notes](docs/developer-notes.md)
|
|
128
|
+
- [Architecture](docs/dev/architecture.md)
|
|
129
|
+
- [Commands](docs/dev/commands.md)
|
|
130
|
+
- [File Formats](docs/dev/file-formats.md)
|
|
131
|
+
|
|
132
|
+
## License
|
|
133
|
+
|
|
134
|
+
MatchPatch is open source software released under the [MIT License](LICENSE).
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Compatibility wrapper for the historical Helix adjustment command."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
PROJECT_DIR = Path(__file__).resolve().parent.parent
|
|
10
|
+
sys.path.insert(0, str(PROJECT_DIR / "src"))
|
|
11
|
+
|
|
12
|
+
from matchpatch.normalize import main # noqa: E402
|
|
13
|
+
|
|
14
|
+
if __name__ == "__main__":
|
|
15
|
+
arguments = sys.argv[1:]
|
|
16
|
+
|
|
17
|
+
if "--device" not in arguments:
|
|
18
|
+
arguments = ["--device", "helix", *arguments]
|
|
19
|
+
|
|
20
|
+
main(arguments)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import base64
|
|
5
|
+
import json
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
import zlib
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def require_extension(path, expected_ext, label):
|
|
12
|
+
ext = os.path.splitext(path)[1].lower()
|
|
13
|
+
|
|
14
|
+
if ext != expected_ext:
|
|
15
|
+
raise ValueError(f"{label} must have extension {expected_ext}, got {ext or '<none>'}")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_extension(path):
|
|
19
|
+
return os.path.splitext(path)[1].lower()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def parse_args():
|
|
23
|
+
parser = argparse.ArgumentParser(
|
|
24
|
+
description=(
|
|
25
|
+
"Decrypt/unpack a Helix .hls file to JSON, or validate/copy a .hlx preset to .hlx"
|
|
26
|
+
)
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
parser.add_argument("-i", "--input", required=True, help="Input .hls or .hlx file")
|
|
30
|
+
|
|
31
|
+
parser.add_argument(
|
|
32
|
+
"-o",
|
|
33
|
+
"--output",
|
|
34
|
+
required=True,
|
|
35
|
+
help="Output .json file for .hls input, or .hlx for .hlx input",
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
return parser.parse_args()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def main():
|
|
42
|
+
args = parse_args()
|
|
43
|
+
|
|
44
|
+
input_ext = get_extension(args.input)
|
|
45
|
+
|
|
46
|
+
if input_ext == ".hlx":
|
|
47
|
+
require_extension(args.output, ".hlx", "Output")
|
|
48
|
+
|
|
49
|
+
with open(args.input, "r", encoding="utf-8") as f:
|
|
50
|
+
preset = json.load(f)
|
|
51
|
+
|
|
52
|
+
with open(args.output, "w", encoding="utf-8") as f:
|
|
53
|
+
json.dump(preset, f, indent=1)
|
|
54
|
+
|
|
55
|
+
return
|
|
56
|
+
|
|
57
|
+
require_extension(args.input, ".hls", "Input")
|
|
58
|
+
require_extension(args.output, ".json", "Output")
|
|
59
|
+
|
|
60
|
+
with open(args.input, "r", encoding="utf-8") as f:
|
|
61
|
+
wrapper = json.load(f)
|
|
62
|
+
|
|
63
|
+
compressed = base64.b64decode(wrapper["encoded_data"])
|
|
64
|
+
raw = zlib.decompress(compressed)
|
|
65
|
+
text = raw.decode("utf-8")
|
|
66
|
+
|
|
67
|
+
with open(args.output, "w", encoding="utf-8") as f:
|
|
68
|
+
f.write(text)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
if __name__ == "__main__":
|
|
72
|
+
try:
|
|
73
|
+
main()
|
|
74
|
+
except Exception as exc:
|
|
75
|
+
print(f"ERROR: {exc}", file=sys.stderr)
|
|
76
|
+
sys.exit(1)
|