Skip to main content

Instruments

In this section we will give Tutorial Groove its sound: define instruments with inst for each Game Boy voice (pulse, wave, and noise), then assign them to channels. Instrument names can also be used as pattern tokens (especially useful for percussion), and you can switch instruments inside a pattern with inst(name) or inst(name,N).

Instrument type (type=) and its fields are chip-specific. This tutorial uses the Game Boy sound chip. For other chips see Sound Chip Plugins.

A common Game Boy layout for instruments (and the one Tutorial Groove uses) is:

ChannelTypeRole
1pulse1Lead melody
2pulse2Harmony / counter
3waveBass
4noiseDrums

Note: the patterns below use the note syntax from Notes and lengths (C4, C4:4, ., _).

Pulse 1

Channel 1 is a pulse oscillator. Set type=pulse1, pick a duty, and give it a hardware envelope with env:

Add the lead

Interactive playback loads in the browser.

…
inst lead type=pulse1 duty=50 env=gb:13,down,1 gm=81

pat lead_pat = E5 . G5 C6 . G5 E5 . D5 . F5 A5 . G5 . .
…
FieldNotes
dutyPulse timbre — the fraction of each wave cycle that is “on” (high). Game Boy allows only 12.5, 25, 50, or 75 (percent). This shapes the sound, not how long a note lasts in a pattern. 12.5 / 25 sound thinner; 50 is a balanced square; 75 sounds darker/thicker (like 25% flipped).
envHardware volume envelope: gb:<initial>,<up|down>,<period>. initial is starting volume (0–15); up/down is the direction; period is how fast it steps (1–7). Use period=0 to hold a constant volume. Short periods sound plucky; longer ones fade more slowly. Example: gb:13,down,1.
gmOptional General Midi (GM) program 0–127 - this is only used for MIDI export instrument mapping

Hardware sweep

Pulse 1 can also slide pitch with a hardware frequency sweep: sweep=<time>,<up|down>,<shift> (Pulse 2 cannot). Example: sweep=7,up,3. Use a constant envelope (env period 0) so the note stays loud while the pitch moves:

Pulse 1 sweep

Interactive playback loads in the browser.

…
inst riser type=pulse1 duty=50 sweep=7,up,3 env=gb:15,down,0

pat rise = C3:16
…
FieldNotes
timeHow often the sweep steps (0–7). Higher values update more slowly.
directionup raises pitch; down lowers it.
shiftHow strongly each step changes frequency (0–7). Larger values move pitch faster/further.

Hardware sweep is more often used for sound effects rather than music.

Pulse 2

Channel 2 is the second pulse — same duty and envelope options, but no hardware sweep. It is typically used to add harmony / counter under the lead:

Add the harmony

Interactive playback loads in the browser.

…
inst harmony type=pulse2 duty=25 env=gb:10,down,2 gm=80

pat harmony_pat = C4:4 E4:4 G4:4 E4:4
…

Wave

Channel 3 plays a custom wavetable — 32 samples that define the waveform itself. Shape the table and you can get smooth basses, soft pads, bright leads, bells, or metallic / organ-like tones; Tutorial Groove uses a gentle triangle-like table for bass.

Provide the table as 32 nibbles (0–15), a 16-value shorthand (tiled to 32), or a 32-character hex string. Output level is set with volume= — only 0, 25, 50, or 100:

Add the wave bass

Interactive playback loads in the browser.

…
inst bass type=wave volume=100 wave=[0,2,4,6,8,10,12,14,15,14,12,10,8,6,4,2] gm=33

pat bass_pat = C3 . . C3 G2 . . G2 A2 . . A2 F2 . G2 .
…

Noise

Channel 4 is LFSR noise — random-ish hiss shaped by the sound chip. In songs it is typically used for percussion (kicks, snares, hats, toms) and short FX hits rather than pitched melody.

The noise channel does not play musical pitch the way pulse and wave do. Timbre comes mainly from gb:width and the envelope; how “high” or “low” the noise sounds is set by a clock rate. On Game Boy that clock is chosen with uge_note= (hUGETracker note names like C-7), so BeatBax playback and UGE export stay in sync. Patterns still write ordinary notes (e.g. C6) for when each hit fires.

On Game Boy, snares usually use gb:width=7 (metallic crack); hi-hats use gb:width=15 (broader white noise). A short pitch “pop” (via pitch_env — covered under Instrument macros below) helps the snare read as a hit:

Noise snare

Interactive playback loads in the browser.

…
inst snare type=noise gb:width=7 env=gb:13,down,1 length=16 uge_note=C-7 pitch_env=[0,7,0] vol_env=[13,10,6,2]

pat hits = C6 . C6 . C6 C6 . .
…
FieldNotes
gb:width7 = metallic (snares/toms); 15 = white noise (hats/cymbals)
uge_note=Noise clock in hUGETracker notation (e.g. C-7). Controls how high/low the noise sounds in BeatBax and what is written to UGE. Prefer this for percussion you care about hearing correctly.
envHardware envelope, e.g. gb:13,down,1

Instrument macros

Software macros (pitch_env, vol_env, …) add per-tick motion on top of the hardware voice. On Game Boy they also feed hUGETracker UGE subpatterns.

The first four hits below are a plain noise kick; the next four use the same notes with a pitch drop and volume decay — listen for the difference. (inst(name) switches which instrument plays the following notes; more on that in Sequencing.)

Noise kick program

Interactive playback loads in the browser.

…
inst kick_plain type=noise gb:width=7 uge_note=C-6 length=16
inst kick       type=noise gb:width=7 uge_note=C-6 length=16 pitch_env=[0,-2,-4,-6] vol_env=[15,12,8,4]

# Several plain hits, then the same notes with macros (pitch drop + volume decay)
pat kicks = inst(kick_plain) C5:4 . C5:4 . C5:4 . C5:4 . inst(kick) C5:4 . C5:4 . C5:4 . C5:4 .
…

For full details see: Instrument macros.

Percussion with named tokens

Writing C5 / C6 on every drum hit works, but it is clearer to use the instrument name as the pattern token (kick, snare, hat). Add note= so each name has a default pitch; keep uge_note= for the noise clock (as above).

Drum kit

Interactive playback loads in the browser.

…
inst kick  type=noise gb:width=7 uge_note=C-6 length=16 pitch_env=[0,-2,-4,-6] vol_env=[15,12,8,4]
inst snare type=noise gb:width=7 env=gb:13,down,1 length=16 uge_note=C-7 note=C6 pitch_env=[0,7,0] vol_env=[13,10,6,2]
inst hat   type=noise gb:width=15 env=gb:5,down,1 uge_note=C-8 note=C6

pat drums = kick . hat . snare . hat hat kick . hat . snare hat hat .
…

More detail: Instrument note mapping.

Sharing instruments

As well as defining instruments from scratch in each song you can also reuse instruments defined in other files with the import "…" directive. See Imports for more information.

Putting it together

Defining instruments is not enough on its own — BeatBax only plays a voice when you assign it with a channel line. Each line maps one chip voice to:

  1. a default instrument (inst …)
  2. the music it should play (pat … for a single pattern, or seq … for a list of patterns)

Tutorial Groove uses all four Game Boy voices — pulse lead, pulse harmony, wave bass, and noise drums. The Game Boy can play at most these four voices at once; other chips may have fewer or more channels (see Sound Chip Plugins).

channel 1 => inst lead seq lead_pat
channel 2 => inst harmony seq harmony_pat
channel 3 => inst bass seq bass_pat
channel 4 => inst snare seq drums_pat

You need one channel line per voice you want to hear. Patterns, named sequences, and other channel forms are covered in Sequencing. Here is the full song so far:

Tutorial Groove — instruments

Interactive playback loads in the browser.

song name "Tutorial Groove"
song artist "BeatBax Tutorial"
song description "Built step by step in the BeatBax Game Boy tutorial."
song tags "tutorial, gameboy"

chip gameboy
bpm 140

inst lead    type=pulse1 duty=50 env=gb:13,down,1 gm=81
inst harmony type=pulse2 duty=25 env=gb:10,down,2 gm=80
inst bass    type=wave volume=100 wave=[0,2,4,6,8,10,12,14,15,14,12,10,8,6,4,2] gm=33
inst kick    type=noise gb:width=7 uge_note=C-6 length=16 pitch_env=[0,-2,-4,-6] vol_env=[15,12,8,4]
inst snare   type=noise gb:width=7 env=gb:13,down,1 length=16 uge_note=C-7 note=C6 pitch_env=[0,7,0] vol_env=[13,10,6,2]
inst hat     type=noise gb:width=15 env=gb:5,down,1 uge_note=C-8 note=C6

pat lead_pat    = E5 . G5 C6 . G5 E5 . D5 . F5 A5 . G5 . .
pat harmony_pat = C4:4 E4:4 G4:4 E4:4
pat bass_pat    = C3 . . C3 G2 . . G2 A2 . . A2 F2 . G2 .
pat drums_pat   = kick . hat . snare . hat hat kick . hat . snare hat hat .

channel 1 => inst lead    seq lead_pat
channel 2 => inst harmony seq harmony_pat
channel 3 => inst bass    seq bass_pat
channel 4 => inst snare   seq drums_pat

play

Next

Continue with Sequencing — how pat and seq work in more detail, and how to chain different patterns so each part can vary instead of looping a single bar.