DecentSampler: File Format Reference Guide

Document Version: 1.0.8

Table of Contents


Introduction

At its core each DecentSampler sample library consists of two things: a folder containing a bunch of assets like audio files and pictures, and a single text file (called a dspreset file) which describes how the engine should use all of those files. This reference document is a guide to creating dspreset files.

dspreset files are just XML files. As such, each one begins with an XML declaration:

<?xml version="1.0" encoding="UTF-8"?>

The top-level <DecentSampler> element (required)

At the top level of every dspreset file is a <DecentSampler> element. Every file must have one. Here is a list of attributes:

Example:

<?xml version="1.0" encoding="UTF-8"?>
<DecentSampler>
    <!-- More tags go here. :) -->
</DecentSampler>

Underneath the top-level <DecentSampler> element you can put any number of other elements, which are described below:

The <ui> element (optional)

The <ui> element is how you specify a user interface for your instrument. Each dspreset should have at most one <ui> element. There are several important attributes:

Example:

<DecentSampler>
  <ui bgImage="background.png" width="812" height="375">
    <tab name="main">
      <labeled-knob x="560" y="0" label="Tone" type="float" minValue="60" maxValue="22000"
                    textColor="FF000000" value="22000.0" uid="y8AA4uuURh3">
        <binding type="effect" level="instrument" position="0" parameter="FX_FILTER_FREQUENCY"/>
      </labeled-knob>
      <label x="360" y="0" width="50" height="30" text="Reverb"/>
      <control x="360" y="30" parameterName="Reverb" type="float" minValue="0" maxValue="1" textColor="FF000000" value="0.5">
      <!-- Your <binding /> elements should go here -->
      </control>
    </tab>
  </ui>
</DecentSampler>

The <tab> element

The <tab> element lives underneath the <ui> element. This architecture was chosen because we may, at some point, add support for multiple tabs. At present it is only possible to have a single tab within DecentSampler instruments. As such, every UI must have at most one <tab> element.

Attributes:

The <label> element

The <label> element lives underneath the <tab> element. It specifies the position of a text label. Attributes:

The <labeled-knob> and <control> elements

The <labeled-knob> and <control> elements live underneath the <tab> element. These tags correspond to user controls (usually round radial dials) that can be used as part of a UI. These two element types are the same except that <labeled-knob> elements contain built-in labels, where as <control> elements do not. Every tab can have many <control> or <labeled-knob> elements underneath it.

For precise UI creation, it may be advisable to use a combination of <control> & <label> elements rather than <labeled-knob>.

Attributes:

Example:

<DecentSampler>
  <ui>
    <tab>
      <labeled-knob x="560" y="0" label="Tone" type="float" minValue="60" maxValue="22000" textColor="FF000000" value="22000.0">
      <!-- Your <binding /> elements should go here -->
      </labeled-knob>
      <label x="360" y="0" width="50" height="30" text="Reverb"/>
      <control x="360" y="30" parameterName="Reverb" type="float" minValue="0" maxValue="1" textColor="FF000000" value="0.5">
      <!-- Your <binding /> elements should go here -->
      </control>
    </tab>
  </ui>
</DecentSampler>

To learn how to make knobs actually control parameters of your instrument, see “Appendix B: Bindings” section below.

The <groups> element (required)

Every dspreset file should have one and only one <groups> element. This is where you specify the samples that make up your sample library. This element lives right underneath the top-level <DecentSampler> element. The basic structure is this:

<DecentSampler>
    <groups>
        <group>
            <sample /> <!-- This is where -->
            <sample /> <!-- the samples   -->
            <sample /> <!-- get defined   -->
        </group>
    </groups>
</DecentSampler>
Attribute Description
volume (optional) The volume of the instrument as a whole. This will be reflected in the UI in the top-right corner. Value can be in linear 0.0-1.0 or in decibels. If it’s in decibels you must append dB after the value (example: “3dB”). Default: 1.0 (no volume change)
globalTuning (optional) Global pitch adjustment for changing note pitch. In semitones. For example 1.0 would be a half-step up. Default: 0

The <group> element

Samples live in groups. There can be many group elements under the <groups> element. It can be useful to sort your samples into groups in order to apply similar settings to them or to control them with a knob. The order of groups in a file matters insofar as bindings will often reference groups by using an index. The first group in a file is group 0, the second is group 1, etc.

Attribute Description
volume (optional) The volume of the group. Value can be in linear 0.0-1.0 or in decibels. If it’s in decibels you must append dB after the value (example: “3dB”). Default: 1.0
ampVelTrack (optional) The degree to which the velocity of the incoming notes affects the volume of the samples in this group. 0 = not at all. 1 = volume is completely determined by incoming velocity. When the value is 1, a velocity of 127 (max velocity) yields a gain 1.0 (full volume), a velocity of 63 (half velocity) yields a gain of 0.5 (half volume), etc.
groupTuning (optional) Group-level pitch adjustment for changing note pitch. In semitones. For example 1.0 would be a half-step up and -1 would a half-step down. Default: 0
The <sample> element

Underneath the <group> elements are <sample> elements. Each sample corresponds to a playable “zone” of your instrument. Attributes:

Attribute Description
path (required) The relative path of the sample file to play for this zone.
rootNote (required) The MIDI note number (from 1 to 127) of the note.
loNote (optional) The MIDI note number (from 1 to 127) of the lowest note for which the zone should be triggered. Default: 0.
hiNote (optional) The MIDI note number (from 1 to 127) of the highest note for which the zone should be triggered. Default: 127.
loVel (optional) The lowest velocity for which this zone should be triggered. Default: 1
hiVel (optional) The highest velocity for which this zone should be triggered. Default: 127
start (optional) The frame/sample position of the start of the sample audio. This is useful if the sample starts midway through the audio file. Default: 0
end (optional) The frame/sample position of the end of the sample audio. The is useful is the zone ends before the end of the audio file. Default: the file’s length in samples minus 1.
tuning (optional) A fine-tuning number (in semitones) for changing the note pitch. e.g 1.0 would be a half-step up. Default: 0
volume (optional) The volume of the sample. Value can be in linear 0.0-1.0 or in decibels. If it’s in decibels you must append dB after the value (example: “3dB”). Default: 1.0
pan (optional) A number of -100 to 100. -100 in panned all the way to the left, 100 is panned all the way to the right. This can also be set at the <group> or <groups> levels. Default: 0
pitchKeyTrack (optional) A number from 0.0 to 1.0. 0 means that the pitch will stay the same regardless of what note is played. 1 means that the pitch will increase by one semitone when the note increases by one semitone (i.e. normal key pitch tracking). This can also be set at the <group> level. Default: 1
trigger (optional) Valid values: attack means a sample is played when the note on message is received. release means the sample is played when the note off message is received (aka a release trigger). This can also be set at the <group> level. Default: attack.
tags (optional) A command-separated list of tags. Example: tags=”rt,mic1”. These are useful when controlling volumes using tags. See Appendix D.
onLoCCN onHiCCN (optional) If you want a sample to be triggered when a MIDI CC controller message comes in, for example for piano pedal down and pedal up samples, you use these attributes to specify the range of values that should trigger the sample. If you use onLoCCN, you must also use a corresponding onHiCCN for the same MIDI CC number. Example: onLoCC64="90" and onLoCC64="127" would mean that values of CC64 (Sustain Pedal) between 90 and 127 will trigger the given sample. This can also be set at the <group> level. Default:-1 (off)

Looping

Attribute Description
loopStart (optional) The frame/sample position of the start of the sample’s loop. If this is not specified, but the sample is a wave file with embedded loop markers, those will be used instead. Default: 0
loopEnd (optional) The frame/sample position of the end of the sample’s loop. If this is not specified, but the sample is a wave file with embedded loop markers, those will be used instead. Default: the file’s length in samples minus 1.
loopCrossfade (optional) When loop crossfades are used, instead of simply looping at a specific end point, a portion of the audio from before the loop point is faded in just as the audio from the end of the loop is faded out. In this way, smooth audio loops can be achieved on samples that weren’t specifically prepared as looping. This parameter is used for specifying the length of the crossade region in frames/samples. This can also be set at the <group> level. Default: 0 (crossfades off).
loopCrossfadeMode (optional) This parameter is used to specify the curve used for crossfading when loop crossfades are turned on. This can also be set at the <group> level. Value values: linear, equal_power. Default: equal_power.
loopEnabled (optional) A boolean value indicating whether or not the loop should be used. Valid values: true, false

Amplitude Envelope

Each sample as its own ADSR amplitude envelope.

Attribute Description
attack (optional) The attack of the amplitude envelope of this zone. This can also be set at the <group> or <groups> levels.
decay (optional) The decay of the amplitude envelope of this zone. This can also be set at the <group> or <groups> levels.
sustain (optional) The sustain of the amplitude envelope of this zone. This can also be set at the <group> or <groups> levels.
release (optional) The release of the amplitude envelope of this zone. This can also be set at the <group> or <groups> levels.

Round Robins

Round robins allow different samples to be played each time a zone is triggered. This is especially useful with sounds that have short attacks (such as drums), and is a great way to keep your sample libraries from sounding fake. In order for round robins to work, you must specify both a seqMode and a seqPosition for all samples. There are several round-robin modes:

Attribute Description
seqMode (optional) Valid values are random, true_random, round_robin, and always. A value indicating the desired round robin behavior for this sample or group of samples. This can also be set at the <group> and <groups> levels. Default: always
seqPosition (optional) A number indicating this zone’s position in the round robin queue. This can also be set at the <group> level. Default: 1

The <effects> element

Adding global, instrument-wide effects is easy: just add an <effects> element right below your top-level <DecentSampler> element.

The <effect> element

Within the <effects> you can have any number of <effect> elements. These specify parameters for each individual effect that you would like to have in your global effects change. There are currently only a handful effects available although more could definitely be added on request:

Low-pass filter

A 4-pole resonance filter

Example:

<DecentSampler>
  <effects>
    <effect type="lowpass_4pl" resonance="0.7" frequency="22000" />
  </effects>
</DecentSampler>

Attributes:

Attribute Type Valid Range Default
type Required Must be lowpass_4pl lowpass_4pl
resonance Optional The filter resonance (Q) 0 - 1.0, where 1.0 is big, 0 is small. 0.7
frequency Optional The filter frequency 0 - 1.0, where 0 is not damped, 1.0 is fully damped. 0.3
Reverb effect

Example:

<DecentSampler>
  <effects>
    <effect type="reverb" roomSize="" damping="" wetLevel="" />
  </effects>
</DecentSampler>

Attributes:

Attribute Type Valid Range Default
type Required Must be reverb reverb
roomSize Optional The reverb “room size” 0 - 1.0, where 1.0 is big, 0 is small. 0.7
damping Optional The reverb damping level 0 - 1.0, where 0 is not damped, 1.0 is fully damped. 0.3
wetLevel Optional The volume of reverb signal 0 - 1.0 0

Appendix A: The Color Format

Colors are represented throughout the dspreset files using an 8-digit ARGB color format. These are identical to web color hex codes except with an additional 2-digit hex number in front of them. The first two digits are a hexadecimal representation of alpha level with 00 being fully transparent, 80 being 50% transparent, and FF being fully opaque.

Examples:

Appendix B: The <binding> element

Adding a binding to a UI control tells the DecentSampler engine that it should take input from a source and use it to change values in another part of the engine. An example of this would be a knob which controls the volume of a group or a CC controller that changes an effect parameter.

In order to set up a binding for a specific source, create a <binding> element within the source element.

In this example, a labeled knob is controlling the volume of the first group of samples (group 0):

<DecentSampler>
  <ui>
    <tab>
      <labeled-knob x="420" y="100" label="RT" type="float" minValue="0" maxValue="1" value="0.3" textSize="20">
        <binding type="amp" level="group" position="0" parameter="AMP_VOLUME" translation="linear" translationOutputMin="0" translationOutputMax="1.0"  />
      </labeled-knob>
    </tab>
  </ui>
</DecentSampler>

Here’s a full list of parameters for the <binding> element:

Attribute Description
type Required This tells the engine what type of parameter this is. Valid values are: “amp”, “effect”, “labeled_knob”.
level Required Valid values are ui, instrument, group
position Required The specific 0-based index of the element to be modified by this binding. If you are targeting a group, for example, the first group would be 0, the second group would be 1, etc.
identifier Required A string identifying the specific parameter that you wish to change. If you are modulating based on tags, you would put the tag you are targeting here. See Appendix D for example.
parameter Required A token describing the specific kind of parameter that you wish to change. A list of controller parameters are below.
translation Optional Valid values are linear and table. Explanation of both translation modes is in a separate section below. Default: linear
translationOutputMin Optional This is the min value this binding should send to the target parameter. This is only looked at if translation is set to linear.
translationOutputMax Optional This is the max value this binding should send to the target parameter. This is only looked at if translation is set to linear.
translationReversed Optional Valid values are true and false. Default: false. This is only looked at if translation is set to linear.
translationTable Optional A list of input-output pairs that make up the translation table. The input and output are separated by commas. The groups of coordinates themselves are separated by semi-colons. Default: 0,0;1,1. You must have at least two coordinates in your list. This is only looked at if translation is set to table.

Controllable Parameters

This is a list of parameters that can be used in conjunction with the <binding> element above.

Description type level position identifier parameter Valid Range
Global Volume amp instrument N/A N/A AMP_VOLUME 0.0 - 16.0
Global Tuning amp instrument N/A N/A GLOBAL_TUNING -36.0 - 36.0
Global Amp Envelope Attack amp instrument N/A N/A ENV_ATTACK 0.0 - 2.0
Global Amp Envelope Decay amp instrument N/A N/A ENV_DECAY 0.0 - 2.0
Global Amp Envelope Sustain amp instrument N/A N/A ENV_SUSTAIN 0.0 - 2.0
Global Amp Envelope Release amp instrument N/A N/A ENV_RELEASE 0.0 - 2.0
Filter Cutoff amp instrument N/A N/A FX_FILTER_FREQUENCY 0.0 - 22000.0
Filter Resonance amp instrument N/A N/A FX_FILTER_RESONANCE 0.0 - 2.0
Reverb Wet Level amp instrument N/A N/A FX_REVERB_WET_LEVEL 0.0 - 1.0
Reverb Room Size amp instrument N/A N/A FX_REVERB_ROOM_SIZE 0.0 - 1.0
Group Volume amp group The 0-based index of the group N/A AMP_VOLUME 0.0 - 16.0
Group Tuning amp group N/A N/A GROUP_TUNING -36.0 - 36.0
Group Amp Envelope Attack amp group The 0-based index of the group N/A ENV_ATTACK 0.0 - 2.0
Group Amp Envelope Decay amp group The 0-based index of the group N/A ENV_DECAY 0.0 - 2.0
Group Amp Envelope Sustain amp group The 0-based index of the group N/A ENV_SUSTAIN 0.0 - 2.0
Group Amp Envelope Release amp group The 0-based index of the group N/A ENV_RELEASE 0.0 - 2.0
Tag Volume amp tag N/A The tag AMP_VOLUME 0.0 - 16.0

Translation Modes

There are currently two binding translation modes: linear and table:

  1. linear mode allows values that come in to be scaled up or down before they get passed along to the binding’s target. If you set your translation mode to linear you should also translationOutputMin and translationOutputMax.
  2. table mode allows you to transform the binding’s input in a more complex fashion before it gets passed along to the binding’s target. If you set your translation mode to table you must define the translationTable parameter as well. This consists of a series of input-output pairs, separated by semi-colons.

Appendix C: Boilerplate .dspreset File

<?xml version="1.0" encoding="UTF-8"?>
<DecentSampler>
  <ui bgImage="background.png" width="812" height="375" layoutMode="relative"
      bgMode="top_left">
    <tab name="main">
      <labeled-knob x="560" y="0" label="Tone" type="float" minValue="60" maxValue="22000"
                    textColor="FF000000" value="22000.0" uid="y8AA4uuURh3">
        <binding type="effect" level="instrument" position="0" parameter="FX_FILTER_FREQUENCY"/>
      </labeled-knob>
      <labeled-knob x="655" y="0" label="Reverb" type="percent" minValue="0" maxValue="100"
                    textColor="FF000000" value="50.0" uid="lKv29kggDro">
        <binding type="effect" level="instrument" position="1" parameter="FX_REVERB_WET_LEVEL"
                 factor="0.01"/>
      </labeled-knob>
    </tab>
  </ui>
  <groups attack="0.000" decay="25" sustain="1.0" release="0.430" volume="-3dB">
    <group>
      <sample loNote="21" hiNote="21" rootNote="21" path="DefaultPiano-21.aif"
              length="805888"/>
      <sample loNote="22" hiNote="33" rootNote="33" path="DefaultPiano-33.aif"
              length="807552"/>
      <sample loNote="34" hiNote="45" rootNote="45" path="DefaultPiano-45.aif"
              length="759168"/>
      <sample loNote="46" hiNote="57" rootNote="57" path="DefaultPiano-57.aif"
              length="756480"/>
      <sample loNote="58" hiNote="69" rootNote="69" path="DefaultPiano-69.aif"
              length="758656"/>
      <sample loNote="70" hiNote="77" rootNote="77" path="DefaultPiano-77.aif"
              length="595328"/>
      <sample loNote="78" hiNote="89" rootNote="89" path="DefaultPiano-89.aif"
              length="457600"/>
      <sample loNote="90" hiNote="96" rootNote="96" path="DefaultPiano-96.aif"
              length="469888"/>
      <sample loNote="94" hiNote="108" rootNote="108" path="DefaultPiano-108.aif"
              length="75264"/>
    </group>
  </groups>
  <effects>
    <effect type="lowpass_4pl" frequency="22000.0"/>
    <effect type="reverb" wetLevel="0.5"/>
  </effects>
</DecentSampler>

Appendix D: How to Control Parameters Using Tags (Example: Mic-level Knobs)

As of version 1.0.2, the best way to implement mic-level knobs is using the new sample tagging feature. It is possible to assign tags to specific samples. In this way, you can specify which type of sound they are:

<sample volume="0.0dB" tags="note,mic1" />
<sample volume="0.0dB" tags="rt,mic1" />
<sample volume="0.0dB" tags="note,mic2" />
<sample volume="0.0dB" tags="rt,mic2" />

You can also assign tags at the group level. You can also mix and match, and the tags specified at the group level will be added to the list of tags already specified at the sample level:

<group tags="note">
  <sample volume="0.0dB" tags="mic1" />
  <sample volume="0.0dB" tags="mic2" />
</group>
<group tags="rt">
  <sample volume="0.0dB" tags="mic1" />
  <sample volume="0.0dB" tags="mic2" />
</group>

Then you can make controls with bindings that reference those tags:

<control x="246" y="115" parameterName="MIC 1" style="linear_bar_vertical" type="float" minValue="0" maxValue="100" value="60" width="20" height="70" trackForegroundColor="FFFFFFFF" trackBackgroundColor="FF888888">
    <binding type="amp" level="tag" identifier="mic1" parameter="AMP_VOLUME" />
</control>

<control x="346" y="115" parameterName="MIC 2" style="linear_bar_vertical" type="float" minValue="0" maxValue="100" value="60" width="20" height="70" trackForegroundColor="FFFFFFFF" trackBackgroundColor="FF888888">
    <binding type="amp" level="tag" identifier="mic2" parameter="AMP_VOLUME" />
</control>