Skip to content

These docs were made completely by AI, so they might be right, or wrong, you'll need to test them yourself. This was made for a easier understanding of everything. So use at your own risk. If anything is wrong, please don't hurt to make a PR on the page you have a problem with. ON GITHUB

Audio

LCE’s audio system is wrapped in a two-class hierarchy. ConsoleSoundEngine defines the platform interface, and SoundEngine provides the shared implementation. The system handles positional 3D audio, background music streaming, and UI sound effects.

The original console builds used the Miles Sound System (MSS) library from RAD Game Tools. LCEMP has replaced Miles with miniaudio (miniaudio.h), a single-header C audio library. The API surface is the same (the ConsoleSoundEngine interface hasn’t changed), but the backend is different. Xbox 360 used native XAudio instead of Miles.

ConsoleSoundEngine in Common/Audio/Consoles_SoundEngine.h defines the pure virtual interface:

class ConsoleSoundEngine {
public:
virtual void tick(shared_ptr<Mob>* players, float a) = 0;
virtual void destroy() = 0;
virtual void play(int iSound, float x, float y, float z, float volume, float pitch) = 0;
virtual void playStreaming(const wstring& name, float x, float y, float z,
float volume, float pitch, bool bMusicDelay = true) = 0;
virtual void playUI(int iSound, float volume, float pitch) = 0;
virtual void updateMusicVolume(float fVal) = 0;
virtual void updateSystemMusicPlaying(bool isPlaying) = 0;
virtual void updateSoundEffectVolume(float fVal) = 0;
virtual void init(Options*) = 0;
virtual void add(const wstring& name, File* file) = 0;
virtual void addMusic(const wstring& name, File* file) = 0;
virtual void addStreaming(const wstring& name, File* file) = 0;
virtual char* ConvertSoundPathToName(const wstring& name, bool bConvertSpaces) = 0;
virtual void playMusicTick() = 0;
virtual bool GetIsPlayingStreamingCDMusic();
virtual bool GetIsPlayingStreamingGameMusic();
virtual void SetIsPlayingStreamingCDMusic(bool bVal);
virtual void SetIsPlayingStreamingGameMusic(bool bVal);
virtual bool GetIsPlayingEndMusic();
virtual bool GetIsPlayingNetherMusic();
virtual void SetIsPlayingEndMusic(bool bVal);
virtual void SetIsPlayingNetherMusic(bool bVal);
static const WCHAR* wchSoundNames[eSoundType_MAX];
static const WCHAR* wchUISoundNames[eSFX_MAX];
};

The sound name tables (wchSoundNames and wchUISoundNames) map sound type enums (defined in Minecraft.World/SoundTypes.h) to human-readable names. These are defined in SoundNames.cpp and must stay in sync with the enum order.

SoundEngine extends ConsoleSoundEngine. In LCEMP, it uses miniaudio as the backend:

class SoundEngine : public ConsoleSoundEngine {
static const int MAX_SAME_SOUNDS_PLAYING = 8;
ma_engine m_maEngine; // miniaudio engine
bool m_maEngineInitialized;
ma_sound m_activeSounds[MA_MAX_SOUNDS]; // active sound pool (64 slots)
bool m_activeSoundUsed[MA_MAX_SOUNDS];
ma_sound m_musicStream; // current streaming music
bool m_musicStreamActive;
};

MA_MAX_SOUNDS is 64, the maximum number of sounds that can play at once. The engine manages this pool with findFreeSoundSlot() (finds a free slot) and cleanupFinishedSounds() (reclaims slots from finished sounds).

Game code never touches Miles directly. The chain goes:

Entity/Level code
|
v
LevelListener::playSound()
|
v
ServerLevelListener --> LevelSoundPacket (network)
|
v
SoundEngine::play() -- 3D positioned sound
SoundEngine::playUI() -- non-positional UI sound
SoundEngine::playStreaming() -- music / jukebox

When SoundEngine::play() fires, it converts the dot-separated sound name to a file path using ConvertSoundPathToName() and plays it through the audio backend. In the original Miles builds, this produced event names like "Minecraft/mob.zombie". In LCEMP’s miniaudio backend, it resolves to audio files on disk.

The engine supports multiple listeners for split-screen:

AUDIO_LISTENER m_ListenerA[MAX_LOCAL_PLAYERS];
int m_validListenerCount;

Each listener has:

typedef struct {
bool bValid;
AUDIO_VECTOR vPosition; // world position
AUDIO_VECTOR vOrientFront; // facing direction
} AUDIO_LISTENER;

In splitscreen, the engine can’t just set one listener position. Instead, it calculates the Manhattan distance from each sound to every active player, picks the closest one, and uses that distance for the 3D falloff. The listener is placed at the origin and the sound is placed along the Z axis at the calculated distance. This gives reasonable spatial audio across all screen splits.

The AUDIO_INFO struct describes a sound to play:

typedef struct {
F32 x, y, z; // world position
F32 volume, pitch;
int iSound; // sound type ID
bool bIs3D; // positional audio
bool bUseSoundsPitchVal;
} AUDIO_INFO;

Key playback methods:

MethodPurpose
play(iSound, x, y, z, volume, pitch)Play a 3D positional sound
playUI(iSound, volume, pitch)Play a non-positional UI sound
playStreaming(name, x, y, z, volume, pitch, bMusicDelay)Start streaming music

The MAX_SAME_SOUNDS_PLAYING = 8 limit stops the same sound effect from stacking too much. Per-sound tracking is kept in CurrentSoundsPlaying[eSoundType_MAX + eSFX_MAX].

LevelRenderer is the bridge between game events and audio:

void playSound(int iSound, double x, double y, double z,
float volume, float pitch, float fSoundClipDist = 16.0f);
void playStreamingMusic(const wstring& name, int x, int y, int z);

The fSoundClipDist parameter (default 16 blocks) controls how far away a sound can be heard.

All 3D sounds use a custom linear falloff function instead of the default engine rolloff. In the original Miles builds, this was registered as a callback. LCEMP implements the same logic in miniaudio:

F32 AILCALLBACK custom_falloff_function(
HSAMPLE S, F32 distance, F32 rolloff_factor, F32 min_dist, F32 max_dist)
{
// Thunder has no attenuation at all
if (max_dist == 10000.0f)
return 1.0f;
// Linear falloff: full volume at distance 0, silent at max_dist
F32 result = 1.0f - (distance / max_dist);
if (result < 0.0f) result = 0.0f;
if (result > 1.0f) result = 1.0f;
return result;
}

The max_dist parameter (called distanceScaler in the code) controls how far a sound carries:

Sound typeDistance (blocks)Notes
Most sounds16Default fSoundClipDist
Ghast sounds30Audible from further away
Ender Dragon100Boss sounds carry far
Thunder10,000Effectively infinite, always full volume
Music discs64Jukebox carries 4x further than normal

Sounds are grouped by naming prefix. Every sound in the game has an entry in the eSOUND_TYPE enum in SoundTypes.h.

Ambient, hurt, death, and step sounds for every mob:

Enum patternString name patternNotes
eSoundType_MOB_ZOMBIE_AMBIENTmob.zombieIdle groaning
eSoundType_MOB_ZOMBIE_HURTmob.zombiehurtTaking damage
eSoundType_MOB_ZOMBIE_DEATHmob.zombiedeathDying
eSoundType_MOB_CREEPER_HURTmob.creeperCreeper hurt
eSoundType_MOB_WOLF_BARKmob.wolf.barkWolf barking
eSoundType_MOB_WOLF_HURTmob.wolf.hurtWolf hurt
eSoundType_MOB_WOLF_DEATHmob.wolf.deathWolf death
eSoundType_MOB_WOLF_GROWLmob.wolf.growlWolf growl
eSoundType_MOB_WOLF_PANTINGmob.wolf.pantingTamed wolf panting
eSoundType_MOB_WOLF_WHINEmob.wolf.whineWolf whine
eSoundType_MOB_WOLF_SHAKEmob.wolf.shakeWolf shaking off water
eSoundType_MOB_CAT_HITTmob.cat.hitCat hit
eSoundType_MOB_CAT_PURRmob.cat.purrCat purr
eSoundType_MOB_CAT_PURREOWmob.cat.purreowCat purr-meow
eSoundType_MOB_CAT_MEOWmob.cat.meowCat meow
eSoundType_MOB_CHICKEN_AMBIENTmob.chickenChicken clucking
eSoundType_MOB_CHICKEN_HURTmob.chickenhurtChicken hurt
eSoundType_MOB_CHICKENPLOPmob.chickenplopEgg laying
eSoundType_MOB_COW_AMBIENTmob.cowCow mooing
eSoundType_MOB_COW_HURTmob.cowhurtCow hurt
eSoundType_MOB_PIG_AMBIENTmob.pigPig oinking
eSoundType_MOB_PIG_DEATHmob.pig.deathPig death
eSoundType_MOB_SHEEP_AMBIENTmob.sheepSheep bleating
eSoundType_MOB_GHAST_MOANmob.ghast.moanGhast moaning
eSoundType_MOB_GHAST_DEATHmob.ghast.deathGhast death
eSoundType_MOB_GHAST_FIREBALLmob.ghast.fireballGhast shooting
eSoundType_MOB_GHAST_SCREAMmob.ghast.screamGhast screaming
eSoundType_MOB_GHAST_CHARGEmob.ghast.chargeGhast charging
eSoundType_MOB_BLAZE_HURTmob.blaze.hitBlaze hurt
eSoundType_MOB_BLAZE_DEATHmob.blaze.deathBlaze death
eSoundType_MOB_BLAZE_BREATHEmob.blaze.breatheBlaze ambient
eSoundType_MOB_ENDERMEN_IDLEmob.endermen.idleEnderman ambient
eSoundType_MOB_ENDERMEN_HITmob.endermen.hitEnderman hurt
eSoundType_MOB_ENDERMEN_DEATHmob.endermen.deathEnderman death
eSoundType_MOB_ENDERMEN_PORTALmob.endermen.portalEnderman teleport
eSoundType_MOB_ZOMBIEPIG_AMBIENTmob.zombiepig.zpigZombie pigman idle
eSoundType_MOB_ZOMBIEPIG_HURTmob.zombiepig.zpighurtZombie pigman hurt
eSoundType_MOB_ZOMBIEPIG_DEATHmob.zombiepig.zpigdeathZombie pigman death
eSoundType_MOB_ZOMBIEPIG_ZPIGANGRYmob.zombiepig.zpigangryZombie pigman angry
eSoundType_MOB_ENDERDRAGON_GROWLmob.enderdragon.growlDragon growl
eSoundType_MOB_ENDERDRAGON_HITmob.enderdragon.hitDragon hurt
eSoundType_MOB_ENDERDRAGON_MOVEmob.enderdragon.moveDragon wingflap
eSoundType_MOB_ENDERDRAGON_ENDmob.enderdragon.endDragon death
eSoundType_MOB_SILVERFISH_AMBIENTmob.silverfish.saySilverfish ambient
eSoundType_MOB_SILVERFISH_HURTmob.silverfish.hitSilverfish hurt
eSoundType_MOB_SILVERFISH_DEATHmob.silverfish.killSilverfish death
eSoundType_MOB_SILVERFISH_STEPmob.silverfish.stepSilverfish walk
eSoundType_MOB_SKELETON_AMBIENTmob.skeletonSkeleton ambient
eSoundType_MOB_SKELETON_HURTmob.skeleton.hurtSkeleton hurt
eSoundType_MOB_SPIDER_AMBIENTmob.spiderSpider ambient
eSoundType_MOB_SPIDER_DEATHmob.spiderdeathSpider death
eSoundType_MOB_SLIMEmob.slimeSlime
eSoundType_MOB_SLIME_ATTACKmob.slimeattackSlime attack
eSoundType_MOB_CREEPER_DEATHmob.creeperdeathCreeper death
eSoundType_MOB_ZOMBIE_WOODmob.zombie.woodZombie hitting wood door
eSoundType_MOB_ZOMBIE_WOOD_BREAKmob.zombie.woodbreakZombie breaking wood door
eSoundType_MOB_ZOMBIE_METALmob.zombie.metalZombie hitting metal door
eSoundType_MOB_MAGMACUBE_BIGmob.magmacube.bigLarge magma cube
eSoundType_MOB_MAGMACUBE_SMALLmob.magmacube.smallSmall magma cube
eSoundType_MOB_IRONGOLEM_THROWmob.irongolem.throwIron golem throw
eSoundType_MOB_IRONGOLEM_HITmob.irongolem.hitIron golem hurt
eSoundType_MOB_IRONGOLEM_DEATHmob.irongolem.deathIron golem death
eSoundType_MOB_IRONGOLEM_WALKmob.irongolem.walkIron golem walk
eSoundType_MOB_VILLAGER_HAGGLEmob.villager.haggleVillager trading
eSoundType_MOB_VILLAGER_IDLEmob.villager.idleVillager ambient
eSoundType_MOB_VILLAGER_HITmob.villager.hitVillager hurt
eSoundType_MOB_VILLAGER_DEATHmob.villager.deathVillager death
eSoundType_MOB_VILLAGER_YESmob.villager.yesVillager accepting trade
eSoundType_MOB_VILLAGER_NOmob.villager.noVillager declining trade
eSoundType_MOB_ZOMBIE_INFECTmob.zombie.infectZombie infecting villager
eSoundType_MOB_ZOMBIE_UNFECTmob.zombie.unfectZombie villager curing
eSoundType_MOB_ZOMBIE_REMEDYmob.zombie.remedyZombie cure remedy
EnumString nameUsed for
eSoundType_STEP_STONEstep.stoneWalking on stone
eSoundType_STEP_WOODstep.woodWalking on wood
eSoundType_STEP_GRAVELstep.gravelWalking on gravel
eSoundType_STEP_GRASSstep.grassWalking on grass
eSoundType_STEP_METALstep.metalWalking on metal
eSoundType_STEP_CLOTHstep.clothWalking on wool
eSoundType_STEP_SANDstep.sandWalking on sand
eSoundType_STEP_SNOWstep.snowWalking on snow
eSoundType_STEP_LADDERstep.ladderClimbing ladders
eSoundType_DIG_GRASSdig.grassBreaking grass blocks
eSoundType_DIG_STONEdig.stoneBreaking stone
eSoundType_DIG_WOODdig.woodBreaking wood
eSoundType_DIG_GRAVELdig.gravelBreaking gravel
eSoundType_DIG_CLOTHdig.clothBreaking wool
eSoundType_DIG_SANDdig.sandBreaking sand
eSoundType_DIG_SNOWdig.snowBreaking snow
eSoundType_TILE_PISTON_INtile.piston.inPiston retracting
eSoundType_TILE_PISTON_OUTtile.piston.outPiston extending
EnumString nameUsed for
eSoundType_RANDOM_EXPLODErandom.explodeExplosions
eSoundType_RANDOM_BOWrandom.bowFiring a bow
eSoundType_RANDOM_CHEST_OPENrandom.chestopenOpening a chest
eSoundType_RANDOM_CHEST_CLOSErandom.chestclosedClosing a chest
eSoundType_RANDOM_DOOR_OPENrandom.door_openOpening a door
eSoundType_RANDOM_DOOR_CLOSErandom.door_closeClosing a door
eSoundType_RANDOM_CLICKrandom.clickButtons, levers
eSoundType_RANDOM_GLASSrandom.glassBreaking glass
eSoundType_RANDOM_FIZZrandom.fizzFire extinguish, lava pop
eSoundType_RANDOM_POPrandom.popItem pickup
eSoundType_RANDOM_ORBrandom.orbExperience orb pickup
eSoundType_RANDOM_SPLASHrandom.splashWater splash
eSoundType_RANDOM_DRINKrandom.drinkDrinking potion
eSoundType_RANDOM_EATrandom.eatEating food
eSoundType_RANDOM_ANVIL_USErandom.anvil_useUsing an anvil
eSoundType_RANDOM_ANVIL_LANDrandom.anvil_landFalling anvil landing
eSoundType_RANDOM_ANVIL_BREAKrandom.anvil_breakAnvil breaking
eSoundType_RANDOM_FUSErandom.fuseTNT fuse
eSoundType_RANDOM_BOW_HITrandom.bowhitArrow hitting target
eSoundType_RANDOM_BURPrandom.burpBurping after eating
eSoundType_RANDOM_BREAKrandom.breakItem breaking
EnumString name
eSoundType_AMBIENT_WEATHER_RAINambient.weather.rain
eSoundType_AMBIENT_WEATHER_THUNDERambient.weather.thunder
eSoundType_AMBIENT_CAVE_CAVEambient.cave.cave
PrefixExamplesPurpose
portal.*portal.portal, portal.trigger, portal.travelPortal effects
fire.*fire.ignite, fire.fireFire sounds
damage.*damage.hurtflesh, damage.fallsmall, damage.fallbig, damage.thornsPlayer damage
note.*note.harp, note.bd, note.snare, note.hat, note.bassattackNote blocks
liquid.*liquid.water, liquid.lava, liquid.lavapopLiquid sounds
minecart.*minecart.base, minecart.insideMinecart movement

UI sounds are a separate, smaller enum:

enum ESoundEffect
{
eSFX_Back, // "back"
eSFX_Craft, // "craft"
eSFX_CraftFail, // "craftfail"
eSFX_Focus, // "focus"
eSFX_Press, // "press"
eSFX_Scroll, // "scroll"
eSFX_MAX
};

These get played through SoundEngine::playUI() and are routed to the "Minecraft/UI/" event path in the soundbank.

The eMUSICFILES enum lists all music tracks:

Overworld:

  • eStream_Overworld_Calm1 through Calm3
  • eStream_Overworld_hal1 through hal4
  • eStream_Overworld_nuance1, nuance2
  • eStream_Overworld_piano1 through piano3
  • Creative mode tracks (non-Xbox): Creative1 through Creative6
  • Menu tracks (non-Xbox): Menu1 through Menu4

Nether:

  • eStream_Nether1 through Nether4

The End:

  • eStream_end_dragon, eStream_end_end

Music discs (CD):

  • eStream_CD_1 through eStream_CD_12

Total: eStream_Max entries.

File paths follow the pattern music/<trackname>.binka for background music and cds/<discname>.binka for music discs. The .binka format is Bink Audio (compressed, from RAD Game Tools).

enum eMUSICTYPE {
eMusicType_None,
eMusicType_Game, // background music (not 3D positioned)
eMusicType_CD, // jukebox music (3D positioned, attenuates with distance)
};

Background music plays globally with no 3D positioning. Jukebox music is 3D-positioned at the jukebox block with a distance scaler of 64 blocks (4x the normal sound range).

enum MUSIC_STREAMSTATE {
eMusicStreamState_Idle,
eMusicStreamState_Stop,
eMusicStreamState_Stopping,
eMusicStreamState_Opening,
eMusicStreamState_OpeningCancel,
eMusicStreamState_Play,
eMusicStreamState_Playing,
eMusicStreamState_Completed,
};

The state transitions:

Idle --> Opening --> Playing --> Completed --> Stop --> Stopping --> Idle

OpeningCancel handles the case where a new track is requested while one is still opening.

Music streaming runs on a dedicated thread:

C4JThread* m_openStreamThread;
static int OpenStreamThreadProc(void* lpParameter);

getMusicID(int iDomain) picks a random track that fits the current dimension:

int SoundEngine::getMusicID(int iDomain)
{
switch (iDomain)
{
case LevelData::DIMENSION_END:
return m_iStream_End_Min; // always plays dragon-alive track
case LevelData::DIMENSION_NETHER:
return GetRandomishTrack(m_iStream_Nether_Min, m_iStream_Nether_Max);
default:
return GetRandomishTrack(m_iStream_Overworld_Min, m_iStream_Overworld_Max);
}
}

The track ranges are configurable per texture/mash-up pack:

void SetStreamingSounds(int iOverworldMin, int iOverWorldMax,
int iNetherMin, int iNetherMax,
int iEndMin, int iEndMax, int iCD1);

GetRandomishTrack(iStart, iEnd) selects a track, using m_bHeardTrackA to avoid playing the same track back to back. Once all tracks in the range have been heard, the array resets. It doesn’t try too hard, so occasionally you will hear the same track twice.

playMusicTick() is called each game tick. It manages the delay between tracks (m_iMusicDelay, up to about 3 minutes of random delay) and drives the streaming state machine. playMusicUpdate() handles the actual state transitions.

Music disc playback is tracked separately. The m_CDMusic field stores the current disc track name. GetIsPlayingStreamingCDMusic() and SetIsPlayingStreamingCDMusic() manage this state. The track name gets matched against the m_szStreamFileA array to find the right file.

MethodPurpose
updateMusicVolume(float fVal)Set master music volume (0.0 to 1.0)
updateSoundEffectVolume(float fVal)Set master SFX volume (0.0 to 1.0)
updateSystemMusicPlaying(bool isPlaying)Handle system music (e.g., Spotify) overlay
getMasterMusicVolume()Get effective music volume

The master volumes (m_MasterMusicVolume, m_MasterEffectsVolume) are set from the Options class values.

In the original console builds, the Miles Sound System used a compiled sound bank (Minecraft.msscmp) containing all SFX, loaded into HMSOUNDBANK m_hBank. HDIGDRIVER m_hDriver was the audio driver handle, and HSTREAM m_hStream was the streaming music handle.

LCEMP replaces this with miniaudio. The ma_engine handles mixing and output, ma_sound instances manage individual sounds (up to 64 active in m_activeSounds[]), and m_musicStream handles the current streaming track.

Sound files and music files get registered through add(), addMusic(), and addStreaming() during initialization.

DLC packs (mash-up packs) can provide their own audio through DLCAudioFile.h. The TexturePack::hasAudio() method tells you whether a pack includes custom audio. When a DLC pack with audio is active, SetStreamingSounds() reconfigures the music track ranges.

Audio resources are stored in:

  • Common/res/audio/ for base game sound banks
  • Common/res/TitleUpdate/audio/ for title update audio additions

These notes apply to the original console builds, not LCEMP:

  • PS3: initAudioHardware() has a platform-specific implementation for Cell audio initialization. There is also a PS3_SoundEngine.cpp with PS3-specific Miles integration.
  • PS4 (Orbis): Uses int32_t m_hBGMAudio for the background music audio handle
  • PS Vita: Miles integration through a Vita-specific MSS build with updateMiles() called during the mixer callback
  • Xbox 360: Uses native XAudio instead of Miles (no mss.h include). Has its own Xbox/Audio/SoundEngine.cpp and SoundEngine.h

LCEMP uses miniaudio on all platforms. The initAudioHardware() method is a no-op stub that just returns its input parameter.

MinecraftConsoles adds a large batch of new sound types to SoundTypes.h. These cover mobs and features that don’t exist in LCEMP:

  • eSoundType_FIREWORKS_LAUNCH
  • eSoundType_FIREWORKS_BLAST / _FAR
  • eSoundType_FIREWORKS_LARGE_BLAST / _FAR
  • eSoundType_FIREWORKS_TWINKLE / _FAR
  • eSoundType_MOB_BAT_IDLE, _HURT, _DEATH, _TAKEOFF
  • eSoundType_MOB_WITHER_SPAWN, _IDLE, _HURT, _DEATH, _SHOOT
  • eSoundType_MOB_HORSE_LAND, _ARMOR, _LEATHER
  • Variant death sounds: _ZOMBIE_DEATH, _SKELETON_DEATH, _DONKEY_DEATH, _DEATH
  • Variant hurt sounds: _ZOMBIE_HIT, _SKELETON_HIT, _DONKEY_HIT, _HIT
  • Variant idle sounds: _ZOMBIE_IDLE, _SKELETON_IDLE, _DONKEY_IDLE, _IDLE
  • _DONKEY_ANGRY, _ANGRY, _GALLOP, _BREATHE, _WOOD
  • eSoundType_MOB_WITCH_IDLE, _HURT, _DEATH

A bunch of mob step sounds are added that LCEMP was missing:

  • eSoundType_MOB_COW_STEP, _CHICKEN_STEP, _PIG_STEP
  • eSoundType_MOB_ENDERMAN_STARE, _SCREAM
  • eSoundType_MOB_SHEEP_SHEAR, _SHEEP_STEP
  • eSoundType_MOB_SKELETON_DEATH, _SKELETON_STEP
  • eSoundType_MOB_SPIDER_STEP
  • eSoundType_MOB_WOLF_STEP
  • eSoundType_MOB_ZOMBIE_STEP
  • eSoundType_LIQUID_SWIM

eSoundType_MOB_CAT_HITT (typo with double T in LCEMP) is renamed to eSoundType_MOB_CAT_HIT in MinecraftConsoles.