Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
156 commits
Select commit Hold shift + click to select a range
b5fb123
Added: the NES register model for the player
JakimPL Aug 18, 2026
d7cc9ff
Added: the play-call clock for the player
JakimPL Aug 18, 2026
a6a172c
Merge branch 'main' into nsf
JakimPL Aug 18, 2026
eec0b98
Added: the song format and the register-trace model for the player
JakimPL Aug 18, 2026
51b3006
Added: a CC65 driver stub
JakimPL Aug 19, 2026
e273545
Refactored: the NES driver
JakimPL Aug 19, 2026
863ddd0
Bumped: project version
JakimPL Aug 19, 2026
8afd286
Refactored: the player's song and schedule as models
JakimPL Aug 19, 2026
5b20ffc
Merge branch 'dev' into nsf
JakimPL Aug 19, 2026
6228ea4
Updated: glossary
JakimPL Aug 19, 2026
ec9f42c
Added: a declared import graph for the packages and the player
JakimPL Aug 19, 2026
2b50d2c
Added: version-upgrade engine for stored data formats
JakimPL Aug 19, 2026
c068dda
Moved: equal temperament to the shared package
JakimPL Aug 19, 2026
9e0a322
Merge branch 'nsf' into stems
JakimPL Aug 19, 2026
039b6a1
Merge branch 'nsf' into stems
JakimPL Aug 19, 2026
9dd6733
Renamed: GeneratorName to ChannelName
JakimPL Aug 19, 2026
c7da7d1
Renamed: LibraryGeneratorName to GeneratorName
JakimPL Aug 19, 2026
4df1611
Fixed: reconstruction upgrade
JakimPL Aug 19, 2026
4460a88
Updated: changelog
JakimPL Aug 19, 2026
3aefe6e
Resolved: same-kind channels score through the lowest free channel
JakimPL Aug 19, 2026
26ab1cd
Refactored: candidate scoring into a shared frame matcher
JakimPL Aug 19, 2026
f95faf1
Added: stems frame assignment
JakimPL Aug 19, 2026
20af57c
Added: stems assignment tests
JakimPL Aug 19, 2026
90e3211
Partially implemented: stems
JakimPL Aug 20, 2026
57dada8
Added: the NSF file export
JakimPL Aug 20, 2026
0b32a9e
Added: py65/ffpmeg toolchain, mixing utilities
JakimPL Aug 20, 2026
21e1f8a
Introduced: multiple source audios
JakimPL Aug 20, 2026
7328f95
Merged: stems into nsf
JakimPL Aug 20, 2026
f8605f8
Routed: program lookups through the shared locator
JakimPL Aug 20, 2026
bbcb3b6
Widened: the tracker seam into an export seam
JakimPL Aug 20, 2026
39579ad
Added: an NSF export backend
JakimPL Aug 20, 2026
1cd21fe
Added: stems application card
JakimPL Aug 20, 2026
e584100
Added: application NSF export option
JakimPL Aug 21, 2026
9bca1fe
Loaded: the driver when the NSF export backend is built
JakimPL Aug 21, 2026
1054e38
Modelled: the import boundary rules
JakimPL Aug 21, 2026
4b1f502
Minor changes
JakimPL Aug 21, 2026
30895bb
Moved: the import boundary declaration into shipped configuration
JakimPL Aug 21, 2026
e9f9b30
Documented: the boundaries configuration domain
JakimPL Aug 21, 2026
a6d3b37
Stems: unify conversion around the stems pipeline
JakimPL Aug 21, 2026
ca94538
Fixed: non-refreshing stems names
JakimPL Aug 21, 2026
e67861a
Derived: the play rate from the NTSC frame rate
JakimPL Aug 21, 2026
8062a37
Merged: the stems branch into the NSF export seam
JakimPL Aug 21, 2026
2935f78
Fixed: the stem-filtered original audio and the waveform partial sum
JakimPL Aug 21, 2026
fa66a85
Merge branch 'stems' of github.com:JakimPL/SampleToNES into stems
JakimPL Aug 21, 2026
c985c77
Fixed: every channel carries one entry per frame in a stems assignment
JakimPL Aug 21, 2026
4248fe8
Restored: the configured decoder over the stems assignment
JakimPL Aug 21, 2026
cf399ae
Cut: conversion at the job seam, uniformly over stems
JakimPL Aug 21, 2026
8e189dd
Modelled: the converter's stems setup
JakimPL Aug 21, 2026
68c8bcd
Added: stems mode to the converter card
JakimPL Aug 21, 2026
72fc480
Documented: the stems conversion pipeline
JakimPL Aug 22, 2026
01b52a1
Modelled: the stems setup as an ordered list of levels
JakimPL Aug 22, 2026
440b9bd
Reworked: the converter's stems card
JakimPL Aug 22, 2026
e42e275
Extended: the browser with stems gestures
JakimPL Aug 22, 2026
312c5ab
Fixed: conversion progress and dialog sizing
JakimPL Aug 22, 2026
94513f1
Documented: the converter's stems gestures
JakimPL Aug 22, 2026
125e81d
Flattened: a project into the player's channel streams
JakimPL Aug 22, 2026
852a41e
Added: a token codec for the player's channel streams
JakimPL Aug 22, 2026
336a5b9
Increased: test coverage threshold
JakimPL Aug 22, 2026
b22a904
Extracted: measured-duration tests into their own benchmark pass
JakimPL Aug 22, 2026
6454308
Extracted: the stems list into one shared element
JakimPL Aug 22, 2026
11980cc
Reshaped: the player's song around compressed channel planes
JakimPL Aug 22, 2026
eec02ae
Refined: the stems list margins
JakimPL Aug 22, 2026
d86beb1
Fixed: the stems row hover, margins and dragging
JakimPL Aug 22, 2026
2634f7c
Sped: the codec by reusing what each parse already measured
JakimPL Aug 22, 2026
d587a54
Taught: the export to report its progress and answer a cancel
JakimPL Aug 22, 2026
2340dbb
Rebuilt: the stems card on the shared list
JakimPL Aug 22, 2026
991043d
Joined: the export service to the shared progress vocabulary
JakimPL Aug 22, 2026
7b67317
Added: stem removal from a loaded reconstruction
JakimPL Aug 22, 2026
0874fb5
Showed: what an export is doing while it runs
JakimPL Aug 22, 2026
47a1dc8
Added: the converter's overwrite confirmation
JakimPL Aug 22, 2026
26cfcc0
Fixed: the frozen application behind a dialog raised between frames
JakimPL Aug 22, 2026
5fe4076
Simplified: the interface guide and removed stale documentation links
JakimPL Aug 22, 2026
71a6616
Merged: the stems branch into the player work
JakimPL Aug 22, 2026
7cd1a6f
Taught: the console to play compressed channel planes.
JakimPL Aug 22, 2026
e54ddea
Fixed: wrong theme of a disabled remove button
JakimPL Aug 22, 2026
1e9de48
Offered: a whole song as an NSF program
JakimPL Aug 22, 2026
5e17943
Added: the reconstruction engine rate to the source card
JakimPL Aug 22, 2026
8b1a848
Added: NSF compression scheme explanation
JakimPL Aug 22, 2026
a91e556
Merge branch 'stems' into nsf
JakimPL Aug 22, 2026
20f6bfa
Matched: each stem against its own recording
JakimPL Aug 22, 2026
c7de4ea
Renamed: the project's sample pool into its voices
JakimPL Aug 23, 2026
91b166c
Unified: how a channel reads a voice into one reading
JakimPL Aug 23, 2026
518a2b6
Added: the shape, a voice written by hand rather than converted
JakimPL Aug 23, 2026
d2e1882
Carried: a shape into the tracker formats and the console
JakimPL Aug 23, 2026
76c2abd
Turned: the samples list into the voices panel, with shapes on it
JakimPL Aug 23, 2026
e2f24ef
Read: a pitch cell in the terms of the voice its channel carries
JakimPL Aug 23, 2026
c76300e
Typed: a note into the grid, piano-style, at the octave in force
JakimPL Aug 23, 2026
ef6881e
Edited: a shape's envelopes on the Reconstructions tab
JakimPL Aug 23, 2026
d9f6322
Documented: voices, shapes and the two faces of a pitch cell
JakimPL Aug 23, 2026
e3b9371
Sounded: a new shape from the moment it is placed
JakimPL Aug 23, 2026
93bd743
Opened: the voice list
JakimPL Aug 23, 2026
c89c022
Restructurized: instrument and project entities
JakimPL Aug 23, 2026
42fd99b
Renamed: the tracker's sample column into the voice column
JakimPL Aug 23, 2026
e619843
Cleanups
JakimPL Aug 23, 2026
8b2fb8b
Fixed: the generator rows of the instruction library
JakimPL Aug 23, 2026
b44a07d
Fixed: the generator rows of the instruction library
JakimPL Aug 23, 2026
2230b7f
Added: the Voice menu
JakimPL Aug 23, 2026
9a65230
Added: shortcut codebase guards
JakimPL Aug 23, 2026
35cd38c
Added: reading a FamiTracker instrument file
JakimPL Aug 23, 2026
07209bc
Added: importing a FamiTracker instrument file
JakimPL Aug 23, 2026
9dab24e
Refactored: one path for exporting an instrument
JakimPL Aug 23, 2026
10f0a69
Added: exporting a voice as an instrument file
JakimPL Aug 23, 2026
ac7e6df
Added: a new instrument from a sample's channel
JakimPL Aug 23, 2026
147ec95
Renamed: the tracker's voice column back into the sample column
JakimPL Aug 23, 2026
0498c09
Added: a reconstruction's account of how far it has come
JakimPL Aug 23, 2026
95ad930
Added: a line a task reports its own progress back to the run on
JakimPL Aug 23, 2026
9eed0ba
Renamed: the tracker's first slot from instrument to voice
JakimPL Aug 23, 2026
9c2ddff
Added: each conversion job reporting its own stages to the run
JakimPL Aug 23, 2026
8cec99b
Added: a colour for each kind of voice
JakimPL Aug 23, 2026
f178da6
Added: the voice kind to the history detail
JakimPL Aug 23, 2026
221ce21
Added: a conversion's bar reading the reconstruction under way
JakimPL Aug 24, 2026
60cfb91
Documented: how a long operation says how far it has come
JakimPL Aug 24, 2026
3f6e3f6
Colored: tracker voice slot
JakimPL Aug 24, 2026
c22487b
Updated: documentation
JakimPL Aug 24, 2026
a21c516
Fixes
JakimPL Aug 24, 2026
8c5b145
Temporarily disabled: pylint fixme
JakimPL Aug 24, 2026
b368038
Renaming
JakimPL Aug 24, 2026
aa77afb
Renaming
JakimPL Aug 24, 2026
4c03f93
Extracted: optional module availability into one helper
JakimPL Aug 24, 2026
32f0090
Fixed: platform-dependent logging and path assertions
JakimPL Aug 24, 2026
f6c44b5
Merge pull request #59 from JakimPL/color
JakimPL Aug 24, 2026
5bbf717
Added: separator between voice menu items
JakimPL Aug 24, 2026
040187e
Merge pull request #60 from JakimPL/menu
JakimPL Aug 24, 2026
1ab8b49
Added: conversion separator
JakimPL Aug 24, 2026
162e0d5
Paired: every envelope with the item it repeats from
JakimPL Aug 24, 2026
df3cb0c
Implemented: loop point parsing symbol
JakimPL Aug 24, 2026
2664b14
Retired: global loop point
JakimPL Aug 24, 2026
026c0ba
Removed: pitch widgets
JakimPL Aug 24, 2026
e637395
Added: the instrument audition
JakimPL Aug 24, 2026
de980af
Drew: a hand-written voice on the waveform card
JakimPL Aug 24, 2026
f7b4f99
Colored: the Instructions plots by their generator
JakimPL Aug 24, 2026
0dbcf0b
Recorded: an instrument edit in the history
JakimPL Aug 24, 2026
3bebf02
Told: what a voice row holds, on hover
JakimPL Aug 24, 2026
e7d5dfe
Restated: the documentation for per-envelope loops and the audition
JakimPL Aug 24, 2026
6b64f00
Fixed: a waveform series keeping the first color it was drawn in
JakimPL Aug 24, 2026
72507fb
Moved: the release deployment values out of the source tree
JakimPL Aug 24, 2026
11207e2
Corrected: the documentation left standing by per-envelope loops and …
JakimPL Aug 24, 2026
7f6d6c3
Aligned: the cancellation vocabulary with the rest of the repository
JakimPL Aug 24, 2026
febdbb0
Merged: progress into the voice features
JakimPL Aug 24, 2026
9c662fd
Kept: an instrument's release inside the FamiTracker item limit
JakimPL Aug 24, 2026
edd41bd
Renamed: the voice history actions and the spelling of a traveling stage
JakimPL Aug 24, 2026
edeac9a
Renamed: the voices panel's hooks after the voices they carry
JakimPL Aug 24, 2026
9a397ba
Sealed: the graph layers into a package so they stop shadowing the st…
JakimPL Aug 24, 2026
a0ae512
Divided: the sequencer grid panels into subpackages
JakimPL Aug 24, 2026
c47ee5d
Divided: the sequencer tab coordinator into a subpackage
JakimPL Aug 24, 2026
ae2540b
Restated: the architecture ledger and the smaller contracts the revie…
JakimPL Aug 24, 2026
0ad2113
Sounded: an audition through to the release the voice states
JakimPL Aug 25, 2026
268f8ae
Added: pitch and hi-pitch envelopes to the instruction model, the gen…
JakimPL Aug 25, 2026
a8ebc78
Added: a hi-pitch palette token and the bend rows the instruments pan…
JakimPL Aug 25, 2026
4e6d2b8
Carried: pitch and hi-pitch sequences through a FamiTracker file, pin…
JakimPL Aug 25, 2026
9c838db
Held: the bend a voice writes through the song walk and a row's modif…
JakimPL Aug 25, 2026
080c66e
Added: a refinement pass bending each chosen note onto the divider it…
JakimPL Aug 25, 2026
dd2fbc3
Added: a bend plane per tone channel
JakimPL Aug 25, 2026
75c6fc2
Fixed: incorrect benchmarks
JakimPL Aug 25, 2026
49a28ec
Merge pull request #61 from JakimPL/vibrato
JakimPL Aug 25, 2026
1004647
Merge pull request #62 from JakimPL/shapes
JakimPL Aug 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,7 @@ jobs:
run: uv run python -m pytest src/ --doctest-modules --no-cov

- name: Run the unit and integration suites with coverage
run: uv run python -m pytest -n auto --cov
run: uv run python -m pytest -n auto --cov --ignore=tests/benchmarks

- name: Run the benchmarks
run: uv run python -m pytest tests/benchmarks --no-cov
8 changes: 8 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ repos:
pass_filenames: false
verbose: true

- id: shortcut-actions
name: shortcut actions
entry: uv run scripts/checks/shortcut_actions.py
language: system
files: (\.py|^src/sampletones_config/keybindings/.*\.yaml)$
pass_filenames: false
verbose: true

- id: mypy
name: mypy
entry: uv run mypy
Expand Down
154 changes: 79 additions & 75 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,75 +1,79 @@
# SampleToNES

## v0.3.2

* Added NSF player and export.

## v0.3.1 [2026-08-18]

* Added support to [Bitphase](https://github.com/paator/bitphase).
* Fixed arpeggio editing shifting a sample's pitch permanently.
* Enhanced application options:
* Display settings
* Theme selector
* Keybinding settings
* Bumped the reconstruction data-version to `2.1`.
* Improved Sequencer module playback.
* Added song export to WAV/MP3.
* Added tracker selection operations.
* Added a _SampleToNES_ logo.

## v0.3.0 [2026-07-31]

* Added a _Sequencer_ view with FamiTracker-style patterns.
* Added project export in a FamiTracker-compatible format.
* Improved matching algorithms and extended available methods (`LogFFT`, `CQT`).
* Improved the general layout of the application.
* Changed the internal file formats (`.stn`, `.ins`).
* Switched to `uv` as the package manager.
* Detect the NVIDIA driver at setup and install the matching _CuPy_ build automatically, on Linux and Windows.

## v0.2.3 [2026-01-09]

* Improved the application's graphical interface.
* Added the main page with filesystem explorer.
* Added editing and saving reconstructions.
* Added audio settings panel.
* Implemented instructions library autogeneration.
* Simplified instructions library tree.

## v0.2.2 [2025-11-21]

* Added GPU support via _CuPy_.
* Fixed generation bugs.
* Made minor visual improvements.
* Improved code quality.
* Released the application.

## v0.2.1 [2025-11-17]

* Optimized the output file structure.
* Improved application error handling.
* Enhanced task processing communication with the GUI.
* Fixed installer bugs.
* Created a Python package and an application installer via _PyInstaller_.

## v0.2.0 [2025-11-08]

* Created a graphical interface for the application.
* Added application content:
* Instruction instruction data explorer
* Audio reconstruction viewer
* Included instruction data creation and converter windows.
* Added audio graphs and spectrum plots.
* Implemented audio playback.

## v0.1.0 [2025-10-23]

* Added spectral features and FFT windows for the sample approximator.
* Included mixer levels for adjusting the general amplitude of sound.
* Created an instruction instruction data for reconstruction optimization.
* Added instruction data and generation configurations.

## v0.0.1 [2025-09-24]

First version of _SampleToNES_, containing basic reconstruction scripts and all 2A03 generators.
# SampleToNES

## v0.3.2

* Added NSF player and export.
* Added stems conversion: mix several recordings into one reconstruction
* Matched each stem against its own recording, so a stem plays what was recorded on it
* Added a per-source channel cap
* Bumped the reconstruction data-version to `2.2` with backward compatibility for `2.1`.

## v0.3.1 [2026-08-18]

* Added support to [Bitphase](https://github.com/paator/bitphase).
* Fixed arpeggio editing shifting a sample's pitch permanently.
* Enhanced application options:
* Display settings
* Theme selector
* Keybinding settings
* Bumped the reconstruction data-version to `2.1`.
* Improved Sequencer module playback.
* Added song export to WAV/MP3.
* Added tracker selection operations.
* Added a _SampleToNES_ logo.

## v0.3.0 [2026-07-31]

* Added a _Sequencer_ view with FamiTracker-style patterns.
* Added project export in a FamiTracker-compatible format.
* Improved matching algorithms and extended available methods (`LogFFT`, `CQT`).
* Improved the general layout of the application.
* Changed the internal file formats (`.stn`, `.ins`).
* Switched to `uv` as the package manager.
* Detect the NVIDIA driver at setup and install the matching _CuPy_ build automatically, on Linux and Windows.

## v0.2.3 [2026-01-09]

* Improved the application's graphical interface.
* Added the main page with filesystem explorer.
* Added editing and saving reconstructions.
* Added audio settings panel.
* Implemented instructions library autogeneration.
* Simplified instructions library tree.

## v0.2.2 [2025-11-21]

* Added GPU support via _CuPy_.
* Fixed generation bugs.
* Made minor visual improvements.
* Improved code quality.
* Released the application.

## v0.2.1 [2025-11-17]

* Optimized the output file structure.
* Improved application error handling.
* Enhanced task processing communication with the GUI.
* Fixed installer bugs.
* Created a Python package and an application installer via _PyInstaller_.

## v0.2.0 [2025-11-08]

* Created a graphical interface for the application.
* Added application content:
* Instruction instruction data explorer
* Audio reconstruction viewer
* Included instruction data creation and converter windows.
* Added audio graphs and spectrum plots.
* Implemented audio playback.

## v0.1.0 [2025-10-23]

* Added spectral features and FFT windows for the sample approximator.
* Included mixer levels for adjusting the general amplitude of sound.
* Created an instruction instruction data for reconstruction optimization.
* Added instruction data and generation configurations.

## v0.0.1 [2025-09-24]

First version of _SampleToNES_, containing basic reconstruction scripts and all 2A03 generators.
35 changes: 30 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.PHONY: help setup install build release system-deps run clean pre-commit test \
ftm-samples icons check-import-boundary check-tag-names check-unused-tags \
check-language-keys check-palette-colors calibration lint pylint mypy format
.PHONY: help setup install build release system-deps run clean pre-commit test benchmarks \
ftm-samples nsf-samples nsf-render compression-report icons player check-import-boundary check-tag-names check-unused-tags \
check-language-keys check-palette-colors check-shortcut-actions calibration lint pylint mypy format

ifeq ($(OS),Windows_NT)
ifeq ($(MSYSTEM),)
Expand Down Expand Up @@ -66,11 +66,16 @@ help:
@echo $(Q) make setup - Set up development environment (uv); GPU auto-detected, GPU=0 forces CPU$(Q)
@echo $(Q) make pre-commit - Install pre-commit hooks$(Q)
@echo $(Q) make system-deps - Install system packages required to build and run (Debian-based, or Homebrew on macOS)$(Q)
@echo $(Q) make build - Compile standalone executable (respects current deployment config)$(Q)
@echo $(Q) make release - Compile standalone executable with the release deployment config$(Q)
@echo $(Q) make build - Compile standalone executable (development deployment config: DEBUG, strict history)$(Q)
@echo $(Q) make release - Compile standalone executable with the release deployment config (INFO, self-healing history)$(Q)
@echo $(Q) make test - Run unit tests with coverage$(Q)
@echo $(Q) make benchmarks - Run the measured-duration suite on its own$(Q)
@echo $(Q) make ftm-samples - Emit example .ftm files to build/ftm via the integration suite$(Q)
@echo $(Q) make nsf-samples - Emit example .nsf files to build/nsf via the integration suite$(Q)
@echo $(Q) make nsf-render - Render the .nsf files in build/nsf to waves with ffmpeg$(Q)
@echo $(Q) make compression-report - Measure the song codec into build/compression$(Q)
@echo $(Q) make icons - Generate the icon suite into src/sampletones_assets/icons$(Q)
@echo $(Q) make player - Assemble the NES player driver with cc65$(Q)
@echo $(Q) make calibration - Score the reconstruction corpus; the report lands in Documents/SampleToNES/calibration$(Q)
@echo $(Q) make clean - Remove build artifacts and cache files$(Q)
@echo $(Q) make lint - Run linting (pylint, mypy)$(Q)
Expand Down Expand Up @@ -107,13 +112,30 @@ pre-commit:
test:
$(call script,dev/tests)

benchmarks:
uv run python -m pytest tests/benchmarks --no-cov

ftm-samples: export SAMPLETONES_FTM_OUTPUT_DIR := build/ftm
ftm-samples:
uv run python -m pytest tests/integration/famitracker

nsf-samples: export SAMPLETONES_NSF_OUTPUT_DIR := build/nsf
nsf-samples:
uv run python -m pytest tests/integration/nsf

nsf-render: nsf-samples
uv run scripts/nsf_render.py

compression-report: export SAMPLETONES_COMPRESSION_OUTPUT_DIR := build/compression
compression-report:
uv run python -m pytest tests/integration/nsf/test_compression_report.py

icons:
uv run --group assets python scripts/assets/icons.py

player:
uv run scripts/player.py

check-import-boundary:
uv run scripts/checks/import_boundary.py --all

Expand All @@ -129,6 +151,9 @@ check-language-keys:
check-palette-colors:
uv run scripts/checks/palette_colors.py

check-shortcut-actions:
uv run scripts/checks/shortcut_actions.py

calibration:
uv run scripts/calibration.py

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ It supports:
* `pulse2`
* `triangle`
* `noise`
* exporting reconstructed audio as FamiTracker `.fti` instruments, Bitphase `.json` instrument presets, or `.wav`
* exporting reconstructed audio as FamiTracker `.fti` instruments, Bitphase `.json` instrument presets, `.nsf` programs the NES itself plays, or `.wav`

## Installation

Expand Down
20 changes: 11 additions & 9 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
import importlib.util
from pathlib import Path
from typing import Final, Optional, Tuple

JEEPNEY_MODULE: Final[str] = "jeepney"
from sampletones_shared.utils.system.modules import JEEPNEY_MODULE, module_available

PORTAL_PATHS: Final[Tuple[str, ...]] = (
JEEPNEY_PATHS: Final[Tuple[str, ...]] = (
"src/sampletones_application/utils/file_dialogs/backends/portal",
"src/sampletones_shared/utils/system/reveal/file_manager1.py",
"tests/unit/sampletones_application/utils/file_dialogs/backends/portal",
"tests/unit/sampletones_application/utils/file_dialogs/test_selection.py",
"tests/unit/sampletones_shared/utils/system/reveal/test_file_manager1.py",
)

PORTAL_LIBRARY_INSTALLED: Final[bool] = importlib.util.find_spec(JEEPNEY_MODULE) is not None
JEEPNEY_INSTALLED: Final[bool] = module_available(JEEPNEY_MODULE)


def pytest_ignore_collect(collection_path: Path) -> Optional[bool]:
"""
Keeps collection to the modules the running platform imports.

``jeepney`` is declared for Linux alone, so what speaks to the desktop portal is collected
where that library is installed. The behaviour those modules describe belongs to the Linux
desktop, and the Linux runs of the suite cover it.
``jeepney`` is declared for Linux alone, so what speaks D-Bus — the desktop portal's file
dialogs and the ``FileManager1`` reveal backend — is collected where that library is
installed. The behavior those modules describe belongs to the Linux desktop, and the Linux
runs of the suite cover it.

Args:
collection_path: The file or directory pytest is about to look into.
Expand All @@ -28,11 +30,11 @@ def pytest_ignore_collect(collection_path: Path) -> Optional[bool]:
Optional[bool]: ``True`` for a path that stays out of collection, ``None`` to leave the
choice with pytest.
"""
if PORTAL_LIBRARY_INSTALLED:
if JEEPNEY_INSTALLED:
return None

root = Path(__file__).parent
if any(collection_path.is_relative_to(root / path) for path in PORTAL_PATHS):
if any(collection_path.is_relative_to(root / path) for path in JEEPNEY_PATHS):
return True

return None
10 changes: 5 additions & 5 deletions docs/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ from sampletones import (
InstructionLibrary,
Reconstruction,
Reconstructor,
GeneratorName,
ChannelName,
Generator,
PulseGenerator,
TriangleGenerator,
Expand All @@ -31,8 +31,8 @@ from sampletones import (
| `Window` | analysis window derived from a config (`Window.from_config(config)`) |
| `InstructionLibrary` | the library of candidate instructions a reconstruction searches |
| `Reconstructor` | runs a reconstruction: `Reconstructor(config)("sample.wav")` |
| `Reconstruction` | the result of a reconstruction — its approximation audio, per-generator instructions, and the config used |
| `GeneratorName` | enum naming the four channels: `pulse1`, `pulse2`, `triangle`, `noise` |
| `Reconstruction` | the result of a reconstruction — its approximation audio, per-channel instructions, and the config used |
| `ChannelName` | enum naming the four channels: `pulse1`, `pulse2`, `triangle`, `noise` |
| `Generator` | shared base class of the oscillator generators |
| `PulseGenerator`, `TriangleGenerator`, `NoiseGenerator` | render one channel's waveform from an instruction |
| `Instruction` | shared base class of the per-frame channel instructions |
Expand Down Expand Up @@ -110,7 +110,7 @@ write_wave("reconstruction.wav", sample_rate, reconstruction.approximation)

### Load a reconstruction

`Reconstruction.load` reads a saved `.stn` back into a `Reconstruction`, carrying its approximation, per-generator instructions, and config:
`Reconstruction.load` reads a saved `.stn` back into a `Reconstruction`, carrying its approximation, per-channel instructions, and config:

```python
from sampletones import Reconstruction
Expand All @@ -120,7 +120,7 @@ reconstruction = Reconstruction.load("reconstruction.stn")

### Export instruments

`Reconstruction.export` returns the per-channel [features](../formats/instruction-libraries.md), one entry per generator, and each set saves as a FamiTracker `.fti` instrument:
`Reconstruction.export` returns the per-channel [features](../formats/instruction-libraries.md), one entry per channel, and each set saves as a FamiTracker `.fti` instrument:

```python
from sampletones import Reconstruction
Expand Down
4 changes: 2 additions & 2 deletions docs/concepts/calibration.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ and runs as a script:
```
python scripts/calibration.py [--config <base>] [--methods fft,cqt]
[--perceptual-exponents 0.5,1.0] [--temporal-weights 0.1,0.3]
[--generators pulse1,triangle,noise]
[--channels pulse1,triangle,noise]
```

The base configuration comes from `--config` when given; otherwise the saved
application configuration is used, so a run inherits the current app settings —
sample rate, gamma, selector and the rest. The channel set is the exception:
calibration pins the generators itself (`--generators`, by default pulse 1 +
calibration pins the channels itself (`--channels`, by default pulse 1 +
triangle + noise), so every run reconstructs with an explicitly chosen channel
set and results stay comparable across machines.

Expand Down
Loading
Loading