Skip to main content

Read and write Elektron SidStation patch (.syx) SysEx files

Project description

pysidstation

Read and write Elektron SidStation patch (.syx) SysEx files in pure Python — no dependencies.

The SidStation is a synthesizer built around the MOS 6581/8580 "SID" chip from the Commodore 64. Its patches are exchanged as MIDI System Exclusive dumps. pysidstation parses those dumps into editable Patch objects and writes them back byte-for-byte.

The complete, corrected file format is documented in docs/FORMAT.md.

Install

pip install pysidstation

Requires Python 3.10+.

Quick start

import sidstation

bank = sidstation.read("SidStation_Presets_r1.syx")

print(len(bank), "patches")          # 90 patches
for patch in bank:
    print(patch.name)                # Anpanman, Krutong, Floating-7, ...

# Edit a patch
lead = bank[0]
lead.name = "My Lead"
lead.poly = True
lead.filter_cutoff = 90
lead.oscillators[0].waveform = sidstation.Waveform.SAW
lead.oscillators[0].ring_mod = True
lead.lfos[0].lfo_type = sidstation.LfoType.RAMP

bank.write("edited.syx")

An unmodified file round-trips exactly:

data = open("SidStation_Presets_r1.syx", "rb").read()
assert sidstation.loads(data).to_bytes() == data

Building a bank from scratch

from sidstation import Bank, Patch, Waveform

p = Patch(name="Init")
p.osc1_enabled = True
p.oscillators[0].waveform = Waveform.PULSE
p.oscillators[0].attack = 2
p.oscillators[0].sustain = 12

bank = Bank.from_patches([p])   # prepends the all-clear message by default
bank.write("init.syx")

What you can read and write

Each Patch exposes the full parameter set as plain attributes that read and write the underlying patch bytes directly:

  • Namepatch.name (and patch.name_bytes for the raw 10 bytes)
  • Modeosc1_enabled, osc2_enabled, osc3_enabled, poly, legato, filter_wrap, filter_env_invert
  • Filterfilter_routing, filter_osc1/2/3, resonance, filter_type, filter_lfo, filter_cutoff, filter_env_attack/decay/sustain/release, filter_env_depth, filter_lfo_depth, filter_lfo_wheel_depth
  • Per-patch syncsync_speed, sync_hcut
  • Oscillatorspatch.oscillators[0..2] with waveform, ring_mod, sync, test, sync_pwm, gate, track, arp_speed, transpose, detune, pitchbend_range, attack, decay, sustain, release, delay, pwm_start, pwm_add, pwm_lfo, pwm_lfo_depth, portamento, vibrato_lfo, vibrato_depth, vibrato_wheel_depth, table_speed, plus decode helpers transpose_semitones, detune_value, detune_cents
  • LFOspatch.lfos[0..3] with lfo_type, ctrl_source, ctrl_dest, sync, invert, above_zero, sync_note_off, speed, sample_hold, depth, add_lfo, lace, lace_with, add_depth, ctrl_value, fade_in
  • Direct controllerspatch.direct_controllers[0..3] with value, limit_down, limit_up
  • Tablespatch.tables (three Tables of TableSteps) and patch.replace_tables(...)

Need the raw bytes? patch.data is the mutable, decoded bytearray that backs every attribute above, indexed exactly as in docs/FORMAT.md.

Command line

sidstation info  SidStation_Presets_r1.syx   # summary table
sidstation names SidStation_Presets_r1.syx   # one name per line
sidstation show  SidStation_Presets_r1.syx 0 # detail for patch 0

(Equivalently python -m sidstation ....)

A couple of things the manual gets wrong

pysidstation is built from the owner's manual and verified against a real bank. A few corrections matter in practice:

  • Every stored parameter byte is nibble-swapped relative to the synth's working value. The library undoes this on load (and re-applies on save), so patch.data and every attribute hold the synth's true values while files still round-trip byte-for-byte. This single fact is why the manual's waveform, LFO-type and detune layouts looked off — once un-swapped they line up. (e.g. the waveform is really in the OSC_WAVE high nibble, SID-control style.)
  • LFO type 5 is "Flat", not 7, and detune spans ≈ ±1 semitone, not ±½ — both corrections to the manual's tables.
  • The size field in each patch header is unreliable (54 of 90 patches in the reference bank disagree with it). The library parses by message boundary and preserves the stored value so files still round-trip exactly.

All are explained in docs/FORMAT.md.

Development

pip install -e ".[dev,lint]"
pytest
ruff check .
ruff format --check .

The test suite uses Elektron's factory preset bank as a fixture. That file is Elektron's copyrighted content and is not committed here — tests/conftest.py downloads it on demand from Elektron's official SidStation Sound Pack archive, verifies its SHA-256, and caches it locally. To run offline, point SIDSTATION_PRESETS at a local copy; if it can't be obtained, the dependent tests are skipped.

All tests run in CI (GitHub Actions) across Python 3.10–3.13, and the distribution is built and checked there too. The lint job uses the pinned ruff from the lint extra, which Dependabot keeps current.

License

Apache-2.0. See LICENSE.

SidStation and Elektron are trademarks of Elektron Music Machines. This is an independent, unofficial library and is not affiliated with or endorsed by Elektron.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pysidstation-0.2.0.tar.gz (35.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pysidstation-0.2.0-py3-none-any.whl (23.9 kB view details)

Uploaded Python 3

File details

Details for the file pysidstation-0.2.0.tar.gz.

File metadata

  • Download URL: pysidstation-0.2.0.tar.gz
  • Upload date:
  • Size: 35.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pysidstation-0.2.0.tar.gz
Algorithm Hash digest
SHA256 a96fb38e842ff54fa535b2ca0d6cf4cf42346b1f8fc2c26402160ed1db4150a6
MD5 23473165bc0f6750ea72b3c163ae5d31
BLAKE2b-256 7a872b10bbe9835e3d8ce3c718f5a90210ae81c25906bb5450d9c8f26bf70ae0

See more details on using hashes here.

Provenance

The following attestation bundles were made for pysidstation-0.2.0.tar.gz:

Publisher: publish.yml on anarkiwi/pysidstation

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pysidstation-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: pysidstation-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 23.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pysidstation-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a85f07928ed8251423614018c833c0b540b7394a25aa519de7909c1399323d2c
MD5 c56ca8329aa4c09bfa2b2ea9a0c7e0d5
BLAKE2b-256 bb2131f4fb3ee6624832070b19a05af8067f9a2b6650874712a74cec353e1df3

See more details on using hashes here.

Provenance

The following attestation bundles were made for pysidstation-0.2.0-py3-none-any.whl:

Publisher: publish.yml on anarkiwi/pysidstation

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page