Subsystem Search

Keeping a sample library

By the end of this chapter, your library grows from one session to the next and stays tidy: new sounds load while Subsample runs, a folder of sounds comes in whole, and near-duplicates are found and thinned.

The project so far

The project from A kit of your own: your kit in a folder of its own, kits/kitchen/, with its map, its names and its sounds, and the player pointed at it.

$ mkdir kitchen-kit
$ cd kitchen-kit
$ subsample --init
…
recorder:
  enabled: true
player:
  midi_map: kits/kitchen/midi-map.yaml
  watch_midi_map: true
  enabled: true
similarity:
  weight_timbre_onset: 2
detection:
  release_threshold_db: 4
  retrigger_threshold_db: 15
  min_peak_db: -45
tempo:
  bpm: 120
notes:
  kick: 36
  snare: 38
  hat: 42
  open_hat: 46
cc:
  brightness: 74
channels:
  kit: 10
definitions: { my: names.yaml }
channel: my.kit
templates:
  pad:
    process:
      - compress: true
  quiet:
    gain: -6
assignments:
  - name: Kick
    template: pad
    notes: my.kick
    select: { where: { directory: kick }, pick: any }
  - name: Snare
    template: pad
    notes: drum.snare_1
    select: { where: { directory: snare }, pick: any }
    stack: true
  - name: Snare layer
    template: [pad, quiet]
    notes: drum.snare_1
    select: { where: { directory: layer }, pick: any }
    stack: true
  - name: Closed hi-hat
    template: pad
    notes: drum.hi_hat_closed
    select: { where: { directory: hat }, pick: any }
  - name: Open hi-hat
    template: pad
    notes: drum.hi_hat_open
    select: { where: { directory: open-hat }, pick: any }
    silenced_by: drum.hi_hat_closed

What lands on disk

Every sound Subsample keeps is three files side by side: the audio, what Subsample measured in it, in .analysis.json, and a picture of it, .preview.png. A sound recorded live is named for the moment it ended, and one cut from a file for the file and its place in it, as hits_1 was.

The audio is a WAV file unless you choose FLAC, which is lossless and smaller:

recorder:
  audio:
    audio_format: flac
    bit_depth: 24

recorder.audio.audio_format chooses between wav and flac, and recorder.audio.bit_depth its bit depth, 16, 24 or 32. FLAC takes 16 or 24, so it and 32 together are refused when Subsample starts, and a 32-bit file you bring in under FLAC is kept as WAV. The sounds you have already load whatever you choose here.

The picture shows the sound's shape and where its energy lies, so you can tell a thud from a tick in a file manager, where it sits beside the audio as a file of its own. What it is drawn from is kept in the analysis file too, so a picture you delete is drawn again the next time Subsample starts. recorder.previews set to false writes neither.

A library across sessions

What Subsample records goes to recorder.directory, and what it plays from is loaded from library.directory, and both are samples/captures unless you change them. So every sound you record joins the library, and the library is there, and larger, the next time you start. Point the two at different folders to play one collection while you record into another.

When Subsample starts, it loads the library folder and every folder inside it, so you can sort a library into folders of your own. A sound is known by its path, so two sounds in different folders can share a name, and then a name in a map chooses both, and a directory narrows it to one.

At the same start, it tidies: a sound that has lost its analysis or its picture gets them again, a sound whose analysis an earlier release wrote, or whose audio has changed, is measured again, and an analysis or a picture whose sound has gone is deleted. So you can rename, move and delete sounds between sessions, in any program, and the library follows. The first start after an upgrade can take a while, as it measures your sounds again.

How much it holds in memory

Subsample holds the library in memory, to play it with no wait. When a new sound would take it past library.max_memory_mb, it lets go of the oldest sounds in memory, and a note that played one plays its next-best match instead. It never deletes a file:

library:
  max_memory_mb: 512

Left out, it is a share of max_memory_mb, everything Subsample may hold, which it sets from the machine's memory. Set either on a machine that runs other software hungry for memory.

When the player starts, it adds the library's share to transform.max_memory_mb, what it may hold of processed sounds, and warns if the two come to more than three quarters of the machine's memory: as they fill, the machine could run short, and the audio break up.

New sounds while it plays

Subsample loads the library when it starts. To have it load a sound that arrives while it plays, have it watch the library:

library:
  watch: true

library.watch loads a WAV, FLAC, AIFF, OGG or MP3 file that appears in library.directory, whatever wrote it: another program, a script, or a copy you make. It waits until the file stops growing, measures it if nothing measured it already, and adds it to the library, where a map can choose it. A file deleted or renamed away leaves the library too. It watches the folder itself and not the folders inside it, and it needs the player on.

A folder of sounds at once

subsample import, which brought your taps in whole in Pitched instruments and loops, takes a whole folder of sounds that are already cut as readily, from a sample pack or another recorder, one sample each:

Example not checked: it is not run when this site is built.

$ subsample import ~/Downloads/percussion/*.wav

Each is trimmed of the silence at either end, given a fade too short to hear wherever an edge would otherwise click, written in the format you chose, measured, and put in recorder.directory, and each prints a line with its length, its peak and its loudness. --to puts them in another folder, and --force replaces sounds already there with the same name.

Near-duplicates

A microphone left running records the same sound again and again. subsample catalog writes a table, one line for each sound in the library, and with --group it gathers the sounds that are nearly the same into piles, biggest first, marking the loudest in each as the one to keep:

Example not checked: it is not run when this site is built.

$ subsample catalog --group -o library.csv

A recording for this step is planned. Until then, use one of your own.

The sound you struck three or four times alike in A drum kit from a recording is a pile of three or four. Open library.csv in a spreadsheet: group numbers the piles, group_size says how many are in each, and group_keeper is yes for the one to keep. Listen to a pile, and delete the sounds you do not want, each with its two files; the next start tidies anything you missed. --similarity-threshold says how alike sounds must be to share a pile, and in one room everything is a little alike, so listen to a pile or two before trusting it.

--order similarity lists each sound next to the one it sounds most like, so choosing between them is a matter of comparing neighbours. Four columns point at the sounds most likely to be thrown away: snr_db, how far the sound rises above the quiet in it, near_silent, clipping_risk, and noisiness, from 0, a clean hit, to 1, noise from end to end.

With a library that looks after itself, the next chapter plays two kits at once, and switches the drums between kits as you play.