11K — Raw PCM Audio (.11K / .5K / .8K)¶
FA audio files are raw, headerless, signed 8-bit mono PCM. The sample rate is encoded in the file extension:
| Extension | Sample rate | Notes |
|---|---|---|
.5K |
5512 Hz | |
.8K |
8000 Hz | Confirmed via TOOLKIT LIBPTR cache |
.11K |
11025 Hz | Most common |
.22K |
22050 Hz | Supported by TOOLKIT; not observed in FA LIBs (may be ATF/USNF only) |
Tools¶
fx¶
fx audio info <file.11K|.5K|.8K> # sample rate, sample count, duration
fx audio unpack <file.11K|.5K|.8K> [-o out.wav] # raw PCM → WAV
fx audio pack <in.wav> -o <out.11K|.5K|.8K> # WAV → raw PCM
[-r 11025] # override sample rate (default from ext)
The output extension determines the stored sample rate when packing.
Input WAV must be mono, 8-bit; fx rejects stereo or 16-bit input.
Other Tools¶
Audacity can also import the raw PCM file directly without the fx step
(File → Import → Raw Data: signed 8-bit, mono, sample rate from extension).
- Audacity — free, cross-platform; raw import, noise reduction, pitch/tempo tools
- Adobe Audition
$— paid; professional mastering and spectral repair
File Layout¶
Single-byte samples; no multi-byte integers.
- Signed 8-bit (
int8_t), range −128..127 - Mono (1 channel)
- No header, no footer — the file is raw samples from byte 0
Filename Prefix Conventions¶
The filename prefix (before any letters) is an engine convention, not a format difference:
| Prefix | Meaning | Example |
|---|---|---|
& |
Looping ambient / cockpit sound | &AFTB2.11K |
^ |
Voice / radio callout (one-shot) | ^ENGAGE.11K, ^MLTRY-A.11K |
fx lib unpack maps & and ^ to _ on extraction because Windows rejects
those characters in filenames. The original names are preserved in memory for
patching.
WAV Conversion¶
WAV stores 8-bit audio as unsigned (0..255), not signed. Apply ^ 0x80 on
both directions:
// FA raw → WAV sample
wav_byte = (uint8_t)((int8_t)fa_byte + 128); // equivalently: fa_byte ^ 0x80
// WAV sample → FA raw
fa_byte = (int8_t)(wav_byte - 128);
WAV header (mono, 8-bit, sample rate R):
RIFF chunk: "RIFF" + (file_size - 8) u32LE + "WAVE"
fmt chunk: "fmt " + 16 u32LE + 1 u16LE (PCM) + 1 u16LE (channels)
+ R u32LE (sample rate) + R u32LE (byte rate)
+ 1 u16LE (block align) + 8 u16LE (bits per sample)
data chunk: "data" + sample_count u32LE + [samples]
To create a .5K variant of a sound: pack at 11025 Hz after doubling playback
speed 2×, then rename the extension to .5K. The engine plays it at half rate,
yielding the correct pitch with reduced quality.
Engine Notes¶
AIL Runtime Integration (the game executable)¶
The game executable calls the Miles Audio Interface Library (AIL) API directly. The following API calls and globals were confirmed via Ghidra analysis of the The game executable main binary:
Initialization sequence:
_AIL_startup_0();
_AIL_set_preference_8(4, 0x78); // MIDI preference
_AIL_midiOutOpen_12(&_musicDriverHandle, 0, 0xFFFFFFFF); // open MIDI driver
_AIL_lock_0();
_AIL_set_XMIDI_master_volume_8(...);
_AIL_unlock_0();
_AIL_register_timer_4(&_PollMod__YGXK_Z) → _timerHandle; // register poll callback
_AIL_set_timer_frequency_8(_timerHandle, 0x1e); // 30 Hz
_AIL_start_timer_4(_timerHandle);
_AIL_set_preference_8(0xf, 0);
_AIL_set_preference_8(0xe, 0x4000);
_AIL_set_preference_8(0, 0x10);
_AIL_set_preference_8(2, 0x28f);
_AIL_waveOutOpen_16(&_soundDriverHandle, 0, 0, &fmt); // 22050 Hz, stereo, 16-bit
// Allocate mix channels (loop):
_AIL_allocate_sample_handle_4(_soundDriverHandle) → _mixChanHandle[i]
Runtime globals:
| Global | Type | Role |
|---|---|---|
_musicDriverHandle__3PAU_MDI_DRIVER__A |
MDI_DRIVER* | MIDI driver handle |
_soundDriverHandle__3PAU_DIG_DRIVER__A |
DIG_DRIVER* | Digital audio driver handle (22050 Hz stereo 16-bit) |
_timerHandle__3JA |
HTIMER | 30 Hz poll timer for _PollMod |
_mixChanHandle__3PAPAU_SAMPLE__A |
HSAMPLE[] | Per-channel digital audio handles |
_ailActive__3DA |
bool | AIL system active flag |
Channel teardown: _AIL_end_sample_4(channel) — called per channel on
shutdown.
The WAIL32.DLL and msapi.dll are the AIL wrapper DLLs loaded at runtime. Their import surface has not been traced (no Ghidra output available for the secondary project). IP.EXE audio path is also uncharted.
Round-Trip Notes¶
The format is raw samples with no derived fields, so WAV → PCM → WAV round
trips are byte-identical; tests/test_audio.cpp asserts the PCM round-trip.
The ^ 0x80 signedness flip is exactly self-inverse.
An earlier draft of this page described .MUS files as named pointers to
.11K audio; the confirmed decode shows .MUS playlists drive .XMI
MIDI tracks instead — see MUS.md for the corrected music-slot table
and modding workflow.
Related¶
Formats: LIB — container archives (and the &/^ extraction
mapping); MUS — the music playlist DLLs (MIDI, not PCM);
CB8 — FMV clips pair with a .11K of the same stem;
VDO — briefing videos share one .11K narration per 3-character
group prefix (AAC.11K for AACA…AACE), not per full stem.