Tying a control to a synth

A control can be tied to a setting of a synth. The dial then is that setting: it takes its range, its unit and where it starts from the synth, and turning it sets it. There is nothing in between to write.

const lead = makeSynth("lead")

dial("cutoff", lead, "cutoff")
scope(lead)
keyboard(lead, { octave: 4 })

function draw() {
  background("midnightblue")
}

Play a key and turn the dial while the note sounds. The scope shows the wave change.

What can be tied

CallWhat it is
dial(label, synth, "setting")A dial that is a setting with a number: "cutoff", "attack", "echo"
slider(label, synth, "setting")The same, as a slider
select(label, synth, "setting")A setting that is a choice: "wave", "filter", "mode". The choices come from the synth
toggle(label, synth, "setting")A setting that is on or off
keyboard(synth)Piano keys that play it, and light up as it plays
scope(synth)The wave it is making
meter(synth)How loud it is

The setting is any of the synth's, by any of its names: Every sound, synth and setting lists them. The label may be left out, and is then the setting's name: dial(lead, "volume").

A setting that is changed some other way moves its dial: set lead.cutoff = 400 in the program and the dial turns.

A whole panel

const lead = makeSynth("lead")

select("wave", lead, "wave")
dial("cutoff", lead, "cutoff")
dial("resonance", lead, "resonance")
dial("echo", lead, "echo")
slider("attack", lead, "attack")
slider("release", lead, "release")
scope(lead)
meter(lead)
keyboard(lead, { octave: 4 })

function draw() {
  background("midnightblue")
}

Try changing "lead" to "bass", "pad" or "chip", and adding dial("vibrato", lead, "vibrato").

All the sound together

soundOutput() is everything the program is playing (sound_output() in Python). A scope and a meter on it show the whole sound, whatever is making it:

scope(soundOutput())
meter(soundOutput())

function onMouseDown() {
  playNotes("C4 E4 G4 C5", 0.25)
}

mainSynth() is the synth that playNote plays (main_synth()), so a keyboard can play it and a dial can shape it:

keyboard(mainSynth())
dial("reverb", mainSynth(), "reverb")

Two synths, two rows

const lead = makeSynth("lead")
const bass = makeSynth("bass")

label("Lead")
dial("cutoff", lead, "cutoff")
dial("echo", lead, "echo")
row()
label("Bass")
dial("cutoff", bass, "cutoff")
dial("sub", bass, "sub")
keyboard(lead, { octave: 4 })

The microphone

The microphone is a synth to the controls too. Its voice is a choice, its pitch is a dial and hearing yourself is a switch:

const mic = useMicrophone()

select("voice", mic, "voice")          // robot, chipmunk, monster and the rest
dial("pitch", mic, "pitch")            // -12 to 12 semitones
dial("echo", mic, "echo")
toggle("listen", mic, "listening")     // wear headphones before you switch this on
scope(mic)
meter(mic)

The scope and the meter show your voice even while it is not heard. The microphone is not connected in Circuitry's own preview yet: there the controls appear and the scope stays flat.

A sample or a recording

A sample is a synth, and so is a recording. A keyboard plays it at any pitch and a dial is any of its settings:

const meow = loadSample("meow.wav")

dial("reverb", meow, "reverb")
dial("cutoff", meow, "cutoff")
toggle("backwards", meow, "reverse")
keyboard(meow, { octave: 4 })          // middle C is the sound as it was recorded

A knob on your desk turns a dial

With a MIDI controller plugged in, learn ties the next knob you turn to a setting. The dial on the screen then turns with the knob, and still turns by hand:

const lead = makeSynth("lead")
const cutoff = dial("cutoff", lead, "cutoff")
const echo = dial("echo", lead, "echo")
keyboard(lead, { octave: 4 })

lead.playFromMidi()                                          // a MIDI keyboard plays it too
lead.learn("cutoff", (value) => { cutoff.value = value })    // the first knob you turn
lead.learn("echo", (value) => { echo.value = value })        // and the second

In JavaScript the function given to learn is called with each new value, and sets the dial. In Python a dial tied to the same setting turns by itself. MIDI is not connected in Circuitry's own preview yet: there the dials and the on-screen keys work by hand.

Which MIDI device

The MIDI keyboard a program listens to is a target too, with a "device" and a "channel", so choosing one is a select:

const lead = makeSynth("lead")
lead.playFromMidi()

select("midi in", midiInput(), "device")
select("channel", midiInput(), "channel")
meter(midiInput())                       // a light that flashes when a key is hit
keyboard(lead)

The choices follow what is plugged in. Choosing the device on the screen has the rest, and midiOutput() for what is sent. Like the knob above, it needs MIDI, which Circuitry's own preview does not have yet.

A target of your own

A control is not tied to synths by name. It can be tied to anything, and what it does depends on what the thing can do. Every part is optional.

The thing hasWhat a control does with it
A property, and nothing elseReads and writes it: dial("size", ball, "radius", { min: 5, max: 80 })
set(name, value), get(name)Calls them to write and read a setting
describe(name)Takes the range, the unit, the step and the choices from it. labels: { 0: "auto" } shows a name in place of a value
onChange(fn)Keeps up when the target says its choices have changed
noteOn(note, velocity), noteOff(note)A keyboard plays it. note is a number where 60 is middle C, and velocity is from 0 to 1
notes()A keyboard lights the notes that are sounding
samples()A scope draws it: numbers from -1 to 1
level()A meter shows it: from 0 to 1

In Python the names are note_on and note_off.