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
| Call | What 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 recordedA 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 secondIn 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 has | What a control does with it |
|---|---|
| A property, and nothing else | Reads 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.