construct imaginary worlds.


paracosms is a sampler+tracker that can throw loops, slice loops, write and record loops. main features:


between april and june 2022 I made music primarily with scripts, SuperCollider, sox and random pre-recorded samples from other musicians. this endeavor culminated in an album of 100 songs. (more on that here).

during this time I put together a SuperCollider class I called “paracosms” which is essentially allowed unlimited synchronized turntables that can be switched between one-shots and synchronized loops. I used this to remix songs from the album I had made by performing them. i.e. I took a bunch of samples I collected and threw them into the grid with a thin norns wrapper around this SuperCollider paracosms class. it was very fun.

also during this time I was thinking about recording perfectly seamless loops of audio. I added a new function to do this easily in softcut. but I realized I wanted to do it with SuperCollider too. I ended up making “ouroborus” which allows recording of seamless loops directly to disk by fading in a post-roll to the beginning of a recording.

I realized that I could combine ourborous with paracosms together into sampler/looper. its basically a thing that excels at recording and playing perfect audio loops. norns became the glue for these two supercollider classes which is now this paracosms script.


this script wouldn’t exist without the ceasless inspiration from the likes of @sixolet, @jaseknighter, @tyleretters, @dan_derks, @yams, @license, and others who are all pushing the boundaries of what norns can do. also thanks to Ezra who showed me the art of SuperCollider - namely class-based designs.



playing loops


E1 will select sample. K1+E1 will select sample that is loaded.

K3 will play a sample. holding K3 will fade the sample (in or out dependong on whether its playing).

the start/end points can be changed (press K2 to find the menu or use PARAMS). the loops always try to play in sync no matter the length. with the grid you can sequence the loop positions for chopping things (more below).

note: loops appear on the screen as single channel even if they are stereo.

playing one shots


loops can be placed into “oneshot” mode. press K2 until you reach the screen with “mode”, “offset”, “start”, and “end”. then hold K1 and turn E2 to modify the mode to “oneshot” or “loop”.


K3 plays a sample in oneshot mode. if you hold K3 it will toggle the euclidean sequencer (which can also be toggled by the parameters menu or in one of the K2 parameter screens).



K1+K3 will prime a recording. you always can skip waiting and you can start recording immediately by pressing K1+K3 again.

by default paracosms will wait to record until audio crosses a threshold to start recording. once recording is detected, it records the full length specified by the sample parameters (in beats, plus the crossfade post-roll). paracosms uses a latency term to capture the milliseconds right before recording (because there is an inherent delay in starting recording after detecting it) and this can be changed in the parameters. generally this latency should be really small (<20 ms).

parameters on the go

K2/K1+K2 will cycle through parameters.

E2/E3 or K1+(E2/E3) will modulate the current parameters.

there are a bunch of sample-specific parameters: volume (+lfo), panning (+lfo), sample start/end, filters (low+high), fx sends, timestretching. these are all available in the PARAMS menu, but they are also accessible from the main screen to avoid some menu-diving. us K2 to cycle through them and hold K1 to see the other alt parameters on each screen..


there are three global effects - greyhole, clouds and tapedeck. their parameters are editable in the main parameters menu. every parameter for clouds is controlled by an LFO. every sample has its own send to the main bus (no fx) and to these two effects.

automatic warping

imported audio is automatically warped when either the guess bpm parameter is activated (i.e. from the startup script), or when “bpmX” occurs in the filename. for example of this latter case: if your sample is called “cool_sound_bpm120.wav” then it will assume a bpm of 120 and automatically stretch it to match the current norns clock in a way that doesn’t affect pitch. note: if you change the norns clock after starting paracosms then the samples will not be warped to fit anymore.

another note: if you include “drum” in the filename, then warping happens without using pitch-compensation.

you can change the warping at any time by going to the sample and editing the warping parameters. a new warped file is automatically generated and loaded when editing any parameter. all the warped files are stored in the data/paracosms folder. this makes subsequent reloads faster.

gapless playback

recorded samples: gapless playback is achieved in recorded samples by recording post-roll audio and crossfading that back into the beginning. paracosms takes care of this automatically.

imported samples: imported samples are assumed to already have been processed for gapless playback. read the tutorial below to edit your samples for gapless playback:

a tutorial on making audio with gapless playback.</summary>

I created a tool to automatically make seamless loops out of audio. to use this tool simply rename your file to include bpmX in the filename (where X is the source bpm of the file). for example, a 120 bpm file, “drums.wav” would be renamed “drums_bpm120.wav”. this tool is included with paracosms - its called seamlessloop. you can run seamlessloop on folders or files. for example:

os.execute("/home/we/dust/code/paracosms/lib/seamlessloop --in-folder ~/dust/audio/loops --out-folder ~/dust/audio/quantized-loops")

this tool does one of two things: if the number of determined beats is greater than a multiple of 4 then those extra beats are used to crossfade and make a seamless sample. otherwise, if the number determined beats is slightly less than a multiple of 4 then a gap of silence is appended to the end and the endpoints are faded by 5 ms to reduce clicks.


the grid

the grid essentially makes it easy to toggle on/off samples. it does give special functionality to create patterns from toggles, and even create patterns from start/stop positions (making it easy to break up samples).


keyboard / tracker


pushing a key on a keyboard opens the tracker. twisting an encoder closes the tracker (but it will still be running if you started it).

the keyboard layout closely follows the renoise layout.


the keyboard controls a sequencer. the sequencer has two dimensions. each row is a measure of 4 beats. those 4 beats are subdivided evenly across everything put onto a line. so if you put 8 things onto a line, each of those things will occur each 1/8th note. if you put 4 things, each will occur at each 1/4 note. if you put 7 things each will occur at each 1/7th note (approximately).

there are notes, note offs, and note ties. by default, anytime a note changes it will do a note off since each sequence is monophonic (though you can have as many sequences playing as you want). you can use the note ties and note offs to create syncopation. for example, the following is quarter note tied to an eight note:

C4 - - . . . . .

there are 8 things, so each thing gets 1/8th note. the C4 gets 1/8 note and its tied twice (“- -”) and doesn’t get turned off until the 4th 1/8th note hits, so it lasts only 3/8th notes.

customization / loading sample banks


paracosms is ready to be customized. the initial script can be changed to your liking. open up paracosms.lua in maiden, or copy and paste its contents into a new file.

the functions substance() and style() run at the start and at the end of loading, respectively (substance before style as they say). you can use these to trigger certain behaviors or activate parameters once everything is loaded. I like to make a script for each track I’m working on where the substance() sets the clock speed and style() loads specific files into specific banks.

the “blocks” allows you to customize the startup samples. you can load up to 16 samples per line per entry, with 7 entries available. each entry has a folder and all the files in the folder will be loaded. for instance the first line will loaded into slots 1-16. the second line will load into slots 17-32. etc. you can also create parameters that are shared across each block. any parameter that is available can be updated here. for example, say you wanted to load all the 909-samples as one-shots, you could include this line:


where oneshot=2 defines the oneshot parameter to be activated for all those samples (as opposed to looping). or you might want to include some loops and have paracosms guess the bpm for them. in this case you can do:


all the parameter ids are valid. for instance you can load a block of samples and have them all be used for the clouds fx:


saving / loading

saving and loading is done by writing and reading PSETs. the save will store all the current parameters, patterns and references to audio files. since only the audio file reference is stored, if the file is moved then your save may no longer function properly (there is a way to fix this though if it happens).



  • rain on a windowpane thing for composing songs from loops
  • more fx (strobe)
  • utilize @sixolet’s more canonical syncing between sc and lua


  • rarely a bug occurs where SuperCollider does not free all the synths when exiting. (fixed, I think)
  • there is a rare bug where the playback position escapes the start/stop points (maybe fixed)
  • the cpu will be overloaded if you play too many samples simultaneously (this limit depends on your cpu) or if you activate all the fx (tape + clouds + greyhole, simultaneously).
  • if you change the norns clock then samples will continue to play at the rate according to the clock that they were initialized with. until there is a fix for this, I suggest reloading the script after you change the norns clock, or simply goto the sample individually and modify something in its warping parameters.



the first time you open the script it will ask to install the rest of paracosms.


update the script by deleting and reinstalling or just running this in maiden:

os.execute("cd /home/we/dust/code/paracosms && git fetch --all && cd /home/we/dust/code/paracosms && git reset --hard origin/paracosms