Skip to content

Play Your MIDI Gear

On this page you connect resonon to your MIDI gear. Resonon plays a bass line on a synth, you play along on a keyboard, and a knob on the keyboard turns a filter on the drums.

You need a synth that takes MIDI — hardware, or an instrument in a DAW — and a MIDI keyboard with at least one knob. Work in a project, as in Your First Sound.

Finish Signals and Modulation. Open your project’s src/main.non, evaluate RESET; on its own, then remove that line. Check that earlier audio and MIDI tracks are silent. Turn down the synth’s output before testing the connections, then raise it to a comfortable listening level.

Which ports your machine has is a fact about the machine, not about the music. So you do not write them into the piece. You declare them once in the preferences, and each one gets a short name, an alias. In a terminal, run:

Terminal window
resonon setup

On the MIDI pages, pick the port of your synth as the output and give it the alias synth. Pick your keyboard as an input and give it the alias kb. On the last page, confirm. The file ~/.resonon/preferences.toml now has two entries like these:

[[midi.outputs]]
alias = "synth"
port = "IAC Driver Bus 1"
[[midi.inputs]]
alias = "kb"
port = "KeyStep"

If a server is already running, run this line in VSCode so that it opens the new ports:

reload_preferences();

A MidiTrack is like an AudioTrack, but its notes go out of a MIDI port instead of into an instrument. Write this into src/main.non, select it, and press Cmd+Enter:

let bass = MidiTrack("bass");
bass >> MidiOutput("synth");
bass << [C2 _ C2 G2];
PLAY;

Your synth plays the bass line. >> picks the track’s output, as it does for an AudioTrack: here the synth port, on channel 1. A new track has no output until you route it. Everything you know about patterns works the same way here: only where the notes go is different.

Make a second track that takes its notes from the keyboard:

let keys = MidiTrack("keys")
.set_input("kb")
.set_monitor("in");
keys >> MidiOutput("synth", 2);

Play a few notes. They go through resonon to the synth, on channel 2, over the bass line.

  • .set_input("kb") connects the keyboard to the track.
  • .set_monitor("in") passes what comes in on to the track’s output. Without it, the track listens but does not play what you play.

A knob on your keyboard sends CC messages, each with a number. Let resonon find the number: run this line, and turn the knob within ten seconds.

use "std/signals" { Cc_learn };
let knob = Cc_learn();

The Output panel prints the knob’s call, for example Learned: Cc(74, 1): CC 74 on channel 1. knob is now a signal that follows the knob, from 0 to 1.

Add drums with a filter, and send the knob into the filter’s cutoff:

use "std/instruments" { Sampler, Kit };
use "std/effects" { Lowpass };
let drums = AudioTrack("drums");
drums.set_instrument(Sampler(Kit("CR-78")));
drums << [bd hh sd hh];
let filter = Lowpass("lowpass", 2000);
drums.set_effects(#[filter]);
filter.parameter("Cutoff") << knob.smooth(50).range_exp(200, 8000);

Turn the knob. The drums go from dark to bright.

  • .smooth(50) smooths the knob’s 128 steps over 50 ms, so the filter does not click.
  • .range_exp(200, 8000) maps 0–1 onto 200 Hz to 8000 Hz. It spreads the range the way the ear hears pitch.

Cc_learn() waits for a knob each time it runs. When you save the piece, write the call it printed instead:

use "std/signals" { Cc };
let knob = Cc(74, 1);
STOP;

Every sounding note gets a note-off, so nothing hangs on the synth.