#audio #compression #codec #adhoc

bin+lib adhoc_audio

A very basic audio codec, written in pure rust

5 releases

0.1.4 Oct 20, 2022
0.1.3 Dec 3, 2021
0.1.2 Nov 30, 2021
0.1.1 Nov 30, 2021
0.1.0 Nov 30, 2021

#129 in WebAssembly

Download history 7/week @ 2022-11-28 13/week @ 2022-12-05 22/week @ 2022-12-12 52/week @ 2022-12-19 7/week @ 2022-12-26 5/week @ 2023-01-02 14/week @ 2023-01-09 10/week @ 2023-01-16 26/week @ 2023-01-23 30/week @ 2023-01-30 13/week @ 2023-02-06 25/week @ 2023-02-13 19/week @ 2023-02-20 3/week @ 2023-02-27 15/week @ 2023-03-06 19/week @ 2023-03-13

67 downloads per month
Used in fluffl



Adhoc Audio

Audio compression written in pure rust. It Doesn't link to any bindings so its buildable for wasm32-unknown-unknown.

What is this?

Its a collection of audio codecs I'm cobbling together to compress audio. I'm currently using it to:

  • compress microphone data on client's browser (using this repo compiled to wasm)
  • send data to server (POST request multipart)
  • re-encode compressed data to a standard format (here i'll use rust bindings to libavcodec or something)

Currently, there's only one codec that actually compresses audio [AdhocCodec] and a WAVE Reader/Writer Utility I wrote [WavCodec].


The need arose to compress microphone data coming from the WEBAUDIO api during the development of a WASM application I was writing. A pure rust solution is needed to keep the build steps of the project simple. AFAIK, there are a few pure rust audio decoders for things like VORBIS(lewton) ,MP3(puremp3) etc but most of those crates do not support encoding.


Probably not very fast but I haven't really tested this. The encoding/decoding algorithm is O(N) so it should be fast enough. And I will definitely make optimizations if I can't meet my speed requirements. the Vec implementation does allocation, so there should be log(N) allocations.


Compression savings seems to be anywhere from 20%-70% but I haven't done extensive testing to say concretely. The codec is not lossy, however, it does quantize the audio on higher "compression-levels" to make significant space savings. Quantization doesn't effect audio quality too badly, I was pretty suprised at that discovery.

Encode Example

use adhoc_audio::{codec::Streamable, AdhocCodec, WavCodec};
use std::fs::File;

fn main() {
    println!("compressing file example..");

    //set up a buffer for reading/writing samples
    let mut samples = [0.0; 1024];

    //open wav file
    let mut wav_reader = WavCodec::load(File::open("./resources/taunt.wav")
    let mut adhoc = AdhocCodec::new()
        // level 0 means no quantization ,so its basically lossless at level 0
        // levels 1-10 means quantization so compression is better but 
        // quality suffers (dithering is added to compensate)
        // AdhocCodec::with_info(.. ) MUST BE CALLED 
        // before calling encode/decode when you are 
        // creating a new instance of AdhocCodec

    //'decode' wav stream bit-by-bit
    //Note:in this case we are just reading PCM info
    while let Some(samples_read) = wav_reader.decode(&mut samples) {
        //encode wav data bit-by-bit
        //memory is allocated as needed

    //write compressed audio back to disk

    println!("taunt.adhoc written to: ./resources");

Decode Example

use adhoc_audio::{codec::Streamable, AdhocCodec, WavCodec};
use std::fs::File;

fn main() {
    println!("decompressing file from 'compress' example...");

    //set up a buffer for reading/writing samples
    let mut samples = [0.0; 1024];

    //open wav file
    let mut adhoc = AdhocCodec::load(
        File::open("./resources/taunt.adhoc").expect("run example 'compress' before this one"),
    let mut wav_writer = WavCodec::new(adhoc.info());

    //decode adhoc stream a chunk of samples at a time
    while let Some(samples_read) = adhoc.decode(&mut samples) {
        //encode wav data bit-by-bit
        //memory is allocated as needed

    //write compressed audio back to disk

    println!("taunt.adhoc written to: ./resources");

Command line interface

This package has a simple command line tool to convert back and forth between .wav and the .adhoc format.

In terminal simply do:

cargo install --path .

to see flag options do:

adhoc_audio -h


the simplest way to compress a wav is like so:

adhoc_audio ./resources/taunt.wav 

and it will create a taunt.codec in the current directory


building of the first example to decompress taunt.codec just:

adhoc_audio ./taunt.codec

and decompressed wav file will be written to your cwd


~48K SLoC