Ableton Move · Schwung sound generator

Concat

A corpus synthesizer. Point it at samples, it cuts them into slices, measures each one, and lays them out on a map of timbre. Then you play the map.

36 descriptors per slice 3 play modes: Notes, Map, Mosaic 16 pad clusters corpus files with live reload web Corpus Builder Schwung 1.3.0+

I made Concat because the granular modules on the Move each read one buffer. Concat reads a whole sample library at once: you travel through timbre across many files, or sing into it and hear your voice rebuilt from the corpus.

The idea

A map of sounds, not a timeline

Every slice gets measured: how bright, how noisy, how loud, what pitch, what timbre (13 MFCCs), each as an average and a variation over the slice. That puts every slice at a point in a 36-dimensional space. Concat flattens it to a 2-D map and plays a cloud of grains from the slices nearest your position.

DecodeWAV · AIFF · FLAC · MP3
→
Sliceat onsets, 20 ms to 2 s
→
Describe36 numbers per slice
→
MapRaw axes or Learned (PCA)
→
Playnearest slices as grains

A corpus

One sample, one folder, or a .concat file that gathers many folders and samples, trimmed and filtered.

A position

X and Y on the map, moved by knobs, the LFO, a note (Zone), a held pad (clusters), or your voice (Mosaic).

A cloud

Grains at a density you set, each a slice near the position, never the same one twice in a row, flowing from the last.

Quickstart

First sound in a minute

  1. In Schwung, add Concat to a track. A new Concat loads the first sample of your first Samples folder by itself.
  2. To choose your own: open Corpus from the root menu, select Source (knob 1), press the jog wheel, and pick a sample, or a .concat file from Corpora.
  3. Scope (on Mod & Set) decides what a picked sample means: File (default) makes that sample the whole corpus, cut into many slices; Folder takes its whole folder.
  4. Wait for Analyze to reach 100 %. A big folder takes a minute the first time; after that it loads from the cache.
  5. Play the pads. Each pad plays a different part of the corpus.
  6. Open View: see the map, and turn the jog wheel through the Recipes. Try Cloud, then Drone.
Next: build a corpus from several folders in the Corpus Builder, trim the samples, hear its map in the browser, and load it onto the Move from there.
The View page

The corpus on the Move's screen

Each dot is a slice. The ring is your position and radius; the small trail is the last slices played. The recipe name and its number sit on top; the bottom line names the knob you touch or says what the analysis is doing.

Knobs on View

X Position, Y Position, Radius, Density, Grain Size, K Nearest, Smooth, Filter: everything you need to move around without leaving the map.

Status line

analysing 3/40 while it works, then nothing. If something went wrong: out of memory, kept old, bad JSON: ..., kept old, 2 sources missing. A failed load never stops the corpus that is playing.

Play modes

Three ways in

Notes (default)

Polyphonic: each pad is a voice with its own envelope. Note Match: Zone puts each pad somewhere else on the map, at natural pitch. Pitch picks the nearest-pitched slice and retunes it. Off plays the current position, retuned.

Map

Move the position with X/Y, or let Follow do it (LFO, or Sequence on the MIDI clock). Hold a pad to jump to one of 16 timbre clusters; let go to come back.

Mosaic

Concat listens to the line/mic input about every 23 ms and answers with the nearest slices. Beatbox into drums, hum into field recordings. Dry Mix blends your input in.

Reference

The pages

The root page holds 8 performance knobs. The menu below it opens View · Corpus · Map · Mod & Set · Grain · Shape · Play · Out.

Root

KnobParamWhat it does
K1 · K2X / Y PositionWhere you are on the map.
K3DensityGrains per second.
K4Grain SizeGrain length.
K5 · K6Amp Attack / ReleasePer-note envelope (Notes).
K7PolyphonyGrain voice ceiling.
K8FilterBipolar DJ filter: left darker, right thinner.

Corpus

ParamRangeDefaultNotes
Sourcefile browserautoA sample (.wav .aif .aiff .flac .mp3) or a .concat corpus file.
Pool Cap16 to 512 MB128RAM for corpus audio; 128 MB is about 25 minutes of mono. Free RAM can lower it, then Concat keeps an even subset of slices.
RescantriggerTurn right: analyse again from scratch.
Slice ModeOnset / FixedOnsetCut at attacks, or in even grains of Max Slice.
Min / Max Slice20 to 500 / 100 to 2000 ms20 / 2000Slice length limits.
Analyze0 to 100 %Progress, read only.
Silence Gate0 to 10.02Drops quieter slices.

A .concat file's own slicing settings replace Slice Mode, Min/Max Slice and Silence Gate.

Map

ParamRangeDefaultNotes
X / Y DescriptorBright, Pitch, Loud, Noisy, Rolloff, MFCC1-3Bright / PitchThe axes in Raw mode.
X / Y Position0 to 10.5Good targets for the Move's LFOs.
Map ModeRaw / LearnedRawLearned uses the two directions along which this corpus varies most (PCA), so it spreads evenly.
Radius0 to 10.15How far grains may wander from the position.
K Nearest1 to 164How many nearest slices a grain picks from.
Repeat Avoid0 to 164Skips the last N slices played.

Mod & Set

ParamRangeDefaultNotes
FollowManual / LFO / SequenceManualLFO moves the position by itself; Sequence locks it to the MIDI clock.
LFO Rate0.01 to 100.2Hz with LFO; cycles per beat with Sequence (0.25 = a bar, 2 = an eighth).
LFO ShapeCircle, SineX, SineY, S&HCircleS&H with Sequence jumps on the beat.
Smooth0 to 10.35How much each grain follows on from the last one.
Pos Jitter0 to 10.15Random start inside the slice.
ScopeFolder / FileFileWhat a picked sample means: just it, or its whole folder.

Grain

ParamRangeDefaultNotes
Density1 to 100 g/s20Grains per second.
Grain Size10 to 2000 ms120Longer than its slice, a grain loops it with a crossfade.
Grain EnvHann, Tukey, Tri, Gauss, Expo, RevExpo, Trapez, BlackHannWindow shape.
Pitch-24 to +24 st0Transpose.
Pan Spread0 to 10.3Random stereo position per grain.
Grain Random0 to 10Random grain length.
Reverse0 to 10Chance a grain plays backwards.
Pitch Jitter0 to 10Random detune per grain.

Shape

ParamDefaultNotes
Amp Attack / Decay / Sustain / Release0.01 / 0.2 / 1 / 0.2Per-note envelope (Notes mode). Map and Mosaic play at full level.
Filter Env0.45Envelope amount on the Filter (0.5 = none).
Filter Attack / Decay / Sustain0.01 / 0.3 / 0Filter envelope.

Play

ParamRangeDefaultNotes
Play ModeMap / Notes / MosaicNotesSee Play modes.
Note MatchOff / Pitch / ZoneZoneNotes mode.
PressureOff, Proximity, Density, Bright, Sat, Pitch, Grain, JitterDensityWhat pad pressure changes.
Pressure Amt0 to 11
Velocity Amt0 to 10.80 ignores velocity.
Polyphony1 to 12848Grain voice ceiling.

Out

ParamRangeDefaultNotes
Filter0 to 10.5Centre off, left low-pass down, right high-pass up.
Resonance0 to 10
Saturation0 to 10tanh drive with make-up gain.
Dry Mix0 to 10Live input in the mix (Mosaic).
Volume0 to 10.8
Width0 to 11Stereo width.
Level Norm0 to 10.5Evens out slices from different recordings.
Pads & MIDI

Hands on

Pads

Notes: up to 16 held notes, each with its own envelope, sharing up to 128 grain voices.

Map: hold a pad to jump to a timbre cluster (cluster = note number mod 16). The last pad pressed wins; let go to return.

Pressure goes where the Pressure param says; velocity scales the level.

MIDI

Pitch bend transposes ±2 semitones. MIDI clock drives Follow = Sequence. CC 123 releases all notes. Poly aftertouch and channel pressure both work.

Recipes

Eight starting points

On the View page, the jog wheel browses them. A recipe sets play and sound parameters and never changes your corpus.

RecipeWhat it sets up
InitDefaults.
CloudMap + slow circular LFO, dense 400 ms grains, wide, smooth.
StutterNotes/Zone, 40 ms grains, tight neighbourhood, repeats allowed.
DroneMap + very slow LFO, 1.5 s Gauss grains, long attack and release.
ScatterMap + S&H LFO, random sizes, detune, reverse, the whole map in play.
PitchedNotes/Pitch: the corpus played chromatically.
MosaicMosaic mode, 80 ms grains, some dry input.
SequenceMap + clock-locked LFO, one cycle per bar. Needs the MIDI clock.
Corpus Builder

Build a corpus in the browser, hear it before the Move does

A web page that runs on your Move. Gather folders and samples, trim them, choose the descriptors, see and play the map, then load it onto Concat's track. It runs Concat's own analysis code (compiled to WebAssembly), so what you see is what the Move will compute: the same slice boundaries, descriptors within 0.06 %.

Open it

With the Move on your network (or connected over USB), open this in a desktop browser:

http://move.local:7700/api/remote-ui/module-assets/concat/builder/app.html

It is also one click away in schwung-manager's Remote UI: Concat's track has an Open the Corpus Builder button. If your Move answers on another name or address, replace move.local with it.

The page lives on the Move, served by schwung-manager, so the link above only works when your computer can reach the Move. It needs Concat 0.2.0 installed.

Build a corpus

  1. Gather. Drag folders and samples from the Library onto the corpus column, or use +. Ctrl+A selects every sample in a folder; drag them all, or press Add. ↑ ↓ step through samples and play each one.
  2. Listen and prune. A folder arrives collapsed: open it (▸) to hear its samples one by one and leave some out (✕, + brings them back). Only / Skip take name patterns like *Kick*.
  3. Trim. Click a sample: drag on its waveform to keep only that part. Click a slice to hear just that slice. For a sample inside a folder, Trim on its own pulls it out first.
  4. Slice. Onsets or fixed grains, min and max length, gate: saved into the corpus file.
  5. Choose descriptors. The Descriptors tab shows each one's range, median and histogram, and how much it shapes the map. Untick what you don't want Concat to listen for.

Hear the map

Two views, like Concat

Learned (3-D; Move view flattens it to the plane Concat uses) or Raw with Concat's X/Y menu. Colour by source, by a descriptor, or by Pad clusters. Click a source and its slices light up; click a dot to hear it.

Play it

Play the map (or P, or Shift+drag): press and move, and grains fire like Concat's Map mode, with Density, Grain and Spread. With Pad clusters, hold a pad in the grid to hear what that pad reaches on the Move.

Record

● Rec (or R) records what you play. Download the WAV, or save it to Recordings/Corpus Builder on the Move and add it straight back into the corpus.

Size it

The summary shows slices, files and length, and a meter against Concat's Pool Cap: it tells you the Pool Cap to set when the corpus is bigger than 128 MB.

Save and load

Save (Ctrl+S) writes UserLibrary/Corpora/<name>.concat. The header shows which track Concat is on and what it plays. Load on track N saves and makes that track play the corpus, with live progress. After that, every save reloads it on the Move while the old version keeps playing. Unsaved work survives a page reload.

Corpus files

The .concat format

Plain JSON, written by the Builder and readable by hand. Pick one in Source like a sample.

{
  "concat": 1,
  "name": "Night Market",
  "sources": [
    { "path": "Samples/Ahuntsic_Ambiances" },
    { "path": "Samples/MELLOTRON/M300SaxB-20.wav", "start": 0.4, "end": 6.2 },
    { "path": "Samples/DRUMS", "include": ["*Kick*"], "recurse": false }
  ],
  "exclude": ["*click*"],
  "descriptors": { "use": ["loud", "centroid", "flatness", "pitch", "mfcc1-13"] },
  "slicing": { "mode": "onset", "min_ms": 40, "max_ms": 600, "gate": 0.02 }
}
KeyMeaning
sourcesFolders and samples, relative to /data/UserData/UserLibrary. A missing one is skipped and counted.
start · endSeconds: only that part of a sample.
include · excludeFile-name patterns for a folder (*, ?, case ignored). A top-level exclude applies to every folder.
recursefalse keeps a folder to its own files.
descriptors.useloud, centroid, flatness, zcr, pitch, mfcc, mfccN, mfccA-B. Left-out descriptors leave the search, the clusters and the Learned map.
slicingmode, min_ms, max_ms, gate: replaces the Corpus page settings.

Live reload: when the loaded file changes, Concat rebuilds it in the background while the old corpus keeps playing, and only new or changed files are analysed again (a 9170-slice corpus went live in 8.6 s instead of 76 s).

Remote UI

Concat's panel in schwung-manager

In the manager's Remote UI (http://move.local:7700/remote-ui), Concat's track shows a small panel: the corpus playing and its status, a menu of your corpus files to load, and Open the Corpus Builder. Switch Interface to Default at the top of the track for every knob; the manager forgets that choice when the page reloads.

Memory & caches

What it costs

RAM

Pool Cap (128 MB by default, 512 max), checked against free RAM at every load with 350 MB kept for the Move. Too big a corpus keeps an even subset of slices across all of it.

CPU

On a 25,000-slice corpus, under 2 ms per audio block at worst (the budget is 2.9 ms). Analysis runs on its own thread on cores 0 to 2.

Disk

Caches in /data/UserData/schwung/concat-cache: whole corpus (instant reload) and per file (edits). Nothing cleans them yet; delete the folder to reclaim space.

Install

Get it on the Move

  1. Your Move runs Schwung 1.3.0 or later.
  2. Open schwung-manager (http://move.local:7700) and install a custom module from this repo (filliformes/concat-move), or upload concat-module.tar.gz from the latest release.
  3. Power-cycle the Move (Schwung reads module manifests at startup).
Troubleshooting

When it doesn't

You seeDo this
no audio filesThe pick has nothing Concat can read. Pick a sample, not a folder.
out of memory, kept oldLower Pool Cap or trim the corpus.
bad JSON: ...The corpus file has a mistake; the old corpus keeps playing. Save it again from the Builder.
No soundCheck Play Mode and Volume, that Analyze reached 100 %, and that a pad is held (Notes) or the position sits among the dots (Map).
Source shows a numberThe module metadata did not load: power-cycle the Move.
Builder: Concat is not on a trackAdd Concat to a track; the badge updates by itself.
Cheat sheet

Corpus Builder keys

Ctrl+ASelect every sample in the library folder
EnterAdd the selected samples
↑ / ↓Step through samples and play each one
→ / ←Open / close a folder source
SpacePlay / pause the selected sample
EscStop, clear selections, show the whole map
PMap: rotate ↔ play
Shift + dragMap: play while rotating
RRecord what you play
Ctrl+SSave to the Move
?Keys and tips
Credits

Made with

Built on Schwung by Charles Vestal and contributors. Decoding with dr_libs (public domain). Algorithms studied, not copied, from FluCoMa (BSD-3) and Diemo Schwarz's CataRT papers on corpus-based concatenative synthesis; the DSP is written from scratch.

Inspired by Mosaïque (site), a corpus-based concatenative synthesizer for Max for Live that lays a corpus out in a 3-D timbral space, made by UdeM's Laboratoire formes • ondes (LFO-lab).

Instrument, DSP and Builder by Filliformes. MIT license.