-
-
Notifications
You must be signed in to change notification settings - Fork 103
XML file format documentation
Below is a reasonably in-depth example of a Deluge song’s XML file, with comments explaining the purpose of the various tags and attributes. Please feel free to expand!
<?xml version="1.0" encoding="UTF-8"?>
<song
firmwareVersion="3.0.0-beta" // The firmware version this file was saved with
earliestCompatibleFirmware="3.0.0-beta" // The earliest firmware version which is able to read this file
previewNumPads="144" // This will always be 144 for the 144-pad production-model Deluge
// Hexadecimal representation of the preview-image for the song. Each 2 characters is one 0-255 number.
// Each "pixel" is 3 such numbers (R, G and B), so 6 characters. Goes from left to right, bottom to top, one row at a time
preview="00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080156500000000000000000000000000000001000100000001000100000001000005000400000000000000000000000000FF06005AA500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF06005AA5F0000FFC0003E60019E60019F0000FF0000F000000E60019B0004FFC0003B0004FF0000FB0004F00000000000000000000FF06005AA5"
arrangementAutoScrollOn="0" // Whether "follow" is switched on for arranger
// Current scroll and zoom, for clips and song view
xScroll="0"
xZoom="12"
yScrollSongView="-5"
// Current scroll and zoom, for arranger
yScrollArrangementView="-6"
xScrollArrangementView="0"
xZoomArrangementView="96"
// These represent the tempo, in a roundabout way.
timePerTimerTick="459" // The length of a “tick” at the song’s “resolution” (see below), in individual audio samples at 44.1kHz
timerTickFraction="1610612736" // The “after the decimal point” part of the above number,
// if one were to convert it to an unsigned 32-bit int and treat it as a fraction out of 2^32
inputTickMagnitude="1" // The song’s resolution is 96 * 2 ^ inputTickMagnitude.
// E.g.
// “0” would mean 96th-notes.
// “1” would mean 192nd-notes - this is usual for songs created before V3.1.x
// “2” would mean 384th-notes - this is the default for songs created since V3.1.x
// Can also be thought of as “the number of times you have to double the resolution of
// MIDI beat clock to get to the song’s resolution”.
rootNote="0" // MIDI note
swingAmount="0" // Swing. 0 means off. Range is -50 to 50
swingInterval="7" // As editable in the settings menu
affectEntire="0" // Affect-entire, at the song level
activeModFunction="1" // Which mod knob function is active, at song level. 0 to 7
// These are all at the song-level
lpfMode="24dB"
modFXType="flanger" // flanger, chorus, phaser
modFXCurrentParam="feedback"
currentFilterType="lpf">
// The notes making up the current scale / mode. Relative to the root note. Numbers between 0 and 11
<modeNotes>
<modeNote>0</modeNote>
<modeNote>2</modeNote>
<modeNote>4</modeNote>
<modeNote>5</modeNote>
<modeNote>7</modeNote>
<modeNote>9</modeNote>
<modeNote>11</modeNote>
</modeNotes>
<reverb
roomSize="1288490496"
dampening="1546188288"
width="2147483647"
pan="0">
// The sidechain compressor settings to be applied to the reverb.
// If "volume" is a negative number, then these will not apply, and instead the Deluge will
// apply the sidechain settings of the sound which has the most reverb. This is discussed in the manual
<compressor
attack="-1555122208"
release="1090618117"
volume="-21474836"
shape="-601295438"
syncLevel="6" />
</reverb>
<delay
pingPong="1"
analog="0"
syncLevel="7" />
<compressor // Unused - there is no sidechain compressor at the song level.
syncLevel="6"
attack="327244"
release="936" />
// The FX params at the song level - including automation in arranger
<songParams
reverbAmount="0x80000000"
volume="0x3504F334"
pan="0x00000000"
sidechainCompressorShape="0xDC28F5B2"
modFXDepth="0x00000000"
modFXRate="0xE0000000"
stutterRate="0x00000000"
sampleRateReduction="0x80000000"
bitCrush="0x80000000"
modFXOffset="0x00000000"
modFXFeedback="0x80000000">
<delay
rate="0x00000000"
feedback="0x80000000" />
<lpf
frequency="0x7FFFFFFF"
resonance="0x80000000" />
<hpf
frequency="0x80000000"
resonance="0x80000000" />
<equalizer
bass="0x00000000"
treble="0x00000000"
bassFrequency="0x00000000"
trebleFrequency="0x00000000" />
</songParams>
// A complete list of all instruments, or "tracks" as seen as rows in arranger.
// The various types are shown below.
// This was different before V2.0
<instruments>
// Note: if any "instrument" listed here does not have any clips anywhere, then it must have
// a <defaultParams> tag,
// containing the data that would normally exist in the <soundParams> or <kitParams> tag inside a clip.
// Such param data is normally stored at the clip level so that params may
// be automated, and may be different
// between different clips
// A V3.0-style audio track, which can contain audio clips.
<audioTrack
name="AUDIO1"
inputChannel="left"
isArmedForRecording="0"
lpfMode="24dB"
modFXType="flanger"
modFXCurrentParam="feedback"
currentFilterType="lpf">
<delay
pingPong="1"
analog="0"
syncLevel="7" />
<compressor
syncLevel="6"
attack="327244"
release="936" />
</audioTrack>
// A "CV" instrument
<cvChannel
channel="0"
isArmedForRecording="0" />
// A "MIDI" instrument
<midiChannel
channel="0"
suffix="-1"
isArmedForRecording="0" />
// A "synth", including sample-based or multi-sampled melodic instruments
<sound
presetSlot="0" // Preset number
presetSubSlot="-1" // Preset suffix letter, as a number. -1 means no suffix.
//0 means A - thru 25 means Z.
// -- or --
name="Square lead" // As of V3.0, a name can be specified here in place of the previous two tags
isArmedForRecording="0"
polyphonic="poly"
voicePriority="1"
mode="subtractive"
transpose="-12"
lpfMode="24dB"
modFXType="none">
<osc1
type="saw"
transpose="0"
cents="0"
retrigPhase="-1" />
<osc2
type="square"
transpose="-12"
cents="0"
retrigPhase="-1" />
<lfo1 type="sine" syncLevel="0" />
<lfo2 type="sine" />
<unison num="4" detune="10" />
<compressor
syncLevel="6"
attack="327244"
release="936" />
<delay
pingPong="1"
analog="1"
syncLevel="7" />
// List of what the gold knobs control. For each gold knob, for each pair of "functions".
// Starting from bottom left, then top left, then progressing right-wards
<modKnobs>
<modKnob controlsParam="pan" />
<modKnob controlsParam="volumePostFX" />
<modKnob controlsParam="lpfResonance" />
<modKnob controlsParam="lpfFrequency" />
<modKnob controlsParam="env1Release" />
<modKnob controlsParam="env1Attack" />
<modKnob controlsParam="delayFeedback" />
<modKnob controlsParam="delayRate" />
<modKnob controlsParam="reverbAmount" />
<modKnob controlsParam="volumePostReverbSend" patchAmountFromSource="compressor" />
// If the knob in fact controls modulation depth from a modulation source to the
// listed param, that's expressed like this, with the modulation source
// specified in "patchAmountFromSource"
<modKnob controlsParam="pitch" patchAmountFromSource="lfo1" />
<modKnob controlsParam="lfo1Rate" />
<modKnob controlsParam="portamento" />
<modKnob controlsParam="stutterRate" />
<modKnob controlsParam="oscBVolume" />
<modKnob controlsParam="oscBPhaseWidth" />
</modKnobs>
</sound>
// A Kit
<kit
presetSlot="43" // Preset number
presetSubSlot="-1" // Preset suffix letter, as a number.
// -1 means no suffix. 0 means A - thru 25 means Z.
isArmedForRecording="0"
lpfMode="24dB"
modFXType="flanger"
modFXCurrentParam="feedback"
currentFilterType="lpf">
<delay
pingPong="1"
analog="0"
syncLevel="7" />
<compressor
syncLevel="6"
attack="327244"
release="936" />
<soundSources> // The various sounds / items within the Kit. Examples of each are shown below
// A MIDI note output
<midiOutput channel="0" note="0">
</midiOutput>
// A gate output
<gateOutput channel="2">
</gateOutput>
// A synth / sample
<sound
name="befall" // The name that displays when you hold down an audition pad
polyphonic="auto"
voicePriority="1"
mode="subtractive"
lpfMode="24dB"
modFXType="none">
<osc1
type="sample"
loopMode="0"
reversed="0"
timeStretchEnable="0"
timeStretchAmount="0"
fileName="SAMPLES/Artists/Andrew Stirton/Frugal/befall.wav">
<zone
startSamplePos="0"
endSamplePos="129379" />
</osc1>
<osc2
type="sample"
loopMode="0"
reversed="0"
timeStretchEnable="0"
timeStretchAmount="0">
</osc2>
<lfo1 type="triangle" syncLevel="0" />
<lfo2 type="triangle" />
<unison num="1" detune="8" />
<compressor
syncLevel="6"
attack="327244"
release="936" />
<delay
pingPong="1"
analog="0"
syncLevel="7" />
<arpeggiator
mode="off"
numOctaves="2"
syncLevel="7" />
<modKnobs>
// Same as in example above of a synth-instrument
</modKnobs>
</sound>
</soundSources>
<selectedDrumIndex>0</selectedDrumIndex>
</kit>
</instruments>
<sections> // Always contains all 12 song-sections, specifying important attributes of each
<section id="0" numRepeats="0" />
<section id="1" numRepeats="0" />
<section id="2" numRepeats="0" />
<section id="3" numRepeats="0" />
<section id="4" numRepeats="0" />
<section id="5" numRepeats="0" />
<section id="6" numRepeats="0" />
<section id="7" numRepeats="0" />
<section id="8" numRepeats="0" />
<section id="9" numRepeats="0" />
<section id="10" numRepeats="0" />
<section id="11" numRepeats="0" />
</sections>
// FKA "<tracks>". Contains all session clips in the order that they appear from bottom to top in "song view"
<sessionClips>
// New V3.0-style audio clip
<audioClip
trackName="AUDIO1"
filePath="SAMPLES/CLIPS/REC00150.WAV"
startSamplePos="2086" // In audio samples
endSamplePos="90286" // In audio samples
pitchSpeedIndependent="1"
attack="-1546188233"
priority="1"
isPlaying="1"
isSoloing="0"
isArmedForRecording="1"
length="192"
colourOffset="11"
section="0"
selected="1">
<params
reverbAmount="0x80000000"
volume="0xE0000000"
pan="0x00000000"
sidechainCompressorShape="0xDC28F5B2"
modFXDepth="0x00000000"
modFXRate="0xE0000000"
stutterRate="0x00000000"
sampleRateReduction="0x80000000"
bitCrush="0x80000000"
modFXOffset="0x00000000"
modFXFeedback="0x80000000">
<delay
rate="0x00000000"
feedback="0x80000000" />
<lpf
frequency="0x7FFFFFFF"
resonance="0x80000000" />
<hpf
frequency="0x80000000"
resonance="0x80000000" />
<equalizer
bass="0x00000000"
treble="0x00000000"
bassFrequency="0x00000000"
trebleFrequency="0x00000000" />
</params>
</audioClip>
// An instrument clip, which we used to called a "<track>" before V3.0.
// This example instrument clip is for a kit.
<instrumentClip
yScroll="0"
affectEntire="0"
// Instrument details, with which to load the instrument
// already specified in the <instruments> tag, detailed above
instrumentPresetSlot="43"
instrumentPresetSubSlot="-1"
isPlaying="1"
isSoloing="0"
isArmedForRecording="1"
length="384"
colourOffset="66"
section="0">
// Params for the assigned kit instrument - specific to (and automatable within) this clip
<kitParams
reverbAmount="0x80000000"
volume="0x3504F334"
pan="0x00000000"
sidechainCompressorShape="0xDC28F5B2"
modFXDepth="0x00000000"
modFXRate="0xE0000000"
stutterRate="0x00000000"
sampleRateReduction="0x80000000"
bitCrush="0x80000000"
modFXOffset="0x00000000"
modFXFeedback="0x80000000">
<delay
rate="0x00000000"
feedback="0x80000000" />
<lpf
frequency="0x7FFFFFFF"
resonance="0x80000000" />
<hpf
frequency="0x80000000"
resonance="0x80000000" />
<equalizer
bass="0x00000000"
treble="0x00000000"
bassFrequency="0x00000000"
trebleFrequency="0x00000000" />
</kitParams>
<noteRows> // Here's how this looks for a "kit" - it's a little different for "synth" sounds
<noteRow
colourOffset="53" // Only for kits is this specified at the note-row level
drumIndex="0" // Only for kits. The index (numbered from 0) of the
// drum/item/sound within the kit,
// as counted from the top of the <soundSources> tag in the
// <kit>. Sorry, I realise
// order isn't suppose to matter in XML files
noteData="0x000000300000000C4014" />
// Only for kits, each note-row whose kit-item is a synth/sound/sample must specify
// params for that
// sound. Potentially including automation
<soundParams
arpeggiatorGate="0x00000000"
portamento="0x80000000"
compressorShape="0xDC28F5B2"
oscAVolume="0x7FFFFFFF"
oscAPulseWidth="0x00000000"
oscBVolume="0x80000000"
oscBPulseWidth="0x00000000"
noiseVolume="0x80000000"
volume="0x4CCCCCA8"
pan="0x00000000"
lpfFrequency="0x7FFFFFFF"
lpfResonance="0x80000000"
hpfFrequency="0x80000000"
hpfResonance="0x80000000"
lfo1Rate="0x1999997E"
lfo2Rate="0x00000000"
modulator1Amount="0x80000000"
modulator1Feedback="0x80000000"
modulator2Amount="0x80000000"
modulator2Feedback="0x80000000"
carrier1Feedback="0x80000000"
carrier2Feedback="0x80000000"
modFXRate="0x00000000"
modFXDepth="0x00000000"
delayRate="0x00000000"
delayFeedback="0x80000000"
reverbAmount="0x80000000"
arpeggiatorRate="0x00000000"
stutterRate="0x00000000"
sampleRateReduction="0x80000000"
bitCrush="0x80000000"
modFXOffset="0x00000000"
modFXFeedback="0x00000000">
<envelope1
attack="0x80000000"
decay="0xE6666654"
sustain="0x7FFFFFD2"
release="0x80000000" />
<envelope2
attack="0xE6666654"
decay="0xE6666654"
sustain="0xFFFFFFE9"
release="0xE6666654" />
<patchCables>
<patchCable
source="velocity"
destination="volume"
amount="0x3FFFFFE8" />
</patchCables>
<equalizer
bass="0x00000000"
treble="0x00000000"
bassFrequency="0x00000000"
trebleFrequency="0x00000000" />
</soundParams>
</noteRow>
</noteRows>
</instrumentClip>
// This instrument clip is for a "synth" sound
<instrumentClip
inKeyMode="1" // Whether it's locked to the scale
yScroll="35"
yScrollKeyboard="50"
instrumentPresetSlot="0"
instrumentPresetSubSlot="-1"
isPlaying="1"
isSoloing="0"
isArmedForRecording="1"
length="192"
colourOffset="-60"
section="0">
// Params for the assigned synth instrument - specific to (and automatable within) this clip
<soundParams
arpeggiatorGate="0x00000000"
portamento="0x80000000"
compressorShape="0xDC28F5B2"
oscAVolume="0x7FFFFFFF"
oscAPulseWidth="0x00000000"
oscBVolume="0x47AE1457"
oscBPulseWidth="0x00000000"
noiseVolume="0x80000000"
volume="0x7FFFFFFF"
pan="0x00000000"
lpfFrequency="0x10000000"
lpfResonance="0xA2000000"
hpfFrequency="0x80000000"
hpfResonance="0x80000000"
lfo1Rate="0x1999997E"
lfo2Rate="0x00000000"
modulator1Amount="0x80000000"
modulator1Feedback="0x80000000"
modulator2Amount="0x80000000"
modulator2Feedback="0x80000000"
carrier1Feedback="0x80000000"
carrier2Feedback="0x80000000"
modFXRate="0x00000000"
modFXDepth="0x00000000"
delayRate="0x00000000"
delayFeedback="0x80000000"
reverbAmount="0x80000000"
arpeggiatorRate="0x00000000"
stutterRate="0x00000000"
sampleRateReduction="0x80000000"
bitCrush="0x80000000"
modFXOffset="0x00000000"
modFXFeedback="0x00000000">
<envelope1
attack="0x80000000"
decay="0xE6666654"
sustain="0x7FFFFFFF"
release="0x851EB851" />
<envelope2
attack="0xA3D70A37"
decay="0xA3D70A37"
sustain="0xFFFFFFE9"
release="0xE6666654" />
<patchCables>
<patchCable
source="velocity"
destination="volume"
amount="0x3FFFFFE8" />
<patchCable
source="envelope2"
destination="lpfFrequency"
amount="0x1C28F5B8" />
<patchCable
source="note"
destination="lpfFrequency"
amount="0x08F5C28C" />
<patchCable
source="velocity"
destination="lpfFrequency"
amount="0x0F5C28F0" />
</patchCables>
<equalizer
bass="0x00000000"
treble="0x00000000"
bassFrequency="0x00000000"
trebleFrequency="0x00000000" />
</soundParams>
<noteRows> // Here's how this looks for a "synth" - it's a little different for "kits"
<noteRow
y="60" // The MIDI note number for this row
noteData="0x000000300000000C4014" />
<noteRow
y="62"
noteData="0x0000000C0000000C4014000000240000000C40140000006C0000000C4014" />
<noteRow
y="64"
noteData="0x000000000000000C4014000000300000000C40140000003C0000000C4014000000780000000C4014000000840000000C4014000000900000000C4014" />
<noteRow
y="65"
noteData="0x000000180000000C4014000000240000000C4014000000540000000C4014" />
<noteRow
y="67"
noteData="0x000000600000000C4014" />
<noteRow
y="69"
noteData="0x000000600000000C4014000000780000000C4014000000900000000C4014" />
</noteRows>
</instrumentClip>
</sessionClips>
</song>
All note events for a given pitch are grouped together. For example:
The attribute “y” encodes the note value in accord with the Midi standard. The noteData encodes information about the starting time and duration of the notes in the track with that pitch.
Each note event is 20 hexadecimal digits long. All notes the digits in noteData must be either 0-9 or A-F (uppercase only).
Starting with the leftmost digit as digit 0:
Digits 0-7 encodes the start time of the note in beat units. Digits 8-15 encode the duration of the note in beat units. Digits 16-17 encode the velocity of the note (0-127). Digits 18-19 are the “condition code” for the note.
To interpret a condition code, you need to ignore the “high order bit for a moment. This is done via: let code = conditionByte & 0x7F.
The condition codes are:
Less than 0x14 hex, it is a probability of the note sounding in units of 5%. If it is 0x14, then its a normal note. If it is greater than 0x15, then the note is X time out of Y times by, according to the table below:
14 1 out of 1 times thru
15 1 out of 2 times thru
16 2 out of 2 times thru
17 1 out of 3 times thru
18 2 out of 3 times thru
19 3 out of 3 times thru
1A 1 out of 4 times thru
1B 2 out of 4 times thru
1C 3 out of 4 times thru
1D 4 out of 4 times thru
1E 1 out of 5 times thru
1F 2 out of 5 times thru
20 3 out of 5 times thru
21 4 out of 5 times thru
22 5 out of 5 times thru
23 1 out of 6 times thru
24 2 out of 6 times thru
25 3 out of 6 times thru
26 4 out of 6 times thru
27 5 out of 6 times thru
28 6 out of 6 times thru
29 1 out of 7 times thru
2A 2 out of 7 times thru
2B 3 out of 7 times thru
2C 4 out of 7 times thru
2D 5 out of 7 times thru
2E 6 out of 7 times thru
2F 7 out of 7 times thru
30 1 out of 8 times thru
31 2 out of 8 times thru
32 3 out of 8 times thru
33 4 out of 8 times thru
34 5 out of 8 times thru
35 6 out of 8 times thru
36 7 out of 8 times thru
37 8 out of 8 times thru
If the high order bit of the condition code is set, the note is “dotted”, which means the note is activated only if an earlier note with the same probability was not activated. (Actually the rules for the high order bit flag are a more complicated than that, RTFM).
noteData="0x000000000000000C4014000000300000000C4014
- 0x // ignore 0x
- First note:
- 00000000 // start at time 0
- 0000000C // 12 beat units long (a 16th note)
- 40 // velocity = 64
- 14 // always play
- Second note:
- 00000030 // start at time 48 (second quarter note in bar)
- 0000000C // 12 units long (a 16th note)
- 40 // velocity = 64
- 14 // always play
Starting with version 4.0.0, Rohan added another field to the note encoding scheme. This is a release-velocity value, also 0-127.
Data encoded with this extra field is stored under the noteDataWithLift attribute instead of the noteData attribute. The addition occurs just after the velocity field and thus moves the condition code information forward one byte.
The modified note event scheme is:
Digits 0-7 encodes the start time of the note in beat units. Digits 8-15 encode the duration of the note in beat units. Digits 16-17 encode the velocity of the note (0-127). Digits 18-19 encode the release-velocity for the note. Digits 20-21 are the “condition code” for the note.
I created a spreadsheet describing the various parameter values used in the Deluge XML format. You can view it at https://docs.google.com/spreadsheets/d/1ag6yWUS6tJw3BRG9Ejs5ItM_YSq4r47SFzaebH8hH7g/edit?usp=sharing.
Parameter values are encoded in a number of different ways in the Deluge XML format. As I discovered the schemes, I gave them names which are used in the Downrush program for formatting, and in the parameter database I created under the “Format” heading. Rohan Hill probably calls them something else!
The most common format is fixh, which means “fixed point hexadecimal”. The value starts with “0x” and is followed by 8 hexadecimal digits. The lowest possible value is “negative zero”, or 0x80000000 (or -2147483648, the middle value is 0x00000000, or “actual zero”, and the highest possible value is 0x7FFFFFFF, which corresponds to 2147483647.
On the 4 digit display of the Deluge, a fixh value appears as a number between 0 and 50. Why is this so? It turns out computers are very fast at computing with numbers between -2147483648 and 2147483647, much faster than computing with numbers that have a digits to the right of the decimal point (called floating point numbers). A common technique is to scale up a number with a smaller range so that it spans a larger range, with the added numbers in between represents a fractional amount. (A common example is computing dollars in units of pennies).
In the case of the fixh format, we are scaling the range 0 to 50 to fully occupy the range -2147483648 to 2147483647. -2147483648 (0x80000000) corresponds to display value 0, 0x00000000 corresponds to display value 25, and 2147483647 (0x7FFFFFFF) corresponds to display value 50.
Another scheme is called “fixpan”, which is used to represent panning from -32 Left to +32 Right. It also uses the normalized fixed point scheme with -25L as 0x80000000 and +25R as 0x7FFFFFFF.
Additional schemes and how they map:
fixphase maps 0x80000000 to 0 degrees, 0x7FFFFFFF to 360 degrees, with “all ones” 0xFFFFFFFF meaning “Off”.
fixpos50 maps 0x00000000 to 0, 0x7FFFFFFF to the range 0 to 50 (ignoring the negative side).
fixrev converts a decimal number (which does not start with 0x), from between 0 and 2147483647 into the range 0 to 50.
fmtMidiCC maps 0x80000000 to 0, 0x7FFFFFFF to 127.
fmtonoff converts the number 0x00000000 to the letters “OFF”, and anything else to “ON”.
fmtprior maps the numbers 0, 1, & 2 to “low”, “medium”, and “high”.
fmtscattack and fmtscrelease converts from a nonlinear range of integer values into a range of 0-50 using a lookup table as shown in the FmtSound.js file in Downrush.
fmtsync converts a number between 0 and 9 into a “sync level” string as follows: var syncLevelTab = ["off", "4 bars", "2 bars", "1 bar", "2nd", "4th", "8th", "16th", "32nd", "64th"];
fmttime displays a value in milliseconds as fractional seconds.
fmttransp formats a transposition factor and value in cents into fractional half-steps (with cents after the decimal point).
fmtinterp formats the linearInterpolation flag as follows: 0 (or no value at all) means use SINC interpolation, while a value of 1 means use LINE (linear) interpolation.