DecentSampler: File Format Reference Guide

Document Version: 1.2.3

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
glideTime (optional) The glide/portamento time in seconds. A value of 0.0 would mean no portamento. This value can also be set at the <group> and <sample> levels, although most people will want to set it globally at the <groups> level. Default: 0.0
glideMode (optional) Controls the glide/portamento behavior. Possible values are: always (glide is always performed), legato (glide is performed only when transitioning from one note to another), and off. This value can also be set at the <group> and <sample> levels, although most people will want to set it globally at the <groups> level. Default: legato

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
loCCN hiCCN (optional) Using these parameter, you can use MIDI continuous controllers to filter whether or not a note should be played. This lets you, for example, have one set of samples that get played when the piano sustain pedal is down and another set that get played when it is up. Each time a MIDI CC value comes for a specific CC#, the engine stores that value. When a “note on” signal is received, the engine makes a decision (based on the last received value and the range defined by these attributes) about whether or not this sample should be played. If you use loCCN, you must also use a corresponding hiCCN for the same MIDI CC number so that you are defining a range of values. Example: loCC64="90" and hiCC64="127" would mean that a “note on” message will only trigger this sample if the last received value for CC64 (Sustain Pedal) is between 90 and 127. This can also be set at the <group> level. Default:-1 (off)
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). first means that the sample will only be played if no other notes are playing. legato means that the sample will only be played if some other notes are already playing. 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 onHiCC64="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 has 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

Voice-Muting / Legato

Looping

Attribute Description
silencedByTags (optional) A command-separated list of tags. Example: tags=”rt,mic1”. If a sample containing one of these tags gets triggered, then this sample will be stopped. This is useful when setting up drums as it will allow you mute one hi-hat when another hi-hat plays. See Appendix D.
silencingMode (optional) Controls how quickly voices get silenced. fast = immediately; normal = triggers the sample’s release phase. This second option, when used in conjunction with the release attribute, allows you to specify a longer release time. Values: fast, normal. Default: fast
previousNotes (optional) Only play this sample if the previously triggered note equals one of these notes. Format: a comma-separated list of MIDI note numbers (from 1 to 127) of the note.
legatoInterval (optional) This is similar to the previousNote attribute. This causes the engine to only play the sample if the previously triggered note is exactly this semitone distance from the previous note. For example, if the note for which this sample is being triggered is a C3 and the legatoInterval is set to -2, then the sample will only play if the previous note was a D3 because D3 minus 2 semitones equals C3. Format: This can be a positive or negative whole number.

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> element, you can have any number of <effect> sub-elements. These specify parameters for each individual effect that you would like to have in your global effects chain. 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
Delay effect

Example:

<DecentSampler>
  <effects>
    <effect type="delay" delayTime="0.5" stereoOffset="0.01" feedback="0.2" wetLevel="0.5" />
  </effects>
</DecentSampler>

Attributes:

Attribute Type Valid Range Default
type Required Must be reverb reverb
delayTime Optional The delay time in seconds 0 - 10.0 0.7
feedback Optional The feedback level. 0 - 1.0, where 0 is no feedback, 1.0 is max feedback. 0.2
stereoOffset Optional The parameter allows you to introduce delay variations between the left and right channels. Half of this amount is subtracted from the left channel’s delay time and half of this amount is added to the right channel’s delay time. For example, if the delayTime is 0.5 seconds and the stereoOffset is 0.02 s, then the actual left channel delay time will be 0.49 s and the actual right channel delay time will be 0.51 s so that the two channels are offset by 0.02 seconds. -10 - 10 0
wetLevel Optional The volume of the delay signal 0 - 1.0 0.5
Chorus effect

Example:

<DecentSampler>
  <effects>
    <effect type="chorus" mix="0.5" modDepth="0.2" modRate="0.2"/>
  </effects>
</DecentSampler>

Attributes:

Attribute Type Valid Range Default
type Required Must be chorus chorus
mix Optional The wet/dry mix which controls how much of the chorus signal we hear 0 - 1.0, where 1.0 is just chorus, 0 is just dry signal. 0.5
modDepth Optional The modulation depth of the effect 0 - 1.0, where 0 is no modulation, 1.0 is max modulation. 0.2
modRate Optional The modulation speed in Hz. 0 - 10.0 0.2
Phaser effect

Example:

<DecentSampler>
  <effects>
    <effect type="phaser" mix="0.5" modDepth="0.2" modRate="0.2" centerFrequency="400" feedback="0.7" />
  </effects>
</DecentSampler>

Attributes:

Attribute Type Valid Range Default
type Required Must be phaser phaser
mix Optional The wet/dry mix which controls how much of the chorus signal we hear 0 - 1.0, where 1.0 is just chorus, 0 is just dry signal. 0.5
modDepth Optional The modulation depth of the effect 0 - 1.0, where 0 is no modulation, 1.0 is max modulation. 0.2
modRate Optional The modulation speed in Hz. 0 - 10.0 0.2
centerFrequency Optional The center frequency (in Hz) of the phaser all-pass filters modulation 0 - 1.0 400
feedback Optional Sets the feedback volume of the phaser. -1 - 1.0 0.7

The <midi> element

MIDI mappings can be added to your instrument by adding a <midi> element right below your top-level <DecentSampler> element.

The <cc> element

Within the <midi> element, you can have any number of <cc> elements. These allow you to map changes in incoming continuous controller messages to specific parameters of your instrument. To use this functionality, you’ll want to add a separate <cc> element for each CC number you would like to respond to. The <cc> element has a single required attribute number="" which specifies the number (from 0 to 127) of the continuous controller you would like to listen on. Beneath the <cc> element, you can have any number of bindings.

<midi>
    <cc number="11">
      <binding level="ui" type="control" position="0" parameter="value" translation="linear" 
               translationOutputMin="0" translationOutputMax="1"/>
    </cc>
    <cc number="1">
      <binding level="ui" type="control" position="1" parameter="value" translation="linear" 
               translationOutputMin="0" translationOutputMax="1"/>
    </cc>
  </midi>
Bindings within the <midi> section

The bindings that the <cc> element listens on are the same as those used by the UI controls. See Appendix B for a complete description of these.

If you have a UI control mapped to the same internal parameter as a MIDI mapping, you’ll want to have your MIDI mapping control the UI control instead of the parameter directly. The benefit of doing this is that, as the MIDI CC input is received, the UI control will be updated as well as the desired internal parameter.

The way to accomplish this is to make use of the labeled_knob or control binding types (control was introduced in version 1.1.7) as follows:

<binding level="ui" type="control" position="0" parameter="value" translation="linear" translationOutputMin="0" translationOutputMax="1"/>

You’ll notice that the control type has a level value of ui and a parameter value of value. Another thing to notice is the position="" parameter. This contains the 0-based index of the control to be modified. NOTE: The indexes of the parameter list also includes UI controls that are not editable, such as <label> UI controls, so you’ll want to account for that when calculating your positions.

The <tags> element

The <tags> element lives right below your top-level <DecentSampler> element. It allows you to specify details about the tags you use throughout your instrument. It is however not actually necessary to include a <tags> element for every tag you use. You only need to create this if you want to specify additional details about your tags.

The <tag> element

Underneath the <tags> element, you can have any number of <tag> elements. These specify details for each individual tag that you use throughout your sample mapping. Attributes:

Attribute Description
volume (optional) A number for 0.0 to 1.0 that specifies the initial volume for a tag. Default: 1.0
polyphony (optional) A whole number that specifies the number of voices allowed for this tag.

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”, “control”.
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
Pan amp instrument N/A N/A PAN -100 - 100
Amplitude Velocity Tracking amp instrument N/A N/A AMP_VEL_TRACK 0.0 - 1.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
Glide/Portamento Time amp instrument N/A N/A GLIDE_TIME 0.0 - 10.0
Lowpass Filter Cutoff effect instrument N/A N/A FX_FILTER_FREQUENCY 0.0 - 22000.0
Lowpass Filter Resonance effect instrument N/A N/A FX_FILTER_RESONANCE 0.0 - 2.0
Reverb Wet Level effect instrument N/A N/A FX_REVERB_WET_LEVEL 0.0 - 1.0
Reverb Room Size effect instrument N/A N/A FX_REVERB_ROOM_SIZE 0.0 - 1.0
Chorus/Phaser Mix Level effect instrument N/A N/A FX_MIX 0.0 - 1.0
Chorus/Phaser Mod Depth effect instrument N/A N/A FX_MOD_DEPTH 0.0 - 1.0
Chorus/Phaser Mod Rate effect instrument N/A N/A FX_MOD_RATE 0.0 - 10.0
Phaser Center Frequency effect instrument N/A N/A FX_CENTER_FREQUENCY 0.0 - 22000.0
Phaser/Delay Feedback effect instrument N/A N/A FX_FEEDBACK 0.0 - 1.0
Delay Time effect instrument N/A N/A FX_DELAY_TIME 0.0 - 1.0
Delay Stereo Offset effect instrument N/A N/A FX_STEREO_OFFSET 0.0 - 1.0
Delay Wet Level effect instrument N/A N/A FX_WET_LEVEL 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 The 0-based index of the group N/A GROUP_TUNING -36.0 - 36.0
Pan amp group The 0-based index of the group N/A PAN -100 - 100
Amplitude Velocity Tracking amp group The 0-based index of the group N/A AMP_VEL_TRACK 0.0 - 1.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
Group Glide/Portamento Time amp group The 0-based index of the group N/A GLIDE_TIME 0.0 - 10.0
Tag Volume amp tag N/A The tag AMP_VOLUME 0.0 - 16.0
UI Control control ui The 0-based index of the control to be modified (see note 1 below) N/A value 0.0 - 1.0

Notes:

  1. NOTE: The indexes of the parameter list also include UI controls that are not editable, such as <label> UI controls, so you’ll want to account for that when calculating your positions.

    Here’s a quick example:

    If your UI’s <tab> section has the following elements under it: <label>, <control>,<label>,<control>. The position indexes of the four elements will be 0, 1, 2, 3. Therefore, the indexes of the two <control> elements will be 1 and 3, respectively.

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>

Appendix E: How to do voice-muting for drums

Voice muting makes use of the tags functionality, these are text labels that you can use to identify samples or groups of samples. You start by adding tags to all of your groups (you can also add them to individual samples if you’d like). Next, you add a silencedByTags attribute to groups or sample elements that you want to be silenced by other samples. When a sample with a tag matching one of the tags in the silencedByTags is played, it will silence the current sample (or group).

Here’s an example:

<DecentSampler>
    <groups>
        <group tags="hihat" silencedByTags="hihat" silencingMode="fast">
            <!-- Your samples go here. -->
        </group>
    </groups>
</DecentSampler>

Note the use of the silencingMode attribute as well (a value of “fast” means we immediately silence, whereas “normal” means we trigger the ADSR release phase).

Appendix F: How to implement true legato

Let’s walk through how to build a basic true legato instrument. Legato instruments generally consist of either two or three groups:

  1. First, there’s the initial looping sustain sample that will get played when the note is first pressed down.
  2. Then there is the legato transition sample that will get played when a second note gets pressed
  3. (optional) Depending on the implementation, there may be a third looping sustain group that gets played after the legato transition sample plays. In such cases, this third group usually contains the same samples as were used in group 1.

Step 1: Voice muting

Before we get into legato, let’s talk about voice muting. This is the behavior wherein one set of samples causes another set of samples to stop playing. This can be desirable in situations such as legato instruments where two samples should not be sounding at the same time.

In Decent Sampler, voice-muting makes use of tags. These are text labels that you can use to identify samples or groups of samples. You can add a silencedByTags attribute to groups or sample elements. This consists of a comma-separated list of tags that specify which samples should silence the current samples. When a sample with a tag matching one of the tags in the silencedByTags is played, it will silence the current sample (or group). Here’s an example:

<DecentSampler>
    <groups>
        <group tags="sustain" silencedByTags="legato" silencingMode="normal" release="1.0">
            <!-- Your sustain samples go here. -->
        </group>
        <group tags="legato" silencedByTags="legato" silencingMode="normal" release="1.0">
            <!-- Your legato samples go here. -->
        </group>
    </groups>
</DecentSampler>

In the above scenario, if a legato sample is matched, any sample that might be playing from the “sustain” group will be stopped.

It’s also worth mention the silencingMode attribute as well (a value of fast means we immediately silence that sample, whereas normal means we trigger the ADSR release phase).

Step 2: Legato

In order to specify which samples should be triggered first, we use the trigger attribute. This can that can be added to the <group> or individual <sample> tags. The default value is attack, but there are two useful new values:

Here is an example of how this might look in cunjunction with our example from above:

<DecentSampler>
    <groups>
        <group trigger="first" tags="sustain" silencedByTags="legato" silencingMode="normal" release="1.0">
            <!-- Your sustain samples go here. -->
        </group>
        <group trigger="legato" tags="legato" silencedByTags="legato" silencingMode="normal" release="1.0">
            <!-- Your legato samples go here. -->
        </group>
    </groups>
</DecentSampler>

Step 3: Specifying previous notes

When creating a legato instrument, it is often essential to limit which legato transition gets played based on which note we are transition from. This can be achieved using either the previousNote or the legatoInterval attributes. The previousNote attribute causes the engine to only play this sample if the previously triggered note matches the specified note. Example usage:

<sample path="Samples/LV_Legato_F2_G2.wav" rootNote="G2" loNote="G2" hiNote="G2" previousNote="F2" start="43000" />
<sample path="Samples/LV_Legato_G2_A2.wav" rootNote="A2" loNote="A2" hiNote="A2" previousNote="G2" start="43000" />

The legatoInterval attribute causes the engine to only play the sample if distance between the current note and the previously triggered note is exactly this semitone distance. For example, if the note for which this sample is being triggered is a C3 and the legatoInterval is set to -2, then the sample will only play if the previous note was a D3 because D3 minus two semitones equals C3.

Step 4: Polyphony

In legato instruments, it is sometimes useful to limit polyphony for a specific sample or set of samples. This is achieve using tags. At the top-level of your file, you can specify a element as follows:

<DecentSampler>
    <groups>
        <group tags="some-tag" >
            <!-- ... -->
        </group>
    </groups>
    <tags>
        <tag name="some-tag" polyphony="1" />
    </tags>
</DecentSampler>

Putting it all together

Here is a full example of a legato instrument:

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

<DecentSampler pluginVersion="1">
  <groups>
    <group tags="sustain" silencedByTags="legato" trigger="first"
           silencingMode="normal" release="0.3">
      <sample path="Samples/LV_Sustain_D3.wav" rootNote="D3" loNote="C3" hiNote="D3"/>
      <sample path="Samples/LV_Sustain_E3.wav" rootNote="E3" loNote="D#3" hiNote="E3"/>
      <!-- More samples go here -->
    </group>
    <group tags="legato" silencedByTags="legato" trigger="legato"
           silencingMode="normal" attack="0.1" decay="0.2" sustain="0" release="1">
              previousNote="C#3"/>
      <sample path="Samples/LV_Legato_D3_E3.wav" rootNote="E3" loNote="E3"
              hiNote="E3" start="43000" previousNote="D3"/>
      <sample path="Samples/LV_Legato_E3_F3.wav" rootNote="F3" loNote="F3"
              hiNote="F3" start="43000" previousNote="E3"/>
      <!-- More samples go here -->
    </group>
    <group tags="legato-tails" silencedByTags="legato-tails" trigger="legato"
           attack="0.3" silencingMode="normal" release="0.3" start="5000">
      <sample path="Samples/LV_Sustain_D3.wav" rootNote="D3" loNote="C3" hiNote="D3"/>
      <sample path="Samples/LV_Sustain_E3.wav" rootNote="E3" loNote="D#3" hiNote="E3"/>
      <!-- More samples go here -->
    </group>
  </groups>
</DecentSampler>