Skip to content

File and Storage Formats#

While the various storage formats we use may well not be a standard in a technical sense, it is our intent that it should, when at all possible, be stable in perpetuity. As such, this document documents the formats for our various types of data.

This document describes our persistence format, the Sketchpad and everything that that contains, and following that a number of other persistence formats, such as sketches, sounds, samples, and the equalizer data chunks.

If you are looking to discover how the system itself is configured, check the System Configuration chapter.

Sketchpad#

The Sketchpad is a folder structure, and it is the thing which contains the entire musical setup for a set of ten Sketches, in any arbitrary number of potential versions, as well as one active working copy.

We will start by describing the highest level format of the Sketchpad, and then delve into each individual part as we dig deeper. The listing below contains links to the relevant sections for the listed files.

For a hypothetical Sketchpad containing two saved versions, the folder structure might be as follows:

Sketchpad-Name:
Sketchpad-Name/Autosave.sketchpad.json
Sketchpad-Name/Sketchpad-Name.sketchpad.json
Sketchpad-Name/Some-Named-Version.sketchpad.json
Sketchpad-Name/sequences:
Sketchpad-Name/sequences/autosave:
Sketchpad-Name/sequences/autosave:
Sketchpad-Name/sequences/autosave/metadata.sequence.json
Sketchpad-Name/sequences/autosave/patterns:
Sketchpad-Name/sequences/autosave/patterns/part1a.pattern.json
Sketchpad-Name/sequences/autosave/patterns/part4b.pattern.json
Sketchpad-Name/sequences/autosave/patterns/part7e.pattern.json
Sketchpad-Name/sequences/autosave/patterns/part10a.pattern.json
Sketchpad-Name/sequences/Sketchpad-Name:
Sketchpad-Name/sequences/Sketchpad-Name/global:
Sketchpad-Name/sequences/Sketchpad-Name/global/metadata.sequence.json
Sketchpad-Name/sequences/Sketchpad-Name/global/patterns:
Sketchpad-Name/sequences/Sketchpad-Name/global/patterns/part1a.pattern.json
Sketchpad-Name/sequences/Sketchpad-Name/global/patterns/part4b.pattern.json
Sketchpad-Name/sequences/Sketchpad-Name/global/patterns/part7e.pattern.json
Sketchpad-Name/sequences/Some-Named-Version:
Sketchpad-Name/sequences/Some-Named-Version/global:
Sketchpad-Name/sequences/Some-Named-Version/global/metadata.sequence.json
Sketchpad-Name/sequences/Some-Named-Version/global/patterns:
Sketchpad-Name/sequences/Some-Named-Version/global/patterns/part1a.pattern.json
Sketchpad-Name/soundsets:
Sketchpad-Name/soundsets/Autosave.zss
Sketchpad-Name/soundsets/Sketchpad-Name.zss
Sketchpad-Name/soundsets/Some-Named-Version.sketchpad.json
Sketchpad-Name/wav
Sketchpad-Name/wav/sampleset:
Sketchpad-Name/wav/sampleset/sample-bank.1:
Sketchpad-Name/wav/sampleset/sample-bank.1/Some Field Recording.wav
Sketchpad-Name/wav/sampleset/sample-bank.10:
Sketchpad-Name/wav/sampleset/sample-bank.10/Fancy Sound From The Store.wav

Sketchpad.json#

A sketchpad.json file contains the data which defines the sound setup of a sketchpad version which is not contained in the pattern and snapshot files.

Suspect keys - things which will want attention before we ship

  • connectedPattern likely is not really needed any longer (as it is redundant with the active clip)
  • sample_picking_style should really be slotPickingStyle, as that's what it's deciding (not just samples)
  • track audioTypeSettings other than trackPassthrough may be redundant with the snapshot data
  • we have several locations where we refer to the name "sketch" where it should reasonably be "skit"
  • routing overrides don't need to serialise the jackname (as that's constructed at runtime anyway)
  • clips should probably not be lists with a single entry (there used to be a reason for this, but would likely make sense to not do that any longer)
  • enabled field for samples seems irrelevant, probably don't store that
  • the layers_snapshot, routeThroughGlobalFX fields in tracks seems not irrelevant
  • the data used in clips elements (row, col, id) are not very descriptive of what they are supposed to be for, and we should probably fix that
  • the trackPassthroughClients entry in the song would likely be better suited to live in the snapshot (as it helps to define the sound of a track). We do not currently expose the eq settings for the two, and so it's non-critical, but it would make better sense for it to live there

The following listing only contains one instance of most lists (or it would result in this page being unwieldy).

{
  "name": "Arresting-Movement", // The name of the sketchpad
  "bpm": [ // The BPM for each of the ten scenes in the sketchpad
    120, 120, 120, 120, 120, 120, 120, 120, 120, 120
  ],
  "volume": 100, // The base volume (between 0 and 100) for the sketchpad
  "selectedScaleIndex": 0, // The sketchpad's scale offset from C (e.g. F3 would be 6)
  "octave": 2, // The octave of the sketchpad's scale (the number part of e.g. F3)
  "tracks": [ // Data for each of the ten tracks in an ordered list
    {
      "name": null, // The name of the track (null if unnamed, otherwise a string with the name)
      "color": "#b34d00", // The colour chosen by the user in Track Settings
      "volume": 0, // The track volume in gain adjustment (as opposed to gain dB)
      "audioTypeSettings": {
        "synth": { // The mixerbus settings for each of the sections of our mixerbus (see the section on audio routing for deeper details on this)
          "trackPassthrough": [ // The pre-fx mixer amounts for each of the ten lanes which can make up a track, dependent on the slot picking style
            { // In 1:1 mode, Synth and Sample slot 1 only, and in standard mode, all Synth and Sample slots
              "panAmount": 0, // Pan adjustment for the given slots (from -1 through 1, with 0 being no panning)
              "dryAmount": 1, // The amount (in gain adjustment, 0 and up) passed through to either subsequent effects, or to global playback if there are no effects for Sound
              "wetFx1Amount": 0, // The amount (from 0 through 1) of the signal sent to the Global FX 1 (nominally Delay)
              "wetFx2Amount": 0 // The amount (from 0 through 1) of the signal sent to the Global FX 2 (nominally Reverb)
            },
            { // In 1:1 mode, Synth and Sample slot 2 only, and nothing in standard mode
              // The contents are as the first entry
            },
            { // In 1:1 mode, Synth and Sample slot 3 only, and nothing in standard mode
              // The contents are as the first entry
            },
            { // In 1:1 mode, Synth and Sample slot 4 only, and nothing in standard mode
              // The contents are as the first entry
            },
            { // In 1:1 mode, Synth and Sample slot 5 only, and nothing in standard mode
              // The contents are as the first entry
            },
            { // In 1:1 mode, Skit slot 1 only, and in standard mode, all Skit slots
              "panAmount": 0, // Pan adjustment for the given slots (from -1 through 1, with 0 being no panning)
              "dryAmount": 1, // The amount (in gain adjustment, 0 and up) passed through to either subsequent effects, or to global playback if there are no effects for Skits
              "wetFx1Amount": 0, // The amount (from 0 through 1) of the signal sent to the Global FX 1 (nominally Delay)
              "wetFx2Amount": 0 // The amount (from 0 through 1) of the signal sent to the Global FX 2 (nominally Reverb)
            },
            { // In 1:1 mode, Skit slot 2 only, and nothing in standard mode
              // The contents are as the first entry
            },
            { // In 1:1 mode, Skit slot 3 only, and nothing in standard mode
              // The contents are as the first entry
            },
            { // In 1:1 mode, Skit slot 4 only, and nothing in standard mode
              // The contents are as the first entry
            },
            { // In 1:1 mode, Skit slot 5 only, and nothing in standard mode
              // The contents are as the first entry
            }
          ],
          "synthPassthrough": [ // The pan and dry values for each of the track's five synth slots
            { // Mixerbus settings for Synth slot 1
              "panAmount": 0, // Pan adjustment for the given slot (from -1 through 1, with 0 being no panning)
              "dryAmount": 1 // The amount (in gain adjustment, 0 and up) passed through to the track passthrough
            },
            // The remaining four entries are similarly laid out
          ],
          "fxPassthrough": [ // The pan and wet/dry mix amount for the five Sound effect slots
            { // Mixerbus settings for FX slot 1
              "panAmount": 0, // Pan adjustment for the given slot (from -1 through 1, with 0 being no panning)
              "dryWetMixAmount": 1.4399995708465576 // From 0 through 2, 0 being 100% dry and 0% wet, 1 being 100% dry and 100% wet, and 2 being 0% dry and 100% wet
            },
            // The remaining four entries are similarly laid out
          ],
          "sketchFxPassthrough": [ // The pan and wet/dry mix amount for the five Skit effect slots
            { // Mixerbus settings for Skit FX slot 1
              "panAmount": 0, // Pan adjustment for the given slot (from -1 through 1, with 0 being no panning)
              "dryWetMixAmount": 1 // From 0 through 2, 0 being 100% dry and 0% wet, 1 being 100% dry and 100% wet, and 2 being 0% dry and 100% wet
            },
            // The remaining four entries are similarly laid out
          ]
        }
      },
      "connectedPattern": 0, // The currently selected pattern for this track (no longer used)
      "chainedSounds": [ // The ID (currently midi_chan) of the synth engine in the Zynthbox ZSS Snapshot
        3, // Slot 1 synth engine should use the snapshot with ID 3 in the layers section of Zynthbox ZSS Snapshot's
        -1, -1, -1, -1 // Slots 2 through 5 are empty
      ],
      "allowMulticlip": true, // Whether the track allows for multiple simultaneously active clips
      "trackStyle": "everything", // The style of the track (default is everything). Supports: everything, one-to-one, drums, 2-low-3-high, manual
      "trackType": "synth", // Whether the track plays into the sounds (the default, "synth"), using loops ("sample-loop"), or external data ("external")
      "trackRoutingStyle": "standard", // How the sound is routed from sound slots to effect slots ("standard" or "one-to-one")
      "synthRoutingData": [ // Data defining custom overrides for the routing for a specific slot (for side chaining etc)
        { // The override information for Synth slot 1
          "name": "Calf Monosynth > Barkline", // The human-readable name for this engine and its current preset (used for display purposes)
          "audioInPorts": [], // A list of audio input ports on the engine, where such exist
          "midiInPorts": [ // A list of midi input ports on the engine, where such exist
            {
              "name": "midi_in", // A short name for this input port
              "jackname": "Calf_Monosynth-00:midi_in", // The fully qualified name for the synth port
              "sources": [] // The midi output ports which should be connected to this input port
            }
          ]
        },
        // Four further entries, laid out as the first
      ],
      "fxRoutingData": [
        // Five entries (one for each slot), with routing overrides for the effects on sounds (layout as synthRoutingData)
      ],
      "sketchFxRoutingData": [
        // Five entries (one for each slot), with routing overrides for the effects on skits (layout as synthRoutingData)
      ],
      "synthKeyzoneData": [ // The key zones for each of the five synth slots
        { // The key zone setup for Synth slot 1
          "keyZoneStart": 0, // The first midi note accepted by this synth
          "keyZoneEnd": 127, // The last midi note accepted by this synth
          "rootNote": 60 // The note which should be considered C4 by this synth
        },
        // Four further enties, laid out as the first
      ],
      "targetTrack": 0, // The index of the track that any patterns playing on this track will play to
      "externalMidiChannel": -1, // In external mode, which midi channel to send out on (-1 being the same as the track, 0 through 15 being a specific channel)
      "externalCaptureVolume": 0, // The gain adjustment for capturing external audio (default is no adjustment)
      "externalAudioSource": "", // In external mode, which audio device to listen to (default is no capture)
      "externalKeyValueStores": {}, // A key-value store usable by Control Surfaces and their scripts to do persist data between sessions
      "externalDefaultKeyValueStore": { // A set of values used by the default external mode control surface
        "controls": [ // Twelve entries (for a layout containing 4 columns with 3 controls in each)
          { // The midi channel and cc for the first knob in the first column
            "midiChannel": -1, // The midi channel for the control (same logic as externalMidiChannel)
            "ccControl": 2 // The CC control this entry controls
          },
          // Eleven further entries laid out as the first
        ]
      },
      "externalSelectedModule": "", // The module used for the Controls page in External mode. An empty string means using the default module.
      "externalMidiOutDevice": "", // The midi output device this track plays to in External mode. An empty string means using the 5-pin output on systems where that exists.
      "clips": [ // A list of the track's five clips
        [ // Data for clip one
          { // Key-value stored data for the clip
            "path": null, // If set, this will contain the filename for the audio file used for looping when the track is in Loop mode, relative to the sketchpad's wav folder
            "enabled": false, // Whether or not this clip is enabled for playback
            "metadata": {} // A set of metadata identical to that used by samples
          }
        ],
        // Four further entries laid out as the first
      ],
      "selectedClip": 0, // The currently selected clip
      "samples": [ // A list of the track's five sample slots
        { // Data for the sample in slot one
          // If set, this will contain the filename for the audio file used for this sample slot, relative to this track's sample bank folder (wav/sample-bank.1 for track 1)
          "path": "Chillhop Music - Nymano Producers Drumkit - lofi & boombap - 16 nymano_kick1.wav",
          "enabled": false, // Whether this sample is enabled or not (this is redundant)
          "metadata": { // The metadata for this sample - identically laid out to the tags in the sample when stored in the library
          }
        },
        // Four further enties laid out as the first
      ],
      "layers_snapshot": [],
      "sample_picking_style": "all", // The method for picking which slot to play, supported values are "all", "same", or "first", with "all" being default
      "trustExternalDeviceChannels": false, // Whether or not to trust the midi channel given to us by external devices when using the "same" slot picking style
      "keyzone_mode": "all-full", // Keyzone auto-setup definition, supported values are "all-full", "split-full", "split-narrow", "2-low-3-high", and "manual"
      "routeThroughGlobalFX": true, // Whether or not to route this track through the global fx
      // The slotsData fields are convenience data stored for ease of display of a track in an informative browser (such as Webconf), and they containing the display values for each of the five slots for each slot type
      "synthSlotsData": [ "Calf Monosynth > Barkline", "", "", "", "" ],
      "sampleSlotsData": [ "Chillhop Music - Nymano Producers Drumkit - lofi & boombap - 16 nymano_kick1.wav", "", "", "", "" ],
      "fxSlotsData": [ "", "", "", "", "" ],
      "sketchSlotsData": [ "", "", "", "", "" ],
      "sketchFxSlotsData": [ "", "", "", "", "" ],
      "externalSlotsData": [ "Capture: None", "Midi Channel: 1", "Midi 5-Pin", null, null ]
    },
    // This would contain ten elements, but we only display one for the sake of the page's readability
  ],
  "scenes": { // Data directly related to the Sketchpad's scenes
    "scenesData": { // The data for each individual scene (can be an arbitrary number, but there will usually be ten)
      "0": { // Data for the scene with the internal name "0"
        "name": "A", // The human-readable name for the scene
        "clips": [ // A list of the clips which are enabled for the given scene
          { // Clip 2 on track 4 from song 0 is enabled in this scene
            "row": 3, // The index of the track the clip is on
            "col": 0, // The index of the conceptual song this clip is a part of (usually 0)
            "id": 1 // The index of the clip
          }
        ]
      },
      // The dictionary will contain any number of entries, but there will usually be ten
      // They will be laid out as the "0" entry, but with keys "1", "2", and so on, and the names "B", "C", and so on
    },
    "selectedSketchpadSongIndex": 0, // The currently selected conceptual song (this will usually be 0)
    "selectedSceneIndex": 0 // The currently selected scene
  },
  "arrangements": { // Data which defines an arrangement of clips over time (essentialy, the data used by song mode)
    "selectedArrangementIndex": 0, // The currently selected arramgenent
    "arrangements": [ // All the arrangements in the sketchpad
      { // An object representing a single arrangement
        "arrangementId": 0, // The ID of the arrangement (this usually would be the same as the index of the arrangement, but this is not guaranteed
        "segments": [ // An ordered list of all variations in the arrangement
          [ // A single variation, containing an ordered list of the segments which make up the variation
            { // One segment, which defines a period of time in the arrangement
              "barLength": 1, // The number of bars this segment is long
              "beatLength": 0, // The number of beats this segment is long, added to the bar length
              "tickLength": 0, // The number of ticks (a tick being 1/96th of a beat)
              "clips": [ // A list of the clips included in this segment
                { // The first clip included in this segment (in this case clip 2 on track 4)
                    "row": 3, // The index of the track the clip is on
                    "col": 0, // The index of the conceptual song this clip is a part of (usually 0)
                    "id": 1 // The index of the clip
                }
                // Any number of clips can be listed here
              ],
              "restartClips": [], // A list of clips for which to restart playback at the start of this segment (same format as "clips")
              "timerCommandDetailsBefore": [ // An ordered list of timer commands to run before this segment (run after the previous segment's after ones)
                { // A single timer command
                  "operation": 10, // The integer representation of a the operation for this command (in this case 10 means that this a SetBpmOperation - see also the API documentation for TimerCommand)
                  "parameter": 160, // An integer value the command would use
                  "parameter2": 0, // An integer value the command can use (in this case 0, as it is unused by operation 10)
                  "parameter3": 0, // An integer value the command can use (in this case 0, as it is unused by operation 10)
                  "parameter4": 0, // An integer value the command can use (in this case 0, as it is unused by operation 10)
                  "bigParameter": 0, // An 64 bit unsigned integer value the command can use (in this case 0, as it is unused by operation 10)
                  "dataParameter": 0, // A void pointer value the command can use (in this case 0, as it is unused by operation 10, and also this likely would never actually be stored)
                  "variantParameter": None // A Variant data value the command can use (in this case 0, as it is unused by operation 10)
                }
                // This can contain any number of items
              ],
              "timerCommandDetailsAfter": [] // A list of timer commands to run immediately after this segment (run before the next segment's before ones)
            }
          ]
        ]
      },
      // Any number of entries can be found here, but there are usually ten defined by default
    ]
  },
  "globalPlaybackClient": { // The mixerbus equaliser and compressor data for the global playback client - see Equalizer Data below for details
  },
  "trackPassthroughClients": [ // The pre-fx equaliser settings for each track (one each track, and then one each for sound and skit)
    [ // Equaliser settings for track 1
      [ // The settings for the Sound slots
        { // The mixerbus equaliser and compressor data for this slot - see Equaliser Data below for details
        }
      ],
      [ // The settings for the Skit slots (again, as above)
      ]
    ],
    // Further nine entries, with identical layout to the above
  ]
}

Metadata.sequence.json#

A very small file which simply contains helpful information pertaining to all the patterns:

No longer needed

It seems to me that this file doesn't contain anything actually useful any longer. It used to, a very long time ago, contain details on which patterns had data in them (but those files simply no longer exist), and it was used to determine details about the sketchpad without loading it (but that also no longer is relevant). As such, it seems like... maybe we should just get rid of this file.

{
    "activePattern": 16, // Which pattern index is displayed by the sequencer (here: track 4 pattern 2)
    "bpm": 120 // The sketchpad's BPM when the sequence was saved
}

Pattern.json#

A file which contains the midi playback information (or pattern) for a single clip, including its various settings.

Filename change

The pattern files likely want to be named for what they represent (clip), rather than what they once were (part)

Suspect keys

  • midiChannel might not be needed (at least for storage), being as that's a track setting
  • noteDestination might not be needed (at least for storage), being as that's a track setting
  • sketchpadTrack might not be needed (at leas for storage), being as that is kind of inherent anyway
{
  "activeBar": 0, // Which bar is currently intended to be displayed
  "bankLength": 8, // How many bars are in a bank
  "width": 16, // How many steps are in a bar
  "bankOffset": 0, // Which bank is currently active (this will usually be a multiple of bankLength)
  "stepLength": 24, // The duration of a single step in 1/96th of a beat
  "enabled": false, // Convenience field to say whether the clip the pattern is associated with is enabled
  "gridModelEndNote": 64, // The highest note displayed in the pattern's note grid
  "gridModelStartNote": 48, // The lowest note displayed in the pattern's note grid
  "hasNotes": false, // Whether the pattern has any notes in it (if the pattern has any non-default settings, this can be false)
  "height": 16, // How many bars exist in the model (default is 16, meaning a total of two banks)
  "midiChannel": 0, // The midi channel associated with this pattern
  "noteDestination": 0, // The destination any note in this pattern should use (0 is synth (default), 1 is sample-trig, 2 is sample-looped, 3 is external)
  "patternLength": 16, // How many steps should be used for playback for this pattern (usually a multiple of the width, but can be any number up to width*bankLength)
  "scale": "chromatic", // The scale this pattern is supposed to be in (can be any of the 52 options found in the KeyScales API documentation, with the default being chromatic)
  "octave": "octave4", // The octave part of this pattern's key
  "pitch": "c", // The pitch part of this pattern's key
  "lockToKeyAndScale": 0, // The method by which the key and scale should be applied (0 is display only, 1 blocks off-scale keys, 2 rewrites off-scale keys to be on-scale
  "sketchpadTrack": 0, // Which track this pattern is associated with
  "swing": 50, // Every even-numbered step in a pattern can be offset by positioning it closer to either the previous or next step (0 being on top of the previous step, 100 being on top of the next, and 50 (default) being in the middle between the two)
  "defaultNoteDuration": 8, // How many 1/32nd of a beat a single step should be
  "notes": "" // See separate description below
}

The Notes#

The notes field of a pattern json gets to have a section of its own, as it requires a bit of further description than what the above would reasonably allow for. It contains a serialised json object, which is made up of a list of bars, which in turn are a list of steps, and each step in turn contains a key value store, as well as the entries for the step (made up of a combination of notes, and the metadata that goes with each of them).

[ // A list of bars (there should be a number of entries equal to the pattern's height)
    [ // A list of steps for the given bar (there should be a number of entries equal to the pattern's width)
        { // The data for the first step in the bar
            "keyeddata": { }, // A list of key-value pairs containing arbitrary data that doesn't require equivalent data to the notes
            "metadata": [ // A list of dictionaries containing arbitrary metadata, one for each of the subnotes in the step's container note object
                { // The metadata associated with the first step entry (there are further supported keys than what is described here)
                    "velocity": 105 // The velocity of the first step entry
                },
                {
                    "velocity": 105, // The velocity of the second step entry
                    "delay": 8 // How much later than the step position this entry will be played (in this case, 8/32th of a beat later)
                },
                {
                    "velocity": 49, // The velocity of the second step entry
                    "duration": 96 // How long the step entry's note will be held for (in this case, one beat, being 96/96th of a beat)
                }
            ],
            "note": {
                "midiChannel": -1, // This can be any value from -1 through 15, but for compound notes will usually be -1
                "midiNote": 40786, // This can be any arbitrary number for compound note objects, as long as it is above 128
                "subnotes": [ // Technically a list of notes contained within the parent note object, but for the sequencer, this is the list of entries for the step (listed in midi note order)
                    { // The first step entry
                        "midiChannel": 3, // The specific midi channel for this step entry
                        "midiNote": 60 // The midi note value for this step entry
                    },
                    { // The second step entry
                        "midiChannel": 2, // The specific midi channel for this step entry
                        "midiNote": 53 // The midi note value for this step entry
                    },
                    { // The third step entry
                        "midiChannel": 2, // The specific midi channel for this step entry
                        "midiNote": 54 // The midi note value for this step entry
                    }
                ]
            }
        },
        { // The data for the second step in the bar (as an example, this one has no notes, and consequently no data stored within it)
            "keyeddata": { },
            "metadata": null,
            "note": { }
        },
        // There will be any number of further entries here, but it should optimally match the pattern's width
    ],
    // There will be any number of further entries here, but it should optimally match the pattern's height
]

Zynthbox ZSS Snapshot#

The snapshots contain the setup for all the synth and fx engines for a sketchpad. The example here describes a sketchpad with one synth engine in slot 1 on track 1, and one fx engine in slot 1 on track 1, and all other synth and fx slots empty.

Snapshot file suffix

While we share some of the same data as the old zynthian snapshots with which we share a file suffix, a fair number of changes have been made to the format, and it would seem reasonable if we decided to rename the files we store to for example .zbs instead (that is, zynthbox shapshot), to avoid potential confusion in the future

Suspect keys

  • there is a mix between s and z named keys (in particular for the equalizer), and that really should all be, well, equalized...
  • there are a number of keys which are kept because we have been considering backwards compatibility with Zynthian snapshots: Is this something we still want, or would it make sense for us, also given the file suffix mention above, to get rid of the entries we don't use?
  • bank_info and preset_info: These two currently contain absolute paths, which seems potentially dangerous. Does this want to change to a relative path, with the presets etc kept in a folder known by the plugin, perhaps set in plugins.json? Further, is storing them actually required? They seem redundant (and get re-created when loading an engine)
  • midi_chan for a synth engine is the index used by Zynthian to tell root layers apart, and this is what we will want to adjust to allow for more than 15 simultaneous engines. It is not the only thing which would need changing, however it is the root cause.
{
  "index": 0, // The index of this snapshot (will usually be 0)
  "layers": [
    {
      "plugin_id": "ZBP_SYNTH_00008", // The ID of the synth engine plugin (see the plugins.json section below for details on what this ID is)
      "plugin_version": "0000",
      "engine_name": "Jalv/synthv1", // The plugin's name
      "engine_nick": "JV/synthv1", // The plugins nickname
      "engine_type": "MIDI Synth", // The type of engine (currently either MIDI Synth or Audio Effect)
      "midi_chan": 0, // The midi channel used to identify the engine for routing purposes
      "track_index": 0, // The index of the Sketchpad track this engine is associated with
      "slot_type": "TracksBar_synthslot", // The type of slot the engine is (TracksBar_synthslot signifying this is a synth slot)
      "slot_index": 0, // The index of the slot (from 0 through 4)
      "bank_index": 0, // The index of the currently selected bank of presets
      "bank_name": "392Synthv1Patches", // The human-readable name for the currently selected bank of presets
      "bank_info": [ // A set of information describing the currently selected bank of presets (engine-specific layout)
        "file:///zynthian/zynthian-data/presets/lv2/synthv1_392Synthv1Patches.presets.lv2/synthv1_bank_392Synthv1Patches", null, "392Synthv1Patches", null
      ],
      "preset_index": 100, // The index of the currently selected preset in the currently selected bank
      "preset_name": "EdgeOfHeaven2Fixed", // The human-readable name for the currently selected preset
      "preset_info": [ // A set of information describing the currently selected preset (engine-specific layout)
        "file:///zynthian/zynthian-data/presets/lv2/synthv1_392Synthv1Patches.presets.lv2/392Synthv1Patches_EdgeOfHeaven2Fixed.ttl", null, "EdgeOfHeaven2Fixed", "file:///zynthian/zynthian-data/presets/lv2/synthv1_392Synthv1Patches.presets.lv2/synthv1_bank_392Synthv1Patches"
      ],
      "controllers_dict": { // The current values for all the controllers on the engine
        "DCO1_SHAPE1": { "value": 1 },
        "DCO1_WIDTH1": { "value": 1 },
        "DCO1_BANDL1": { "value": 0 },
        "DCO1_SYNC1": { "value": 0 },
        "DCO1_SHAPE2": { "value": 1 },
        "DCO1_WIDTH2": { "value": 0.5 },
        // As there can be a great many of these, this is not a complete list for the example engine here
        // The important part here is that this dictionary holds the name of the controller as the key, and
        // data for the controller in the form of a dictionary (usually containing only the "value" key)
      },
      "zs3_list": [ // Zynthian sub-snapshots (unused by Zynthbox)
        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null
      ],
      "active_screen_index": 0, // Which of the pages of controllers is currently displayed
      "mixer_settings": { // The mixerbus values for this engine
        "panAmount": 0, // The position of the engine in the stereo field (-1 through 1, 0 meaning no pan)
        "dryAmount": 1 // The gain for this slot (in gain adjustment rather than dB)
      },
      "equalizer_settings": { /* the mixerbus equaliser and compressor settings for this engine - see Equalizer Data below for details */ }
    },
    { // As an example, this synth (in synth slot 1 on track 5) would use a system soundfont,
      // Of particular note here is the bank_name field, and bank_info field which defines the soundfont
      "plugin_id": "ZBP_SYNTH_00017",
      "plugin_version": "0000",
      "engine_name": "FluidSynth",
      "engine_nick": "FS",
      "engine_type": "MIDI Synth",
      "midi_chan": 3,
      "track_index": 4,
      "slot_type": "TracksBar_synthslot",
      "slot_index": 0,
      "bank_index": 26,
      "bank_name": "Guitars Universal 1.4",
      "bank_info": [
        "/zynthian/zynthian-data/soundfonts/sf2/Guitars Universal 1.4.sf2",
        10,
        "Guitars Universal 1.4",
        "_",
        "Guitars Universal 1.4.sf2",
        // Indices 5 and 6 for this contain the soundfont's ID, and it's version (see the plugins.json section below for details on this)
        "ZBP_SF_00010",
        "0000"
      ],
      "preset_index": 0,
      "preset_name": "12 String Guitar",
      "preset_info": [
        "/zynthian/zynthian-data/soundfonts/sf2/Guitars Universal 1.4.sf2/000-005 12 String Guitar",
        [
          0,
          0,
          5
        ],
        "12 String Guitar",
        "/zynthian/zynthian-data/soundfonts/sf2/Guitars Universal 1.4.sf2"
      ],
      "controllers_dict": { // The current values for all the controllers on the engine
        "volume": { "value": 96 },
        "modulation": { "value": 0 },
        "pan": { "value": 64 },
        "expression": { "value": 127 },
        "sustain": { "value": 0 },
        // As there can be a great many of these, this is not a complete list for the example engine here
        // The important part here is that this dictionary holds the name of the controller as the key, and
        // data for the controller in the form of a dictionary (usually containing only the "value" key)
      },
      "zs3_list": [ // Zynthian sub-snapshots (unused by Zynthbox)
        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null
      ],
      "active_screen_index": 0, // Which of the pages of controllers is currently displayed
      "mixer_settings": { // The mixerbus values for this engine
        "panAmount": 0, // The position of the engine in the stereo field (-1 through 1, 0 meaning no pan)
        "dryAmount": 1 // The gain for this slot (in gain adjustment rather than dB)
      },
      "equalizer_settings": { /* the mixerbus equaliser and compressor settings for this engine - see Equalizer Data below for details */ }
    },
    { // As an example, this synth (in synth slot 3 on track 7) would use a user-provided soundfont,
      // Of particular note here is the bank_name field, and bank_info field which defines the soundfont
      "plugin_id": "ZBP_SYNTH_00017",
      "plugin_version": "0000",
      "engine_name": "FluidSynth",
      "engine_nick": "FS",
      "engine_type": "MIDI Synth",
      "midi_chan": 3,
      "track_index": 6,
      "slot_type": "TracksBar_synthslot",
      "slot_index": 2,
      "bank_index": 52,
      "bank_name": "MY/SF3 Sonic Pocket Adventure Soundfont Redux",
      "bank_info": [
        "/zynthian/zynthian-my-data/soundfonts/sf2/SF3_Sonic_Pocket_Adventure_Soundfont_Redux.sf3",
        52,
        "MY/SF3 Sonic Pocket Adventure Soundfont Redux",
        "MY",
        "SF3_Sonic_Pocket_Adventure_Soundfont_Redux.sf3"
        // Index 5 is empty for this instance, since this was a user-provided soundfont (so it doesn't have an ID)
        "",
        // Index 6 for user-provided soundfonts contains the sha256 sum of the sound font file
        // In the case of SFZ entries, the sha256 sum is made from the sfz file
        "73a0ce7abd433ba628fc4aebeb887baa68936ef585803cc3383f0bcdb1fe9fef"
      ],
      "preset_index": 0,
      "preset_name": "Drum Kit",
      "preset_info": [
        "/zynthian/zynthian-my-data/soundfonts/sf2/SF3_Sonic_Pocket_Adventure_Soundfont_Redux.sf3/128-000 Drum Kit",
        [
          0,
          1,
          0
        ],
        "Drum Kit",
        "/zynthian/zynthian-my-data/soundfonts/sf2/SF3_Sonic_Pocket_Adventure_Soundfont_Redux.sf3"
      ],
      "controllers_dict": { // The current values for all the controllers on the engine
        "volume": { "value": 96 },
        "modulation": { "value": 0 },
        "pan": { "value": 64 },
        "expression": { "value": 127 },
        "sustain": { "value": 0 },
        // As there can be a great many of these, this is not a complete list for the example engine here
        // The important part here is that this dictionary holds the name of the controller as the key, and
        // data for the controller in the form of a dictionary (usually containing only the "value" key)
      },
      "zs3_list": [ // Zynthian sub-snapshots (unused by Zynthbox)
        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null
      ],
      "active_screen_index": 0, // Which of the pages of controllers is currently displayed
      "mixer_settings": { // The mixerbus values for this engine
        "panAmount": 0, // The position of the engine in the stereo field (-1 through 1, 0 meaning no pan)
        "dryAmount": 1 // The gain for this slot (in gain adjustment rather than dB)
      },
      "equalizer_settings": { /* the mixerbus equaliser and compressor settings for this engine - see Equalizer Data below for details */ }
    },
    {
      "plugin_id": "ZBP_FX_10009", // The ID of the synth engine plugin (see the plugins.json section below for details on what this ID is)
      "plugin_version": "0000",
      "engine_name": "Jalv/GxDistortionPlus", // The plugin's name
      "engine_nick": "JV/GxDistortionPlus", // The plugin's nickname
      "engine_type": "Audio Effect", // The type of engine (currently either MIDI Synth or Audio Effect)
      "midi_chan": 15, // Audio effects are all stored on channel 15, as they are not directly addressed by midi in most cases, and don't require auto-routing
      "track_index": 0, // The index of the Sketchpad track this engine is associated with
      "slot_type": "TracksBar_fxslot", // The type of slot the engine is (TracksBar_fxslot signifying this is an effects slot for sounds)
      "slot_index": 0, // The index of the slot (from 0 through 4)
      "bank_index": 0, // The index of the currently selected bank of presets
      "bank_name": "None", // The human-readable name for the currently selected bank of presets 
      "bank_info": [ // A set of information describing the currently selected bank of presets (engine-specific layout)
        "None", null, "None", null
      ],
      "preset_index": 0, // The index of the currently selected preset in the currently selected bank
      "preset_name": "Default", // The human-readable name for the currently selected preset
      "preset_info": [ // A set of information describing the currently selected preset (engine-specific layout)
        "file:///zynthian/zynthian-plugins/lv2/gx_DistortionPlus.lv2/default-preset", null, "Default", "None"
      ],
      "controllers_dict": { // The current values for all the controllers on the engine
        "DISTORTION": { "value": 0.5 },
        "OUTPUT": { "value": 0.5 },
        "BASSBOOST": { "value": 0 }
        // As there can be a great many of these, this is not a complete list for the example engine here
        // The important part here is that this dictionary holds the name of the controller as the key, and
        // data for the controller in the form of a dictionary (usually containing only the "value" key)
      },
      "zs3_list": [ // Zynthian sub-snapshots (unused by Zynthbox)
        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null
      ],
      "active_screen_index": 0, // Which of the pages of controllers is currently displayed
      "mixer_settings": { // The mixerbus values for this engine
        "panAmount": 0, // The position of the engine in the stereo field (-1 through 1, 0 meaning no pan)
        "dryWetMixAmount": 1 // From 0 through 2, 0 being 100% dry and 0% wet, 1 being 100% dry and 100% wet, and 2 being 0% dry and 100% wet
      },
      "equalizer_settings": { /* the mixerbus equaliser and compressor settings for this engine - see Equalizer Data below for details */ }
    }
  ],
  "global_fx": [
    // Note in particular that for both global fx entries, there are no mixerbus and equaliser settings
    {
      "plugin_id": "ZBP_FX_10016",
      "plugin_version": "0000",
      "engine_name": "Jalv/Gxdigital_delay_st",
      "engine_nick": "JV/Gxdigital_delay_st",
      "engine_type": "Audio Effect",
      "midi_chan": -1,
      "track_index": -1,
      "slot_type": "",
      "slot_index": -1,
      "bank_index": 0,
      "bank_name": null,
      "bank_info": null,
      "preset_index": 0,
      "preset_name": null,
      "preset_info": null,
      "controllers_dict": {
        "BPM": { "value": 120 },
        "FEEDBACK": { "value": 50 },
        "GAIN": { "value": 100 },
        // As there can be a great many of these, this is not a complete list for the example engine here
        // The important part here is that this dictionary holds the name of the controller as the key, and
        // data for the controller in the form of a dictionary (usually containing only the "value" key)
      },
      "zs3_list": [ // Zynthian sub-snapshots (unused by Zynthbox)
        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null
      ],
      "active_screen_index": 0
    },
    {
      "plugin_id": "ZBP_FX_10033",
      "plugin_version": "0000",
      "engine_name": "Jalv/TAP Reverberator",
      "engine_nick": "JV/TAP Reverberator",
      "engine_type": "Audio Effect",
      "midi_chan": -1,
      "track_index": -1,
      "slot_type": "",
      "slot_index": -1,
      "bank_index": 0,
      "bank_name": null,
      "bank_info": null,
      "preset_index": 0,
      "preset_name": null,
      "preset_info": null,
      "controllers_dict": {
        "decay": { "value": 2800 },
        "drylevel": { "value": -4 },
        "wetlevel": { "value": 10 },
        // As there can be a great many of these, this is not a complete list for the example engine here
        // The important part here is that this dictionary holds the name of the controller as the key, and
        // data for the controller in the form of a dictionary (usually containing only the "value" key)
      },
      "zs3_list": [ // Zynthian sub-snapshots (unused by Zynthbox)
        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null
      ],
      "active_screen_index": 0
    }
  ],
  // Zynthian fallback information (unused by Zynthbox)
  "clone": [ /* ... */ ],
  "note_range": [ /* ... */ ],
  "audio_capture": { /* ... */ },
  "audio_routing": { /* ... */ },
  "midi_routing": { /* ... */ },
  "extended_config": { /* ... */ },
  "midi_profile_state": { /* ... */ }
}

Sketch#

A Sketch file contains both the entire sound setup for a single sketchpad track in Sketch mode, and the midi information represented by the patterns, stored in a single file that can be easily transferred. The data is stored in RIFF tags within a wave file, and the wave data in the file conceptually contains a preview of what that track would be (and will usually be either all clips (for a track in one-to-one mode), or otherwise just one of the clips).

As-yet undefined

Since we have not yet implemented this, we cannot really describe the file format very well. However, it would not be unreasonable that it looked very much like a Sound, just with some added fields, and a new file suffix (e.g. .sketch) to signify that difference

Sound#

A Sound file contains the entire sound setup for a single sketchpad track in Sketch mode, but without the midi clips found in a Sketch. The data is stored in RIFF tags within a wave file, and the wave data in the file conceptually contains a preview of the sound. This may be generated in a number of ways, but optimally it would be generated automatically when saving the sound.

Not a sample

While the storage mechanism is very similar, it is important to note that this type of file is different to a Zynthbox Enhanced sample, in that while it is guaranteed to contain the entire sound setup, it does not contain any information relating to the playback of the preview, such as loop points, gain adjustments, equalizer data or the like.

The fields stored in a Sound are:

ZYNTHBOX_SOUND_CATEGORY: The ID of the category this sound belongs to. This will be an integer number from 0 through 99, which translates to a known category.

ZYNTHBOX_SOUND_SYNTH_SLOTS_DATA, ZYNTHBOX_SOUND_FX_SLOTS_DATA, and ZYNTHBOX_SOUND_SAMPLE_SLOTS_DATA: These three fields each contain a string, which in turn is laid out as ["Slot 1 Title"], [""], [""], [""], [""] where Slot 1 Title is a descriptive string for the item in that slot type's first slot (and so on for the other four entries in the list). For Synth and FX slots, this will usually be the name of the engine and the selected preset, while for samples it would be the file title (that is, the name of the file without suffixes). However, this is informative only, and should not be used for inference. The intention is to make displaying the data for the Sound easier.

ZYNTHBOX_SOUND_SYNTH_FX_SNAPSHOT: This contains a snapshot for the synth and fx engines which constitute the setup for this Sound. It does not include data for global FX (as those would be defined by the Sketchpad itself, not for the individual track), and instead contains simply the data for the engines in the synth and fx slots. This field then contains the same data as found in a Zynthbox ZSS Snapshot, but without information that is not directly relevant to these engines.

ZYNTHBOX_SOUND_SAMPLE_SNAPSHOT: This contains a snapshot of the sample setup for this. It is a string-serialised json object, which contains five objects with the keys "0", "1", "2", "3", and "4", and which each contains the same data as the entries in a Sketchpad track's samples field in a Sketchpad json

ZYNTHBOX_SOUND_TRACK_STYLE_SNAPSHOT: This contains all a string serialised json object which holds the settings that affect the sound of a track onto which the sound would be loaded. It consequently contains the following keys (which each have the same data as that found in the same field on a Sketchpad json track):

  • trackStyle
  • trackRoutingStyle
  • fxRoutingData
  • synthRoutingData
  • sketchFxRoutingData
  • synthKeyzoneData
  • sample_picking_style
  • trustExternalDeviceChannels
  • keyzone_mode

Sample#

You will encounter two different types of sample in a Sketchpad (and in our archive): One which is a raw sample, for example if you went out and recorded the sound of a babbling brook or downloaded something off of freesounds.org and dropped the unprocessed sound into your Zynthbox library. The other is a sample which has been processed by Zynthbox, and then saved to the archive. The latter will also usually be what you would find on the Zynthbox store.

Zynthbox Enhanced Samples#

When a sample is enhanced with our metadata, the following RIFF tags are added to the file.

Non-wav formats

Our entire metadata storage system for this data uses taglib, but i cannot currently say how much work it would be, and whether it would in fact be possible, to store arbitrary data in a tag format within other formats (such as flac or ogg/vorbis). It is entirely possible this is simple and potentially even drop-in, however it is something which will need investigating before we commit to this ability.

// The gain adjustment for this sample in gain adjustment (0 and up)
"ZYNTHBOX_GAIN": [ "0.500000536441803" ]
// The pan adjustment for this sample (0 is no pan, from -1 through 1)
"ZYNTHBOX_PAN": [ "0.0" ]
// Whether, when editing the sample, the length of the playback window should be snapped to multiples of a beat
"ZYNTHBOX_SNAP_LENGTH_TO_BEAT": [ "True" ]
// The absolute path for where this file was originally before being added into a slot in a Sketchpad
"ZYNTHBOX_ORIGINAL_PATH: [ "/zynthian/zynthian-my-data/samples/my-samples/found-sounds/creaky-door.wav" ]

"ZYNTHBOX_TIMESTRETCHSTYLE": [ "TimeStretchOff" ]

// How many supplemental voices are created when a sample is played (defaulting to 0)
"ZYNTHBOX_SUBVOICE_COUNT": [ "0" ],
// The settings for each of the subvoices:
// - pan is between -1 and 1, defaulting to no pan at 0
// - pitch is a number of semitones to adjust the subvoice's playback (between -12.00 and 12.00, defaulting to 0.00)
// - gain is the gain adjustment for the subvoice in gain adjustment (as opposed to dB)
"ZYNTHBOX_SUBVOICE_SETTINGS": [ "[{\"pan\":0.0,\"pitch\":0.0,\"gain\":1.0},{\"pan\":0.0,\"pitch\":0.0,\"gain\":1.0},{\"pan\":0.0,\"pitch\":0.0,\"gain\":1.0},{\"pan\":0.0,\"pitch\":0.0,\"gain\":1.0},{\"pan\":0.0,\"pitch\":0.0,\"gain\":1.0},{\"pan\":0.0,\"pitch\":0.0,\"gain\":1.0},{\"pan\":0.0,\"pitch\":0.0,\"gain\":1.0},{\"pan\":0.0,\"pitch\":0.0,\"gain\":1.0},{\"pan\":0.0,\"pitch\":0.0,\"gain\":1.0},{\"pan\":0.0,\"pitch\":0.0,\"gain\":1.0},{\"pan\":0.0,\"pitch\":0.0,\"gain\":1.0},{\"pan\":0.0,\"pitch\":0.0,\"gain\":1.0},{\"pan\":0.0,\"pitch\":0.0,\"gain\":1.0},{\"pan\":0.0,\"pitch\":0.0,\"gain\":1.0},{\"pan\":0.0,\"pitch\":0.0,\"gain\":1.0},{\"pan\":0.0,\"pitch\":0.0,\"gain\":1.0}]" ]

// How the sample will be played back, from one of the following options:
// - NonLoopingPlaybackStyle (will play for as long as the key is held down)
// - LoopingPlaybackStyle (will play in a looping manner for as long as the key is held down)
// - OneshotPlaybackStyle (will play the sample once, without looping, regardless of how long the key is held down)
// - GranularNonLoopingPlaybackStyle (will play the sample using a granular method, once until the playhead reaches the end of the sample or the key is released)
// - GranularLoopingPlaybackStyle (will play the sample using a granular method, in a looping manner, for as long as the key is held down)
// - WavetableStyle (will play the sample in a looping manner for as long as the key is held down, and move the play start position using a windowed style)
"ZYNTHBOX_PLAYBACK_STYLE": [ "OneshotPlaybackStyle" ]

// The start position of the sample's playback window in samples
"ZYNTHBOX_STARTPOSITION_SAMPLES": [ "0" ]
// The length of the sample's playback window in samples (as counted from the start position)
"ZYNTHBOX_LENGTH_SAMPLES": [ "96000" ]
// When in a looping playback style, the number of samples ahead of the start position to begin from after reaching the end (that is, when playback reaches the start+length position)
"ZYNTHBOX_LOOPDELTA_SAMPLES": [ "0" ]
// When in a looping playback style, the release section of playback will be allowed to pass the sample's stop position and reach this point (that is, start+length+loopdelta2) before stopping
"ZYNTHBOX_LOOPDELTA2_SAMPLES": [ "0" ]
// When looping, we can crossfade between runs of the loop area
// How much crossfading should be done between loops (between 0 and 0.5)
"ZYNTHBOX_LOOP_CROSSFADE_AMOUNT": [ "0.0" ]
// Whether to keep playback inside or outside the loop section
// Outie mode will start the next loop at the stop position, and keep playing past the end for (crossfade amount * length)
// Innie mode will start the next loop at start+length-(crossfade amount * length)
"ZYNTHBOX_LOOP_START_CROSSFADE_DIRECTION": [ "CrossfadeOutie" ]
// Whether to start playback from behind the loop position, or inside the loop area
// Outie will start playback at start+loop delta-(crossfade amount * length)
// Innie will start playback at the start+loop delta position
"ZYNTHBOX_STOP_CROSSFADE_DIRECTION": [ "CrossfadeOutie" ]

// The envelope used for playback control
// The envelope's attack duration in seconds
"ZYNTHBOX_ADSR_ATTACK": [ "0.0" ]
// The envelope's decay duration in seconds
"ZYNTHBOX_ADSR_DECAY": [ "0.0" ]
// The envelope's release duration in seconds
"ZYNTHBOX_ADSR_RELEASE": [ "0.05000000074505806" ]
// The amount of sustain for this sample (from 0 through 1)
"ZYNTHBOX_ADSR_SUSTAIN": [ "1.0" ]

// Time stretching bits
// Whether to sync speed ratio to the sketchpad's BPM
"ZYNTHBOX_SYNC_SPEED_TO_BPM": [ "True" ]
// The BPM for this sample
"ZYNTHBOX_BPM": [ "120.0" ]
// The speed ratio for this sample
"ZYNTHBOX_SPEED_RATIO": [ "1.0" ]
// The amount of pitch adjustment done to this sample
// This is done in a time-stretched manner, hence why it is here
// For adjusting the root note, see Keyzone data below
"ZYNTHBOX_PITCH": [ "0.0" ]

// The settings for the six-channel equaliser and compressor available for each sample slot
// See the details for this data in the Equaliser Data section above
"ZYNTHBOX_EQUALISER_SETTINGS": [ /* string containing serialized equaliser data */ ],
// A base64 serialised dump of the slice data for this sample (once unencoded, this section contains data as described in Slices below)
"ZYNTHBOX_SLICE_SETTINGS": [ "AAAAAwAAABQAYwBvAG4AdABpAGcAdQBvAHUAcwAAAAEAAAAAABAAcwBlAHQAdABpAG4AZwBzAAAACQAAAAAAAAAACgBjAG8AdQBuAHQAAAACAAAAAAA=" ]

// Keyzone data:
// The note at which this sample should be played without pitch adjustment
"ZYNTHBOX_ROOT_NOTE": [ "60" ]
// The first midi note at which this sample should play (-1 meaning disabled, 0 through 127, must be equal to or below keyzone end)
"ZYNTHBOX_KEYZONE_START": [ "0" ]
// The last midi note at which this sample should play (-1 meaning disabled, 0 through 127, must be equal to or above keyzone start)
"ZYNTHBOX_KEYZONE_END": [ "127" ]
// The minimum velocity at which this sample should play (1 through 127, must be equal to or below velocity maximum)
"ZYNTHBOX_VELOCITY_MINIMUM": [ "1" ]
// The maximum velocity at which this sample should play (1 through 127, must be equal to or above velocity minimum)
"ZYNTHBOX_VELOCITY_MAXIMUM": [ "127" ]

// The grainerator settings are used to determine how to play the sample when the playback style is one of the Granular styles
"ZYNTHBOX_GRAINERATOR_INTERVAL": [ "10.0" ]
"ZYNTHBOX_GRAINERATOR_INTERVAL_ADDITIONAL": [ "10.0" ]
"ZYNTHBOX_GRAINERATOR_PAN_MAXIMUM": [ "1.0" ]
"ZYNTHBOX_GRAINERATOR_PAN_MINIMUM": [ "-1.0" ]
"ZYNTHBOX_GRAINERATOR_PITCH_MAXIMUM1": [ "1.0" ]
"ZYNTHBOX_GRAINERATOR_PITCH_MAXIMUM2": [ "1.0" ]
"ZYNTHBOX_GRAINERATOR_PITCH_MINIMUM1": [ "1.0" ]
"ZYNTHBOX_GRAINERATOR_PITCH_MINIMUM2": [ "1.0" ]
"ZYNTHBOX_GRAINERATOR_PITCH_PRIORITY": [ "0.5" ]
"ZYNTHBOX_GRAINERATOR_POSITION": [ "0.0" ]
"ZYNTHBOX_GRAINERATOR_SCAN": [ "0.0" ]
"ZYNTHBOX_GRAINERATOR_SIZE": [ "100.0" ]
"ZYNTHBOX_GRAINERATOR_SIZE_ADDITIONAL": [ "50.0" ]
"ZYNTHBOX_GRAINERATOR_SPRAY": [ "1.0" ]
"ZYNTHBOX_GRAINERATOR_SUSTAIN": [ "0.30000001192092896" ]
"ZYNTHBOX_GRAINERATOR_TILT": [ "0.5" ]

Slice Settings#

Equalizer Data#

This same json format data is contained within a number of locations, and so rather than explaining them in each of those separate locations, you can find it here, once.

{
  "equaliserSettings": [ // A list of six entries, representing each one band of the equaliser
    { // One band on the equaliser
      // The type of filter for this band. Can be any of:
      // - NoFilterType
      // - HighPassType
      // - HighPass1stType
      // - LowShelfType
      // - BandPassType
      // - AllPassType
      // - AllPass1stType
      // - NotchType
      // - PeakType
      // - HighShelfType
      // - LowPass1stType
      // - LowPassType
      "filterType": "HighPassType",
      "frequency": 20, // The frequency at which this filter band sits (from 20.00 through 20,000.00)
      "quality": 0.7071067690849304, // The "quality" of the filter (the Q value), from 0.00 through 10.00)
      "soloed": false, // Whether this filter is soloed
      "gain": 1, // The gain for this filter (in gain adjustment)
      "active": false // Whether or not the filter is active (solo will override this during runtime)
    },
    // A further five entries with the same layout as above
  ],
  "equaliserEnabled": false, // Whether or not the equaliser is active
  "compressorEnabled": false, // Whether or not the compressor is enabled
  "compressorSidechannelLeft": "", // The left channel sidechain for the compressor (can be any of audio input source definition values, see the API documentation for MidiRouterDeviceModel::audioInSourceToJackPortNames for a comprehensive list)
  "compressorSidechannelRight": "", // The right channel sidechain for the compressor (as above)
  "compressorSettings": { // The settings specific to the compressor
    "thresholdDB": -10, // The dB value above which the compressor should kick in
    "makeUpGainDB": 0, // The amount of dB by which the compressor amplifies the resultant audio after applying compression
    "kneeWidthDB": 0, // The sharpness of the threshold (at 0 the threshold is applied in full immediatley, and at wider values, some compression is applied prior to reaching the threshold, resulting in a smoother signal)
    "ratio": 4 // The amount of compression applied to the audio once the threshold is reached
    "attack": 30, // Once threshold is reached, the attack defines how rapidly the compression is applied
    "release": 150, // Once the level goes back below the threshold, the release defines how rapidly we stop applying the compression
  }
}