Cookbook: audio
Start by reusing a song (R06) or playing your own file (R07/R43). ChipAsm is a separate, advanced route.
Setup: a working mod from Getting Started. Examples target Red/local single-player unless a recipe explicitly says otherwise. Use Modding Basics for syntax and Glossary for unfamiliar terms. Save and restart after content edits. A validation pass and an in-game checkpoint are different checks.
Where code goes: insert Lua fragments inside your existing
return function(mod) ... end in main.lua. A complete-file label or named
other file overrides that default. Do not paste a second entry function
inside the first. Read the recipe's requirements before copying its code.
For output, use Read log output; for IDs,
use Find internal IDs.
Audio definition formats and the full workflow: Guide: Audio Authoring; worked path: Tutorial 09.
R06 - Retarget a map's music
First change. Before you paste: A working mod. This reuses an imported song, so no new audio file is needed. Enter Pallet Town after restarting and listen.
Complete walkthrough / required concept.
Insert in main.lua inside the entry function (unless a filename is shown).
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.
Gen 2 / Gen 3: Gold keeps the shared map_songs target. On Gen 3 a
map_songs row must name a music id your mod registers (a native MUS_*
name is an unresolved reference), keyed by that game's map id, for example
mod.content.map_songs:register("FR_PALLET_TOWN", "Music_ModChip") with R26's
song.
R07 - Replace one SFX with a file
Basic Lua. Before you paste: Put your original sound at assets/save.ogg inside the mod. SFX means sound effect. Test by saving after the file loads.
Complete walkthrough / required concept.
Insert in main.lua inside the entry function (unless a filename is shown).
mod.content.sfx:override("Save", { file = mod.assets:path("assets/save.ogg") })
Checkpoint: saving plays your sound; other sound effects keep their original sound.
This replacement applies only to the sound named Save.
A def that fails to load is skipped with a mod-attributed log line when
its cue fires.
Gen 3: key the row by the native sound name and register it, since
there is no vanilla row to override: mod.content.sfx:register("SE_SAVE", { file = ... }). The Gen 3 audio engine plays it in place of the cart sound
(src/core/game3/mod_audio.lua).
R26 - Author a chiptune (ChipAsm)
Advanced audio. Before you paste: This needs the supported ChipAsm module and imported base audio. It builds a chip program, not an audio file; test Pallet Town after loading it.
Complete walkthrough / required concept.
Insert in main.lua inside the entry function (unless a filename is shown).
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.
Gen 3: chip rows play on every Gen 3 game; point a Gen 3 map at the song
with map_songs:register and that game's map id (see R06).
R43 - CD-quality map soundtrack (file-backed)
Basic Lua + audio. Before you paste: Supply both assets/pallet_intro.ogg and assets/pallet_loop.ogg in the mod. The first is an intro; the second is the repeating section.
Complete walkthrough / required concept.
MSU protocol is not implemented; streamed { file, loopFile } songs are
the supported path for CD-quality replacements:
Insert in main.lua inside the entry function (unless a filename is shown).
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.
Gen 3: music:register("MUS_PALLET", { file = ..., loopFile = ... })
replaces FireRed's and LeafGreen's Pallet Town song by its native name
(Hoenn songs have their own MUS_* names). music.select only sees mod
songs on Gen 3; the cart's own songs never reach it.
R44 - Distance / indoor music volume
Hooks. Before you paste: Enter a Pokemon Center. This example halves its music volume; a gradual distance ramp would require your own position-based calculation.
Complete walkthrough / required concept.
Insert in main.lua inside the entry function (unless a filename is shown).
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).
Gen 3: only a mod song (a music row playing in place of a cart song)
reaches music.volume; the cart's own songs are never scaled by it.
R55 - Give a species or a trainer its own battle theme
Basic Lua + audio. Before you paste: Provide assets/legend.ogg. The species example applies to a wild Mewtwo; the trainer example applies to Giovanni's trainer class.
Complete walkthrough / required concept.
Battle music normally comes from the kind alone (wild / trainer / gym /
final). Two record fields override it for one opponent, both taking a
music id, so a legendary can fight to its own track:
Insert in main.lua inside the entry function (unless a filename is shown).
mod.content.music:register("Music_LegendTheme",
{ file = mod.assets:path("assets/legend.ogg") })
-- wild battles with this species
mod.content.pokemon:patch("MEWTWO", { battleTheme = "Music_LegendTheme" })
-- every battle this trainer class fights
mod.content.trainers:patch("OPP_GIOVANNI", { battleTheme = "Music_LegendTheme" })
The species theme applies to wild battles only, so a trainer whose
lead happens to be that species still fights to the trainer's own theme;
trainers.battleTheme wins wherever both could apply. The victory jingle
stays kind-based either way.
On Gold the same two fields work, spelled the same way; the trainer one lives on the trainer class record:
Outline / alternative: read the requirements above; this is not a complete mod.
mod.content.trainers:patch("FALKNER", { battleTheme = "Music_LegendTheme" })
Do not confuse it with encounterMusic, which is Gold's own key for the
short jingle that plays while the trainer walks up
(data/trainers/encounter_music.asm); the battle theme replaces it a
moment later. Both can be set, and they do not collide.
Checkpoint: the wild encounter and that trainer's fight play your track; every other battle keeps the vanilla kind default.
Gen 3: no Gen 3 battle reads battleTheme; an api 3 mod gets
unknown field battleTheme there.
Start here
Playing
Tutorials
- Choose a tutorial
- 01 Sprite and Text Tweak
- 02 Balance Patch
- 03 New Species
- 04 New Item and Ball
- 05 New Move
- 06 NPC and Dialogue
- 07 New Map
- 08 Quest
- 09 Custom Music
- 10 New Mechanic
- 11 Custom UI Screen
- 12 Mini Total Conversion
Creative guides
Concepts
Recipes and reference
Author and developer tools
Home · Start Playing · Glossary · Troubleshooting · Repository · Community
Game data is imported locally from a supported ROM supplied by the player. Shared mods contain original work or transform recipes, never extracted game content. Check each guide's target game before using its examples.