bitcomposer 1.0.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.
Files changed (65) hide show
  1. bitcomposer-1.0.0/LICENSE +21 -0
  2. bitcomposer-1.0.0/PKG-INFO +267 -0
  3. bitcomposer-1.0.0/README.md +245 -0
  4. bitcomposer-1.0.0/bitcomposer/__init__.py +6 -0
  5. bitcomposer-1.0.0/bitcomposer/__main__.py +5 -0
  6. bitcomposer-1.0.0/bitcomposer/arp.py +192 -0
  7. bitcomposer-1.0.0/bitcomposer/bass.py +173 -0
  8. bitcomposer-1.0.0/bitcomposer/builder.py +403 -0
  9. bitcomposer-1.0.0/bitcomposer/cli.py +284 -0
  10. bitcomposer-1.0.0/bitcomposer/composer.py +715 -0
  11. bitcomposer-1.0.0/bitcomposer/drums.py +291 -0
  12. bitcomposer-1.0.0/bitcomposer/echo.py +154 -0
  13. bitcomposer-1.0.0/bitcomposer/harmony.py +327 -0
  14. bitcomposer-1.0.0/bitcomposer/instruments.py +216 -0
  15. bitcomposer-1.0.0/bitcomposer/it_format.py +376 -0
  16. bitcomposer-1.0.0/bitcomposer/melody.py +543 -0
  17. bitcomposer-1.0.0/bitcomposer/mix.py +66 -0
  18. bitcomposer-1.0.0/bitcomposer/names.py +158 -0
  19. bitcomposer-1.0.0/bitcomposer/packs/__init__.py +30 -0
  20. bitcomposer-1.0.0/bitcomposer/packs/evermore.py +358 -0
  21. bitcomposer-1.0.0/bitcomposer/packs/ffvi.py +475 -0
  22. bitcomposer-1.0.0/bitcomposer/packs/mana.py +373 -0
  23. bitcomposer-1.0.0/bitcomposer/packs/megamanx.py +397 -0
  24. bitcomposer-1.0.0/bitcomposer/pattern.py +474 -0
  25. bitcomposer-1.0.0/bitcomposer/player/__init__.py +4 -0
  26. bitcomposer-1.0.0/bitcomposer/player/__main__.py +4 -0
  27. bitcomposer-1.0.0/bitcomposer/player/app.py +327 -0
  28. bitcomposer-1.0.0/bitcomposer/player/audio.py +162 -0
  29. bitcomposer-1.0.0/bitcomposer/player/autostart.py +93 -0
  30. bitcomposer-1.0.0/bitcomposer/player/backend.py +479 -0
  31. bitcomposer-1.0.0/bitcomposer/player/desktop.py +139 -0
  32. bitcomposer-1.0.0/bitcomposer/player/engine.py +601 -0
  33. bitcomposer-1.0.0/bitcomposer/player/fonts/JetBrainsMono-Bold.ttf +0 -0
  34. bitcomposer-1.0.0/bitcomposer/player/fonts/JetBrainsMono-Regular.ttf +0 -0
  35. bitcomposer-1.0.0/bitcomposer/player/fonts/LICENSE.txt +93 -0
  36. bitcomposer-1.0.0/bitcomposer/player/icons/bitcomposer.svg +34 -0
  37. bitcomposer-1.0.0/bitcomposer/player/mediakeys_win.py +47 -0
  38. bitcomposer-1.0.0/bitcomposer/player/mpris.py +317 -0
  39. bitcomposer-1.0.0/bitcomposer/player/openmpt.py +208 -0
  40. bitcomposer-1.0.0/bitcomposer/player/qml/Main.qml +1764 -0
  41. bitcomposer-1.0.0/bitcomposer/player/update.py +203 -0
  42. bitcomposer-1.0.0/bitcomposer/player/window.py +113 -0
  43. bitcomposer-1.0.0/bitcomposer/registers.py +78 -0
  44. bitcomposer-1.0.0/bitcomposer/samples/__init__.py +385 -0
  45. bitcomposer-1.0.0/bitcomposer/samples/chip.py +459 -0
  46. bitcomposer-1.0.0/bitcomposer/samples/dsp.py +459 -0
  47. bitcomposer-1.0.0/bitcomposer/samples/genesis.py +369 -0
  48. bitcomposer-1.0.0/bitcomposer/samples/snes.py +242 -0
  49. bitcomposer-1.0.0/bitcomposer/structure.py +382 -0
  50. bitcomposer-1.0.0/bitcomposer/theory.py +248 -0
  51. bitcomposer-1.0.0/bitcomposer.egg-info/PKG-INFO +267 -0
  52. bitcomposer-1.0.0/bitcomposer.egg-info/SOURCES.txt +63 -0
  53. bitcomposer-1.0.0/bitcomposer.egg-info/dependency_links.txt +1 -0
  54. bitcomposer-1.0.0/bitcomposer.egg-info/entry_points.txt +3 -0
  55. bitcomposer-1.0.0/bitcomposer.egg-info/requires.txt +4 -0
  56. bitcomposer-1.0.0/bitcomposer.egg-info/top_level.txt +1 -0
  57. bitcomposer-1.0.0/pyproject.toml +51 -0
  58. bitcomposer-1.0.0/setup.cfg +4 -0
  59. bitcomposer-1.0.0/tests/test_arrangement.py +272 -0
  60. bitcomposer-1.0.0/tests/test_format.py +150 -0
  61. bitcomposer-1.0.0/tests/test_packs.py +153 -0
  62. bitcomposer-1.0.0/tests/test_pattern.py +44 -0
  63. bitcomposer-1.0.0/tests/test_player.py +693 -0
  64. bitcomposer-1.0.0/tests/test_samples.py +91 -0
  65. bitcomposer-1.0.0/tests/test_theory.py +62 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Enlightened Solutions LLC
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,267 @@
1
+ Metadata-Version: 2.4
2
+ Name: bitcomposer
3
+ Version: 1.0.0
4
+ Summary: Procedural 16-bit chiptune music generator — creates Impulse Tracker (.it) files
5
+ Author-email: CatDogBark <catdogbark@pm.me>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/CatDogBark/bitComposer
8
+ Project-URL: Repository, https://github.com/CatDogBark/bitComposer
9
+ Project-URL: Issues, https://github.com/CatDogBark/bitComposer/issues
10
+ Project-URL: Changelog, https://github.com/CatDogBark/bitComposer/blob/main/CHANGELOG.md
11
+ Keywords: chiptune,tracker,music,procedural,16-bit,snes,genesis,impulse-tracker
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Multimedia :: Sound/Audio
15
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Sound Synthesis
16
+ Requires-Python: >=3.10
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Requires-Dist: PySide6-Essentials>=6.5
20
+ Requires-Dist: jeepney>=0.8; sys_platform == "linux"
21
+ Dynamic: license-file
22
+
23
+ <h1>
24
+ <picture>
25
+ <source media="(prefers-color-scheme: dark)" srcset="docs/images/logo-dark.svg">
26
+ <img src="docs/images/logo-light.svg" alt="bitComposer" height="64">
27
+ </picture>
28
+ </h1>
29
+
30
+ *Endless music. Keep what moves you.*
31
+
32
+ [![CI](https://github.com/CatDogBark/bitComposer/actions/workflows/ci.yml/badge.svg)](https://github.com/CatDogBark/bitComposer/actions/workflows/ci.yml)
33
+ [![Release](https://img.shields.io/github/v/release/CatDogBark/bitComposer)](https://github.com/CatDogBark/bitComposer/releases/latest)
34
+ ![License](https://img.shields.io/badge/license-MIT-green)
35
+
36
+ Procedural 16-bit game music. A player that composes the next song as the
37
+ current one ends, with a live mixer, on Linux and Windows; a command line
38
+ and a generator library underneath, pure Python with no dependencies,
39
+ writing Impulse Tracker `.it` modules any tracker player reads.
40
+
41
+ Every run composes a new song: a motif-based melody with call-and-response
42
+ phrasing, voice-led harmony, bass, arpeggio and drums, arranged into a form
43
+ (verse–chorus, AABA, rondo, through-composed) with a drawn intro, an energy
44
+ curve and a real ending, titled after what it drew, between 1:15 and 3:30
45
+ long. Seven sounds, picked with `--sound`:
46
+
47
+ - **snes** — sampled-style voices built the way the SNES made sound, through a BRR codec model and the SNES echo.
48
+ - **ffvi**, **mana**, **evermore**, **megamanx** — style packs: an instrument set rebuilt from each game's own sound chip (every sample profiled, nothing copied) plus the arrangement habits of its score. Details under [Sounds](#sounds).
49
+ - **genesis** — FM bells, brass, organ and bass.
50
+ - **chip** — square, pulse and triangle waves. Closest to NES and Game Boy.
51
+
52
+ **[Listen in your browser](https://catdogbark.github.io/bitComposer/)** — the actual modules, played live by libopenmpt in WebAssembly: one song per sound, straight from the generator, regenerated with each release.
53
+
54
+ **Reproducible, not frozen.** The same seed on the same version gives the same song, byte for byte. A new version may change what a seed draws, and the song message records the version that wrote the file.
55
+
56
+ ## Install
57
+
58
+ **Windows.** Every release carries `bitComposer-setup.exe`: the player, the
59
+ command line, a Start menu entry and an uninstaller; or `bitComposer-windows.zip`,
60
+ the same program as a folder with nothing to install. No Python needed. See
61
+ [Windows](#windows).
62
+
63
+ **Linux.** From PyPI with [pipx](https://pipx.pypa.io/), so it lands on your
64
+ PATH without touching the system Python (Debian and Fedora refuse a plain
65
+ `pip install` there; `sudo apt install pipx libopenmpt0` or
66
+ `sudo dnf install pipx libopenmpt` gets pipx and the module library). The
67
+ player's window is Qt, which pipx brings along (PySide6, about 80 MB):
68
+
69
+ ```bash
70
+ pipx install bitcomposer
71
+ bitcomposer-player
72
+ ```
73
+
74
+ That first launch adds bitComposer to your app menu (under Multimedia,
75
+ with its icon); from then on start it from there like any other program.
76
+ The command line is `bitcomposer`, e.g. `bitcomposer -d out -s 42 -v` for
77
+ a reproducible song with details.
78
+
79
+ The player needs libopenmpt (above) and an audio output: `paplay`
80
+ (pulseaudio-utils), `pw-cat` (pipewire-bin) or `aplay` (alsa-utils).
81
+ `bitcomposer-player --check` says what it found. Upgrades: the UPDATE
82
+ button in the player, or `pipx upgrade bitcomposer`.
83
+
84
+ To uninstall, take the menu entry out first (pipx cannot), then the
85
+ program:
86
+
87
+ ```bash
88
+ bitcomposer-player --remove-desktop
89
+ pipx uninstall bitcomposer
90
+ ```
91
+
92
+ A menu entry you delete yourself stays deleted;
93
+ `bitcomposer-player --install-desktop` puts it back.
94
+
95
+ From a clone, for development, or for the generator alone: the command
96
+ line needs nothing but Python, and only the player needs Qt.
97
+
98
+ ```bash
99
+ git clone https://github.com/CatDogBark/bitComposer.git
100
+ cd bitComposer
101
+ python3 -m bitcomposer -d out
102
+ ```
103
+
104
+ Play the result with [OpenMPT](https://openmpt.org/) (Windows),
105
+ [Schism Tracker](https://schismtracker.org/), VLC, Audacious, `xmp`, or
106
+ anything built on libopenmpt.
107
+
108
+ Python 3.10 or newer. The generator has no dependencies; the player's
109
+ window is Qt (PySide6, installed with the package).
110
+
111
+ ## Sounds
112
+
113
+ A style pack pairs an instrument set with the arrangement habits of the score it imitates. Each is built from the game's SPC snapshots: every sample decoded and profiled, matched to the community's instrument tables where they exist, and re-synthesised; nothing from the games is in the repository.
114
+
115
+ - `ffvi`: every voice modelled on the game's own sample bank and named by its instrument table: the chorused string section, flutes in chords, the dark synth lead of Locke and the Returners, trumpet, trombone, oboe, Terra's and Cyan's pan flutes, cello, choir, pipe organ and rock organ, the Aria's soprano, the Battle theme's distortion guitar, piano, harp, picked string, acoustic guitar, tubular bell, xylophone, a bass guitar and a kit of its own (kick, snare, hats, cymbal, timpani, wood block), with ostinato strings, a brass counter-line in the chorus, timpani rolls into sections and the game's short, wet echo.
116
+ - `mana`: every voice modelled on the game's own sample bank: a soft slow-breathed flute, bright chorused strings, an 'ah' choir, a high whistle, soft and synth brass, marimba, vibraphone, electric piano, tubular bell, reed, accordion, glass and sine pads, fingered, electric and slap basses and a kit of its own (kick, snare, hats, crash, tom, castanet), with major and pentatonic keys, syncopated harmony, bouncy arps, light swing, the kick and snare set back and the game's one-row echo.
117
+ - `evermore`: every voice modelled on the game's own sample bank: a slow bright string swell, a warm pad, a dark pad, a glass bell, a breathy flute, a reed, an "oo" choir, harp, tinker music box, piano, pluck and kalimba, a textured drone and a wind loop, a bass, and a quiet kit (soft kick, frame drum, brushes, hat, cymbal, wood ping), with slow tempos, sustained harmony, a drone bass, sparse or no drums, long linear forms and the game's sparing 80 ms echo.
118
+ - `megamanx`: every voice modelled on the game's own sample bank and named by it: a driven, chorused lead guitar, a chugging rhythm guitar on power chords, the overdrive guitar for arps and counter-lines, synth brass, strings, a guitar swell pad, a saw pad, organ, the boomer synth lead, square and bright leads, a hollow wave, a bell synth, an acoustic pluck, the orchestra hit for stabs, slap and synth basses on a riff, and a tight kit, at fast tempos in minor keys with the game's 48 ms slapback echo.
119
+
120
+ `--sound` picks a palette or a pack in one word; left to chance, the four packs together weigh as much as plain snes.
121
+
122
+ - **snes** — sampled-style voices rendered the way the SNES actually made sound: strings, brass, a formant choir, flute, organ, e-piano, bells, plucks and a gated drum kit at 16 kHz with loop points, passed through a BRR codec model for the grain, with the lead, harmony and arp through an echo modelled on the SNES unit's result: fading, darkening repeats on a beat fraction, drawn per song.
123
+ - **genesis** — FM bells, brass, organ and bass.
124
+ - **chip** — square, pulse and triangle waves.
125
+
126
+ ## What you can steer
127
+
128
+ Everything defaults to `random`.
129
+
130
+ ```
131
+ --sound chip|snes|genesis|ffvi|mana|evermore|megamanx the sound in one word: a palette or a style pack (overrides the two below)
132
+ --style chip|snes|genesis sound palette
133
+ --pack ffvi|mana|evermore|megamanx|none|random style pack: an instrument set with the habits of the scores it imitates (a pack implies snes)
134
+ --echo on|off|random echo (random: 70% of snes songs, never chip or genesis)
135
+ --echo-wet light|normal|wet|random how much of the lead, harmony and arp the echo carries
136
+ --echo-delay eighth|dotted|quarter|slap|row|random beat fraction between repeats, a 48 ms slap, or one row (random: weighted by tempo)
137
+ --echo-stereo bounce|centre|random repeats alternate sides, or sit under their source
138
+ --keys moving|home moving: choruses/bridges may change key; home: stay put
139
+ --tempo slow|medium|fast 80–110 / 110–140 / 140–180 BPM
140
+ --energy chill|normal|intense density and arrangement weight
141
+ --scale minor|major|pentatonic
142
+ --form standard|aaba|rondo|short|linear
143
+ --drum-density sparse|normal|busy --no-fills --swing off|light|heavy
144
+ --melody simple|phrased phrased = motif-based, has a hook
145
+ --harmony-voicing thin|full two real voices, or three
146
+ --harmony-mode stabs|sustain|rhythmic
147
+ --bass-weight heavy|medium|light
148
+ --lead-shift SEMITONES move the lead's window (negative lowers it); default: the sound's own
149
+ --name title|timestamp file naming; --prefix / --suffix add a marker ("(auto) " is the player's)
150
+ -s SEED -n COUNT -o FILE -d DIR -v
151
+ ```
152
+
153
+ Some starting points:
154
+
155
+ ```bash
156
+ # Overworld — bright, sampled palette with echo
157
+ bitcomposer -d out --style snes --scale major --tempo medium --form standard
158
+
159
+ # FM boss fight
160
+ bitcomposer -d out --style genesis --tempo fast --energy intense --scale minor --drum-density busy --form short
161
+
162
+ # Game Boy flavour — square waves, thin harmony, no echo
163
+ bitcomposer -d out --style chip --echo off --harmony-voicing thin --bass-weight light --form short
164
+
165
+ # Credits roll
166
+ bitcomposer -d out --style snes --tempo slow --energy chill --scale major --drum-density sparse --no-fills --form linear
167
+ ```
168
+
169
+ ## How it works
170
+
171
+ 1. Pick a key and a scale weighted toward game music (minor pentatonic, dorian, harmonic minor, mixolydian…), then a progression for it. The tables include borrowed chords and secondary dominants — ♭VII, ♭VI, V/V — not just the diatonic set.
172
+ 2. Choose a form and its energy curve; decide which sections repeat. Repeated sections draw the same music from the same seed, so the hook comes back.
173
+ 3. Generate a motif (rhythm template plus contour) and vary it per bar in statement/answer pairs. Fourteen rhythm templates, six of them with 16th-note pushes and pickups.
174
+ 4. Each four-bar pattern holds a chord timeline; about half the time the back two bars move to a related chord. Melody resolves onto chord tones at each change. Harmony is two or three real voices placed near fixed anchors, so it steps rather than leaps and keeps the chord's third; the anchors are set per voice family (pads low and wide, brass and guitars mid and close), the top voice stays under the lead's line, and a stab holds for as long as the voice needs to speak. Bass and arp follow and rest with the section's energy.
175
+ 5. Drums come from one-bar templates by section and density, with fills, retriggered snare rolls and tick-level swing.
176
+ 6. Instruments are synthesized per song from the chosen palette and written as samples. SNES voices get attack-then-loop sustain and the BRR treatment.
177
+ 7. The echo: held lead notes and phrase endings come back as three fading, darkening repeats, the harmony and arp as lighter ones, each on return channels of their own, drums and bass dry. Everything is written as a 19-channel `.it` with the title and a song message (key, BPM, palette, form, seed, and a `layout:` line naming every channel's role) that trackers display.
178
+
179
+ Each song gets a title that reads the song: its scale, sound, energy and
180
+ tempo lean the words, so a slow minor Evermore piece and a fast Mega Man X
181
+ track are named differently (*Lunar Snow*, *Lighthouse of Steel*, *The
182
+ Power Plant of Sparks*).
183
+
184
+ ## Measuring instead of guessing
185
+
186
+ `tools/analyze.py` parses `.it` files back from disk (stdlib only, independent
187
+ of the generator) and scores a batch on the things that correlate with
188
+ "sounds like a song": section reuse, motif repetition, rhythmic grid, chord
189
+ voicing variety, voice motion, effect vocabulary, drum density.
190
+
191
+ ```bash
192
+ python3 tools/analyze.py 'out/*.it' # metric table
193
+ python3 tools/analyze.py --grid out/song.it # tracker-style pattern dump
194
+ ```
195
+
196
+ [docs/ANALYSIS.md](docs/ANALYSIS.md) is the story of this project: the
197
+ output was once limited by three silent arrangement bugs that nine commits
198
+ of ear-checking never caught, and every improvement since has been measured
199
+ before and after. Read it before changing the generator.
200
+
201
+ Tests:
202
+
203
+ ```bash
204
+ python3 -m unittest discover -s tests -v
205
+ ```
206
+
207
+ ## The player
208
+
209
+ <img src="docs/images/player.png" alt="The player: now playing, transport, gain, generate, settings and mix, the playlist" width="400">
210
+
211
+ `bitcomposer-player` (Linux) and `bitComposer.exe` (Windows) are the same
212
+ program: a folder of songs played through libopenmpt, GENERATE AND PLAY,
213
+ auto-generate when a track ends (the "radio"), the settings of what it
214
+ composes (sound, tempo, energy, scale, form, echo, bass, drums, harmony)
215
+ with presets, a live mixer per channel with the KIT and ECHO buses and
216
+ APPLY TO TRACK to write the mix into the file, gain with a soft limiter,
217
+ shuffle, and the playlist with KEEP: every track the player makes is
218
+ provisional (`(auto) <Title>.it`, so a file browser sorts them together)
219
+ and pruned after ten unless kept. It
220
+ opens no taller than the screen it lands on, the
221
+ SET and MIX panels open inside it (scrolling on a small or scaled
222
+ screen), and it keeps the size you give it; Ctrl + and
223
+ Ctrl − zoom it, Ctrl 0 resets. Closing the window leaves the music playing
224
+ in the tray (quit from the tray menu), and starting it again brings that
225
+ window back rather than a second player. The media keys drive it: on
226
+ Linux through the desktop's media controls (MPRIS, so the Plasma media
227
+ applet and lock screen, GNOME and `playerctl` see it too), on Windows as
228
+ global keys. SET → PLAYER → LOGIN, or the tray menu, starts it when you
229
+ log in: in the tray, not playing. When a newer
230
+ release exists an UPDATE button appears. It says what the update will do,
231
+ then shows it happening: on Linux it reinstalls through pipx, pipx's
232
+ output scrolling past, and restarts the player; on Windows it downloads
233
+ the release's installer and runs it. A player installed from a release candidate is
234
+ offered the next candidate; a release player only releases.
235
+
236
+ ## Windows
237
+
238
+ Every release carries `bitComposer-setup.exe` (the installer) and `bitComposer-windows.zip` (the same `bitComposer` folder, no install), built by GitHub Actions on every push to main and attached on the tag: `bitComposer.exe`, the player, with Qt and libopenmpt beside it; and `bitcomposer-cli.exe`, the command line. The installer installs for your user by default (no administrator prompt; all users is an option on its first page), and the player's UPDATE button runs the next one quietly and reopens the player. Each build also renders the player offscreen at common screen sizes and scalings (1366×768, 1920×1080 at 100% and 150%, 2560×1440 at 125%, 4K at 200%), kept as the workflow's `player-screenshots-windows` artifact. Songs are `.it` files; [OpenMPT](https://openmpt.org) and XMPlay play them too. Windows releases are to be code-signed through the SignPath Foundation's programme for open-source projects (see [Code signing policy](#code-signing-policy)); until that is in place they are unsigned, so SmartScreen asks once ("More info", "Run anyway"). With Python installed instead, `pipx install bitcomposer` gives the same programs as `bitcomposer-player` and `bitcomposer`.
239
+
240
+ ## Code signing policy
241
+
242
+ Free code signing provided by [SignPath.io](https://about.signpath.io), certificate by [SignPath Foundation](https://signpath.org).
243
+
244
+ Status: applied for in October 2026. Until it is approved, the Windows builds are unsigned.
245
+
246
+ What is signed: the Windows release files built by this repository's GitHub Actions workflow from the source in this repository: `bitComposer.exe`, `bitcomposer-cli.exe` and `bitComposer-setup.exe`. Libraries included from upstream projects (Python, Qt, libopenmpt) are their own projects' builds.
247
+
248
+ - Committers and reviewers: [CatDogBark](https://github.com/CatDogBark)
249
+ - Approvers: [CatDogBark](https://github.com/CatDogBark)
250
+
251
+ Every release is approved by hand before it is signed. Everyone with these roles uses multi-factor authentication on GitHub and SignPath.
252
+
253
+ ## Privacy
254
+
255
+ bitComposer composes and plays music on your computer. It collects nothing about you, your music or how you use it, and sends none of it anywhere.
256
+
257
+ One thing goes over the network on its own: when the player starts, it asks GitHub's public releases list (`api.github.com`) whether a newer version exists, so it can offer the UPDATE button. That request carries only what any web request does (your IP address and the program's name), and [GitHub's privacy statement](https://docs.github.com/site-policy/privacy-policies/github-general-privacy-statement) covers it. Turn it off in the player under SET → PLAYER → UPDATES. Updating itself downloads only when you press UPDATE: the installer from GitHub on Windows, the package from PyPI with pipx.
258
+
259
+ The [listening page](https://catdogbark.github.io/bitComposer/) is a website: GitHub Pages serves it and Google Fonts serves its font, each under its own privacy policy. It plays the songs in your browser and keeps nothing.
260
+
261
+ ## License and contact
262
+
263
+ MIT, copyright 2026 Enlightened Solutions LLC (see [LICENSE](LICENSE)).
264
+ Every instrument is synthesized; no samples were taken from any game.
265
+
266
+ Bugs and ideas: [GitHub issues](https://github.com/CatDogBark/bitComposer/issues).
267
+ Anything else: CatDogBark, catdogbark@pm.me.
@@ -0,0 +1,245 @@
1
+ <h1>
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="docs/images/logo-dark.svg">
4
+ <img src="docs/images/logo-light.svg" alt="bitComposer" height="64">
5
+ </picture>
6
+ </h1>
7
+
8
+ *Endless music. Keep what moves you.*
9
+
10
+ [![CI](https://github.com/CatDogBark/bitComposer/actions/workflows/ci.yml/badge.svg)](https://github.com/CatDogBark/bitComposer/actions/workflows/ci.yml)
11
+ [![Release](https://img.shields.io/github/v/release/CatDogBark/bitComposer)](https://github.com/CatDogBark/bitComposer/releases/latest)
12
+ ![License](https://img.shields.io/badge/license-MIT-green)
13
+
14
+ Procedural 16-bit game music. A player that composes the next song as the
15
+ current one ends, with a live mixer, on Linux and Windows; a command line
16
+ and a generator library underneath, pure Python with no dependencies,
17
+ writing Impulse Tracker `.it` modules any tracker player reads.
18
+
19
+ Every run composes a new song: a motif-based melody with call-and-response
20
+ phrasing, voice-led harmony, bass, arpeggio and drums, arranged into a form
21
+ (verse–chorus, AABA, rondo, through-composed) with a drawn intro, an energy
22
+ curve and a real ending, titled after what it drew, between 1:15 and 3:30
23
+ long. Seven sounds, picked with `--sound`:
24
+
25
+ - **snes** — sampled-style voices built the way the SNES made sound, through a BRR codec model and the SNES echo.
26
+ - **ffvi**, **mana**, **evermore**, **megamanx** — style packs: an instrument set rebuilt from each game's own sound chip (every sample profiled, nothing copied) plus the arrangement habits of its score. Details under [Sounds](#sounds).
27
+ - **genesis** — FM bells, brass, organ and bass.
28
+ - **chip** — square, pulse and triangle waves. Closest to NES and Game Boy.
29
+
30
+ **[Listen in your browser](https://catdogbark.github.io/bitComposer/)** — the actual modules, played live by libopenmpt in WebAssembly: one song per sound, straight from the generator, regenerated with each release.
31
+
32
+ **Reproducible, not frozen.** The same seed on the same version gives the same song, byte for byte. A new version may change what a seed draws, and the song message records the version that wrote the file.
33
+
34
+ ## Install
35
+
36
+ **Windows.** Every release carries `bitComposer-setup.exe`: the player, the
37
+ command line, a Start menu entry and an uninstaller; or `bitComposer-windows.zip`,
38
+ the same program as a folder with nothing to install. No Python needed. See
39
+ [Windows](#windows).
40
+
41
+ **Linux.** From PyPI with [pipx](https://pipx.pypa.io/), so it lands on your
42
+ PATH without touching the system Python (Debian and Fedora refuse a plain
43
+ `pip install` there; `sudo apt install pipx libopenmpt0` or
44
+ `sudo dnf install pipx libopenmpt` gets pipx and the module library). The
45
+ player's window is Qt, which pipx brings along (PySide6, about 80 MB):
46
+
47
+ ```bash
48
+ pipx install bitcomposer
49
+ bitcomposer-player
50
+ ```
51
+
52
+ That first launch adds bitComposer to your app menu (under Multimedia,
53
+ with its icon); from then on start it from there like any other program.
54
+ The command line is `bitcomposer`, e.g. `bitcomposer -d out -s 42 -v` for
55
+ a reproducible song with details.
56
+
57
+ The player needs libopenmpt (above) and an audio output: `paplay`
58
+ (pulseaudio-utils), `pw-cat` (pipewire-bin) or `aplay` (alsa-utils).
59
+ `bitcomposer-player --check` says what it found. Upgrades: the UPDATE
60
+ button in the player, or `pipx upgrade bitcomposer`.
61
+
62
+ To uninstall, take the menu entry out first (pipx cannot), then the
63
+ program:
64
+
65
+ ```bash
66
+ bitcomposer-player --remove-desktop
67
+ pipx uninstall bitcomposer
68
+ ```
69
+
70
+ A menu entry you delete yourself stays deleted;
71
+ `bitcomposer-player --install-desktop` puts it back.
72
+
73
+ From a clone, for development, or for the generator alone: the command
74
+ line needs nothing but Python, and only the player needs Qt.
75
+
76
+ ```bash
77
+ git clone https://github.com/CatDogBark/bitComposer.git
78
+ cd bitComposer
79
+ python3 -m bitcomposer -d out
80
+ ```
81
+
82
+ Play the result with [OpenMPT](https://openmpt.org/) (Windows),
83
+ [Schism Tracker](https://schismtracker.org/), VLC, Audacious, `xmp`, or
84
+ anything built on libopenmpt.
85
+
86
+ Python 3.10 or newer. The generator has no dependencies; the player's
87
+ window is Qt (PySide6, installed with the package).
88
+
89
+ ## Sounds
90
+
91
+ A style pack pairs an instrument set with the arrangement habits of the score it imitates. Each is built from the game's SPC snapshots: every sample decoded and profiled, matched to the community's instrument tables where they exist, and re-synthesised; nothing from the games is in the repository.
92
+
93
+ - `ffvi`: every voice modelled on the game's own sample bank and named by its instrument table: the chorused string section, flutes in chords, the dark synth lead of Locke and the Returners, trumpet, trombone, oboe, Terra's and Cyan's pan flutes, cello, choir, pipe organ and rock organ, the Aria's soprano, the Battle theme's distortion guitar, piano, harp, picked string, acoustic guitar, tubular bell, xylophone, a bass guitar and a kit of its own (kick, snare, hats, cymbal, timpani, wood block), with ostinato strings, a brass counter-line in the chorus, timpani rolls into sections and the game's short, wet echo.
94
+ - `mana`: every voice modelled on the game's own sample bank: a soft slow-breathed flute, bright chorused strings, an 'ah' choir, a high whistle, soft and synth brass, marimba, vibraphone, electric piano, tubular bell, reed, accordion, glass and sine pads, fingered, electric and slap basses and a kit of its own (kick, snare, hats, crash, tom, castanet), with major and pentatonic keys, syncopated harmony, bouncy arps, light swing, the kick and snare set back and the game's one-row echo.
95
+ - `evermore`: every voice modelled on the game's own sample bank: a slow bright string swell, a warm pad, a dark pad, a glass bell, a breathy flute, a reed, an "oo" choir, harp, tinker music box, piano, pluck and kalimba, a textured drone and a wind loop, a bass, and a quiet kit (soft kick, frame drum, brushes, hat, cymbal, wood ping), with slow tempos, sustained harmony, a drone bass, sparse or no drums, long linear forms and the game's sparing 80 ms echo.
96
+ - `megamanx`: every voice modelled on the game's own sample bank and named by it: a driven, chorused lead guitar, a chugging rhythm guitar on power chords, the overdrive guitar for arps and counter-lines, synth brass, strings, a guitar swell pad, a saw pad, organ, the boomer synth lead, square and bright leads, a hollow wave, a bell synth, an acoustic pluck, the orchestra hit for stabs, slap and synth basses on a riff, and a tight kit, at fast tempos in minor keys with the game's 48 ms slapback echo.
97
+
98
+ `--sound` picks a palette or a pack in one word; left to chance, the four packs together weigh as much as plain snes.
99
+
100
+ - **snes** — sampled-style voices rendered the way the SNES actually made sound: strings, brass, a formant choir, flute, organ, e-piano, bells, plucks and a gated drum kit at 16 kHz with loop points, passed through a BRR codec model for the grain, with the lead, harmony and arp through an echo modelled on the SNES unit's result: fading, darkening repeats on a beat fraction, drawn per song.
101
+ - **genesis** — FM bells, brass, organ and bass.
102
+ - **chip** — square, pulse and triangle waves.
103
+
104
+ ## What you can steer
105
+
106
+ Everything defaults to `random`.
107
+
108
+ ```
109
+ --sound chip|snes|genesis|ffvi|mana|evermore|megamanx the sound in one word: a palette or a style pack (overrides the two below)
110
+ --style chip|snes|genesis sound palette
111
+ --pack ffvi|mana|evermore|megamanx|none|random style pack: an instrument set with the habits of the scores it imitates (a pack implies snes)
112
+ --echo on|off|random echo (random: 70% of snes songs, never chip or genesis)
113
+ --echo-wet light|normal|wet|random how much of the lead, harmony and arp the echo carries
114
+ --echo-delay eighth|dotted|quarter|slap|row|random beat fraction between repeats, a 48 ms slap, or one row (random: weighted by tempo)
115
+ --echo-stereo bounce|centre|random repeats alternate sides, or sit under their source
116
+ --keys moving|home moving: choruses/bridges may change key; home: stay put
117
+ --tempo slow|medium|fast 80–110 / 110–140 / 140–180 BPM
118
+ --energy chill|normal|intense density and arrangement weight
119
+ --scale minor|major|pentatonic
120
+ --form standard|aaba|rondo|short|linear
121
+ --drum-density sparse|normal|busy --no-fills --swing off|light|heavy
122
+ --melody simple|phrased phrased = motif-based, has a hook
123
+ --harmony-voicing thin|full two real voices, or three
124
+ --harmony-mode stabs|sustain|rhythmic
125
+ --bass-weight heavy|medium|light
126
+ --lead-shift SEMITONES move the lead's window (negative lowers it); default: the sound's own
127
+ --name title|timestamp file naming; --prefix / --suffix add a marker ("(auto) " is the player's)
128
+ -s SEED -n COUNT -o FILE -d DIR -v
129
+ ```
130
+
131
+ Some starting points:
132
+
133
+ ```bash
134
+ # Overworld — bright, sampled palette with echo
135
+ bitcomposer -d out --style snes --scale major --tempo medium --form standard
136
+
137
+ # FM boss fight
138
+ bitcomposer -d out --style genesis --tempo fast --energy intense --scale minor --drum-density busy --form short
139
+
140
+ # Game Boy flavour — square waves, thin harmony, no echo
141
+ bitcomposer -d out --style chip --echo off --harmony-voicing thin --bass-weight light --form short
142
+
143
+ # Credits roll
144
+ bitcomposer -d out --style snes --tempo slow --energy chill --scale major --drum-density sparse --no-fills --form linear
145
+ ```
146
+
147
+ ## How it works
148
+
149
+ 1. Pick a key and a scale weighted toward game music (minor pentatonic, dorian, harmonic minor, mixolydian…), then a progression for it. The tables include borrowed chords and secondary dominants — ♭VII, ♭VI, V/V — not just the diatonic set.
150
+ 2. Choose a form and its energy curve; decide which sections repeat. Repeated sections draw the same music from the same seed, so the hook comes back.
151
+ 3. Generate a motif (rhythm template plus contour) and vary it per bar in statement/answer pairs. Fourteen rhythm templates, six of them with 16th-note pushes and pickups.
152
+ 4. Each four-bar pattern holds a chord timeline; about half the time the back two bars move to a related chord. Melody resolves onto chord tones at each change. Harmony is two or three real voices placed near fixed anchors, so it steps rather than leaps and keeps the chord's third; the anchors are set per voice family (pads low and wide, brass and guitars mid and close), the top voice stays under the lead's line, and a stab holds for as long as the voice needs to speak. Bass and arp follow and rest with the section's energy.
153
+ 5. Drums come from one-bar templates by section and density, with fills, retriggered snare rolls and tick-level swing.
154
+ 6. Instruments are synthesized per song from the chosen palette and written as samples. SNES voices get attack-then-loop sustain and the BRR treatment.
155
+ 7. The echo: held lead notes and phrase endings come back as three fading, darkening repeats, the harmony and arp as lighter ones, each on return channels of their own, drums and bass dry. Everything is written as a 19-channel `.it` with the title and a song message (key, BPM, palette, form, seed, and a `layout:` line naming every channel's role) that trackers display.
156
+
157
+ Each song gets a title that reads the song: its scale, sound, energy and
158
+ tempo lean the words, so a slow minor Evermore piece and a fast Mega Man X
159
+ track are named differently (*Lunar Snow*, *Lighthouse of Steel*, *The
160
+ Power Plant of Sparks*).
161
+
162
+ ## Measuring instead of guessing
163
+
164
+ `tools/analyze.py` parses `.it` files back from disk (stdlib only, independent
165
+ of the generator) and scores a batch on the things that correlate with
166
+ "sounds like a song": section reuse, motif repetition, rhythmic grid, chord
167
+ voicing variety, voice motion, effect vocabulary, drum density.
168
+
169
+ ```bash
170
+ python3 tools/analyze.py 'out/*.it' # metric table
171
+ python3 tools/analyze.py --grid out/song.it # tracker-style pattern dump
172
+ ```
173
+
174
+ [docs/ANALYSIS.md](docs/ANALYSIS.md) is the story of this project: the
175
+ output was once limited by three silent arrangement bugs that nine commits
176
+ of ear-checking never caught, and every improvement since has been measured
177
+ before and after. Read it before changing the generator.
178
+
179
+ Tests:
180
+
181
+ ```bash
182
+ python3 -m unittest discover -s tests -v
183
+ ```
184
+
185
+ ## The player
186
+
187
+ <img src="docs/images/player.png" alt="The player: now playing, transport, gain, generate, settings and mix, the playlist" width="400">
188
+
189
+ `bitcomposer-player` (Linux) and `bitComposer.exe` (Windows) are the same
190
+ program: a folder of songs played through libopenmpt, GENERATE AND PLAY,
191
+ auto-generate when a track ends (the "radio"), the settings of what it
192
+ composes (sound, tempo, energy, scale, form, echo, bass, drums, harmony)
193
+ with presets, a live mixer per channel with the KIT and ECHO buses and
194
+ APPLY TO TRACK to write the mix into the file, gain with a soft limiter,
195
+ shuffle, and the playlist with KEEP: every track the player makes is
196
+ provisional (`(auto) <Title>.it`, so a file browser sorts them together)
197
+ and pruned after ten unless kept. It
198
+ opens no taller than the screen it lands on, the
199
+ SET and MIX panels open inside it (scrolling on a small or scaled
200
+ screen), and it keeps the size you give it; Ctrl + and
201
+ Ctrl − zoom it, Ctrl 0 resets. Closing the window leaves the music playing
202
+ in the tray (quit from the tray menu), and starting it again brings that
203
+ window back rather than a second player. The media keys drive it: on
204
+ Linux through the desktop's media controls (MPRIS, so the Plasma media
205
+ applet and lock screen, GNOME and `playerctl` see it too), on Windows as
206
+ global keys. SET → PLAYER → LOGIN, or the tray menu, starts it when you
207
+ log in: in the tray, not playing. When a newer
208
+ release exists an UPDATE button appears. It says what the update will do,
209
+ then shows it happening: on Linux it reinstalls through pipx, pipx's
210
+ output scrolling past, and restarts the player; on Windows it downloads
211
+ the release's installer and runs it. A player installed from a release candidate is
212
+ offered the next candidate; a release player only releases.
213
+
214
+ ## Windows
215
+
216
+ Every release carries `bitComposer-setup.exe` (the installer) and `bitComposer-windows.zip` (the same `bitComposer` folder, no install), built by GitHub Actions on every push to main and attached on the tag: `bitComposer.exe`, the player, with Qt and libopenmpt beside it; and `bitcomposer-cli.exe`, the command line. The installer installs for your user by default (no administrator prompt; all users is an option on its first page), and the player's UPDATE button runs the next one quietly and reopens the player. Each build also renders the player offscreen at common screen sizes and scalings (1366×768, 1920×1080 at 100% and 150%, 2560×1440 at 125%, 4K at 200%), kept as the workflow's `player-screenshots-windows` artifact. Songs are `.it` files; [OpenMPT](https://openmpt.org) and XMPlay play them too. Windows releases are to be code-signed through the SignPath Foundation's programme for open-source projects (see [Code signing policy](#code-signing-policy)); until that is in place they are unsigned, so SmartScreen asks once ("More info", "Run anyway"). With Python installed instead, `pipx install bitcomposer` gives the same programs as `bitcomposer-player` and `bitcomposer`.
217
+
218
+ ## Code signing policy
219
+
220
+ Free code signing provided by [SignPath.io](https://about.signpath.io), certificate by [SignPath Foundation](https://signpath.org).
221
+
222
+ Status: applied for in October 2026. Until it is approved, the Windows builds are unsigned.
223
+
224
+ What is signed: the Windows release files built by this repository's GitHub Actions workflow from the source in this repository: `bitComposer.exe`, `bitcomposer-cli.exe` and `bitComposer-setup.exe`. Libraries included from upstream projects (Python, Qt, libopenmpt) are their own projects' builds.
225
+
226
+ - Committers and reviewers: [CatDogBark](https://github.com/CatDogBark)
227
+ - Approvers: [CatDogBark](https://github.com/CatDogBark)
228
+
229
+ Every release is approved by hand before it is signed. Everyone with these roles uses multi-factor authentication on GitHub and SignPath.
230
+
231
+ ## Privacy
232
+
233
+ bitComposer composes and plays music on your computer. It collects nothing about you, your music or how you use it, and sends none of it anywhere.
234
+
235
+ One thing goes over the network on its own: when the player starts, it asks GitHub's public releases list (`api.github.com`) whether a newer version exists, so it can offer the UPDATE button. That request carries only what any web request does (your IP address and the program's name), and [GitHub's privacy statement](https://docs.github.com/site-policy/privacy-policies/github-general-privacy-statement) covers it. Turn it off in the player under SET → PLAYER → UPDATES. Updating itself downloads only when you press UPDATE: the installer from GitHub on Windows, the package from PyPI with pipx.
236
+
237
+ The [listening page](https://catdogbark.github.io/bitComposer/) is a website: GitHub Pages serves it and Google Fonts serves its font, each under its own privacy policy. It plays the songs in your browser and keeps nothing.
238
+
239
+ ## License and contact
240
+
241
+ MIT, copyright 2026 Enlightened Solutions LLC (see [LICENSE](LICENSE)).
242
+ Every instrument is synthesized; no samples were taken from any game.
243
+
244
+ Bugs and ideas: [GitHub issues](https://github.com/CatDogBark/bitComposer/issues).
245
+ Anything else: CatDogBark, catdogbark@pm.me.
@@ -0,0 +1,6 @@
1
+ """bitcomposer — Procedural 16-bit chiptune music generator."""
2
+
3
+ __version__ = "1.0.0"
4
+
5
+ # The registry first, then the packs that register their voices into it.
6
+ from . import samples, packs # noqa: E402,F401
@@ -0,0 +1,5 @@
1
+ """Allow `python3 -m bitcomposer` as a synonym for `python3 -m bitcomposer.cli`."""
2
+
3
+ from .cli import main
4
+
5
+ main()