Add installation instructions for MacBook Pro 15,1 DSP graph under Linux

- Document prerequisites including kernel, ALSA, and required packages.
- Provide steps to clone the repository and install LV2 plugin dependencies.
- Include instructions for verifying plugin URIs and applying the graph.
- Outline troubleshooting steps for common issues.
This commit is contained in:
mynameisdeleted
2026-08-29 09:10:16 -04:00
parent a3e795767b
commit 97b8229ce1
9 changed files with 288 additions and 13 deletions

BIN
15_1/tweeters-44k.wav Normal file

Binary file not shown.

BIN
15_1/tweeters-48k.wav Normal file

Binary file not shown.

BIN
15_1/tweeters-96k.wav Normal file

Binary file not shown.

BIN
15_1/woofers-44k.wav Normal file

Binary file not shown.

BIN
15_1/woofers-48k.wav Normal file

Binary file not shown.

BIN
15_1/woofers-96k.wav Normal file

Binary file not shown.

215
INSTALL.md Normal file
View File

@@ -0,0 +1,215 @@
# Install
How to get this DSP graph running on a **MacBook Pro 15,1** under Linux (T2 /
`t2linux`, or Asahi on the Intel-T2 stack where applicable).
For what the graph *does*, see [README.md](README.md). This file is only the
mechanics of getting the pieces in place.
---
## 1. What has to be true first
This repo is **just a `graph.json`** (plus `apply.sh`). It is not a driver and
not self-contained. Three things must already exist on the machine:
| Requirement | Provided by | Why |
|---|---|---|
| Raw speaker PCM exposed by the kernel/ALSA | the `t2linux` kernel + ALSA stack | there is nothing to process otherwise |
| A hidden sink `alsa_output.platform-sound.RawSpeakers` with a filter-chain spliced in front of it | the **t2 speaker-DSP package** (`t2-linux-audio` / `t2-apple-audio-dsp`), specifically its WirePlumber drop-in `51-t2-dsp.conf` | this graph *attaches to* that spliced filter-chain; no package → no sink → nothing to apply |
| The FIR correction files at `/usr/share/t2-linux-audio/15_1/` | the same package | `graph.json` references them by absolute path (see §4) |
| The LV2 plugins the graph loads | your distro + a source build for one of them | see §3 |
If `wpctl status` shows no **"MacBook Pro 15,1 DSP Speakers"** sink and no
`alsa_output.platform-sound.RawSpeakers`, stop here and install the t2 speaker-DSP
package for your distro first — see <https://wiki.t2linux.org/guides/audio-config/>.
---
## 2. Get the repo
```sh
git clone <this-repo> mbp15-1-audio-dsp
cd mbp15-1-audio-dsp
```
---
## 3. LV2 plugin dependencies
The graph loads four LV2 plugins from three bundles. (`copy` and `convolver` are
PipeWire builtins — nothing to install.)
| Plugin URI in `graph.json` | Bundle | Package (varies by distro) |
|---|---|---|
| `http://lsp-plug.in/plugins/lv2/para_equalizer_x16_stereo` | LSP Plugins | `lsp-plugins` / `lsp-plugins-lv2` |
| `http://lsp-plug.in/plugins/lv2/mb_compressor_stereo` | LSP Plugins | ″ |
| `http://lsp-plug.in/plugins/lv2/loud_comp_mono` | LSP Plugins | ″ |
| `http://plugin.org.uk/swh-plugins/fastLookaheadLimiter` | SWH Plugins | `swh-plugins` / `lv2-swh-plugins` |
| `https://chadmed.au/bankstown` | Bankstown | **not packaged on most distros — build from source** |
### 3a. LSP + SWH (from your package manager)
```sh
# Fedora / Fedora Asahi Remix
sudo dnf install lsp-plugins swh-plugins
# Arch / t2linux
sudo pacman -S lsp-plugins swh-plugins # or AUR: lsp-plugins-lv2
# Debian / Ubuntu
sudo apt install lsp-plugins swh-plugins
```
Package names drift — if the above miss, search: `dnf search lsp`,
`pacman -Ss lsp-plugins`, `apt-cache search swh`. The authority is whether the
URIs resolve (§3c), not the package name.
### 3b. Bankstown (source build)
Bankstown (`virtualbass` in the graph) is chadmed's psychoacoustic bass plugin.
On Fedora Asahi Remix it ships in the `asahi-audio` stack; everywhere else,
build it:
```sh
# needs: rust/cargo, clang, lv2 headers, git
git clone https://github.com/chadmed/bankstown
cd bankstown
make # runs: cargo build --release
# install the bundle. LIBDIR defaults to /usr/lib64 — override on distros
# that use /usr/lib (Arch, Debian/Ubuntu):
sudo make install # Fedora
sudo make install LIBDIR=/usr/lib # Arch, Debian, Ubuntu
# → installs to $LIBDIR/lv2/bankstown.lv2/
cd ..
```
Per-user install (no sudo) also works — copy the built
`target/release/libbankstown.so` → `~/.lv2/bankstown.lv2/bankstown.so` alongside
`bankstown.ttl` and `manifest.ttl` from the repo.
### 3c. Verify all four URIs resolve
```sh
for uri in \
http://lsp-plug.in/plugins/lv2/para_equalizer_x16_stereo \
http://lsp-plug.in/plugins/lv2/mb_compressor_stereo \
http://lsp-plug.in/plugins/lv2/loud_comp_mono \
http://plugin.org.uk/swh-plugins/fastLookaheadLimiter \
https://chadmed.au/bankstown ; do
lv2ls | grep -qxF "$uri" && echo "ok $uri" || echo "MISSING $uri"
done
```
Every line must say `ok`. `lv2ls` is from `lilv` (`lilv-utils` / `lilv`).
---
## 4. FIR correction files
`graph.json` references them by **absolute path**:
```
/usr/share/t2-linux-audio/15_1/tweeters-44k.wav tweeters-48k.wav tweeters-96k.wav
/usr/share/t2-linux-audio/15_1/woofers-44k.wav woofers-48k.wav woofers-96k.wav
```
```sh
ls -l /usr/share/t2-linux-audio/15_1/*.wav
```
These are **not vendored in this repo** and the paths are **deliberately not
relative**:
- The t2 speaker-DSP package installs them to this fixed FHS path on every
distro, and you already need that package for the sink to exist at all (§1),
so the absolute path is stable wherever the prerequisite is met.
- PipeWire's convolver resolves a non-absolute `filename` against the process
working directory, which for a WirePlumber-spawned service is unpredictable
(`/` or `$HOME`). Relative paths would be *less* portable, not more.
If you have your own recalibrated FIRs, drop them at that path (or edit the six
`filename` entries in `graph.json` to point at yours) before §5.
---
## 5. Apply
```sh
./apply.sh
```
This does:
1. `sudo cp graph.json /usr/share/t2-linux-audio/15_1/graph.json`
2. `systemctl --user restart wireplumber`
Optional sanity check first (the tool is `python3-json` / stdlib):
```sh
python3 -m json.tool graph.json > /dev/null && echo "graph.json OK"
```
---
## 6. Confirm it loaded
```sh
wpctl status | grep -i "DSP Speakers"
pw-cli ls Node | grep -i t2-151-speakers
```
Select **"MacBook Pro 15,1 DSP Speakers"** as the output (`wpctl set-default
<id>`, or your DE's sound settings), then play something.
To watch the plugins actually run / spot xruns:
```sh
pw-top # look for the filter-chain node, check for XRUN
```
---
## 7. Pick a sound profile
`user_eq` is the first node in the graph and the only block meant for
hand-editing — an 8-band tone control that defaults flat (= the reference
voicing). Paste one of the preset rows from
[README.md § User preference EQ](README.md#user-preference-eq) into its `control`
block and re-run `./apply.sh`.
---
## 8. After a system update
A `t2-linux-audio` package update **overwrites**
`/usr/share/t2-linux-audio/15_1/graph.json` and silently reverts to the stock
graph. Re-run `./apply.sh` afterward. (Plugin packages updating is fine — the
graph only cares that the URIs still resolve.)
---
## 9. Revert to stock
```sh
sudo cp /path/to/t2-apple-audio-dsp/configs/15_1/graph.json \
/usr/share/t2-linux-audio/15_1/graph.json
systemctl --user restart wireplumber
```
Or reinstall the t2 speaker-DSP package.
---
## Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| No "DSP Speakers" sink after apply | t2 speaker-DSP package / `51-t2-dsp.conf` not installed | §1 |
| Sink present, but silent / falls back to another device | a plugin URI failed to load, so the whole filter-chain fails | §3c — find the `MISSING` line |
| `wireplumber` won't start after apply | malformed `graph.json` | `python3 -m json.tool graph.json`; `journalctl --user -u wireplumber -b` |
| Works, but no bass enhancement | `bankstown` (`virtualbass`) not loaded | §3b, then §3c |
| Distortion when loud | drive too high for your unit — see [README.md § Tuning knobs](README.md#tuning-knobs) | lower `wlim.limit`, or the `user_eq` bass bands |
| Reverted itself after an update | expected — see §8 | re-run `./apply.sh` |

View File

@@ -64,10 +64,10 @@ This fork's answers, point by point:
## Signal chain
```
in ─▶ equalizer ─▶ virtualbass ─▶ multiband_compressor ─▶ limiter ─▶ ell/elr ─▶ copyL/R ─┬▶ convLT/convRT ─▶ tlim ─▶ out
(LSP x16) (bankstown) (LSP mb_comp x8) (fastLookahead) (loud_comp) │ (tweeter FIR) (limit)
└▶ convLW/convRW ─▶ wlim ─▶ out
(woofer FIR) (limit)
in ─▶ user_eq ─▶ equalizer ─▶ virtualbass ─▶ multiband_compressor ─▶ limiter ─▶ ell/elr ─▶ copyL/R ─┬▶ convLT/convRT ─▶ tlim ─▶ out
(LSP x16) (LSP x16) (bankstown) (LSP mb_comp x8) (fastLookahead) (loud_comp) │ (tweeter FIR) (limit)
user prefs voicing └▶ convLW/convRW ─▶ wlim ─▶ out
(woofer FIR) (limit)
```
## Changes vs. upstream `15_1/graph.json`
@@ -184,6 +184,43 @@ distortion.
60–150 Hz window, so the ear perceives low end the driver never has to
physically produce — the psychoacoustic counterpart to the 60 Hz high-pass.
## User preference EQ
`user_eq` is the **first node in the graph** and the only block meant for
hand-editing — a plain 8-band tone control for matching the sound to content
type. It defaults **flat** (every `g_*` = `1.0`), which *is* the reference
voicing; editing it never touches the calibrated `equalizer` / dynamics below.
Because it sits ahead of the compressor and limiters, even an aggressive preset
is dynamically governed — it can't clip or over-excurse, it just gets
compressed if pushed hard.
| Band | `f` | Type | Region |
|---|---|---|---|
| 0 | 70 Hz | low shelf | sub weight / rumble |
| 1 | 110 Hz | bell | bass punch |
| 2 | 220 Hz | bell | warmth / boom |
| 3 | 450 Hz | bell | body / mud |
| 4 | 1 kHz | bell | mids / nasal |
| 5 | 2.5 kHz | bell | presence / attack |
| 6 | 6 kHz | bell | detail / sibilance |
| 7 | 10 kHz | high shelf | air |
Edit the `g_*` values in the `user_eq` `control` block. **Linear, not dB**
(`+3 dB ≈ 1.41`, `−3 dB ≈ 0.71`). Keep each between `0.5` (−6 dB) and `2.0`
(+6 dB). Run `./apply.sh` after.
### Presets — the 8 `g_*` values, `g_0`…`g_7`
| Preset | 70 | 110 | 220 | 450 | 1k | 2.5k | 6k | 10k |
|---|---|---|---|---|---|---|---|---|
| **Reference** (flat) | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 |
| Rock / Pop | 1.00 | 1.26 | 1.00 | 0.94 | 1.00 | 1.12 | 1.19 | 1.12 |
| Classical / Acoustic | 1.00 | 1.00 | 1.06 | 1.00 | 1.00 | 1.00 | 1.12 | 1.12 |
| Electronic / Hip-Hop | 1.26 | 1.19 | 1.00 | 0.94 | 1.00 | 1.00 | 1.06 | 1.00 |
| Movie — dialogue | 0.84 | 0.94 | 1.00 | 1.06 | 1.19 | 1.19 | 1.06 | 1.00 |
| Movie — action | 1.41 | 1.12 | 1.00 | 1.00 | 1.00 | 1.06 | 1.12 | 1.12 |
| Late-night (low level) | 0.63 | 0.79 | 1.00 | 1.00 | 1.06 | 1.12 | 1.00 | 0.94 |
## Tuning knobs
If the woofers still bottom out or anything distorts, in order of preference:
@@ -217,16 +254,20 @@ holds the tweeter/woofer time alignment.
## Install
Full instructions — prerequisites, the LV2 plugin dependencies (LSP, SWH, and a
source build of Bankstown), the FIR files, verification and troubleshooting —
are in **[INSTALL.md](INSTALL.md)**.
Short version, once the prerequisites are met:
```sh
./apply.sh
```
This copies `graph.json` to `/usr/share/t2-linux-audio/15_1/graph.json` (needs
`sudo`) and restarts WirePlumber (`systemctl --user restart wireplumber`).
Requires the `t2-linux-audio` / `t2-apple-audio-dsp` package to already be
installed (it provides the FIR `.wav` files, `51-t2-dsp.conf`, and the
`mic.json` graph).
copies `graph.json` to `/usr/share/t2-linux-audio/15_1/graph.json` (needs `sudo`)
and restarts WirePlumber. Requires the `t2-linux-audio` / `t2-apple-audio-dsp`
package (FIR `.wav` files, `51-t2-dsp.conf`, `mic.json`) and the LV2 plugins the
graph loads.
## Revert
@@ -237,4 +278,5 @@ systemctl --user restart wireplumber
```
Note: a `t2-linux-audio` package update will overwrite the installed file and
silently revert these changes — re-run `./apply.sh` afterward.
silently revert these changes — re-run `./apply.sh` afterward. See
[INSTALL.md § 8](INSTALL.md#8-after-a-system-update).

View File

@@ -3,6 +3,22 @@
"media.name": "MacBook Pro 15,1 DSP Speakers",
"filter.graph": {
"nodes": [
{
"type": "lv2",
"plugin": "http://lsp-plug.in/plugins/lv2/para_equalizer_x16_stereo",
"name": "user_eq",
"control": {
"enabled": 1, "mode": 0, "g_in": 1.0, "g_out": 1.0,
"ft_0": 5, "f_0": 70.0, "g_0": 1.0, "q_0": 0.7, "s_0": 0,
"ft_1": 1, "f_1": 110.0, "g_1": 1.0, "q_1": 1.0,
"ft_2": 1, "f_2": 220.0, "g_2": 1.0, "q_2": 1.0,
"ft_3": 1, "f_3": 450.0, "g_3": 1.0, "q_3": 1.0,
"ft_4": 1, "f_4": 1000.0, "g_4": 1.0, "q_4": 1.0,
"ft_5": 1, "f_5": 2500.0, "g_5": 1.0, "q_5": 1.0,
"ft_6": 1, "f_6": 6000.0, "g_6": 1.0, "q_6": 1.0,
"ft_7": 3, "f_7": 10000.0, "g_7": 1.0, "q_7": 0.7, "s_7": 0
}
},
{
"type": "lv2",
"plugin": "http://lsp-plug.in/plugins/lv2/para_equalizer_x16_stereo",
@@ -190,6 +206,8 @@
}
],
"links": [
{"output": "user_eq:out_l", "input": "equalizer:in_l"},
{"output": "user_eq:out_r", "input": "equalizer:in_r"},
{"output": "equalizer:out_l", "input": "virtualbass:in_l"},
{"output": "equalizer:out_r", "input": "virtualbass:in_r"},
{"output": "virtualbass:out_l", "input": "multiband_compressor:in_l"},
@@ -210,8 +228,8 @@
{"output": "convRT:Out", "input": "tlim:in_2"}
],
"inputs": [
"equalizer:in_l",
"equalizer:in_r"
"user_eq:in_l",
"user_eq:in_r"
],
"outputs": [
"wlim:out_1",