# Inside vgmstream: a decode-only library under six player front ends

> vgmstream is a C library that decodes streamed video game audio into WAV, wrapped in a command line decoder, a command line player, and plugins for Winamp, foobar2000, XMPlay and Audacious. It decodes and never encodes, and that one fact decides where the project fits.

**vgmstream/vgmstream** — vgmstream - A library for playback of various streamed audio formats used in video games.

- Repository: https://github.com/vgmstream/vgmstream
- Website: https://vgmstream.org
- Stars: 2,302 · Forks: 229
- Language: C
- License: NOASSERTION
- Published: 2026-10-14 · Updated: 2026-10-14 · Language: en
- Canonical page: https://hysenlabs.com/projects/vgmstream-vgmstream

## A library core wrapped in six player front ends

vgmstream splits into a core and the programs that feed it. Plain vgmstream, the library itself, handles the internal conversion; the six components are only ways to hand a file to that core and take sound out of it. They are `vgmstream-cli` for batch conversion, `in_vgmstream` as a Winamp plugin, `foo_input_vgmstream` for foobar2000, `xmp-vgmstream` for XMPlay, `vgmstream.so` as an Audacious plugin, and `vgmstream123` as a command line player.

The split shapes debugging. A wrong sample rate belongs to the core and shows up in every front end at once, while a missing option belongs to one host and appears in one plugin only. Feature parity across the components is the stated goal, and the project openly accepts the differences that fall out of missing pieces on its side or gaps in the host player.

## Subsongs, loop points, and data split across companion files

Three mechanisms carry most of the everyday behaviour. Loop points are read from metadata inside the file itself, so a background track repeats with a smooth transition and a sample count that matches what the game used. Subsongs split one container into its separate internal songs, which matters for archives where a single file holds an entire soundtrack and you want one track rather than all of it.

Companion files cover data split across several files, so a bank shipped as separate chunks still decodes as one stream. Custom containers, encryption keys and internal stream names sit on that same path, and that is where the long tail of single-game formats gets handled rather than in the plugin layer.

## TXTH and TXTP move configuration outside the binary

Two sidecar formats extend a build that cannot know every format and cannot know every preference. TXTH describes an extra layout or codec from outside the library, including raw audio in many forms, so a format the core does not recognise can still be played from a text file sitting next to the audio. TXTP is the per file control surface: forced looping, removing channels, selecting one subsong, or fusing several files into a single stream.

Because both are plain files rather than compiled code, changing how a track behaves does not mean rebuilding the decoder. External tagging is a third and lighter mechanism, an `.m3u` file that names tracks for a host player. Note the direction of travel: these files can reshape what vgmstream reads, and they can never turn a `.wav` back into a game stream.

## Converting game files with vgmstream-cli on three platforms

The quick path needs no build at all. Take the prebuilt command line decoder for Windows, Linux or macOS, drag one or more files onto the executable, and it writes `(file.extension).wav` beside the source when the format is supported. Support varies by operating system and distro, which the project does not gloss over.

On Linux that binary is statically linked and is documented to run on kernel v3.2 and above. The Audacious plugin and the `vgmstream123` player cannot be linked that way, so anyone on Linux who wants looping and subsong controls builds from source with the script shipped for Debian and Ubuntu style distros:

```bash
./make-build-cmake.sh
```

The script installs its own dependencies first, which is the whole point on a fresh machine and the reason to follow the steps in `doc/BUILD.md` by hand when you care about what lands on the system.

## The Makefile still aims at Windows, with autotools as the alternative

The root `Makefile` admits its bias in a comment: currently aimed to WIN32 builds but vgmstream-cli should work for others, or use autotools instead. That bias shows in the details. On a Windows target it forces `SHELL = sh`, exports a `DLL_DIR`, and for 64 bit output swaps in `dlltool -m i386:x86-64 --as-flags --64` with results written to `dll-x64`. It also points `LIBAO_DLL_PATH` at `../libao/bin` for builds that include `vgmstream123`.

Warning flags are strict but incomplete. `-ffast-math` sits in the default set and relaxes floating point rounding, format security is promoted to an error, and a commented out line shows that `-Wswitch-default` and `-Wmissing-declarations` were weighed and left off. `VGM_DEBUG_FLAGS` defaults to 0. Two toolchains cover the same source, an autotools path built around `configure.ac` and a Visual Studio path driven by `msvc-build.bat`:

```bash
bootstrap
msvc-build.bat
```

## Decode only: there is no path back to a game format

The clearest boundary is direction. vgmstream cannot encode, so a `.wav` cannot be pushed back into a game stream, and no build flag, TXTH file or TXTP option changes that. Anyone planning a modding pipeline that writes game audio gets nothing from this project.

The second boundary sits between the front ends themselves. Parity is the goal, but the accepted differences come from pieces missing on the project side and from limits in the host player. That is why the foobar2000 component distributed through foobar2000.org tracks a frozen snapshot while vgmstream.org carries current builds, and why bnnm publishes a separate and irregular channel of binaries. Work out which channel your installed plugin came from before spending an afternoon on a loop that one host handles and another ignores.

## Drag-and-drop decoding versus playing through a host player

Two routes cover most needs, and they differ in control rather than in output. Drag and drop onto `vgmstream-cli` is one file in, one `.wav` out, with no options and no subsong picker, but it batch processes a directory in one move and installs nothing. Putting the plugin into foobar2000 on Windows or Audacious on Linux moves looping and subsong selection into menus the player already has, and conversion rides along with the player's own export option. For a listen without installing anything, the project points at an online web player on vgmstream.org.

Pick the CLI when you want a scripted batch. Pick the plugin when you want loop points and subsongs handled by hand. None of the three routes can encode, which is the wall every one of them runs into.

## Nightly binaries carry what numbered tags do not

Freshness is uneven across the distribution channels. The newest numbered release is r2117 dated 2026-05-19, yet the last push to master landed on 2026-09-27, so the source has moved months past that tag, and the project points nightly builds and vgmstream.org at current changes while calling its numbered output infrequent. Version strings are stamped at build time instead of being read from a source file, because the Makefile runs a helper script unless the variable is already set in the environment.

```bash
sh ./version-get.sh
```

Licence terms sit in a custom `COPYING` file at the repository root rather than in one of the standard named licences, so anyone redistributing vgmstream inside a product has to read that file rather than assume a familiar grant.

## Conclusion

vgmstream belongs on a machine that holds game audio no other decoder can open, and it belongs nowhere near a pipeline that has to write game audio back. Before adopting it, check three concrete things: which channel your binary came from, since the numbered tags trail the source by months; whether your host player exposes subsong and loop controls, since parity across the front ends is explicitly incomplete; and what the custom COPYING terms ask you to ship. Convert one file with vgmstream-cli and play the .wav in Audacious before pointing a user at it.

## FAQ

### What is vgmstream and what does it do with a game audio file?

It is a C library that decodes streamed, prerecorded video game audio into ordinary WAV, covering hundreds of music formats and codecs from typical game engine files to obscure single-game ones. It only decodes, so a WAV cannot be converted back into a game format.

### How do I convert game music to WAV with vgmstream-cli?

Take the prebuilt command line decoder, then drag one or more files onto the executable. Each supported file produces `(file.extension).wav` beside the original, and support varies by operating system or distro.

### Can vgmstream play one file that contains several songs?

Yes. Subsongs let one container expose its internal songs separately, so a soundtrack file can be played or converted track by track, and a TXTP file can force one subsong without going through a menu.

### What is the difference between TXTH and TXTP in vgmstream?

TXTH adds external support for formats the library does not know, including raw audio in many forms. TXTP carries per file configuration such as forced looping, removing channels, playing a chosen subsong, or fusing several files into a single stream.

### Why is there no prebuilt Audacious plugin for Linux?

The prebuilt Linux command line binary is statically linked and is documented to work on kernel v3.2 and above, while vgmstream.so and vgmstream123 cannot be statically linked. Linux users who want those components build from source, for instance with `./make-build-cmake.sh`.

## Sources

- [Issues](https://github.com/vgmstream/vgmstream/issues)
- [Project website](https://vgmstream.org)
- [README](https://github.com/vgmstream/vgmstream/blob/master/README.md)
- [Releases](https://github.com/vgmstream/vgmstream/releases)
- [vgmstream/vgmstream on GitHub](https://github.com/vgmstream/vgmstream)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/vgmstream-vgmstream
