================================================================================
AC6 AUDIO EXTRACTION WALKTHROUGH
================================================================================

This walkthrough takes you from a fresh AC6_recomp checkout to playable .wav
files for every track of music, every voiceline, and every cutscene mix in
Ace Combat 6. It also explains why in-game sound effects (engines, missile
lock, explosions, weapons) are NOT covered yet, and what would be required to
extract them.

If you've never extracted assets from this repo before, do the texture
walkthrough first (docs/ac6_asset_extraction_walkthrough.txt). It gets the
runtime PAC dumps populated, which this walkthrough also benefits from.


================================================================================
0. WHAT YOU GET
================================================================================

After running this walkthrough you will have, in
out/ac6_runtime_audio/packs/ :

    bgmpack__00000_off00000000.xma     (47 BGM tracks; one .xma each)
    bgmpack__00001_off01450000.xma
    ...
    voicepack_eng__00000_off00000000.xma   (7523 voicelines, English)
    ...
    voicepack_jpn__00000_off00000000.xma   (7523 voicelines, Japanese)
    ...
    demopack_eng__00000_off00000000.xma    (31 cutscene mixes)
    ...

If vgmstream is installed, each .xma also has a sibling .wav next to it.

You will ALSO have, in out/ac6_runtime_audio/, the runtime-captured FHM
RIFFs (currently 42 voice/event clips from the dumps you've already
collected).

You will NOT yet have:

  - In-game SFX (engines, weapons, lock-on, explosions). See section 6.
  - Cutscene video. moviepack.bin is standard ASF/WMV — see section 5.


================================================================================
1. PREREQUISITES
================================================================================

  - The repo is built and ac6recomp.exe runs (texture walkthrough covers this).
  - Python 3.10+ on PATH.
  - Asset directory exists at:
      out/build/win-amd64-relwithdebinfo/assets/
    containing bgmpack.bin, voicepack_eng.bin, voicepack_jpn.bin,
    demopack_eng.bin, demopack_jpn.bin, moviepack.bin.
  - (Optional, for .wav decoding) vgmstream-cli.exe.
    Download "vgmstream-win64-cli.zip" from https://vgmstream.org/downloads
    and extract anywhere — e.g. C:\tools\vgmstream\.


================================================================================
2. THE QUICK PATH
================================================================================

From the repo root:

    python tools/export_ac6_audio.py --packs ^
        --vgmstream "C:/tools/vgmstream/vgmstream-cli.exe"

That's it. Output:

    out/ac6_runtime_audio/                  (FHM-channel RIFFs as .xma + .wav)
    out/ac6_runtime_audio/packs/            (pack-channel streams as .xma + .wav)

Without vgmstream installed, omit --vgmstream and you'll get .xma files
only — no .wav. The .xma files are still the actual audio, just in the
Xbox 360 codec; any vgmstream-aware player (foobar2000 + vgmstream
plugin, vgmstream-cli later, etc.) will play them.


================================================================================
3. WHAT THE TOOL DOES, IN DETAIL
================================================================================

AC6 ships audio in two structurally different shapes. The exporter handles
each one differently.

----------------------------------------------------------------------------
3a) Standalone "pack" files in the asset directory
----------------------------------------------------------------------------

bgmpack.bin / voicepack_*.bin / demopack_*.bin are flat concatenations of
independent RIFF/WAVE streams, each aligned to a 0x800-byte sector.

Layout per pack:

    +-------------------+  offset 0
    | RIFF <size> WAVE  |  ----+
    | fmt / x2st / data |      | sub-stream 0 = 8 + declared_size bytes
    +-------------------+  ----+
    | (zero padding)    |      | aligned up to 0x800
    +-------------------+
    | RIFF <size> WAVE  |
    | ...               |  sub-stream 1
    +-------------------+
    ...

The splitter reads the declared RIFF size at offset 4, copies
8 + declared_size bytes to its own .xma file, then advances to the next
sector boundary and looks for another RIFF. The codec inside is XMA2 for
bgmpack and XMA1 for voicepack/demopack — both decoded fine by vgmstream.

----------------------------------------------------------------------------
3b) FHM-embedded RIFF entries
----------------------------------------------------------------------------

When AC6 runtime-decompresses a PAC entry containing audio, the FHM
extractor (tools/extract_ac6_runtime_fhm.py) writes each audio child
as <NNN>_RIFF.bin. Those have the Project Aces RIFF/WAVE quirks:

  - The RIFF size field is set to file_size, NOT file_size - 8. The tool
    patches this on export.
  - The fmt chunk uses wFormatTag = 0x0165 (XMA1) but actually carries
    XMA2 streams (an "x2st" chunk follows). Decoders that key off
    wFormatTag alone will misread channels/sample rate; vgmstream knows
    to look at x2st.

The current corpus only has 42 RIFF entries, all from idx_0214 and
idx_0227 — these are voice/event clips. Adding more requires either
playing more of the game with AC6_DUMP_PAC_DECODED=1 or implementing the
offline mode-1 decompressor (see section 6).


================================================================================
4. COMMAND REFERENCE
================================================================================

Default (FHM corpus only, decode if vgmstream is on PATH):

    python tools/export_ac6_audio.py

FHM corpus + asset packs:

    python tools/export_ac6_audio.py --packs

Asset packs only, skip FHM corpus:

    python tools/export_ac6_audio.py --packs-only

Dry-run (list what would be exported, write nothing):

    python tools/export_ac6_audio.py --packs --dry-run

Skip the vgmstream decode step (write .xma only):

    python tools/export_ac6_audio.py --packs --no-decode

Point at a specific vgmstream binary:

    python tools/export_ac6_audio.py --packs ^
        --vgmstream "C:/tools/vgmstream/vgmstream-cli.exe"

Custom asset directory (if your build output is elsewhere):

    python tools/export_ac6_audio.py --packs ^
        --assets "D:/games/AC6/assets"


================================================================================
5. CUTSCENE VIDEO (moviepack.bin)
================================================================================

moviepack.bin starts with the ASF GUID 30 26 B2 75 8E 66 CF 11 — it's a
standard Microsoft ASF container with WMV9 video and WMA audio inside.
Use ffmpeg directly (not vgmstream, not this tool):

    ffmpeg -i moviepack.bin -map 0 -c copy out/movies/all.wmv

Or to remux into mp4 (re-encodes audio):

    ffmpeg -i moviepack.bin -c:v copy -c:a aac out/movies/all.mp4

The ASF object index identifies individual cutscenes; ffmpeg's segment
muxer can split them, but moviepack also tends to be a single concatenated
ASF, in which case ffmpeg will emit one file. Use ffprobe to inspect.


================================================================================
6. THE MISSING SFX, AND WHAT IT TAKES TO GET THEM
================================================================================

If you extract everything above and play the .wavs, you'll hear: music,
dialogue, cutscene mixes. You will NOT hear: jet engines, missile lock
warnings, gun fire, explosions, ECM bursts, ground impacts, cockpit
warnings. Those live in a third channel that the current pipeline cannot
yet open.

Why:

  - There is no sfxpack.bin. Look at the asset directory and you'll see
    bgmpack / voicepack / demopack / moviepack — and that's it for audio.
  - SFX waveforms are inside DATA00.PAC / DATA01.PAC, packed as RIFF/XMA
    entries inside FHM containers like the voice clips above.
  - Those FHM containers are mode-1 compressed. The runtime mode-1 hook
    (see ac6_extraction_roadmap.md) decompresses entries as the game
    requests them. Anything the game hasn't requested in your sessions
    so far is still sitting in DATA*.PAC compressed.
  - The cue tables that name the SFX are present already — idx_0000/
    001_BSN_.bsn (sound bank), idx_0000/00{2,3,4}_BFX_.bfx (effects),
    idx_0001/000_nusc.bin (Namco cue table) — but they only contain
    pointers. The waveform data they point to is in the un-decompressed
    SFX banks.

Two ways forward:

(a) Capture more at runtime.
    Set AC6_DUMP_PAC_DECODED=1 and play missions with combat. The
    SFX-bearing PAC entries will get decompressed by the game and
    written to out/ac6_pac_runtime_dump/ as new entry_*_mode1_*.bin
    files. Then re-run:

        python tools/run_ac6_asset_pipeline.py --skip-pac-extract
        python tools/export_ac6_audio.py --packs

    New idx_<N> directories under out/ac6_runtime_fhm_typed/ should
    contain new RIFF entries.

(b) Finish the offline mode-1 decompressor.
    docs/ac6_extraction_roadmap.md "Path B" — port the guest mode-1
    decoder to Python so every compressed PAC entry can be materialized
    without launching the game. This is the only way to guarantee all
    SFX are extracted, regardless of what mission state you've reached.

The recommended near-term option is (a). For a complete archive (b) is
the right answer.


================================================================================
7. TROUBLESHOOTING
================================================================================

"found 0 RIFF entries"
    Your FHM corpus is empty. Run the asset pipeline first:
        python tools/run_ac6_asset_pipeline.py
    If that produces no output either, you don't yet have any runtime
    dumps — see ac6_asset_extraction_walkthrough.txt.

"assets dir not found"
    Pass --assets pointing at the directory that contains bgmpack.bin
    etc. The default assumes a standard build at
    out/build/win-amd64-relwithdebinfo/assets/.

"vgmstream-cli not on PATH; writing .xma only"
    Not an error — the .xma files are valid. Install vgmstream
    (https://vgmstream.org/downloads) or pass --vgmstream <path> and
    re-run. vgmstream is also available as a foobar2000 plugin if you
    just want to listen, not convert.

"truncated stream at 0x... ; stopping"
    The pack walker found a RIFF whose declared size runs past the end
    of the file. Usually means the pack file is partial / damaged.
    Verify the file size against your install media.

vgmstream decode fails with "unknown format"
    Confirm the .xma file starts with 'RIFF' and that bytes 8..12 are
    'WAVE'. If they aren't, the splitter mis-stepped and the file is
    junk. Try running with --no-decode and inspect the output bytes.

The .wav plays as silence / noise
    For the 42 FHM-channel clips: if vgmstream warns about the format
    tag, that's the 0x0165-but-actually-XMA2 quirk. vgmstream handles
    it correctly when an x2st chunk is present. If you patched the
    file by hand and removed x2st, restore from out/ac6_runtime_fhm_typed
    and re-run the exporter.


================================================================================
8. WHERE THINGS LIVE
================================================================================

Inputs:
    out/build/win-amd64-relwithdebinfo/assets/bgmpack.bin
    out/build/win-amd64-relwithdebinfo/assets/voicepack_*.bin
    out/build/win-amd64-relwithdebinfo/assets/demopack_*.bin
    out/build/win-amd64-relwithdebinfo/assets/moviepack.bin
    out/ac6_runtime_fhm_typed/idx_*/                (FHM-channel RIFFs)

Outputs:
    out/ac6_runtime_audio/                          (FHM-channel .xma/.wav)
    out/ac6_runtime_audio/packs/                    (pack-channel .xma/.wav)

Tools:
    tools/export_ac6_audio.py                       (this walkthrough's tool)
    tools/extract_ac6_runtime_fhm.py                (FHM extractor)
    tools/run_ac6_asset_pipeline.py                 (orchestrator)

Reference:
    docs/ac6_extraction_roadmap.md                  ("Audio extraction"
                                                     section, channel 1/2/3)
    docs/ac6_asset_pipeline.md                      (overall pipeline)
