Skip to content

Add Elektron Tonverk preset (TVPST) format support for reading and writing#153

Open
douglas-carmichael wants to merge 13 commits into
git-moss:mainfrom
douglas-carmichael:add-elektron-tonverk-preset
Open

Add Elektron Tonverk preset (TVPST) format support for reading and writing#153
douglas-carmichael wants to merge 13 commits into
git-moss:mainfrom
douglas-carmichael:add-elektron-tonverk-preset

Conversation

@douglas-carmichael

@douglas-carmichael douglas-carmichael commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds support for the Elektron Tonverk preset format (*.tvpst). In contrast to the existing elmulti/eldrum mapping files, a .tvpst is a full preset that also carries the synthesizer parameters. Both directions were exercised against the factory preset library, and presets written by ConvertWithMoss have been confirmed to load and play on a physical Tonverk.

Reading

All three generator machines are read into the multi-sample model:

  • Multi – a multi-sample mapped to key- and velocity-ranges.
  • One-Shot – a single sample mapped across the keyboard (normalized sample start/end and loop points are scaled to frames).
  • Drum – a kit of eight voices, each on its own key with its own settings.

The amplitude envelope (AHD or ADSR), the multi-mode filter together with its envelope (the bipolar env-depth maps to the cut-off modulator), the sample loops, gain and panning are converted. Synthesizer-specific parameters that have no equivalent in the multi-sample model (arpeggiator, effects, global LFOs, modulation matrix) are intentionally not converted. Samples referenced by absolute device paths (/mnt/sdcard/...) are resolved relative to the preset's location on disk.

Writing

Writes a Multi or Drum machine preset, selectable in the creator settings (Multi-Sample / Drum Kit / Auto-from-source).

The output mirrors the device's SD-card layout so the result can be copied straight onto a Tonverk: the preset is a flat file in User/Presets/<name>.tvpst, and its samples live separately under User/Multi-sampled Instruments/<name>/, referenced by their absolute device path (/mnt/sdcard/User/Multi-sampled Instruments/<name>/<sample>.wav). Both sub-trees accumulate across presets when a whole library is converted. (A .tvpst is only listed by the device when it is a flat file in User/Presets with its samples referenced absolutely; the earlier folder-per-preset/relative-name layout showed nothing on the device.) Samples are written as physically trimmed WAVs, with a sample chunk only when the zone loops and no zero-velocity zones, matching the device's expectations.

The full [parameters] block is generated from a neutral factory template with the converted parameters filled in. The template was captured from a factory preset and has been fully neutralized — effects bypassed, overdrive and vibrato off, the filter wide open with a centered (no-sweep) filter envelope, and every per-machine LFO set to a centered depth (no modulation) — so a converted preset plays the source sample cleanly with only the amplitude envelope and any source filter, free of inherited coloration or modulation.

Envelope times and the filter cut-off are stored as normalized values driven by internal firmware curves. The envelope-time maxima were calibrated against hardware resamples: the firmware was found to follow the same seconds = max · normalized³ cube law the writer uses, so the seconds mapping is close, not merely a guess. Times within the device's range round-trip to within a few percent; times beyond the device's ceiling clamp to it. A Tonverk→Tonverk round-trip remains loss-less (the inverse functions are exact), while a conversion to/from a unit-based format (Waldorf Quantum/Iridium, Synthstrom Deluge) is a close approximation.

Naming

Since every Elektron format ConvertWithMoss currently handles is a Tonverk format, the existing ElektronMulti* classes (the elmulti/eldrum mapping) are renamed to TonverkMulti*, so the format/elektron family is named by device and leaves room for future Elektron devices. The mapping format's user-facing name is also unified to Elektron Tonverk Multisample for both reading and writing — it was previously Elektron Multi when read but Elektron Tonverk when written, the latter easily confused with the new Elektron Tonverk Preset. CLI prefixes are unchanged (Elektron/Emulti for the mapping, Tonverk for the preset), so existing scripts and settings are unaffected.

Testing

Verified on a physical Elektron Tonverk and against the factory preset library:

  • On hardware: presets written by ConvertWithMoss and copied to the SD card are listed, load and play on the device; the flat-file layout and absolute sample references were confirmed against how the device itself saves presets.
  • Envelope calibration: device resamples of presets with known normalized values were used to measure the firmware's attack/release curves and set the seconds mapping. A held-note resample confirmed the neutralized template produces a clean, un-modulated tone (flat sustain, no warble).
  • .tvpst → Waldorf QPAT and → Synthstrom Deluge — amplitude/filter envelopes and the filter carry through.
  • .tvpst.tvpst round-trip reproduces the amplitude and filter envelopes, the filter and the mapping (exact for the stored normalized values).
  • All three machines, including per-voice drum envelopes and the Auto engine selection.

…iting

Reads all three generator machines (One-Shot, Multi, Drum) into the multi-sample model, including the amplitude envelope, the multi-mode filter and its envelope, sample loops, gain and panning. Writes a Multi or Drum machine preset (selectable, with an auto-from-source mode) using a neutral factory parameter template; samples are stored next to the preset and referenced relatively.

The existing ElektronMulti* classes (which handle the Tonverk .elmulti/.eldrum mapping files) are renamed to TonverkMulti* so the Elektron format family is named by device. The user-facing format name and CLI prefix are unchanged.
The .elmulti/.eldrum multi-sample mapping format was labelled "Elektron
Multi" when reading but "Elektron Tonverk" when writing, and the latter
was easily confused with the new "Elektron Tonverk Preset". It is now
"Elektron Tonverk Multi-Sample" on both sides. The CLI prefixes are left
unchanged for backward compatibility.
@douglas-carmichael douglas-carmichael force-pushed the add-elektron-tonverk-preset branch from 9841634 to 8859a5c Compare June 27, 2026 13:21
A preset whose name (or category/tag) contained a single quote was written
into the single-quoted TOML scalar verbatim, e.g. name = 'Tonverk's Test',
which is malformed and rejected by the Tonverk. Mirror the elmulti writer:
fall back to a double-quoted string when the value contains a single quote,
and accept double-quoted values when reading back.
A *.tvpst preset is shown on the Tonverk only when it is a flat file in
'User/Presets'; its samples must live separately under
'User/Multi-sampled Instruments/<name>' and be referenced by their
absolute device path. The creator previously wrote a folder per preset
with the samples next to it and referenced them by bare file name (the
elmulti convention), so the device listed nothing.

The creator now mirrors the SD-card layout below the chosen output
folder: 'User/Presets/<name>.tvpst' plus
'User/Multi-sampled Instruments/<name>/<sample>.wav', each referenced as
'/mnt/sdcard/User/Multi-sampled Instruments/<name>/<sample>.wav'. Both
sub-trees accumulate across presets when a whole library is converted,
and the created 'User' folder can be copied straight onto the device.
The detector already strips the mount prefix and resolves samples
against the preset folder's ancestors, so reading round-trips.
The neutral *.tvpst templates were captured from factory presets, but
the per-machine LFOs were not fully reset: the Multi template's LFO2 had
a real destination (8) and an off-center depth (0.518), and Drum voices
1, 4 and 6 likewise had routed LFOs with off-center depths. Per the
manual a depth of 0.5 is the center that equals no modulation, so these
non-0.5 depths made every converted preset modulate audibly - a ~1 s
warble on a held note. All per-machine LFOs are now set to destination 0
(off) and depth 0.5 (no modulation), matching a static factory preset.
The multi/drum templates were captured from factory presets and carried
non-neutral modulation/effect values that the writer never overwrites, so
every converted preset inherited them and sounded colored:

- multi: vibrato depth, overdrive, a non-open filter cutoff with resonance,
  and a filter-envelope sweep (depth off-center)
- drum: overdrive on six voices and two non-open filter cutoffs

Reset all to their neutral values (depth 0.5 = no modulation, destination/
overdrive/vibrato 0 = off, cutoff 1 = wide open) so a converted preset plays
the source sample cleanly with only the amp envelope and any source filter.
The envelope MAX constants were educated guesses. A Tonverk resample of a
preset with known normalized values shows the firmware uses the same
seconds = max * normalized^3 cube law the writer uses, so the maxima could be
measured directly:

- attack: a linear ramp topping out near 1.6 s, not 8 s (two probes agree:
  norm 0.63 -> 0.40 s and norm 0.79 -> 0.78 s). The old 8 s made every
  converted attack about 5x too fast.
- decay/release: an exponential fade whose time to -60 dB tops out near 22 s,
  not 24 s (norm 0.63 -> ~5.5 s) - a minor correction.

Hold shares the attack scale and decay shares the release scale (both unprobed).
Attack/release times within the device's range now round-trip to within a few
percent; longer times clamp to the device's real ceiling.
A Multi or Drum mapping slot stores only loop points, no sample-trim
start/end, so the detector left the zone's start/stop at the model default
of -1. Creators that write the trim verbatim then emitted a bogus value -
e.g. a Waldorf QPAT showed a sample start and end of -1 on the device
instead of playing the whole sample.

A slot without explicit trim points plays the entire sample, so default the
start to 0 and the stop to the sample's frame count when no trim is stored.
Mirrors the same fix for the .tvpst detector: a mapping slot without
explicit trim points plays the whole sample, so default the zone start to 0
and the stop to the sample's frame count rather than leaving the model
default of -1 (which destinations such as the Waldorf QPAT would write out
verbatim, showing a sample start/end of -1 on the device). Slots that do
carry trim-start/trim-end still read their actual values.
The detector parsed a forward loop's start, end and cross-fade but never set
the loop type or attached the loop to the sample zone, so every converted
instrument silently lost its loop. Set the type to forwards and add the loop
to the zone (matching the .tvpst detector), and guard the points against
negative values.
A preset that parsed without any parameters (e.g. a zero-filled file left by
a failed write or transfer) was reported as 'Unknown Tonverk generator machine
'%1'' - the machine value was null, so the placeholder was left unsubstituted,
and 'unknown machine' was misleading for what is really an empty/corrupt file.
Such files are now reported as empty or corrupt with the file name, and the
unknown-machine message is guarded against a null value.
The envelope time mapping was a cube power law with guessed maxima (attack
1.6 s, decay/release 22 s). Resampling probe presets with known normalized
values on real hardware shows the firmware actually uses a warped
exponential, seconds = floor * (ceiling/floor)^(normalized^warp), and the
old ceilings were far too low - the device takes 3.77 s at attack norm 0.97,
already past the old 1.6 s maximum, so every slow attack converted far too
fast.

Calibrate each stage from the measurements:
- attack (linear ramp): floor ~0.01 s, ceiling 4.46 s, warp 0.91
- decay = release (exponential fade to -60 dB, measured identical at 4.64 s
  vs 4.65 s for norm 0.60): floor ~0.01 s, ceiling 30.8 s, warp 0.53
- hold and delay reuse the attack curve (unprobed)

This is the same exponential form already used for the filter cut-off
(warp 1), so the mappings are consistent, and the inverse stays exact (a
Tonverk-to-Tonverk round-trip remains loss-less). Verified end to end: an
SFZ attack of 3.774 s writes as norm 0.970, and reading norm 0.9699 back
yields 3.773 s, matching the hardware-measured 3.774 s.
@git-moss

Copy link
Copy Markdown
Owner

@douglas-carmichael Hi Douglas, In case you are planning more formats, it would be good to sync up, so we do not inadvertently start to work on the same formats. Might be easier to exchange email addresses, you can PM me on KVR.

One thing missing is the documentation of the format capabilities in: documentation/SupportedFeaturesSampleFormats.ods (edited with LibreOffice Calc) I already added two lines for the 2 new formats (but not yet for this one). Could you please fill the rows? Thanks!

…res sheet

Fill the SupportedFeaturesSampleFormats.ods rows for the new Elektron Tonverk Preset (.tvpst) read and write support (metadata, key/velocity ranges, sample trim, tuning, gain, panning, forward loops, amplitude AHD/ADSR envelope, and the multi-mode filter with its envelope), and rename the existing multi-sample mapping row from "Elektron Tonverk" to "Elektron Tonverk Multisample" to match its new display name.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants