ASCIISYNTH is specification to (de)serialize synthesizer presets from/to ascii-strings which can be copy/pasted. The goal is twofold:
- offer file-agnostic ways of sharing presets (using chat or forums or LLVM’s e.g.).
- offer a way for samplers to backup the synthparameters in the samplename, which generated the sample
An ASCIISYNTH preset is basically a string like this:
FMX1.2!!C!!!23!!!!vf23lk2A
GRANSYN2.12a4bcfeff00ac065a
It’s format consist of the following sequence of tokens:
<synth identifier><version><parametervalues_using_hex_or_chars>
For example:
- synth ID:
FMX - synth version:
1.2(not mandatory but adviced) - parameters:
!!C!!!23!!!!vf23lk2A
NOTE: the width of the Synth ID, Version, and parameters can be decided by the author.
- a user tweaks synthesizer/sampler parameters
- the parameters get encoded (to ASCIISYNTH)
- the ASCIISYNTH name becomes the sample/instrument/preset-name
- the software can now auto-initialize synth(parameters) by detecting supported ASCIISYNTH prefixes
The Synth ID & Version are very easy to detect, and are verbatim (de)serialized.
The parameters however, are (de)serialized to their ascii decimal values.
These decimal values are offset by 33 to keep the characters easy copy/paste-table (below decimal ascii-value 33 are unprintable characters).
FMX1.2!"
- synth ID:
FMX - synth version:
1.2 - parameter 1: 0 (=
!=ASCII decimal 33) - parameter 2: 1 (=
"=ASCII decimal 34 )
The resolution on how much characters the host-application can reserve for a sample/instrument/preset-name.
- Small (a samplename of 20 max chars e.g.): use max parameter resolution is 93 (range
0..93) because of the ASCII requirement (126-33=93) - Bigger: just use hexadecimal values (synth X version 1 with one parametervalue 16 (=hex 10) becomes string
X110e.g.)
Milkytracker has ASCIISYNTH implemented, the gist is basically:
#define SYN_PREFIX_V1 "M1" // samplename 'M<version><params>' hints XM editors that sample was created with milkysynth <version> using <params>
#define SYN_PREFIX_V2 "M2" //
#define SYN_PREFIX_CHARS 2 // "M*"
#define SYN_PARAMS_MAX 32-SYN_PREFIX_CHARS // max samplechars (32) minus "M*" (32-2=30)
#define SYN_OFFSET_CHAR 33 // ASCIISYNTH spec: printable chars only 33..127 = 0..93 (allows ascii copy/paste of synthpresets)
#define SYN_PARAM_MAX_VALUE 93 // 93 printable chars
// handy macro to normalize ASCIISYNTH 0..93 range to 0..1 floats
#define SYN_PARAM_NORMALIZE(x) (1.0f/(float)SYN_PARAM_MAX_VALUE)*x
char* serialize() {
char str[SYN_PREFIX_CHARS+SYN_PARAMS_MAX];
sprintf(str,"%s",SYN_PREFIX_V2); // always bump this to latest version
for( int i = 0; i < SYN_PARAMS_MAX ; i++ ){
str[ i + SYN_PREFIX_CHARS] = i < synth->nparams ? (int)synth->param[i].value + SYN_OFFSET_CHAR : SYN_OFFSET_CHAR;
}
printf("synth: '%s'\n",str);
return str;
}
bool deserialize( string preset ) {
if( preset.startsWith(SYN_PREFIX_V1) || preset.startsWith(SYN_PREFIX_V2) ){ // detect synth version(s)
const char *str = preset.getStrBuffer();
int ID = str[ SYN_PREFIX_CHARS ] - SYN_OFFSET_CHAR;
synth = &(synths[ID]); // replace current synth & initialize
for( int i = 0; i < preset.length() && i < SYN_PARAMS_MAX; i++ ){
setParam(i, str[ i + SYN_PREFIX_CHARS ] - SYN_OFFSET_CHAR );
}
return true;
}else return false;
}
- leonvankammen|gmail.com
This document has no IANA actions.
TODO acknowledge.