HammeriteAudio

Autoloads. Inherits Node

Hammerite Audio runtime facade (autoload: HammeriteAudio).

Everything a game asks of acoustics is here: where its recordings are, what kinds of sound it has, how to play one, how to report a noise that has no sound of its own, how to open and shut a door, and how to bake a map's audio graph. The HammeriteAudioManager underneath is a per-map object that is built again for the next map, so nothing above needs to hold one.

Hooks HammeriteMap3D directly -- no dependency on hammerite-editor or HammeriteMapEditor, so acoustic propagation works in builds that ship without the editor at all.

Call integrate(map_3d) once per HammeriteMap3D you want acoustic propagation on, BEFORE assigning its map, so the manager exists before the map's entities build and ask for it:

HammeriteAudio.sounds.search_paths = ["res://sounds"]
HammeriteAudio.sound_types = load("res://sound_types.tres")
HammeriteAudio.integrate(map_3d)
map_3d.map = map

A map's graph is baked by its author - the editor's Audio Portals tool, or bake() - and saved with it. A map arriving without one is not baked as it loads, which on a large level was seconds of every load: its sound goes in straight lines until it has one, and the editor says so (HammeriteAudioEditorExtension), as it says when a graph is out of date with the map.

If hammerite-editor is also present and you want the audio graph authoring tool (zones/portals) and toolbar button, separately initialize HammeriteAudioEditorExtension.

The state itself lives in HammeriteAudioRuntime, which this delegates to - an autoload cannot be mentioned by anything that has to compile without a scene tree, which is every node in this addon.

The HammeriteAudio autoload is scripts/hammerite_audio.gd, a script extending this with nothing of its own: an autoload is a script or a scene, and its name cannot be a class's.

Properties

TypeNameDefault
StringNameambient_bus
Callableambient_resolver
Callablematerial_resolver
HammeriteAudioMaterialsmaterials
HammeriteAudioMixSettingsmix_settings
HammeriteAudioPreset[]presets
HammeriteAudioSoundTypessound_types
HammeriteAssetLibrarysounds

Methods

ReturnsMethod
voidadd_preset(preset: HammeriteAudioPreset)
HammeriteAudioBakeReportbake(map_3d: HammeriteMap3D)
HammeriteAudioManagerget_manager(context: Node = null)
voidintegrate(map_3d: HammeriteMap3D)
intplay_one_shot(sound_file: String, position: Vector3, sound_type: StringName = &"", volume_db: float = 0.0, propagate: bool = true, context: Node = null)
voidpress_ear_to_portal(portal_name: String, gain_db: float, context: Node = null)
voidreport_sound(sound_type: StringName, position: Vector3, source: Node = null)
boolset_portal_occlusion(portal_name: String, occlusion: float, context: Node = null)
voidtake_ear_from_portal(context: Node = null)

Signals

graph_baked

signal graph_baked(map_3d: HammeriteMap3D, report: HammeriteAudioBakeReport)

Emitted after a map's audio graph has been baked, with what the bake made of it. Connect it to put the warnings wherever this game puts warnings.

Property descriptions

ambient_bus

var ambient_bus: StringName

The bus rooms' ambience plays on; see HammeriteAudioRuntime.get_ambient_bus().

ambient_resolver

var ambient_resolver: Callable

What an ambience id sounds like; see HammeriteAudioRuntime.get_ambient_resolver().

material_resolver

var material_resolver: Callable

Which material a texture IS; see HammeriteAudioRuntime.get_material_resolver(). The game's question rather than Hammerite's, because a texture name is geometry's and what it means is the level author's.

HammeriteAudio.material_resolver = func(texture: String) -> StringName:
return my_surfaces.material_of(texture)

materials

var materials: HammeriteAudioMaterials

What each material does to sound, read by every bake; see HammeriteAudioMaterials. Add to the table it answers with, or assign one of your own.

HammeriteAudio.materials.add_material(HammeriteAudioMaterial.create(
"oak", 0.6, 0.4, 22.0, 0.45, HammeriteAudioMaterial.Category.WOOD))

mix_settings

var mix_settings: HammeriteAudioMixSettings

How every map's sound is mixed: the muffle ladder, how weather fades on the way in, how far a route may be cached. Every value is a first guess to be tuned by ear, which is why they are authored data; see HammeriteAudioMixSettings. Without a table, the defaults there are used.

presets

var presets: HammeriteAudioPreset[]

The reverb characters a room can be given, read by every bake and by the brush inspector's dropdown; see HammeriteAudioRuntime.get_presets(). Add a room of your own kind rather than editing the addon.

HammeriteAudio.add_preset(HammeriteAudioPreset.create(100, "vault", 0.4, 0.3, 0.95, 0.45, 1.0))

Assigning a whole table replaces Hammerite's sixteen, so a game keeping them adds to them instead.

sound_types

var sound_types: HammeriteAudioSoundTypes

The game's sound-type table, assigned at startup. Hammerite has no opinion about what kinds of sound a game has - "footstep" is the game's vocabulary - so the loudness and carrying range of each come from here. Without one, sounds still propagate and are still heard, on the defaults in HammeriteAudioSoundTypes.

sounds

var sounds: HammeriteAssetLibrary

Where a sound's name becomes a recording: a name such as doors/creak.ogg, found in the search paths given here or in a source the game adds.

HammeriteAudio.sounds.search_paths = ["res://sounds"]

Empty until the game says where its audio is: with neither a search path nor a source, no sound resolves and every play reports No sound called ....

Method descriptions

add_preset()

func add_preset(preset: HammeriteAudioPreset) -> void

Add one reverb character to presets, replacing whatever had its id; see HammeriteAudioRuntime.add_preset().

bake()

func bake(map_3d: HammeriteMap3D) -> HammeriteAudioBakeReport

Bake map_3d's audio graph from the world it has compiled, and hear it through the result from the next frame on.

For a map rebaked while it is being played - a wall knocked through, a room added - and for the editor's Audio Portals tool, which is this call. The map keeps its graph, so the bake is saved with it, and what the author wrote (room presets, openings' names and their standing occlusion) survives.

Without a scene tree - a headless or CI bake - call HammeriteAudioRuntime.bake() with the map itself.

get_manager()

func get_manager(context: Node = null) -> HammeriteAudioManager

The HammeriteAudioManager that applies to context, or null if there is none yet.

For the handle API (HammeriteAudioManager.create_positional_sound() and the rest), which is the layer below this one. Everything else a game needs is on this autoload, and asking per call rather than holding what this returns is the difference between a door that still works after the next map and one that does not.

Resolved by walking up from context to the HammeriteMap3D it lives under, since a node inside a map belongs to that map's acoustics. A node outside any map - a player parented to the scene root, which is the normal arrangement - falls back to the only manager there is, and says so rather than guessing when there are several.

integrate()

func integrate(map_3d: HammeriteMap3D) -> void

Wires up automatic HammeriteAudioManager injection for the given HammeriteMap3D.

play_one_shot()

func play_one_shot(sound_file: String, position: Vector3, sound_type: StringName = &"", volume_db: float = 0.0, propagate: bool = true, context: Node = null) -> int

Play a sound once at a point in space and forget about it.

For noises with no object behind them - an impact, a sound whose emitter is about to be freed - where holding a handle would be bookkeeping for something that ends in half a second. The manager releases the sound once it has played through.

Returns the handle, in case the caller wants to stop it early; it is valid only until the sound finishes. Use an HammeriteAudioEmitter3D for anything that repeats or moves.

press_ear_to_portal()

func press_ear_to_portal(portal_name: String, gain_db: float, context: Node = null) -> void

Press the player's ear to the opening named portal_name: what comes through it plays gain_db louder, and nothing else changes. Listening at a door.

This is what is PLAYED. What the player's own HammeriteAudioReceiver3D hears is its HammeriteAudioReceiver3D.press_ear_to_portal(), so captions can follow the ear too.

report_sound()

func report_sound(sound_type: StringName, position: Vector3, source: Node = null) -> void

Report a noise that has no sound of its own.

For the cases where the audible and the audible-to-gameplay come apart: a noise the player is meant to make but not hear themselves, or one whose audio is played by some other system. Plain sounds do not need this - an HammeriteAudioEmitter3D with a HammeriteAudioEmitter3D.sound_type, or play_one_shot() with one, reports itself.

set_portal_occlusion()

func set_portal_occlusion(portal_name: String, occlusion: float, context: Node = null) -> bool

Open or shut the opening named portal_name: 0 is open, 1 costs the opening its authored closed attenuation, and in between is ajar. Returns whether anything carries that name.

The call a door entity makes. Name an opening with the Audio Portals tool; the name lives on the face it is punched from, so it survives a recompile, and hammerite-nav reads the same one.

HammeriteAudio.set_portal_occlusion("cell_door", 1.0, self)

take_ear_from_portal()

func take_ear_from_portal(context: Node = null) -> void

Undo press_ear_to_portal(): nothing is heard louder through any opening.

Hammerite 2.0 · built from 6d57ab2d, 2026-10-17