Terrific Audio Driver v0.3.0

Introducing version 0.3.0 of the Terrific Audio Driver.

This version does not add new features, instead I made 2 major back end changes: The audio driver has been ported to spc-700 assembly and tad-gui now uses the cpal crate to play audio.

The new release can be downloaded from GitHub.

The driver has been ported to spc-700 assembly

I have rewritten the audio driver in assembly using a custom assembler written in rust.

This was done for 4 major reasons:

  1. Simplify TAD compilation. TAD required you to import the wiz git submodule and compile wiz before cargo build to embed the audio driver in the compiler and GUI. I've had to help a few people navigate TAD compilation on Discord. Now, the rust build script uses my new assembler to directly build the audio driver.

  2. The build script now has access to all symbols, constants and labels. The rust code can extract things like a BYTECODE_VERSION constant out of the audio driver and emit a compile-time assert error if it doesn't match a BYTECODE_VERSION constant in the bytecode module.

  3. It enables a few optimisations I could not implement in wiz:

    • Wiz does not allow a label to escape a { } scope.
    • Wiz cannot emit the bbc branch if bit clear nor bbs branch if bit set instructions.
  4. I can add static .assert statements to the audio driver.

Why did I write the audio driver in wiz to begin with? I was using wiz in unnamed-snes-game, loved the language and decided unnamed-snes-game's audio driver will also be written in wiz. Having type checking on variable accesses and forward-referenced inlines greatly sped up development of the audio driver.

Now that the audio driver has matured and the audio driver has excellent test coverage1. The TAD compilation issue was getting more annoying. I did not want to commit the audio driver binary to my git repository, nor did I want the build script to download the audio-driver binary from somebody else's computer. Spending a month writing my own assembler sounded like a nice side project.

Once I realised I do not need namespaces, macros or substitutions (think .IDENT(.SPRINTF(..)) in ca65 or {} in bass) the design became a lot simpler and development greatly sped up. The only complex feature my assembler supports is forward-referenced inline procedures. Keeping the vibrato and portamento effects code next to each other in the source file (despite them being 325 bytes apart in the binary) was well worth it.

Porting the audio driver to assembly involved renaming the .wiz files to .asm and manually fixing the 2331 assembler errors. A lot of the lines were converted using regular expressions. The remaining lines, which were mostly control flow and arithmetic, were manually ported by hand over the course of a few days.

Once the assembler stopped emitting errors, I used hexdump and delta (a colourized diff) to find and manually fix all of times the assembly port was not byte-identical to the wiz audio-driver. I encountered: wrong branch instructions, missing index register typos, wrong operand order in multiple mov instructions, a few missing # (immediate) in the arithmetic instructions, missing clrc instructions and 4 bugs in my assembler.

This was a nice side project. I'm leaving the audio-driver byte-identical for this release. The next release will include many small optimisations I noticed while I was porting the audio-driver to assembly.

tad-gui now uses cpal to play audio

The other pain point when compiling TAD is the SDL dependency. When I wrote tad-gui I used sdl2 crate to handle audio in a simple and cross platform manner. While the sdl2 crate is easy to compile on Linux, setting up the SDL2.0 development libraries on Windows is a bit complicated.

I've replaced the sdl2 dependency with the cpal crate. This involved writing my own resampling ring buffer that converts the audio driver's 32040Hz sampling rate to a 48000Hz sampling rate that most computers expect.

Linux and BSD users will need to install the ALSA development libraries (libasound2-dev on Debian or alsa-lib-devel on Fedora) to compile this latest release.

There are no new dependencies when compiling TAD on windows.

What's Next

Here's what I have planned for the next two releases of the Terrific Audio Driver:

  • Implement those optimisations I can now implement in spc700 assembly.
  • Improve MML command merging.
  • Redesign the samples tab and improve the samples UX.
  • Design the data formats, IO communications protocol and UX needed for sample swapping.

I'm also going to restart development in Space Rescue Squad.


  1. test_bc_interpreter runs TAD songs through an emulated audio driver and a rust bytecode interpreter and verifies that the audio-driver variables and bytecode interpreter state is identical.