Version 3.4.0: Edit tab (edit list, large subtitle, replacements with effects and presets), Sounds tab only browses, ackit fx (pedalboard + own reverb) and replace --fx, first Linux build, catalog without a mod package

This commit is contained in:
2026-10-28 13:54:12 +01:00
parent a706dae419
commit 6de470174e
36 changed files with 2872 additions and 278 deletions

View File

@@ -22,6 +22,13 @@ The first toolkit used ffmpeg (decoding inputs and libvorbis encoding) and vgmst
ffmpeg: an ffmpeg found on the system is used if present, otherwise the user gets a clear "convert to WAV/MP3"
message. Bundling ffmpeg (~80-100 MB, GPL/LGPL build care) for rare formats was judged not worth it.
- **Resampling:** `soxr` (LGPL-2.1).
- **Effects for replacements (any sound):** `pedalboard` (Spotify, GPL-3.0, compatible with this project's GPL-3.0; it
statically contains JUCE and the Rubber Band library): filters, distortion, codec, delay and pitch/formant
shifting (`ackit/fx.py`). The reverb is not pedalboard's (Freeverb sounded metallic): a generated room response
(early reflections + a 4-band noise tail, the highs decaying first) convolved with numpy's FFT. Chosen over
writing the DSP ourselves (user: "just use some libraries") and over scipy (no ready pitch shifter). Its
high/low-pass filters are first order only, so the voice-band cuts are Butterworth magnitudes applied with
numpy's FFT. Wheels for Python 3.14 on Windows and Linux (0.9.26); it needs only numpy.
So there are **no vendor binaries to fetch** (no `tools/fetch_vendor` script was needed): every native
dependency comes from version-pinned PyPI wheels (which embed libsndfile, libvorbis, libogg, FLAC, opus, mpg123,
Qt and Qt Multimedia's FFmpeg backend) that PyInstaller bundles, resolved relative to the app (never `PATH`).
@@ -30,7 +37,7 @@ plus official texts kept in `tools/licenses/` (sources in SOURCES.txt; no networ
its decode/encode/inject smoke test with `PATH` reduced to `C:\Windows` (no ffmpeg, vgmstream or Python).
**Licenses:** PySide6/Qt LGPL-3.0 (dynamic linking, unmodified Qt shared libraries in the one-folder build,
source at https://code.qt.io), libsndfile LGPL-2.1, mpg123 LGPL-2.1, soxr LGPL-2.1, libvorbis/libogg/FLAC/opus
BSD, numpy BSD, Python PSF. One-folder (not one-file) builds keep the LGPL libraries replaceable.
BSD, numpy BSD, pedalboard GPL-3.0, Python PSF. One-folder (not one-file) builds keep the LGPL libraries replaceable.
The only Windows-only part is the in-game test harness (`ackit verify --ingame`, uses WinDbg/cdb and WASAPI
loopback); it is a developer tool and not part of the editor.
@@ -162,15 +169,22 @@ copy per voice language) is filtered the same way, so the sound list never mixes
store does not need it.
## 7. Editor UX choices
- One window with three tabs. *Sounds*: filters (left) and sound table on top, the editor of the selected
sound below across the full width, in three resizable columns (Listen | Replace | Subtitle). Inside each
column the controls are aligned, not packed in rows that wrap: Replace's edit fields in a grid with one
label column, and every column's actions in one full-width bar at its bottom, level across the three
columns (Listen: Original | Installed | Stop; Replace: Apply to game, twice as wide, | Revert | Save WAV;
Subtitle: Apply | Revert). Every row of buttons fills its column's width (Load file / device / Record; Trim
silence / Replacement; Show in list). A/B and Loop are icon buttons with tooltips next to the volume. The editor fits a 1000-pixel-wide window without horizontal scrolling (measured:
minimum 984 px with the window's vertical scroll bar). *Subtitles* and *Menu text*: search, filters, table, editor. The primary flow
(search -> select -> Space to listen -> Load file/Record -> Apply) needs no menus; power features (tags,
- One window with four tabs; browsing and editing are separate (user, mission 4: "the browser for browsing, the
edit tab for editing, not both for both"). *Sounds*: filters (left), sound table, and below it a compact
preview (details, subtitle as text, original/installed waveforms with play buttons, **Edit** / **Add to edit
list**); no editing tools: details | player (Play original, Play installed, Stop together above the
waveforms) | Edit, Add to edit list. *Edit*: the edit list (sounds sent from the browser, kept in the user
data folder with each sound's replacement audio, trim/level values and effects; `app/edit.py`) | the editor
(`app/editor.py`, top to bottom: SUBTITLE large, with the original and the English line, room counter and
buttons on one row; LISTEN = original, installed and replacement, one row each with its play button, the
waveforms take the free height, transport row; REPLACEMENT = Record / input / level / Load file, trim and
level in an aligned grid) with its action bar (Previous | Apply to game | Revert | Save WAV | Next) pinned
below | the effects (`app/effects.py`: a preset list, the effect chain = one line per effect, tick = on, click
= its settings shown below: preset buttons and sliders with readable values, logarithmic for frequencies and
times). No scrolling at 1400 x 900 and 1280 x 800 (tested). Wording is generic (replacement, effects), not
dubbing-specific: the tab edits every kind of sound. *Subtitles* and *Menu text*:
search, filters, table, editor. The primary flow
(search -> select -> Space to listen -> Edit -> Record/Load file -> Apply -> Next) needs no menus; power features (tags,
favorites, multi-select revert, mod packages, settings) are in the toolbar and context menu.
- Long work (loading, encoding, writing 0.5 GB WADs) runs in background jobs with status messages; the
window stays responsive. Errors are shown as plain sentences (game running/locked file, wrong folder,