Unify Manual

Your complete reference to PlugInGuru's creative playground!

User Tools

Site Tools


patch-structure

Unify patch structure

The following information is supplied for the benefit of advanced users with programming experience interested in developing automated techniques to create “unified” patch libraries. For everyone else, please note there is a dedicated section of our online Forum where you can talk about new unified libraries you'd like to have, and share your thoughts about how you think such libraries should be structured.

If you're still reading at this point, please note we are not able to provide technical support for this on a widespread basis. If you are interested, and experienced with programming in C++, or at least Python, contact us at UnifySupport@PlugInGuru.com and we will put you in touch with a small group of other advanced users who may be able to assist.

Also, please note the following is not guaranteed to be 100% up-to-date (but let us know if you're sure it has become invalid).


Introduction

Unify patch files (.unify) are basically XML files, but they are stored as juce::MemoryBlock objects, so they have a small binary header containing a byte count before the XML, and a single zero byte after. Click here to download a couple of small Python scripts to convert `.unify` files to `.xml` and vice versa.

The rest of this document concentrates entirely on the XML structure inside `.unify` files.

Example Unify patch

Consider this simple Unify patch, which has one of every kind of layer:

You can download the .unify file for this patch, and the corresponding XML file shown at the bottom of this page, by clicking this link.

Basic patch structure

See the bottom of this page for a complete listing of the XML corresponding to the example patch shown above. The basic structure is a single UnifyPreset element, which contains lower-level elements as follows:

  • UnifyPreset
    • PresetMetadata (mandatory, always one)
    • bpmData (zero or one)
    • Layer (= INST layer, always at least one, maybe many)
    • MidiLane (= MIDI layer, zero or more)
    • AudioFxLane (= AUX or MASTER EFFECTS layer, always at least one, 1st is MASTER)
    • MacroParameter (8 of these in older patches, usually 32 in newer ones)

Because this is XML, every element can also have simple attributes that are attached to the element itself.

The PresetMetadata element contains the patch name, description, author, etc., all encoded using attributes.

Layers: Layer, MidiLane, AudioFxLane

The MidiLane, Layer, and AudioFxLane elements correspond to the MIDI, INST, and AUX/MASTER layers in the patch, respectively. They all have the same basic structure, based on that of Layer (the most complex):

  • Layer
    • Instrument (mandatory, always one)
    • MidiVelCurve (mandatory, always one)
    • MidiInserts (might be empty)
      • MidiEffect (zero or more)
    • AudioInserts (might be empty)
      • InsertEffect (zero or more)

MidiLane elements are the same, but contain only a MidiVelCurve and MidiInserts elements.

AudioFxLane elements contain only an AudioInserts element. Unify treats the first AudioFxLane element as the MASTER EFFECTS layer, which must always be present; hence there will always be at least one AudioFxLane element present, and there will be more if there are also any AUX layers.

Plug-ins: Instrument, MidiEffect, InsertEffect

Instrument, MidiEffect, and InsertEffect elements all represent individual plug-in instances.

They all contain a PLUGIN element, which specifies the plug-in to use, and a stateInformation text-attribute which stores the saved plug-in state (which Unify will restore with a call to juce::AudioPluginInstance::setStateInformation()). (For details about this and other JUCE function calls referenced here, see https://docs.juce.com/master/classAudioProcessor.html.)

stateInformation

When saving a patch, Unify calls juce::AudioPluginInstance::getStateInformation() on each plug-in instance, to get its current state, in the form of a juce::MemoryBlock object, then calls toBase64Encoding() on that juce::MemoryBlock, and puts the resulting base-64 encoded string into the stateInformation attribute of the Instrument, MidiEffect, or InsertEffect element representing that plug-in instance.

Example patch XML detail

The .zip file linked above contains the My Unify Patch.unify file and also the corresponding XML file, obtained by removing the header and trailer bytes and applying a “pretty print” algorithm to make it more legible. You can open it using any good syntax-coloring text editor (e.g. Notepad++, and it will look like this:

<?xml version="1.0" encoding="UTF-8"?>
 
<UnifyPreset formatVersion="0.3"
             showMidiLanes="1"
             globalTranspose="0"
             masterEffectsDisabled="0">
    <PresetMetadata formatVersion="0.1"
                    name="My Unify Patch"
                    library="User Library"
                    category="TEST"
                    tags="Tag1, Tag2, Tag3"
                    genre=""
                    author="Shane Dunne"
                    comment="This is a simple Unify patch, with one of each kind of layer."
                    hasBpmData="1"
                    masterFxLocked="0"/>
    <bpmData bpm="120.0"
             timeSigNumerator="4"
             timeSigDenominator="4"
             beatDivision="16"
             loopBarCount="0"
             triggerMode="1"
             followHost="0"
             lokey="0"
             hikey="127"/>
    <Layer layerTitle="My INST layer"
           mixLevel="1.0"
           panPos="0.5"
           muteState="1"
           midiDisabled="0"
           midiChannel="0"
           midiConvChannel="0"
           midiSourceIndex="0"
           lovel="0"
           hivel="127"
           keyOffset="0"
           inputBusIndex="-1"
           outputBusIndex="-1"
           lokey="0"
           hikey="127"
           loFadeKey="0"
           hiFadeKey="127"
           loFadeCurvature="0.0"
           hiFadeCurvature="0.0"
           latchEnabled="0"
           directSendLevel="1.0"
           fxSendLevel1="0.0"
           fxSendLevel2="0.0"
           fxSendLevel3="0.0"
           fxSendLevel4="0.0">
        <Instrument stateInformation="0."
                    currentProgram="0">
            <PLUGIN name="Sine Wave Synth"
                    format="Built-In"
                    category="Synth"
                    manufacturer="Built-In"
                    version="1.4.0"
                    file="Sine Wave Synth:"
                    uid="16fd76a8"
                    isInstrument="1"
                    fileTime="0"
                    infoUpdateTime="0"
                    numInputs="0"
                    numOutputs="2"
                    isShell="0"/>
        </Instrument>
        <MidiVelCurve>
            <Segment fxMin="0.0"
                     fxMax="1.0"
                     fyMin="0.0"
                     fyMax="1.0"
                     curvature="0.0"/>
        </MidiVelCurve>
        <MidiInserts/>
        <AudioInserts>
            <InsertEffect stateInformation="884.VMjLgr1....O+fWarAhckI2bo8la8HRLt.iHfTlai8FYo41Y8HRUTYTK3HxO9.BOO0VYmEFQkwVX44COPEjTA0DHoQVOhHFbsMUdtMlHfXWXrUWY8HRLt.iHu3COPEjTA0DHoQVOhLFZuIWcyYTYkQlXgM1Zh.hcgwVck0iHv3BLh7hO7.UPRETSfjFY8HxXn8lb0MWSuQFQkAGcnIBH1EFa0UVOhHCLt.iHu3COPEjTA0DHoQVOhLFZuIWcy0zajYjbkEmHfXWXrUWY8HRLt.iHu3COPEjTA0DHoQVOhLFZuIWcy0zajUlHfXWXrUWY8HBLt.iHu3COPEjTA0DHoQVOhLFZuIWcycUYz0TZ3IBH1EFa0UVOhTCLt.iHu3COPEjTA0DHoQVOhPVYrEVdTkVakwjHfXWXrUWY8HBLtTiL2DSM3jyM0XCLwDSN1LiHu3COPEjTA0DHoQVOhPVYrEVdTkVakIkHfXWXrUWY8HBLtXiLyDSM2jyM3.SM2fiMwLiHu3COPEjTA0DHoQVOhPVZyQGQxklckIBH1EFa0UVOh.iKvHxK9vCTAIUPMARZj0iHjk1bzcTXo4lHfXWXrUWY8HBLt.iHu3COPEjTA0DHoQVOhPVZyQ2TzIWYtcFcnIBH1EFa0UVOh.iKvHxK9vCTAIUPMARZj0iHjk1bzQUdvUlHfXWXrUWY8HBLt.iHu3COPEjTA0DHoQVOhPlboYFcA01a04Fch.hcgwVck0iHv3BLh7hO7.UPRETSfjFY8HBYxk2UkQWSogmHfXWXrUWY8HRMv3BLh7hO7.UPRETSfjFY8HhYhwTYlQmHfXWXrUWY8HhLv3BLh7hO7.UPRETSfjFY8HhYh0zajUlHfXWXrUWY8HBLt.iHu3COPEjTA0DHoQVOhXlXRk1YnQmHfXWXrUWY8HhLv3BLh7hO7.UPRETSfjFY8HhYowFckImQxUVbh.hcgwVck0iH4jSN43RN4jCLxLCMybSMh7hO7.UPRETSfjFY8HhYowFckI2Qgklah.hcgwVck0iHv3BLh7hO7.UPRETSfjFY8HhYowFckIWTh.hcgwVck0iHv3xMvbCLv.CLwbSL1XSLybyMh7hO7.UPRETSfjFY8HhYowFckIGU4AWYh.hcgwVck0iHv3BLh7hO77xSsU1YgQTYrEVd9.."
                          currentProgram="0"
                          isBypassed="0"
                          allowMidiIn="0">
                <PLUGIN name="Omega Delay"
                        format="Built-In"
                        category="Effect"
                        manufacturer="Built-In"
                        version="1.4.0"
                        file="Omega Delay:"
                        uid="86367dc4"
                        isInstrument="0"
                        fileTime="0"
                        infoUpdateTime="0"
                        numInputs="2"
                        numOutputs="2"
                        isShell="0"/>
            </InsertEffect>
        </AudioInserts>
    </Layer>
    <MidiLane title="My MIDI layer"
              lokey="0"
              hikey="127"
              loFadeKey="0"
              hiFadeKey="127"
              loFadeCurvature="0.0"
              hiFadeCurvature="0.0"
              lovel="0"
              hivel="127"
              keyOffset="0"
              midiChannel="0"
              midiConvChannel="0"
              midiSourceIndex="-1"
              latchEnabled="0">
        <MidiVelCurve>
            <Segment fxMin="0.0"
                     fxMax="1.0"
                     fyMin="0.0"
                     fyMax="1.0"
                     curvature="0.0"/>
        </MidiVelCurve>
        <MidiInserts>
            <InsertEffect stateInformation="326.VMjLgzS....O+fWarAhckI2bo8la8HRLt.iHfTlai8FYo41Y8HRUTYTK3HxO9.BOMkFYoYTZrQWYxABausVY40iHvHBHnk1ZkkWOhDiL2HBHskFYoMDZg4lakwVOh.iHfL1atY2PnElatUFa8HBLh.BcxElayA2ayU1SlY1bkQWOh.iHfLWcyQWXo4VSuQVY8HBLh.xb0AGbxU1by0TcrQWZvwVYN8Fck8jay0iHvHBHyUGbvIWYyMGToQ2XnITYtQVOh.iHfLWcvAmbkM2bAYFckIGUuU2Xn0iHvHBHyUGbvIWYyM2PCASOhzRLh.xb0AGbxU1byMzPwziHsDiHfLWcvAmbkM2bCMjL8HRKwHBHyUGbvIWYyM2PCMSOhzRLh.xb0AGbxU1byMzPzziHsDiHfLWcvAmbkM2bCMTM8HRKwHxK9.."
                          currentProgram="0"
                          isBypassed="0">
                <PLUGIN name="MIDI Filter"
                        format="Built-In"
                        category="MidiEffects"
                        manufacturer="Built-In"
                        version="1.4.0"
                        file="MIDI Filter:"
                        uid="8d536d77"
                        isInstrument="0"
                        fileTime="0"
                        infoUpdateTime="0"
                        numInputs="0"
                        numOutputs="0"
                        isShell="0"/>
            </InsertEffect>
        </MidiInserts>
    </MidiLane>
    <AudioFxLane title=""
                 mixLevel="1.0"
                 panPos="0.5"
                 muteState="1"
                 inputBusIndex="-1"
                 outputBusIndex="0">
        <AudioInserts>
            <InsertEffect stateInformation="228.CMlaKA....fQ3IzZ....AvDYMgG...P.....A...........................................................................................................................................................................CMlaKA....fQ3MzZ....AvDYMgG...P.....DPTYlEVcrQG...........................vOjIgm+.H.......vO.B.."
                          currentProgram="0"
                          isBypassed="0"
                          allowMidiIn="0">
                <PLUGIN name="LoudMax"
                        descriptiveName="LoudMax 64bit"
                        format="VST"
                        category="Effect"
                        manufacturer="Thomas Mundt"
                        version="1.2.7.0"
                        file="/Users/AW/Documents/Unify/VST/LoudMax.vst"
                        uid="4c644d78"
                        isInstrument="0"
                        fileTime="169968a1690"
                        infoUpdateTime="16cb5945d42"
                        numInputs="2"
                        numOutputs="2"
                        isShell="0"/>
            </InsertEffect>
        </AudioInserts>
    </AudioFxLane>
    <AudioFxLane title="My AUX layer"
                 mixLevel="1.0"
                 panPos="0.5"
                 muteState="1"
                 inputBusIndex="-1"
                 outputBusIndex="-1">
        <AudioInserts>
            <InsertEffect stateInformation="182.VMjLgzJ....O+fWarAhckI2bo8la8HRLt.iHfTlai8FYo41Y8HRUTYTK3HxO9.BOWEFckImUkImX9vCTAIUPMARZj0iHjIWdWUFcMkFdh.hcgwVck0iH0.iKvHxK9vCTAIUPMARZj0iHlUVYjIVXislHfXWXrUWY8HxMv3BLh7hO7.UPRETSfjFY8HhYowFckImQxUVbh.hcgwVck0iHw.CLv.iKvHxK9vyKWEFckImUkImX9.."
                          currentProgram="0"
                          isBypassed="0"
                          allowMidiIn="0">
                <PLUGIN name="WaterVerb"
                        format="Built-In"
                        category="Effect"
                        manufacturer="Built-In"
                        version="1.4.0"
                        file="WaterVerb:"
                        uid="6aaf22b6"
                        isInstrument="0"
                        fileTime="0"
                        infoUpdateTime="0"
                        numInputs="2"
                        numOutputs="2"
                        isShell="0"/>
            </InsertEffect>
        </AudioInserts>
    </AudioFxLane>
    <MacroParameter id="macro1"
                    name="Macro1"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="0"/>
    <MacroParameter id="macro2"
                    name="Macro2"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="1"/>
    <MacroParameter id="macro3"
                    name="Macro3"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="2"/>
    <MacroParameter id="macro4"
                    name="Macro4"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="3"/>
    <MacroParameter id="macro5"
                    name="Macro5"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="4"/>
    <MacroParameter id="macro6"
                    name="Macro6"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="5"/>
    <MacroParameter id="macro7"
                    name="Macro7"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="6"/>
    <MacroParameter id="macro8"
                    name="Macro8"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="7"/>
    <MacroParameter id="macro9"
                    name="Macro9"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="8"/>
    <MacroParameter id="macro10"
                    name="Macro10"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="9"/>
    <MacroParameter id="macro11"
                    name="Macro11"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="10"/>
    <MacroParameter id="macro12"
                    name="Macro12"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="11"/>
    <MacroParameter id="macro13"
                    name="Macro13"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="12"/>
    <MacroParameter id="macro14"
                    name="Macro14"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="13"/>
    <MacroParameter id="macro15"
                    name="Macro15"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="14"/>
    <MacroParameter id="macro16"
                    name="Macro16"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="15"/>
    <MacroParameter id="macro17"
                    name="Macro17"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="16"/>
    <MacroParameter id="macro18"
                    name="Macro18"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="17"/>
    <MacroParameter id="macro19"
                    name="Macro19"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="18"/>
    <MacroParameter id="macro20"
                    name="Macro20"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="19"/>
    <MacroParameter id="macro21"
                    name="Macro21"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="20"/>
    <MacroParameter id="macro22"
                    name="Macro22"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="21"/>
    <MacroParameter id="macro23"
                    name="Macro23"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="22"/>
    <MacroParameter id="macro24"
                    name="Macro24"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="23"/>
    <MacroParameter id="macro25"
                    name="Macro25"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="24"/>
    <MacroParameter id="macro26"
                    name="Macro26"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="25"/>
    <MacroParameter id="macro27"
                    name="Macro27"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="26"/>
    <MacroParameter id="macro28"
                    name="Macro28"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="27"/>
    <MacroParameter id="macro29"
                    name="Macro29"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="28"/>
    <MacroParameter id="macro30"
                    name="Macro30"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="29"/>
    <MacroParameter id="macro31"
                    name="Macro31"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="30"/>
    <MacroParameter id="macro32"
                    name="Macro32"
                    unit=""
                    value="0.0"
                    minValue="0.0"
                    maxValue="1.0"
                    valueStep="0.0"
                    defaultValue="0.0"
                    index="31"/>
</UnifyPreset>
patch-structure.txt · Last modified: 2021/09/02 22:03 (external edit)