Skip to content

Cookbook Audio

bryanthaboi edited this page Jul 27, 2026 · 2 revisions

Cookbook — audio

Def shapes and the full pipeline: Guide: Audio Authoring; worked path: Tutorial 09.

R06 — Retarget a map's music

mod.content.map_songs:override("PALLET_TOWN", "Music_Routes1")

Checkpoint: Pallet Town plays the Route 1 theme. map_songs maps map id to a music id; a new song registered through music slots in the same way.

R07 — Replace one SFX with a file

mod.content.sfx:override("Save", { file = mod.assets:path("assets/save.ogg") })

Checkpoint: saving plays your sound; every other SFX stays chip-synthed. Defs are shape-dispatched per id — replacing one never touches the rest. A def that fails to load is skipped with a mod-attributed log line when its cue fires.

R26 — Author a chiptune (ChipAsm)

local ChipAsm = require("src.audio.ChipAsm")

mod.content.music:register("Music_ModChip", ChipAsm.song({
  tempo = 140,
  channels = {
    { program = {
        { label = "top" },
        { notetype = { speed = 12, volume = 15, fade = 2 } },
        { octave = 4 },
        { note = "C", len = 4 }, { note = "E", len = 4 },
        { note = "G", len = 4 },
        { loop = { count = 0, to = "top" } },
    } },
  },
}))
mod.content.map_songs:override("PALLET_TOWN", "Music_ModChip")

Checkpoint: an authentic GB channel program plays with no audio file in the mod. src.audio.ChipAsm is a supported require; the event vocabulary is in Audio Authoring.

R43 — CD-quality map soundtrack (file-backed)

MSU protocol is not implemented; streamed { file, loopFile } songs are the supported path for CD-quality replacements:

mod.content.music:override("Music_PalletTown", {
  file = mod.assets:path("assets/pallet_intro.ogg"),
  loopFile = mod.assets:path("assets/pallet_loop.ogg"),
})

Checkpoint: Pallet Town plays your OGG; other maps stay chip. Pair with music.select if you need contextual swaps.

R44 — Distance / indoor music volume

mod.hooks:wrap("music.volume", function(next, vol, ctx)
  vol = next(vol, ctx)
  if ctx.mapId and ctx.mapId:find("POKECENTER") then
    return vol * 0.5  -- muffled indoors
  end
  return vol
end)

Checkpoint: centers are quieter; the hook re-runs every frame while wrapped so tile-distance ramps work too (ctx.x / ctx.y).

Clone this wiki locally