Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
158 commits
Select commit Hold shift + click to select a range
9b13981
Implemented: palette catalog with light/dark themes
JakimPL Aug 6, 2026
eb4cf17
Added: dynamic palette resolution
JakimPL Aug 6, 2026
450d7ef
Added: dynamic palette colors
JakimPL Aug 7, 2026
1e24aa2
Minor script check improvements
JakimPL Aug 8, 2026
db3cf84
Added: display option to application schemas
JakimPL Aug 8, 2026
0cc8094
Added: display settings dialog box
JakimPL Aug 8, 2026
72dd9b4
General improvements
JakimPL Aug 8, 2026
accd937
Added: display panel tests
JakimPL Aug 8, 2026
f5328e5
General improvements
JakimPL Aug 8, 2026
325a515
Fixed: display settings dialog shrinking
JakimPL Aug 8, 2026
b76e4d5
Minor improvements
JakimPL Aug 8, 2026
8d9be21
Fixed: check scripts
JakimPL Aug 8, 2026
f7b7c43
Added: keyboard combination
JakimPL Aug 8, 2026
05a009f
Renamed: grid to tracker
JakimPL Aug 8, 2026
60ba68a
Reformat
JakimPL Aug 8, 2026
aa53471
Reworked: unit tests
JakimPL Aug 8, 2026
814a239
Added: remaining tests
JakimPL Aug 8, 2026
4fb635f
Added: keybinding scheme loaded from configuration
JakimPL Aug 8, 2026
ca817ed
Refactored: sequencer panels onto the keybinding registry
JakimPL Aug 8, 2026
33fc9ba
Refactored: sequencer panels onto the keybinding registry
JakimPL Aug 9, 2026
ab2d93e
Added: tracker beat and bar row emphasis
JakimPL Aug 9, 2026
bd82a08
Updated: themes
JakimPL Aug 9, 2026
af7c9b1
Fixed: unclosable display settings dialog
JakimPL Aug 9, 2026
a89a728
Added: keybinding preferences and live rebinding
JakimPL Aug 9, 2026
7942cba
Documented: keybinding registry and colour ownership
JakimPL Aug 9, 2026
ed78aa3
Extended: key vocabulary
JakimPL Aug 9, 2026
39b0777
Added: shortcut draft over an edited scheme
JakimPL Aug 9, 2026
1b6634f
Added: keyboard shortcuts dialog box
JakimPL Aug 9, 2026
1f0dfa7
Bound: macOS keys + generator keys
JakimPL Aug 9, 2026
d0746c0
Documented: keyboard shortcuts dialog
JakimPL Aug 9, 2026
9c23cc2
Fixed: sequencer keys reaching from other tabs and stale application …
JakimPL Aug 9, 2026
7559c50
Refactored: user profile
JakimPL Aug 9, 2026
ae303bc
Refactored: dialog windows onto a shared keyboard base
JakimPL Aug 9, 2026
9a1db30
Refactored: shared candidate alignment, metadata contract and instrum…
JakimPL Aug 9, 2026
ff0fac3
Refactored: element enums found by type
JakimPL Aug 9, 2026
02d4d92
Added: tracker scrolling to the playing row
JakimPL Aug 9, 2026
273b5e1
Fixed: playhead mark
JakimPL Aug 10, 2026
f93aa8d
Added: follow mode
JakimPL Aug 10, 2026
47c1fa8
Added: follow-mode menu and keyboard shortcuts
JakimPL Aug 10, 2026
3c0a885
Documented: follow modes
JakimPL Aug 10, 2026
34950d6
Fixed: audio teardown ordering on exit
JakimPL Aug 10, 2026
223ecc3
Fixed: song player stop
JakimPL Aug 10, 2026
c222536
Fixed: audio device manager release
JakimPL Aug 10, 2026
709acbd
Documented: audio backend teardown ordering
JakimPL Aug 10, 2026
68c1f47
Fixed: macOS CI PortAudio dependency for pyaudio
JakimPL Aug 10, 2026
ab8ab03
Fixed: unit tests
JakimPL Aug 10, 2026
c537cc2
Merge pull request #48 from JakimPL/display
JakimPL Aug 10, 2026
3937b26
Fixed: playing-row mark scoped to the sounding frame
JakimPL Aug 10, 2026
57bc6f7
Added: groove calculator for tempo-driven row timing
JakimPL Aug 10, 2026
e8f5d0b
Added: metric highlight fields to project settings
JakimPL Aug 10, 2026
0eb5fef
Added: metric highlight inputs and project-driven row tinting
JakimPL Aug 10, 2026
aaa29df
Added: metric highlight fields to project properties
JakimPL Aug 10, 2026
7c00894
Changed: NES frequency default to 60 and tempo range to 32–255
JakimPL Aug 10, 2026
cdc0a8d
Changed: playback row duration to the project's groove
JakimPL Aug 10, 2026
c045eaa
Added: silencing volume column to the Bitphase export
JakimPL Aug 10, 2026
07c61e2
Added: tempo as a groove to the Bitphase export
JakimPL Aug 10, 2026
9ea9f84
Fixed: spectrum method typing in the calibration sweep
JakimPL Aug 10, 2026
250f2d6
Added: tick clock for exact engine-tick duration in samples
JakimPL Aug 10, 2026
ba550ce
Added: streaming audio writers for WAV and MP3
JakimPL Aug 10, 2026
c6c57f1
Added: song render service
JakimPL Aug 10, 2026
1b2c299
Added: project source seam for rendering
JakimPL Aug 10, 2026
4d2482a
Added: render logic and view model for song rendering
JakimPL Aug 10, 2026
5dc24e3
Added: render dialog window
JakimPL Aug 11, 2026
a4c8809
Added: song render wiring, menu entry and shortcut
JakimPL Aug 11, 2026
dbac510
Documented: song rendering to an audio file
JakimPL Aug 11, 2026
bd6ef69
Added: destination path text
JakimPL Aug 11, 2026
05af9fc
Fixed: song synthesis reading the output rate before there is a consumer
JakimPL Aug 11, 2026
58f5411
Merge pull request #49 from JakimPL/render
JakimPL Aug 11, 2026
49f09b4
Added: shallow frame duplication beside deep cloning
JakimPL Aug 11, 2026
5403e59
Extracted: shared sequencer channel axis and slot vocabulary
JakimPL Aug 11, 2026
f29265d
Fixed: an explicit zero transpose reading as an empty one
JakimPL Aug 11, 2026
00239dd
Fixed: channel disagreement indicator
JakimPL Aug 11, 2026
e7576c5
Moved: sample column dispatch into the tracker logic
JakimPL Aug 11, 2026
2bf4921
Added: batched project mutation notifications
JakimPL Aug 11, 2026
dfb9ddc
Added: tracker/order selection
JakimPL Aug 11, 2026
77cfa05
Added: tracker block copy
JakimPL Aug 11, 2026
a6c3a0e
Added: tracker block cut, paste and delete
JakimPL Aug 11, 2026
e859b43
Added: context menu operations
JakimPL Aug 11, 2026
873ddb2
Extracted: shared clipboard action labels
JakimPL Aug 11, 2026
849ccba
Extracted: one action builder
JakimPL Aug 11, 2026
4fc2f42
Added: focus-aware actions in the Edit menu
JakimPL Aug 11, 2026
78f38cf
Fixed: the Edit menu growing
JakimPL Aug 11, 2026
8391b4a
Extracted: the grid drag-selection gesture
JakimPL Aug 11, 2026
5dd8284
Extracted: shared grid selection state
JakimPL Aug 12, 2026
3f1bfcf
Extracted: shared grid block gestures
JakimPL Aug 12, 2026
3fe19bf
Extracted: shared grid selection painting
JakimPL Aug 12, 2026
47b798a
Documented: the focus-aware Edit menu
JakimPL Aug 12, 2026
1dd3167
Added: transpose and volume over a selection
JakimPL Aug 12, 2026
36ed275
Extracted: the grid edit surface
JakimPL Aug 12, 2026
193d602
Added: the samples panel to the Edit menu
JakimPL Aug 12, 2026
2da4f2c
Added: selecting a whole grid, column and subcolumn
JakimPL Aug 12, 2026
9390ecc
Added: auto-scroll while dragging
JakimPL Aug 12, 2026
5f8f181
Added: sequencer blocks on the system clipboard
JakimPL Aug 12, 2026
79b4465
Documented: selection shapes, drag travel and the clipboard form
JakimPL Aug 12, 2026
caced37
Changed: cell menus title
JakimPL Aug 12, 2026
f65badb
Changed: the stacked graph ceiling
JakimPL Aug 12, 2026
b80e37d
Merge pull request #50 from JakimPL/selection
JakimPL Aug 12, 2026
9e5842a
Added: the FamiTracker driver memory footprint
JakimPL Aug 12, 2026
9b468c9
Added: instrument and sample size to the instruments panel
JakimPL Aug 12, 2026
8cbc4a1
Added: envelopes the channel governs
JakimPL Aug 12, 2026
b04453b
Added: every channel present in a reconstruction
JakimPL Aug 12, 2026
b7204c7
Added: channel-held envelope values in playback
JakimPL Aug 12, 2026
a12ceb5
Changed: Bitphase interpretation of empty envelope
JakimPL Aug 12, 2026
c69fa4e
Added: sample size to the samples context menu
JakimPL Aug 12, 2026
84a71b2
Refactored: channel labels, pitch tooltips and footprint totals
JakimPL Aug 13, 2026
a8ea490
Fixed: held-dimension bookkeeping on channels
JakimPL Aug 13, 2026
a8c0bbf
Documented: the tracker byte counter
JakimPL Aug 13, 2026
bbeb67f
Added: coverage for cleared envelopes and per-channel held dimensions
JakimPL Aug 13, 2026
65c1bea
Merge pull request #51 from JakimPL/size
JakimPL Aug 13, 2026
a33e708
Rebound: tab selection to F1–F4
JakimPL Aug 14, 2026
d2fb29b
Added: application image
JakimPL Aug 14, 2026
78dea79
Updated: todos
JakimPL Aug 15, 2026
3993093
Added: reconstructions subdirectory view
JakimPL Aug 15, 2026
e4f433c
Refactored: browser view
JakimPL Aug 15, 2026
f13261e
Added: multiple browser views
JakimPL Aug 15, 2026
229c6e0
Improved: reconstruction double view
JakimPL Aug 15, 2026
dece1e2
Added: parsed configuration fields
JakimPL Aug 17, 2026
155dbd8
Extracted: the unique sibling label rule
JakimPL Aug 17, 2026
7966af3
Refactored: reconstruction browser tree
JakimPL Aug 17, 2026
8536008
Refactored: reconstruction browser tree
JakimPL Aug 17, 2026
5dc244b
Added: pruning and deterministic ordering of browser groups
JakimPL Aug 17, 2026
9f839b8
Fixed: favourite repainting across both browser views
JakimPL Aug 17, 2026
0557715
Added: single-child group collapsing in the browser
JakimPL Aug 17, 2026
e533aab
Extracted: the shared file-browser panel base
JakimPL Aug 17, 2026
67cce88
Merged: sampletones_core.paths into a sampletones_shared.paths
JakimPL Aug 17, 2026
a2f2ead
Moved: icon generation into the sampletones_assets
JakimPL Aug 17, 2026
e9ef7b4
Excluded: build-time Pillow from the standalone bundles
JakimPL Aug 17, 2026
fafc671
Added: logo to README
JakimPL Aug 17, 2026
c14429b
Tracked: the generated icon suite
JakimPL Aug 17, 2026
49d2485
Improved: workflow
JakimPL Aug 17, 2026
330c25f
Merge pull request #52 from JakimPL/logo
JakimPL Aug 17, 2026
ef37024
Refactored: explorer and library onto the file-browser base
JakimPL Aug 17, 2026
d436b21
Added: context menu on browser container rows
JakimPL Aug 17, 2026
faef770
Added: reconstruction browser document
JakimPL Aug 17, 2026
91e1483
Refactored: tree filtering
JakimPL Aug 17, 2026
3ea5bd0
Added: favorites-only tree filter
JakimPL Aug 17, 2026
19f883c
Added: favorites-only browser control
JakimPL Aug 17, 2026
c0f3df7
Documented: favorites-only browser filter
JakimPL Aug 17, 2026
7249ab1
Fixed: favorites filter label reading as disabled
JakimPL Aug 17, 2026
e94921a
Added: browser view-state test fixture
JakimPL Aug 17, 2026
c273054
Fixed: favorites filter opening a starred folder's whole subtree
JakimPL Aug 17, 2026
ec46621
Added: browser remembering which rows stand open
JakimPL Aug 17, 2026
d53af22
Documented: the favorites filter's rules
JakimPL Aug 17, 2026
192f924
Added: Collapse all control in every file browser card
JakimPL Aug 18, 2026
14ad477
Added: Auto-expand favorites preference per kind of favorite
JakimPL Aug 18, 2026
3fc6404
Added: browser shape surviving between application runs
JakimPL Aug 18, 2026
eb7b1d3
Added: explorer folders standing open between application runs
JakimPL Aug 18, 2026
5a0396c
Added: application mark in the About dialog
JakimPL Aug 18, 2026
ad6144c
Documented: the browser's open rule, its remembered shape and the sweep
JakimPL Aug 18, 2026
2e0c6fc
Changed: auto-expand favorites acting on the reader's switch alone
JakimPL Aug 18, 2026
b37fe92
Changed: the About dialog balancing its mark against the name
JakimPL Aug 18, 2026
7992a51
Fixed: the favorites mode folding the way down to rows the reader opened
JakimPL Aug 18, 2026
25386b1
Refactored: the favorites mode's open rule into one answer per pass
JakimPL Aug 18, 2026
4f78db4
Refactored: the favorites mode's release
JakimPL Aug 18, 2026
6c8aa85
Refactored: the browser's open rows memory
JakimPL Aug 18, 2026
da6e992
Refactored: the browser's opening mode and shape into constructor arg…
JakimPL Aug 18, 2026
fd4b942
Documented: the favorites modes
JakimPL Aug 18, 2026
227aa8a
Merge pull request #54 from JakimPL/subdirectories
JakimPL Aug 18, 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
  •  
  •  
  •  
11 changes: 10 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,16 @@ jobs:
- name: Run every pre-commit hook
run: uv run pre-commit run --all-files --show-diff-on-failure --color always

- name: Check the committed icons match the mark
run: uv run pre-commit run icons --all-files --hook-stage pre-push --color always

tests:
name: Tests (${{ matrix.os }}, py${{ matrix.python }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
os: [ubuntu-latest, windows-latest, macos-latest]
python: ["3.12", "3.13"]
steps:
- uses: actions/checkout@v7
Expand All @@ -62,6 +65,12 @@ jobs:
if: runner.os == 'Linux'
run: bash scripts/linux/build/dependencies.sh

- name: Install system libraries (macOS)
if: runner.os == 'macOS'
run: |
bash scripts/macos/build/dependencies.sh
bash scripts/macos/build/build_env.sh >> "$GITHUB_ENV"

- name: Install the development environment
run: uv sync --group dev

Expand Down
12 changes: 7 additions & 5 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ jobs:
os: [ubuntu-latest, windows-latest, macos-latest]
python: ["3.12", "3.13"]
steps:
- uses: actions/checkout@v7
with:
path: repository

- uses: actions/download-artifact@v8
with:
name: dist
Expand All @@ -74,10 +78,8 @@ jobs:
- name: Install PortAudio (macOS)
if: runner.os == 'macOS'
run: |
brew install portaudio
prefix="$(brew --prefix portaudio)"
echo "CFLAGS=-I${prefix}/include" >> "$GITHUB_ENV"
echo "LDFLAGS=-L${prefix}/lib" >> "$GITHUB_ENV"
bash repository/scripts/macos/build/dependencies.sh
bash repository/scripts/macos/build/build_env.sh >> "$GITHUB_ENV"

- name: Install the wheel and check the entry point
shell: bash
Expand Down Expand Up @@ -124,7 +126,7 @@ jobs:
venv_python=.venv-build/bin/python
fi
"$venv_python" -m pip install --upgrade pip
"$venv_python" -m pip install ".[build]"
"$venv_python" -m pip install ".[build]" --group assets

- name: Build the bundle (Linux)
if: runner.os == 'Linux'
Expand Down
11 changes: 3 additions & 8 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,20 @@ __pycache__/
.ipynb_checkpoints/
.mypy_cache/
.pytest_cache/
.ruff_cache/
.venv/
.venv-build/
.vscode/

bin/
build/
dist/
wheels/
!scripts/**/build/
/bin/
/build/

sampletones
!src/sampletones
!tests/sampletones

**/*.idea
**/*.vscode/**
**/*.ipynb_checkpoints/**
**/*__pycache__/**

*.pyc
*.pyo
*.coverage
Expand Down
22 changes: 20 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,18 @@ repos:

- id: tag-names
name: tag names
entry: uv run scripts/checks/tag_names.py
entry: uv run scripts/checks/tag_names.py --all
language: system
types: [python]
files: ^src/sampletones_application/tags/
pass_filenames: false
verbose: true

- id: palette-colors
name: palette colors
entry: uv run scripts/checks/palette_colors.py
language: system
files: (^src/sampletones_application/.*\.py|^src/sampletones_config/.*\.yaml)$
pass_filenames: false
verbose: true

- id: language-keys
Expand Down Expand Up @@ -83,6 +91,16 @@ repos:
require_serial: true
exclude: ^(tests/)

- id: icons
name: icons
entry: uv run python scripts/assets/icons.py
language: system
files: ^src/sampletones_assets/(icons|mark)/
pass_filenames: false
verbose: true
stages:
- pre-push

- id: pytest
name: pytest
entry: make test
Expand Down
13 changes: 0 additions & 13 deletions .pylintrc

This file was deleted.

8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,15 @@

* 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]

Expand Down
4 changes: 3 additions & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ SOFTWARE.

---

The MIT license above covers the SampleToNES source code only.
The MIT license above covers the SampleToNES source code and the application
icons under `src/sampletones_assets/icons/`, which are drawn from the mark
declared in `src/sampletones_assets/mark/`.

Font files bundled under `src/sampletones_assets/fonts/` are the work of third
parties and remain under their own licenses (SIL Open Font License 1.1 and the
Expand Down
31 changes: 21 additions & 10 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 check-import-boundary check-tag-names check-unused-tags \
check-language-keys calibration lint pylint mypy format
ftm-samples icons check-import-boundary check-tag-names check-unused-tags \
check-language-keys check-palette-colors calibration lint pylint mypy format

ifeq ($(OS),Windows_NT)
ifeq ($(MSYSTEM),)
Expand Down Expand Up @@ -43,12 +43,14 @@ endif
BUILD_COMMAND := $(RUN_SCRIPT) $(BUILD_SCRIPT)
RELEASE_COMMAND := $(RUN_SCRIPT) $(BUILD_SCRIPT) --release
SYSTEM_DEPS_COMMAND := bash scripts/linux/build/dependencies.sh
SETUP_ENV :=

ifeq ($(UNAME_S),Darwin)
MACOS_SOURCE_ONLY := bash scripts/macos/source_only.sh
BUILD_COMMAND := $(MACOS_SOURCE_ONLY) 'make build'
RELEASE_COMMAND := $(MACOS_SOURCE_ONLY) 'make release'
SYSTEM_DEPS_COMMAND := $(MACOS_SOURCE_ONLY) 'make system-deps'
MACOS_NO_BUNDLE := bash scripts/macos/build/no_bundle.sh
BUILD_COMMAND := $(MACOS_NO_BUNDLE) 'make build'
RELEASE_COMMAND := $(MACOS_NO_BUNDLE) 'make release'
SYSTEM_DEPS_COMMAND := bash scripts/macos/build/dependencies.sh
SETUP_ENV := ARCHFLAGS="-arch $(shell uname -m)"
endif

GPU ?= auto
Expand All @@ -63,19 +65,22 @@ help:
@echo $(Q)Available targets:$(Q)
@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)$(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 test - Run unit tests with coverage$(Q)
@echo $(Q) make ftm-samples - Emit example .ftm files to build/ftm via the integration suite$(Q)
@echo $(Q) make icons - Generate the icon suite into src/sampletones_assets/icons$(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)
@echo $(Q) make format - Auto-format code (isort, black)$(Q)
@echo $(Q) make run - Run SampleToNES application$(Q)

setup:
uv sync --group dev $(if $(GPU_EXTRA),--extra $(GPU_EXTRA),)
uv tool install --force $(if $(GPU_EXTRA),".[$(GPU_EXTRA)]",.)
$(SETUP_ENV) uv sync --group dev $(if $(GPU_EXTRA),--extra $(GPU_EXTRA),)
$(MAKE) icons
$(SETUP_ENV) uv tool install --force $(if $(GPU_EXTRA),".[$(GPU_EXTRA)]",.)

install:
$(MAKE) setup
Expand Down Expand Up @@ -106,6 +111,9 @@ ftm-samples: export SAMPLETONES_FTM_OUTPUT_DIR := build/ftm
ftm-samples:
uv run python -m pytest tests/integration/famitracker

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

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

Expand All @@ -118,8 +126,11 @@ check-unused-tags:
check-language-keys:
uv run scripts/checks/language_keys.py

check-palette-colors:
uv run scripts/checks/palette_colors.py

calibration:
uv run scripts/calibration.py --all
uv run scripts/calibration.py

lint:
$(call script,dev/lint)
Expand Down
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@
[![Python](https://img.shields.io/pypi/pyversions/sampletones.svg)](https://pypi.org/project/sampletones/)
[![License](https://img.shields.io/pypi/l/sampletones.svg)](https://github.com/JakimPL/SampleToNES/blob/main/LICENSE)

<div align="center">
<img src="https://raw.githubusercontent.com/JakimPL/SampleToNES/main/src/sampletones_assets/icons/sampletones.svg" alt="SampleToNES" width="64">
</div>

## Overview

_SampleToNES_ (`sampletones`) is a desktop tool for people writing music for the NES 2A03 sound chip, mainly in [_FamiTracker_](http://famitracker.com/).

<img src="https://raw.githubusercontent.com/JakimPL/SampleToNES/main/docs/images/sampletones.png" alt="SampleToNES" width="640">

The core idea is to approximate an audio sample using only the chip's basic oscillators — two pulse channels, a triangle, and noise — **without any DPCM samples**.

A built-in sequencer lets you arrange the reconstructed samples into patterns and play them back inside the application, so you can experiment with the results before exporting the instruments into FamiTracker.
Expand Down Expand Up @@ -57,11 +63,12 @@ To install with GPU support, request the `gpu` extra (see [GPU acceleration](#gp
uv tool install "sampletones[gpu]"
```

On Linux, audio playback and file dialogs rely on system libraries that cannot come from
PyPI. Install them first:
On Linux and macOS, audio playback and file dialogs rely on system libraries that come from
the platform's package manager. Install them first:

```sh
sudo apt-get install libportaudio2 libasound2 python3-tk # Debian/Ubuntu
brew install portaudio # macOS
```
### Building the executable yourself

Expand Down
31 changes: 25 additions & 6 deletions THIRD-PARTY-NOTICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,16 @@ are not used in any SampleToNES component name.

Every dependency is installed separately by `pip`/`uv` from PyPI and imported at runtime.

Most dependencies are permissively licensed (MIT, BSD, Apache-2.0, ISC). Two are under the
GNU Lesser General Public License — [Pebble](https://pypi.org/project/Pebble/) (LGPL-3.0,
a direct dependency) and [soxr](https://pypi.org/project/soxr/) (LGPL-2.1-or-later, a
transitive dependency of `librosa`) — and two, `certifi` and `tqdm`, are under MPL-2.0.

All four are used as unmodified, separately installed libraries loaded dynamically at
Most dependencies are permissively licensed (MIT, BSD, Apache-2.0, ISC). Three carry code
under the GNU Lesser General Public License — [Pebble](https://pypi.org/project/Pebble/)
(LGPL-3.0, a direct dependency), [soxr](https://pypi.org/project/soxr/)
(LGPL-2.1-or-later, a transitive dependency of `librosa`), and
[soundfile](https://pypi.org/project/soundfile/) (BSD-3-Clause itself, a direct
dependency, whose wheel carries the libsndfile shared library under LGPL-2.1-or-later with
LAME and mpg123 statically linked into it) — and two, `certifi` and `tqdm`, are under
MPL-2.0.

All of them are used as unmodified, separately installed libraries loaded dynamically at
import time. No LGPL- or MPL-licensed code is copied into the wheel or the sdist, so the
MIT License applies to the PyPI package without further obligation.

Expand Down Expand Up @@ -105,3 +109,18 @@ The published bundles are **CPU-only**: CuPy, the CUDA runtime and the NVIDIA li
are proprietary, and their EULA reserves redistribution to NVIDIA. GPU acceleration comes
from installing _SampleToNES_ from PyPI with the `gpu` extra, which fetches CuPy and the
CUDA components from their publishers straight to your machine.

## Build-time tooling

The application icons are drawn by `sampletones_assets.mark` and rasterized with
[Pillow](https://pypi.org/project/Pillow/), which is under the
[MIT-CMU license](https://github.com/python-pillow/Pillow/blob/main/LICENSE). Pillow belongs
to the `assets` dependency group alone, so `pip`/`uv` installs it on the machine that
generates the icons: it stays out of the wheel's dependency set, and PyInstaller is told to
leave it out of the bundles. Both distributions carry the finished icon files, so Pillow's
attribution clause — a condition on redistributing Pillow itself — rests with the build
environment.

The icons (`sampletones.svg`, `sampletones.png` and the multi-resolution `sampletones.ico`)
are original _SampleToNES_ artwork and fall under the MIT License together with the rest of
the source.
4 changes: 2 additions & 2 deletions docs/concepts/reconstruction.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,12 @@ reconstruction and the original can be shown and played on a common scale.

## Appendix — key parameters and where things live

Default configuration (44.1 kHz, 30 Hz change rate, channels pulse 1 + triangle +
Default configuration (44.1 kHz, 60 Hz change rate, channels pulse 1 + triangle +
noise):

| parameter | default | notes |
|--------------------------|---------|----------------------------------------------------|
| frame length | 1470 | `sample_rate / nes_frequency`, ~33 ms |
| frame length | 735 | `sample_rate / nes_frequency`, ~17 ms |
| spectrum method | `cqt` | `fft` / `logfft` / `cqt` |
| `transformation_gamma` | 0 | 0 = power spectrum, 100 = log |
| spectral / temporal weight | 0.8 / 0.2 | criterion blend |
Expand Down
Loading