Skip to content

Add support for the Kurzweil K2000/K2500/K2600 format (KRZ, K25, K26) - NOT yet tested on hardware#189

Open
douglas-carmichael wants to merge 3 commits into
git-moss:mainfrom
douglas-carmichael:add-kurzweil-k2x00-support
Open

Add support for the Kurzweil K2000/K2500/K2600 format (KRZ, K25, K26) - NOT yet tested on hardware#189
douglas-carmichael wants to merge 3 commits into
git-moss:mainfrom
douglas-carmichael:add-kurzweil-k2x00-support

Conversation

@douglas-carmichael

@douglas-carmichael douglas-carmichael commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

This adds a detector and creator for Kurzweil K2x00 object files (.krz, .k25, .k26). A file is a bank of numbered objects: programs, keymaps and samples, where a sample object may hold several recordings (multiple root keys, stereo left/right pairs). The layout was derived from the source code of the GPL tool KurzFiler by Marc Halbruegge (https://sourceforge.net/projects/kurzfiler/); the implementation here is new code written against a format description extracted from it, documented in documentation/design/KURZWEIL_FORMAT.md. The current Kurzweil range (K2700, PC4, Forte) imports K2x00 files as well, so the created files are not only for the vintage units.

Reading: each program becomes one multi-sample. Its layers reference keymaps, from which the key ranges, the 8 dynamic velocity levels, root keys, per-entry tunings (cents), per-sample volume adjusts, loops and the 16-bit sample data (per-header sample rates, stored as nanosecond periods) are read. All keymap entry layouts (the method bits) are supported, including compacted keymaps with a shared sample ID. Keymaps and samples not referenced by any program are converted as multi-samples of their own. Zones which map samples from the device ROM cannot be converted and are skipped with a note (once per sample) - many factory/commercial K-series banks are affected. A zone appearing identically on several adjacent velocity levels is merged back into one zone.

Writing: the created files use only K2000 features (mode 2 programs) and therefore load on all three device families; a Target Device option selects the file extension - krz (default), k25 or k26 (CLI: -p KurzweilTargetDevice=K2000|K2500|K2600). Each multi-sample becomes a program with one layer and a keymap: one sample object per zone (16-bit; the sample rate is kept up to 96 kHz, the maximum sample playback rate documented in the K2600 manual, higher rates are down-sampled), the zone gain is written into the sample volume adjust (0.5 dB steps, the unit is confirmed by the -64.0..+63.5 dB range of the Volume Adjust parameter in the K2600 manual), velocity layers are distributed onto the 8 dynamic levels (levels with the same zones share one entry table), and tuning, partial/disabled key tracking and the root key are encoded into the per-entry tunings. Since the device plays a loop until the sample end, data after the loop end is cut off. If any zone is stereo, all samples of the program are written as stereo pairs (mono zones are duplicated). Libraries are supported: several multi-samples in one file, split over multiple files when the object IDs (200-999 per type) run out.

Verification: KurzFiler itself was compiled and used as a reference reader. The KurzFiler test corpus (including real-world .k26 banks) converts without errors, and round-tripped files re-load in the reference implementation with byte-identical sample data (CRC-checked), identical keymap entry runs, loops, roots, volume adjusts and maxPitch values. A synthetic stereo + velocity-layer test confirmed channel order, loop truncation, per-sample rates and the 96 kHz down-sampling (including the re-calculated loop positions) in both directions. Not yet tested on the actual hardware - the generated objects mirror KurzFiler's hardware-proven output values, but I do not have a K2x00 at hand. (Since the K2700/PC4/Forte load these files too, a test on one of those would also be meaningful.)

Known limitations (also noted in the docs): the keymap-entry volume adjust unit is unconfirmed and therefore ignored (the per-sample volume adjust is converted), the natural envelopes and program filter/envelope segments are not decoded, loops are forward-only (the per-sample Reverse/Bidirectional playback modes exist on the device but their bit positions in the header are unknown), and keys below C0 (MIDI 12) cannot be mapped.

README-FORMATS.md, the CHANGELOG and the feature support matrix are updated.

Add a detector and creator for Kurzweil K2x00 object files. A file is a
bank of numbered objects: programs, keymaps and samples (which may hold
several recordings for multiple root keys and stereo pairs). The layout
was derived from the source code of the GPL tool KurzFiler by Marc
Halbruegge (see documentation/design/KURZWEIL_FORMAT.md).

Reading converts each program into one multi-sample: the layers reference
keymaps from which the key ranges, the 8 dynamic velocity levels, root
keys, per-entry tunings, loops and the 16-bit sample data are read.
Compacted keymaps (a shared sample ID for all entries) and all entry
layouts (the method bits) are supported. Keymaps and samples which are not
referenced by any program become multi-samples of their own. Zones which
map samples from the device ROM cannot be converted and are skipped with a
note. A zone which appears identically on several adjacent velocity levels
is merged back into one zone.

Writing creates a .krz file which uses only K2000 features and therefore
loads on all three device families. Each multi-sample becomes a program
with one layer and a keymap: one sample object is written per zone (16-bit,
the sample rate is kept), the velocity layers are distributed onto the 8
dynamic levels (levels with the same zones share one entry table), tuning,
partial or disabled key tracking and the root key are encoded into the
per-entry tunings and the data after the loop end is cut off since the
device plays a loop until the sample end. If any zone is stereo, all
samples of the program are written as stereo left/right header pairs (mono
zones are duplicated). Several multi-samples can be written into one file
as a library; when the object IDs (200-999 per type) do not suffice,
multiple files are created.

Verified against the KurzFiler test corpus (including real-world .k26
banks): all files read; round-tripped files re-load byte-identical sample
data, mappings and loops in the reference implementation.
A drop-down selects the device family for which the file is named: K2000
(krz), K2500 (k25) or K2600 (k26). Since the written objects use only
K2000 features and load on all three families, the selection only sets
the file extension. On the command line the device is set with
-p KurzweilTargetDevice=K2000|K2500|K2600 (the extensions are accepted
as well), the default is K2000.
The K2600 manual documents the Volume Adjust parameter of a sample with a
range of -64.0 to +63.5 dB, which confirms that the volume adjust byte of
the sample header holds 0.5 dB steps. The zone gain is now written into it
and read back from it.

The manual also documents the maximum sample playback rate of the devices
as 96 kHz (and the current Kurzweil range - K2700, PC4, Forte, which loads
K2x00 files as well - caps its own audio imports at 96 kHz). Samples with
higher rates are now down-sampled to 96 kHz with the sample positions
re-calculated accordingly.
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.

1 participant