AIL2.NET 1.0.0

dotnet add package AIL2.NET --version 1.0.0
                    
NuGet\Install-Package AIL2.NET -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="AIL2.NET" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="AIL2.NET" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="AIL2.NET" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add AIL2.NET --version 1.0.0
                    
#r "nuget: AIL2.NET, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package AIL2.NET@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=AIL2.NET&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=AIL2.NET&version=1.0.0
                    
Install as a Cake Tool

AIL2.NET

AIL2.NET provides managed AIL/32 sequencing, FM interpretation, MT-32 messages, and PCM/VOC playback. The repository also includes an Avalonia player. Open AIL2.NET.slnx.

NuGet

dotnet add package AIL2.NET
dotnet add package AIL2.NET.Rendering

The projects target .NET 10 and allow any compatible SDK. AIL2.NET.Rendering uses the NukedOPL3Sharp 1.3.1 NuGet package for OPL synthesis.

Builds use the recommended .NET analyzers and Roslynator.Analyzers 5.0.0, with warnings treated as errors. The analyzer package is used only during development. NuGet packages include XML documentation for the public APIs.

The project and assembly names use AIL2.NET; the root namespace is AIL2. The rendering, player and harness namespaces are AIL2.Rendering, AIL2.Player and AIL2.Parity.

dotnet build AIL2.NET.slnx -c Release
dotnet run --project src/AIL2.NET.Player -c Release

The player needs an available OpenAL audio device. Original-code tests additionally require Node.js and GCC. NuGet supplies Unicorn 2 on supported Linux and macOS targets. Run parity on Linux x64; Unicorn 2.1.3 currently terminates under the Windows .NET test host because of its Control Flow Guard incompatibility. The REL105 WR drivers and A214 SOUNDFX.C are included. No game assets are required: tests and default harness scenarios generate their own resources.

NativeAOT

dotnet publish src/AIL2.NET.Player -c Release -r linux-x64 -p:PublishProfile=NativeAot -o artifacts/native-player
./artifacts/native-player/AIL2.NET.Player

The NativeAot profile enables native compilation and treats trimming and AOT warnings as errors. It has been tested on Linux x64 with GCC, binutils, and the zlib development files. The player requires a graphical display. Other runtimes need their corresponding native toolchains.

The player loads OpenAL through native exports and writes MIDI JSON without reflection. Both libraries enable AOT compatibility analysis.

Choosing instruments and chip mode

Choose the music device/profile, OPL chip mode, and instrument bank independently. Select the bank intended for your music; a two-operator .ad bank can be used with Sound Blaster + OPL3.

Bank contents define the instruments. An .opl file can contain two-operator definitions; its extension alone does not imply four-operator instruments or the same sound as another bank.

Device Chip mode Original AIL driver profile
AdLib OPL2 AdLib
Sound Blaster OPL2 Sound Blaster
Sound Blaster Dual OPL2 Sound Blaster Pro 1
Sound Blaster OPL3 Sound Blaster Pro 2
Pro Audio Spectrum Dual OPL2 Pro Audio Spectrum
Pro Audio Spectrum OPL3 PAS OPL3
AdLib Gold OPL3 AdLib Gold
Roland MT-32 No OPL chip MT-32 messages

OPL3 modes accept two-operator .ad instruments and four-operator instruments. OPL2 modes reject four-operator definitions. The digital profile is a separate choice for sampled effects.

The player keeps the selected bank when it is compatible with the new chip mode. Loading different bank contents resets playback and the instrument cache, while changing tracks with the same bank keeps the current session.

Play an XMIDI file, then select and play a VOC to hear music and an effect together. WAV export starts the loaded resources from the beginning and follows the same PCM path. Finite resources finish automatically; use Stop export for looping music. The completed portion is finalized as a playable WAV. Long files use RF64 when necessary. Live controls remain responsive during export. MT-32 messages can be inspected and exported to timestamped JSON; MT-32 synthesis and device transport belong to the host.

Library use

An engine selects the device family and chip mode through the same public configuration as the player:

using AIL2;

var music = new MusicConfiguration(MusicDevice.SoundBlaster, OplChipMode.Opl3);
using var session = new AILSession(
    music,
    DigitalProfile.SoundBlasterPro,
    oplOutput: hostOplOutput,
    sampleOutput: hostSampleOutput);

session.LoadTimbreBank(TimbreBank.Load(File.ReadAllBytes("instruments.ad")));
using var sequence = session.CreateSequence(XmidiFile.Load(File.ReadAllBytes("music.xmi")));
sequence.Start();
session.AdvanceTo(TimeSpan.FromSeconds(1));

For standalone PCM rendering, construct AILRenderer with that configuration and call Render(Span<short>) with an interleaved stereo buffer. The default is 48 kHz. For sampled effects, use CreateSample(VocFile) or create a SampleBuffer with a SampleFormat. The session owns the buffer data. ReplaceBuffer stops the current sample before starting the replacement, and the selected profile quantizes the requested source rate.

See host integration for a complete console export example, state transitions, channel numbering and output-consumer contracts. Public types and members carry XML summaries, parameters, return values and relevant exceptions in the source.

All session operations and callbacks run on the thread that created the session. The core creates no threads, reads no wall clock, and does not dispose output sinks supplied by the caller. Resource loaders copy their input, while playback objects keep the resources they need. Treat sample-block memory as read-only, and copy MIDI spans if they must outlive the callback. Dispose playback objects and sessions on their creating thread. Repeated disposal is safe.

AdvanceTo processes due sample completions, XMIDI services, then MIDI-effect services in deterministic order. XMIDI triggers run synchronously at their original event boundary and may stop, branch or otherwise control a sequence. Recursive advancement and backwards time are rejected. Default service periods are the source's 8,333 µs for music and 10 ms for the sound-effect helper.

The sample consumer declares format support. Uncompressed PCM completes automatically on the session timeline. Compressed bytes are forwarded unchanged only to a capable consumer; that consumer advances the session to its completion timestamp and calls SamplePlayback.CompleteBlock(). No compression decoder is included.

LoadTimbreBank preserves original installation/index order. As in AIL, installing an already resident key does not replace its data. Hosts can preload a bank before starting sequences or use PrepareTimbres for strict demand loading. Original sequence, note and channel capacities are retained; they are musical behavior, not player duration limits.

Verification

dotnet build AIL2.NET.slnx -c Release
dotnet test --project tests/AIL2.NET.Tests -c Release --no-build
dotnet run --project tools/AIL2.NET.Parity -c Release --no-build -- --samples
dotnet run --project tools/AIL2.NET.Parity -c Release --no-build -- --profile all

The parity executable runs the original AIL instructions in Unicorn without DOSBox. It compares output order, timing, status, and sequence position. With no input path, it creates a small set of XMIDI, VOC, and bank files under artifacts/generated-resources/. Expected behavior comes from the original code rather than stored output files. Reports under artifacts/parity/ record input and driver hashes along with each scenario's ending. Music comparisons run finite sequences to completion; looping sequences run twice and then stop. A scenario fails if it exhausts its service budget.

To compare your own resources, pass file or directory paths together with the appropriate bank paths. Directories are scanned recursively; bank names need not match track names. All relative paths resolve from the working directory.

dotnet run --project tools/AIL2.NET.Parity -c Release -- --input /path/to/music.xmi --profile SoundBlasterPro2 --bank /path/to/instruments.ad
dotnet run --project tools/AIL2.NET.Parity -c Release -- --input /path/to/music --profile all --bank-ad /path/to/fm.bank --bank-opl /path/to/opl3.bank --bank-mt /path/to/mt32.bank
dotnet run --project tools/AIL2.NET.Parity -c Release -- --samples --input /path/to/effects

Use --drivers /path/to/REL105/WR to select an external original-driver directory, --sequence INDEX to select one sequence, --marker NUMBER for marked VOC resources, and --help for other options. External music inputs require an explicit compatible bank. Missing inputs, empty directories, sample selections with no played blocks, unsupported resources and oracle failures return a failing exit code. Sample corpus runs require finite VOC playback; compressed completion is tested through an explicit external-consumer schedule, without decoding.

Custom resources and generated reports are not committed. Keep optional inputs outside the checkout or in the ignored private-resources/ directory. The AIL files required by the tests and parity harness are under reference/; see their license grant. Player builds do not include the original drivers or test resources.

The MT-32 parity path repairs a stack-width error in a temporary copy of the original driver. A separate regression test covers the unmodified instruction. See validation.md, oracle-boundaries.md, coverage.md, and host-integration.md. Rendering comparisons feed both AIL event streams through the same NukedOPL3Sharp package; they test AIL2.NET rather than the synthesizer.

AIL2.NET is licensed under the MIT License. Original AIL reference material and dependencies retain their own terms; see THIRD_PARTY_NOTICES.md.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on AIL2.NET:

Package Downloads
AIL2.NET.Rendering

PCM rendering and WAV export for AIL2.NET using NukedOPL3Sharp.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 101 9/7/2026