Subsystem Search

Playing with other software

By the end of this chapter, a sequencer on the same machine plays Subsample through a MIDI port of Subsample's own, Subsample keeps to the sequencer's tempo, and another program hears from Subsample each time it captures a sound.

The project so far

Subsample as Installing Subsample installs it:

$ uv tool install "subsampler==0.6.12"
Resolved … packages in …
Prepared … packages in …
Installed … packages in …
…
Installed 1 executable: subsample

And the project from Several kits at once, and switching live: the player on the ensemble of your keyboard and two kits, midi-map.yaml, with the maps and kits as that chapter left them. Only the configuration matters here:

$ mkdir kitchen-kit
$ cd kitchen-kit
$ subsample --init
…
recorder:
  enabled: true
  audio:
    audio_format: flac
    bit_depth: 24
player:
  midi_map: midi-map.yaml
  watch_midi_map: true
  enabled: true
library:
  max_memory_mb: 512
  watch: true
similarity:
  weight_timbre_onset: 2
detection:
  release_threshold_db: 4
  retrigger_threshold_db: 15
  min_peak_db: -45
tempo:
  bpm: 120

A MIDI port of Subsample's own

A sequencer on the same machine needs somewhere to send its notes. Subsample can make a MIDI port for it:

player:
  virtual_midi_port: Subsample Virtual MIDI

Start Subsample, and while it runs, other software on the machine sees a MIDI port called Subsample Virtual MIDI to send to, as it would a keyboard's. With player.virtual_midi_port set, Subsample opens no MIDI device of its own, and ignores player.midi_device.

Point any sequencer at that port, and it plays what a keyboard would: the kitchen kit on MIDI channel 10, the worktop kit on 11, and the keyboard, the held note and the loop on 1. In Subsample's sister project Subsequence, an algorithmic MIDI sequencer for Python, name the port with output_device="Subsample" when you make the Composition, as its first chapter names a port, or add it beside another with composition.midi_output.

In time with the sequencer

Subsample keeps the tempo you gave it in Pitched instruments and loops, tempo.bpm, which it quantises to and counts beats in. Change the tempo in your sequencer and forget to change it here, and the two drift apart without a word. A sequencer that sends MIDI clock can set it instead:

tempo:
  bpm: 120
  source: midi

With tempo.source set to midi, Subsample takes its tempo from the clock arriving on its MIDI input, the port above, and tempo.bpm is the tempo until the first clock arrives, so keep it. Subsequence sends clock with composition.clock_output().

Messages over OSC

Subsample can tell other software what it does, as it does it, in OSC, Open Sound Control: a message over the network each time it captures a sound and each time a sound joins the library, which a sequencer, a visualiser or a script of your own can listen for. OSC needs one more package, Subsample's osc extra, so install Subsample again with it:

$ uv tool install "subsampler[osc]==0.6.12"
Resolved … packages in …
Prepared 1 package in …
Installed 1 package in …
…
Installed 1 executable: subsample

Then turn it on:

osc:
  enabled: true

Subsample now sends two messages to port 9000 on this machine, where Subsequence listens:

osc.send_host and osc.send_port send them elsewhere.

Subsample can listen too, on two receivers of its own. One takes /sample/import, with the path of an audio file to load into the library to play at once:

osc:
  receive_enabled: true

It listens on port 9002, osc.receive_port, and only to this machine. It reads whatever file a message names, and writes what it measured beside that file, as it does beside a sample it cuts, with its picture where recorder.previews is on. It asks no one first, so osc.receive_host set to 0.0.0.0 to hear other machines belongs only on a network you trust. A sound loaded this way stays until Subsample stops; one kept in library.directory stays for good. Subsequence can send it too, at any beat, with p.osc, once composition.osc sends to port 9002, so a piece can bring in a new sound exactly when it wants one.

The other plays notes, each through your MIDI map as the same MIDI note would play:

osc:
  notes_enabled: true

It listens on port 9003, osc.notes_port, and only to this machine. osc.notes_host set to 0.0.0.0 hears other machines too, which is safer than it is for imports, since a note can only play a sound. /note/on carries a MIDI channel from 1 to 16, a note from 0 to 127 and a velocity as a decimal from 0 to 1, and /note/off a MIDI channel and a note.

A note in an OSC bundle plays at the time the bundle names, as a MIDI note arriving then would, so software that sends its notes a little ahead has each played on its time. A note sent on its own, or one whose time has passed, plays as it arrives. A bundle from another machine needs the two machines' clocks to agree.

A timed note lands its hit on its time, not its start. A sound with a quieter lead-in before its hit, as the foot of a hi-hat pedal comes before the cymbals meet, starts early by as long as the lead-in lasts:

With software playing Subsample, the next chapter sends its sounds out of an interface with many outputs, and records from the inputs you choose.