Loopstyler patches explained
The patch files are stored on SD card, in "patches" directory. You can edit them as you wish (don't forget to make a backup :)
Implementing a complete in-device mechanism to edit, store and duplicate patches is on my TODO list.
In the meantime you can edit the patches manually as text files, rearrange them by renaming the files, or create a new patch by copying one file to another and then editing it.
Filenames must adhere to the existing format, so the Loopstyler can find them: patch[N].json.txt (all lowercase). The N can be one, two or three digits; valid patch numbers are 1 to 999.
There are two ways to access the SD card: either by removing it from the device or by connecting Loopstyler to a PC (the SD card will appear as a new disk drive).
Never remove or insert the SD card while the unit is powered on. Please observe precautions about powering on or off as mentioned here.
When modifying a patch, the Loopstyler software might need to be restarted - depending on whether this patch was already loaded during the session - as then a cached version of the file might keep being used.
To restart, power the unit off and wait until the red LED light stops glowing, slowly count to 5 in order to not stress the electronics, and then power it on again
(in the next firmware update there will be a command to reload patches without restart).
Patch validator
Here is a simple validator for checking patches, to make sure they will work in the Loopstyler. This may be faster than testing them in the device. If there is an error, you can get a detailed message to help you locate it.
Patch file format
Patches use JSON as their file format, with additional ".txt" extension for convenience (so they can be easily opened in any text editor). The JSON syntax is less strict than
required by the JSON standard, for example you can completely omit double quotes from non-numerical keys and values.
Also it can tolerate comments of various styles: inline comments beginning with # or // and multi-line comments wrapped between /* and */.
Let's take patch1.json.txt as an example (you can right click on the link and open the file in another tab).
Following parameters and sections can currently be present in file (this will be expanded over time):
- "dir": directory where to find samples. This value needs to be enclosed in double quotes ("). The ast slash in the path is optional and can be left out.
- "samples": list of particular samples or a wildcard by which the directory (as specified by "dir" parameter) should be searched for samples.
A wildcard can be for example * (all files), *.wav (all wav files), guitar*.wav (will load all samples that start with word "guitar", for example "guitar1_A3.wav").
Loopstyler will analyze files and only load those which are compatible.
If not using a wildcard, you need to specify a list of specific files to be loaded. The order will be preserved for the files to be refered to by numbers in the "region" section.
Please note that all directory names and filenames are case-sensitive, it might not work that way in your operation system but the Loopstyler uses Linux.
- "regions": in this section we can describe how samples or sound engines are assigned to individual keys (or rows / columns / block of keys) of the stylus‑controlled keypad.
The playable area is organized into 4 rows by 12 pads, or 3 segments of 4x4 pads. A row has 12 pads, column has 4 pads, block has 16 pads.
In the current firmware, this parameter can be named "row" (a sample or other engine uses a scale over entire row), "pad" (it is assigned to a particular key selected by number) or you can use
"one_sample_per_pad" option (samples will be simply assigned to individual metallic keys in order as they are found in the directory or listed in the "samples" parameter).
Please note that while the manual refers to metallic stylus-controlled squares as "keys", here in the patch syntax we use keyword "pad" instead,
to not confuse it with "key" parameter from sample / voice description block.
Each "regions" block (unless configured as "one_sample_per_pad") can use following parameters:
- "row:n" or "pad:n": select a row (1-4) or a key (1-48). Rows are numbered from top to bottom, keys are numbered from the top left to bottom right.
- "sample": selects a sample (they are numbered from 1), either exactly as listed in "samples" array, or if wildcard used, as found in the directory.
- "engine": this parameter invokes a synthesized sound engine instead of samples. Its value can be "KS" (Karplus-Strong), "SS" (Supersaw), "FM", "AD" (Additive synthesis)
or "WT" (Wavetable).
Regardless of whether any of these engines are mentioned in the patch, they can be accessed via MIDI on channels 1-5. Please note that "sample" and "engine" parameters are mutually exclusive,
it does not make sense to combine them in one definition.
- "base": this parameter is only used in combination with "sample". It defines a base pitch for the sample - it allows to align tuning of multiple instruments, recorded with an arbitrary pitch at the given sample rate. To figure out what to put here, you should listen to the sample played back at 44.1 kHz and determine its perceived pitch. If the sample is a more complex sound, for example a chord, put down its root note. If the sample is dynamic and does not have a constant pitch, decide whether to use its start point, end point or something else as a reference, depending on how you want the sample to behave. If the sample does not have a pitch (e.g. sound effect or percussion), use A4 which will keep it at the default pitch (as sampled at 44.1 kHz).
- "scale": applicable when "row" parameter is used. It selects one of the pre-defined scales. Their default list is in comments at the end of most patch files,
however this may change when the scales are edited. The scales definitions are stored in the file patches/scales.json.txt
on the SD card. You can add more scales or rearrange them. Don't forget to make a backup of this file when editing it, just in case.
Patches refer to scales by name, so if you need more than 9 scales, it's a good idea to keep all of them in the file. Only first 10 scales are accessible for manual selecting using
command KEY#,
but if needed, this can be expanded easily. In future firmware versions support for microtuning is planned (so the scales definition file will accept decimal numbers / direct frequencies
instead of semitone intervals).
- "key": applicable everywhere. It either defines key for a scale, or pitch for an individual pad. If scales per row are defined, this is the note which 1st pad in the row will get.
- "tuning": not implemented yet, this will allow precise microtuning.
- "panning": limits for stereo spread of monophonic samples or sound engines. Possible values are -100 to 100.
These two numbers define points along 180 degree arc, where -100 is fully left, +100 is fully right and 0 is at the center.
If you want to pan a sample at a precise point, set both limits to the same value, for example [0,0] for center, [-50,-50] for 50% left (i.e. at 45 degrees) etc..
Otherwise, paning is randomized anywhere within the range defined by these limits. In most factory samples this is configured as [-30,30] which means that at each trigger, the instrument will be
panned somewhere within 30% left and 30% right.
Because JSON format uses comma-separated lists, every parameter or section (except for the very last) needs to end with ",". Also, matching pairs of brackets need to be present.
Technical note: In the official JSON standard there is a difference between curly brackets {} denoting objects (unordered key‑value pairs) and square brackets [] used for arrays (ordered lists).
In the Loopstyler's implementation, these
Patch #1
File name: patch1.json.txt |
Samples directory: /media/samples/demo |
Samples mask: * |
row: 1 | sample: 1 (AccGtr02-96OC.wav) | scale: aeolian7sharp | key: c4 | base: e3 | tuning: 0 | panning: [-30,30] | row: 2 | sample: 2 (AccGtr02-KVIC.wav) | scale: aeolian7sharp | key: c4 | base: e4 | tuning: 0 | panning: [-30,30] | row: 3 | sample: 3 (GtrRvb19-277A.wav) | scale: aeolian7sharp | key: c4 | base: e4 | tuning: 0 | panning: [-30,30] | row: 4 | sample: 4 (GtrRvb19-3GA9.wav) | scale: aeolian7sharp | key: c4 | base: e3 | tuning: 0 | panning: [-30,30] |
|
Patch #2
File name: patch2.json.txt |
Samples directory: /media/samples/demo |
Samples mask: * |
row: 1 | sample: 6 (Vibes/A3.wav) | scale: aeolian | key: a3 | base: a3 | tuning: 0 | panning: [-30,30] | row: 2 | sample: 5 (Vibes/A2.wav) | scale: aeolian | key: a2 | base: a2 | tuning: 0 | panning: [-30,30] | row: 3 | sample: 25 (synclavier01.vc_SV001.wav) | scale: aeolian | key: a3 | base: f3 | tuning: 0 | panning: [-30,30] | row: 4 | sample: 27 (synclavier03.vc_SV001.wav) | scale: aeolian | key: a3 | base: f3 | tuning: 0 | panning: [-30,30] |
|
Patch #3
File name: patch3.json.txt |
Samples directory: /media/samples/demo |
Samples mask: * |
row: 1 | sample: 5 (Vibes/A2.wav) | scale: lydian | key: a2 | base: a2 | tuning: 0 | panning: [-30,30] | | | | row: 2 | sample: 6 (Vibes/A3.wav) | scale: lydian | key: a3 | base: a3 | tuning: 0 | panning: [-30,30] | | | | row: 3 | sample: 25 (synclavier01.vc_SV001.wav) | scale: lydian | key: a3 | base: f3 | tuning: 0 | panning: [-30,30] | | | | pad: 37 | sample: 7 (acquaorgan.vc_SV001.wav) | | | base: a4 | tuning: 0 | panning: [-30,30] | loop: 0 | solo: 0 | group: 0 | pad: 38 | sample: 8 (byrdycarp01.vc_SV001.wav) | | | base: a4 | tuning: 0 | panning: [-30,30] | loop: 1 | solo: 1 | group: 1 | pad: 39 | sample: 9 (byrdycarp02.vc_SV001.wav) | | | base: a4 | tuning: 0 | panning: [-30,30] | loop: 1 | solo: 1 | group: 1 | pad: 40 | sample: 10 (carptsylvian1-7IOH.wav) | | | base: a4 | tuning: 0 | panning: [-30,30] | loop: 1 | solo: 1 | group: 1 | pad: 41 | sample: 11 (catscarpet01.vc_SV001.wav) | | | base: a4 | tuning: 0 | panning: [-30,30] | loop: 0 | solo: 0 | group: 0 | pad: 42 | sample: 18 (effects.vc_SV001.wav) | | | base: a4 | tuning: 0 | panning: [-30,30] | loop: 0 | solo: 0 | group: 0 | pad: 43 | sample: 19 (endpeterg01.vc_SV001.wav) | | | base: a4 | tuning: 0 | panning: [-30,30] | loop: 0 | solo: 0 | group: 0 | pad: 44 | sample: 20 (fxsaka01.vc_SV001.wav) | | | base: a4 | tuning: 0 | panning: [-30,30] | loop: 0 | solo: 0 | group: 0 | pad: 45 | sample: 21 (meganoise01.vc_SV001.wav) | | | base: a4 | tuning: 0 | panning: [-30,30] | loop: 1 | solo: 1 | group: 2 | pad: 46 | sample: 22 (meganoise02.vc_SV001.wav) | | | base: a4 | tuning: 0 | panning: [-30,30] | loop: 1 | solo: 1 | group: 2 | pad: 47 | sample: 23 (meganoise03.vc_SV001.wav) | | | base: a4 | tuning: 0 | panning: [-30,30] | loop: 1 | solo: 1 | group: 2 | pad: 48 | sample: 24 (meganoise04.vc_SV001.wav) | | | base: a4 | tuning: 0 | panning: [-30,30] | loop: 1 | solo: 1 | group: 2 |
|
Patch #4
File name: patch4.json.txt |
Samples directory: /media/samples/demo |
Samples mask: "voicesm1ahh.vc_SV001.wav" and 3 more samples |
row: 1 | sample: 2 (AccGtr02-KVIC.wav) | scale: lydian | key: a2 | base: c4 | tuning: 0 | panning: [-30,30] | loop: 1 | sustain: 3 | row: 2 | sample: 1 (AccGtr02-96OC.wav) | scale: lydian | key: a2 | base: g3 | tuning: 0 | panning: [-30,30] | loop: 1 | sustain: 3 | row: 3 | sample: 3 (GtrRvb19-277A.wav) | scale: lydian | key: a3 | base: f3 | tuning: 0 | panning: [-30,30] | | | row: 4 | sample: 4 (GtrRvb19-3GA9.wav) | scale: lydian | key: a3 | base: f3 | tuning: 0 | panning: [-30,30] | | |
|
Patch #5
File name: patch5.json.txt |
Samples directory: /media/samples/demo |
Samples mask: * |
row: 1 | engine: SS | scale: aeolian7sharp | key: c4 | tuning: 0 | panning: [-30,30] | sustain: 0 | group: 1 | row: 2 | engine: SS | scale: aeolian7sharp | key: c3 | tuning: 0 | panning: [-30,30] | sustain: 1 | group: 2 | row: 3 | engine: SS | scale: aeolian7sharp | key: c2 | tuning: 0 | panning: [-30,30] | sustain: 2 | group: 3 | row: 4 | engine: FM | scale: aeolian7sharp | key: c3 | tuning: 0 | panning: [-30,30] | sustain: 2 | group: 4 |
|
Patch #6
File name: patch6.json.txt |
Samples directory: /media/samples/demo |
Samples mask: * |
row: 1 | engine: KS | scale: aeolian7sharp | key: c3 | | tuning: 0 | panning: [-30,30] | solo: 0 | group: 1 | | row: 2 | sample: 2 (AccGtr02-KVIC.wav) | scale: aeolian7sharp | key: c4 | base: e4 | tuning: 0 | panning: [-30,30] | | | | row: 3 | engine: SS | scale: aeolian7sharp | key: c2 | | tuning: 0 | panning: [-30,30] | | group: 2 | sustain: 2 | row: 4 | engine: FM | scale: aeolian7sharp | key: c3 | | tuning: 0 | panning: [-30,30] | | group: 3 | sustain: 2 |
|
Patch #7
File name: patch7.json.txt |
Samples directory: /media/samples/demo |
Samples mask: * |
row: 1 | engine: KS | scale: aeolian7sharp | key: c3 | | tuning: 0 | panning: [-30,30] | solo: 0 | group: 1 | | row: 2 | sample: 2 (AccGtr02-KVIC.wav) | scale: aeolian7sharp | key: c4 | base: e4 | tuning: 0 | panning: [-30,30] | | | | row: 3 | engine: AD | scale: aeolian7sharp | key: c2 | | tuning: 0 | panning: [-30,30] | | group: 2 | sustain: 2 | row: 4 | engine: FM | scale: aeolian7sharp | key: c2 | | tuning: 0 | panning: [-30,30] | | group: 3 | sustain: 2 |
|
Patch #8
File name: patch8.json.txt |
Samples directory: /media/samples/demo |
Samples mask: * |
row: 1 | engine: KS | scale: aeolian | key: c3 | tuning: 0 | panning: [-30,30] | solo: 0 | group: 1 | | row: 2 | engine: AD | scale: aeolian | key: c3 | tuning: 0 | panning: [-30,30] | | group: 2 | sustain: 2 | row: 3 | engine: FM | scale: aeolian | key: c3 | tuning: 0 | panning: [-30,30] | | group: 3 | sustain: 2 | row: 4 | engine: SS | scale: aeolian | key: c2 | tuning: 0 | panning: [-30,30] | | group: 4 | sustain: 2 |
|
Patch #9
File name: patch9.json.txt |
Samples directory: /media/samples/demo_euclid |
Samples mask: *.wav |
|
Patch #10
File name: patch10.json.txt |
Samples directory: /media/samples/demo |
Samples mask: * |
row: 1 | engine: AD | scale: aeolian | key: c3 | tuning: 0 | panning: [-30,30] | sustain: 1 | group: 1 | row: 2 | engine: AD | scale: aeolian | key: c2 | tuning: 0 | panning: [-30,30] | sustain: 1 | group: 2 | row: 3 | engine: SS | scale: aeolian | key: c3 | tuning: 0 | panning: [-30,30] | sustain: 1 | group: 3 | row: 4 | engine: SS | scale: aeolian | key: c2 | tuning: 0 | panning: [-30,30] | sustain: 1 | group: 4 |
|
Patch #11
File name: patch11.json.txt |
Samples directory: /media/samples/demo |
Samples mask: * |
row: 1 | engine: WT | scale: aeolian7sharp | key: c3 | tuning: 0 | panning: [-30,30] | sustain: 2 | group: 1 | row: 2 | engine: AD | scale: aeolian7sharp | key: c3 | tuning: 0 | panning: [-30,30] | sustain: 2 | group: 2 | row: 3 | engine: AD | scale: aeolian7sharp | key: c2 | tuning: 0 | panning: [-30,30] | sustain: 2 | group: 3 | row: 4 | engine: FM | scale: aeolian7sharp | key: c3 | tuning: 0 | panning: [-30,30] | sustain: 2 | group: 4 |
|
Patch #12
File name: patch12.json.txt |
Samples directory: /media/samples/demo |
Samples mask: * |
row: 1 | engine: WT | scale: aeolian7sharp | key: c4 | tuning: 0 | panning: [-30,30] | solo: 1 | group: 1 | | row: 2 | engine: AD | scale: aeolian7sharp | key: c3 | tuning: 0 | panning: [-30,30] | | group: 2 | sustain: 2 | row: 3 | engine: FM | scale: aeolian7sharp | key: c3 | tuning: 0 | panning: [-30,30] | | group: 3 | sustain: 2 | row: 4 | engine: SS | scale: aeolian7sharp | key: c2 | tuning: 0 | panning: [-30,30] | | group: 4 | sustain: 2 |
|
Patch #13
File name: patch13.json.txt |
Samples directory: /media/samples/demo |
Samples mask: * |
row: 1 | engine: WT | scale: aeolian7sharp | key: c4 | tuning: 0 | panning: [-30,30] | solo: 1 | group: 1 | | row: 2 | engine: AD | scale: aeolian7sharp | key: c3 | tuning: 0 | panning: [-30,30] | | group: 2 | sustain: 2 | row: 3 | engine: AD | scale: aeolian7sharp | key: c2 | tuning: 0 | panning: [-30,30] | | group: 3 | sustain: 2 | row: 4 | engine: FM | scale: aeolian7sharp | key: c3 | tuning: 0 | panning: [-30,30] | | group: 4 | sustain: 2 |
|
Patch #14
File name: patch14.json.txt |
Samples directory: /media/samples/demo |
Samples mask: * |
row: 1 | engine: AD | scale: halftone | key: c3 | tuning: 0 | panning: [-30,30] | sustain: 2 | group: 1 | row: 2 | engine: AD | scale: halftone | key: c2 | tuning: 0 | panning: [-30,30] | sustain: 2 | group: 2 | row: 3 | engine: FM | scale: halftone | key: c3 | tuning: 0 | panning: [-30,30] | sustain: 2 | group: 3 | row: 4 | engine: FM | scale: halftone | key: c2 | tuning: 0 | panning: [-30,30] | sustain: 2 | group: 4 |
|
Patch #15
File name: patch15.json.txt |
Samples directory: /media/samples/demo |
Samples mask: * |
row: 1 | sample: 12 (cw_amen_apache.wav) | scale: halftone | key: g#3 | base: c4 | tuning: 0 | panning: [-30,30] | loop: 1 | solo: 1 | group: 1 | row: 2 | sample: 13 (cw_amen_beasty.wav) | scale: halftone | key: g#3 | base: c4 | tuning: 0 | panning: [-30,30] | loop: 1 | solo: 1 | group: 1 | row: 3 | sample: 14 (cw_amen_chopper.wav) | scale: halftone | key: g#3 | base: c4 | tuning: 0 | panning: [-30,30] | loop: 1 | solo: 1 | group: 1 | row: 4 | sample: 15 (cw_amen_comp.wav) | scale: halftone | key: g#3 | base: c4 | tuning: 0 | panning: [-30,30] | loop: 1 | solo: 1 | group: 1 |
|
Patch #16
File name: patch16.json.txt |
Samples directory: /media/samples/demo |
Samples mask: * |
row: 1 | sample: 6 (Vibes/A3.wav) | scale: aeolian | key: a3 | base: a3 | tuning: 0 | panning: [-30,30] | | | | row: 2 | sample: 7 (acquaorgan.vc_SV001.wav) | scale: aeolian | key: a2 | base: d#4 | tuning: 0 | panning: [-30,30] | | | | row: 3 | sample: 16 (cw_amen_deeptouch.wav) | scale: halftone | key: g#3 | base: c4 | tuning: 0 | panning: [-30,30] | loop: 1 | solo: 1 | group: 1 | row: 4 | sample: 17 (cw_amen_vinyl.wav) | scale: halftone | key: g#3 | base: c4 | tuning: 0 | panning: [-30,30] | loop: 1 | solo: 1 | group: 1 |
|
Patch #17
File name: patch17.json.txt |
Samples directory: /media/samples/fairlight_s3_factory |
Samples mask: *.wav |
|
Patch #18
File name: patch18.json.txt |
Samples directory: /media/samples/fairlight_s3_iix |
Samples mask: *.wav |
|
Patch #19
File name: patch19.json.txt |
Samples directory: /media/samples/field_rec/ |
Samples mask: * |
|
List of Demo Samples
Sample number | File name | File size |
1 | AccGtr02-96OC.wav | 356352 |
2 | AccGtr02-KVIC.wav | 356352 |
3 | GtrRvb19-277A.wav | 485376 |
4 | GtrRvb19-3GA9.wav | 485376 |
5 | Vibes/A2.wav | 695886 |
6 | Vibes/A3.wav | 693162 |
7 | acquaorgan.vc_SV001.wav | 502784 |
8 | byrdycarp01.vc_SV001.wav | 177152 |
9 | byrdycarp02.vc_SV001.wav | 319488 |
10 | carptsylvian1-7IOH.wav | 199680 |
11 | catscarpet01.vc_SV001.wav | 510976 |
12 | cw_amen_apache.wav | 1077352 |
13 | cw_amen_beasty.wav | 1330560 |
14 | cw_amen_chopper.wav | 246452 |
15 | cw_amen_comp.wav | 1209600 |
16 | cw_amen_deeptouch.wav | 1540096 |
17 | cw_amen_vinyl.wav | 1412684 |
18 | effects.vc_SV001.wav | 123904 |
19 | endpeterg01.vc_SV001.wav | 147456 |
20 | fxsaka01.vc_SV001.wav | 70656 |
21 | meganoise01.vc_SV001.wav | 434176 |
22 | meganoise02.vc_SV001.wav | 500736 |
23 | meganoise03.vc_SV001.wav | 658432 |
24 | meganoise04.vc_SV001.wav | 305152 |
25 | synclavier01.vc_SV001.wav | 617472 |
26 | synclavier01.vc_SV002.wav | 617472 |
27 | synclavier03.vc_SV001.wav | 265216 |
28 | synclavier03.vc_SV002.wav | 265216 |
29 | voicesm1ahh.vc_SV001.wav | 273408 |
30 | voicesm1ahh.vc_SV002.wav | 305152 |