Hello, Sound
This content is for v0.7. Switch to the latest version for up-to-date documentation.
Let’s make our first sounds. This page quickly covers the live-evaluation model and walks you through your first drum beat and melody.
How Live-Evaluation Works
Section titled “How Live-Evaluation Works”The common way to run Resonon code and hear changes live is using the select-and-execute workflow in Visual Studio Code. You write Resonon code in a .non file, select (highlight) it, and press Cmd+Enter to execute it.
The first time you do this, the extension will automatically start a new Resonon runtime with active server. Then it will send the highlighted code to the server to run. Subsequent code execution then uses that same runtime, so Resonon “remembers” what was exected before.
Alternatively you can use the Resonon extension menu in the sidebar to start a server-runtime and connect to it, before running any Resonon code.
As a first test write the line below into a new .non file, select it and press Cmd+Enter. The output appears in VSCode’s Output panel (select “RESONON” from the dropdown).
PRINT "Hello, RESONON!";Session State
Section titled “Session State”Each evaluation shares the same session, so any state is “remembered” by the runtime and accessible in the code that gets evaluated after. To see this, select and execute the two following lines one by one. The first line defines a new greeting string and assigns the message.
The second line the prints the previously defined greeting to the console.
let greeting = "Hello";PRINT greeting;You can highlight and execute an arbitrary amount of Resonon code at once - Just make sure the highlighted code is valid.
Your First Sound
Section titled “Your First Sound”Resonon has a built-in sample engine. Let’s use it to play a simple drum rhythm. Execute the following code and you should hear it play. We will go over the example line by line afterwards.
use "std/instruments" { Sampler, Kit };
let drums = AudioTrack("drums");let sampler = Sampler(Kit("cr78"));drums.load_instrument(sampler);
drums << [bd sd bd sd];
PLAY;You don’t have to understand all new concepts in their entirety just now. Tracks, instruments and patterns are all deep topics that can be explored as you progress in your Resonon journey. Check the relevant docs pages if you want to read more about anything unknown you encounter. The following guides will explain things in more detail.
Here is a quick explanation of what each line does:
-
use "std/instruments" { Sampler, Kit };Imports
SamplerandKitfrom the Resonon standard library, so we can use them in our program. Note thatAudioTrackis an elementary feature of the language and thus needs no import. -
let drums = AudioTrack("drums");Creates a new audio track called “drums”. Think of a tracks like in regular DAW. They have volume and pan, you can load an instrument and a chain of effects onto them, and their output is default-routed to the master output. More on this later.
-
let sampler = Sampler(Kit("cr78"));Creates a new
Samplerinstrument instance using the CR-78 drum sampleKit. Instruments can be loaded onto audio tracks, and then sent notes via patterns for playback. TheSampleris a Resonon built-in instrument used for non-melodic sample playback (mainly drums). We will later learn about theSamplerMelodicfor sampling melodic instruments, as well as loading any VST3 or CLAP plugin instrument, and even writing your own instruments fully within the Resonon lanuguage. -
drums.load_instrument(sampler);Loads the sampler instrument we just created onto the audio track. Any track can have exactly one instrument loaded onto it. If we then send notes to the track, it will automatically forward them to the loaded instrument. Of course, it is also possible to load effects onto a track, but for now let’s keep things simple.
-
drums << [bd sd bd sd];Assigns a pattern to the drums track for playback. The
bd(bass drum) andsd(snare drum) are sample names from the CR-78 kit. Patterns are the heart of musical composition and sequencing in Resonon. The following guide will dive deeper into how patterns work. For now, just note that patterns are repeating and have a fixed length called the cycle-time. This is then divided by the number of events present in the pattern to determine their length. Per default, the cycle-time in resonon is set to 120bpm at 4 beats per cycle, so 2 seconds. In the above pattern we have 4 total events, so each drum hit gets exactly one beat of time - or 0.5 seconds.If you ever worked with the legendary Alex McLean’s TidalCycles or its newer cousin strudel.cc, you will see many parallels in how Resonon patterns work. We`re standing on the shoulders of giants here.
-
PLAY;Starts playback, so you hear the sequenced sounds.
Drum Samples
Section titled “Drum Samples”Sample names like bd and sd are defined by the loaded kit. The CR-78 kit includes the following (and more):
| Name | Sound |
|---|---|
bd | Bass drum |
sd | Snare drum |
hh | Hi-hat |
cy | Cymbal |
cp | Clap |
cb | Cowbell |
rs | Rimshot |
Now try a slightly more interesting beat. What do you hear?
drums << [bd _ sd _, hh hh hh hh];The comma creates a stack — both layers play simultaneously. The kick-snare rhythm plays alongside steady hi-hats. (More on patterns in the following guide.)
Use _ (underscore) for silence:
drums << [bd _ _ sd, hh _ hh _];Rests take up the same time as a note — they create space in the pattern.
Notes and Melodies
Section titled “Notes and Melodies”Patterns can contain pitched notes using scientific pitch notation. C4 is middle C (MIDI note 60):
use "std/instruments" { SamplerMelodic, Kit };
let keys = AudioTrack("keys");keys.load_instrument(SamplerMelodic(Kit("epiano")));keys << [C4 E4 G4 C5];| Notation | MIDI | Description |
|---|---|---|
C4 | 60 | Middle C |
D4 | 62 | D above middle C |
C#4 / Db4 | 61 | Sharps and flats |
C5 | 72 | One octave up |
60 | 60 | MIDI number directly |
Notes and numbers can be mixed freely: [C4 62 E4 67].
Control the playback speed with setbpm:
setbpm(140); // 140 BPM, 4 beats per cycle (default)A cycle is the fundamental time unit — patterns repeat every cycle. With 4 beats per cycle at 120 BPM, one cycle lasts 2 seconds. A pattern with 4 elements gives each element one beat:
setbpm(120); // 2 seconds per cycledrums << [bd sd bd sd]; // Each hit = 1 beat = 0.5 secondsUse the second argument when your patterns have more or fewer than 4 beats:
setbpm(120, 8); // 8 beats per cycle (4 seconds per cycle)Transport Controls
Section titled “Transport Controls”| Action | Code | Keybinding |
|---|---|---|
| Play | PLAY; | F5 |
| Pause | PAUSE; | F5 (toggle) |
| Stop & reset | — | Shift+F5 |
| Reset session | — | Ctrl+Shift+F5 |
Adding Effects
Section titled “Adding Effects”Apply built-in effects to any audio track:
use "std/effects" { Delay, Lowpass };
drums.load_effect(Delay(0.25, 0.5)); // 250ms delay, 50% feedbackdrums.load_effect(Lowpass(2000)); // Cut frequencies above 2kHzEffects chain in the order you load them. Re-evaluating with different parameters replaces the existing effect by name:
drums.load_effect(Delay(0.125, 0.3)); // Replaces the previous DelayBuild Your Own
Section titled “Build Your Own”Beyond built-in effects, Resonon lets you write custom DSP effects and synthesizers directly in the language — no plugins or external tools needed:
dsp instrument SineOsc { voice state phase: 0.0;
fn render(note, velocity, gate) -> (out_l, out_r) { let freq = mtof(note); phase = fract(phase + freq * INV_SR); let sample = sin(phase * TWOPI) * velocity * gate; return (sample, sample); }}
let synth = AudioTrack("synth");synth.load_instrument(SineOsc());synth << [C4 E4 G4 C5];This is a complete polyphonic synthesizer in 8 lines of DSP code. The Custom DSP page covers effects, instruments, parameters, and filters in detail.
Next Steps
Section titled “Next Steps”You’ve played samples, applied effects, and heard a custom synth. Next, learn how patterns work in depth and how to send them to external synthesizers via MIDI:
- Patterns & Tracks — Time division, nesting, chords, and MIDI