SoundHelix is configured by providing a SoundHelix XML file and by starting SoundHelix with such a file.
SoundHelix XML files must follow the following basic XML structure:
<?xml version="1.0"?> <SoundHelix version="version"> <songNameEngine class="SongNameEngine-class"> ... </songNameEngine> <structure> <bars>...</bars> <beatsPerBar>...</beatsPerBar> <ticksPerBeat>...</ticksPerBeat> <maxVelocity>...</maxVelocity> </structure> <harmonyEngine class="HarmonyEngine-class"> ... </harmonyEngine> <arrangementEngine class="ArrangementEngine-class"> ... </arrangementEngine> <player class="Player-class"> ... </player> </SoundHelix>
In the optional "version" attribute of the <SoundHelix> tag you can specify the SoundHelix application version that is required for the XML file. If you use a specific version in the attribute (e.g., "0.0.4.4"), then the XML file can only be used with exactly that version of SoundHelix (which is normally a bad idea). If you append a plus character behind the version ("0.0.4.4+"), then the XML file can be used with that version or any later version. For comparing versions, the version string is split at dots and the resulting numbers are compared from left to right until the first difference is encountered (e.g., "0.0.4" < "0.0.4.1" < "0.0.5" < "0.1" < "0.9" < "0.11" < "1.0"). A more complex syntax (e.g., version ranges or version alternatives) in the attribute may be supported in the future. The "version" attribute is supported since SoundHelix 0.0.4.2.
The "maxVelocity" tag is supported since version 0.7. It allows you to specify the value of the maximum velocity in the song. This is the velocity used when you don't specify a velocity. It is also the maximum velocity used when a player converts the SoundHelix velocity into (e.g.) MIDI velocity. Prior to version 0.7, this value was always 32767, but you can choose a different (more convenient) value if you like, e.g., 100 or 1000. Note that changing this value in an XML file will have a major impact on the rest of the configuration, where velocities are specified in pattern or other configuration tags. If the "maxVelocity" tag is not provided, 32767 will be used for backwards compatibility.
Each time you encounter a tag with a "class" attribute you must specify in this attribute which implementation of the corresponding component to use. If you specify a fully-qualified class name (FQCN) here, SoundHelix will try to instantiate the given class, which must be available on the classpath and must implement the correct interface. For example, the
<harmonyEngine> tag requires a class that implements the
com.soundhelix.harmonyengine.HarmonyEngine interface. If the implementing class is in the same package as the interface (or, starting from version 0.5, in the interface's "impl" subpackage), it is sufficient to only specify the base name of the class without the package. All built-in components follow this convention and therefore only require the classes' base names. For a list of available implementations please see the relevant sections of the documentation.
In the XML template, the 3 dots represent the implementation-specific XML configuration of the selected component.
The provided SoundHelix XML file is re-read and parsed every time a new song is generated. This means that any changes applied to the XML data in the meanwhile will become active as soon as the next song is created.
XML fragment inclusion via XInclude (including XPointer)
SoundHelix supports XInclude, which is an XML extension that lets you include XML fragments from an external URL into an XML file. In order to use XInclude, you have to import the XInclude namespace into the XML file, e.g. by using
<SoundHelix version="..." xmlns:xi="http://www.w3.org/2001/XInclude">
at the beginning of the XML file. If you now want to include an XML fragment somewhere in the document, simply use
where "URL" is the URL of the XML fragment to include. The
<xi:include> tag will then be replaced by the contents of the referenced XML file. This process is done recursively, i.e., included files themselves may include other XML files (provided that there are no inclusion cycles). The URLs don't have to be absolute. If they are relative, they are treated as relative to the current document's URL. For example, if you use "../includes/Standard-HarmonyEngine.xml" as the inclusion URL and the current document's URL is "http://www.soundhelix.com/applet/examples/SoundHelix-Piano.xml", SoundHelix will try to read the included file from the URL "http://www.soundhelix.com/applet/includes/Standard-HarmonyEngine.xml".
SoundHelix also supports verbatim text inclusion with XInclude, like this:
<chordPattern><xi:include href="URL" parse="text"/></chordPattern>
This will include the contents of the URL verbatim as text, just as if [[CDATA]] was used.
You can also use XPointer within XInclude to specify parts of a referenced XML file:
<xi:include href="URL" xpointer="element(/1)"/></chordPattern>
This will only include the first XML element from the specified URL.
XPointer is a powerful tool, but the Xerces XML processor, which is used by SoundHelix, only supports a subset of the XPointer functionality. For details, please see http://xerces.apache.org/xerces2-j/faq-xinclude.html.
SoundHelix provides a couple of special tags to allow for random selection.
Every time a tag requires an integer or double (floating-point) value, you can use
<random min="minimum" max="maximum"/> to use a uniformly distributed random integer between the given minimum and maximum (both inclusive) at runtime. For a normal (Gaussian) distribution instead of uniform distribution you can use
<random min="minimum" max="maximum" type="normal" mean="mean" variance="variance"/>. The "mean" attribute is optional. If it is not specified, the arithmetic mean of the minimum and maximum will be used. If you want to randomly select the integer or double from a list, you can use
For tags that require a string, a syntax similar to the integer lists are possible. Simply use
<random list="string1|string2|..."/>. Note that for strings the pipe character ("|") is used as a separator instead of a comma. In the list of strings, backslashes serve as escape characters. You can get a literal pipe character (instead of starting the next string) by using "\|" and a literal backslash by using "\\".
For tags that require a boolean, you can use
<random probability="probability"/>, where the probability for the value true is a double, given in percent (e.g., a probability value of "62.5" will generate true with 62.5%, false with 37.5% probability).
Instead of using a fixed integer like
you can use a Gaussian (normally distributed) random value instead:
<bpm><random min="120" max="140" type="normal" variance="7"/></bpm>
Note that these special tags are only available in XML text nodes, not in attribute values.
Configuration of subcomponents
The configuration of components often includes the configuration of subcomponents (e.g., an ArrangementEngine might include one or more SequenceEngine subcomponents). Subcomponents are added to a component by using the tag as specified by the including component (e.g., "<sequenceEngine>") and by providing a "class" attribute (and not more) that specifies which implementation to use. This tag belongs to the including component. The subcomponent can access and use any of the subtags of that tag to configure itself, and it might include further components itself.
There is currently no way to validate a SoundHelix XML file using standard XML validation. This is due to the fact that XML schemas (XSD files) as well as DTDs don't support validation of tags based on attribute values of surrounding tags. In many cases, the expected XML structure of a tag depends on the "class" attribute provided in the outer tag, because different implementations of a SoundHelix component might require different configuration tags.
Various XML validation possibilities are under consideration (Schematron, RELAX NG, etc.). If you have ideas for validation or ideas of improving the XML format in general, please contact me.
XML configuration notation
The configuration of XML-configurable components are described in the documentation by providing the following details for each tag or attribute:
- Tag - this is the name of the XML tag including its path in XPath-like notation (slash-separated); these are mostly simple tag names like "transposition", but nested tags are also possible ("lfo/device" is a <device> tag which has an <lfo> tag as its parent)
- Attribute - this is the name of an attribute that belongs to a tag; if the attribute name is missing ("-"), then the description is for the text node (e.g., "<tag>text</tag>) that belongs to the tag, otherwise it describes the meaning of the attribute itself
- Type - this is the expected data type of the attribute or text node; allowed types are "boolean" (values "true" or "false"), "int" (integer), "double" (decimal value), "string" (any text), "class" (a class name that is optionally a fully-qualified class name), "list of boolean" (a comma-separated list of booleans), "list of int" (a comma-separated list of integers), "list of double" (a comma-separated list of decimal values) and "list of string" (a comma-separated list of strings)
- # - this is the number of allowed occurrences of the tag (if attribute is empty) or of the attribute; "0-1" means that the tag/attribute is optional; "1" means that it is required and that only one occurrence is allowed, "0-n" means that any number (including zero) of occurrences is allowed, "1-n" means that any number larger than 0 is allowed; for attributes only "0-1" or "1" is possible (an attribute may never occur more than once)
- Example - this is an example value that would be valid to use in this text node or attribute
- Description - this is the description of the meaning of the attribute or text node
If only attributes are listed for a tag, the tag is expected to have an empty text node.
In all "list of ..." types, one character (usually the comma, but different characters may be used as well) serves as a separator and backslashes serve as escape characters. You can get a literal separator character (instead of starting the next value in the list) by preceding the separator character with a backslash. You can get a literal backslash by using a double backslash ("\\"). This escape mechanism is currently only needed for string lists, because for all other list types neither a comma nor a backslash is a valid character within the values (booleans, ints and doubles never contain commas or backslashes).