A bespoke sample compression codec for 64k intros

Related tags

Compression pulsejet
Overview

pulsejet

A bespoke sample compression codec for 64K intros

pulsejet codec overview

codec

pulsejet lifts a lot of ideas from Opus, and more specifically, its CELT layer, which is used for coding musical signals. This blog post outlines much of the current codec design, as well as provides some background behind why certain decisions were made.

Relatively speaking, pulsejet is in its early days, and is admittedly pretty crude, especially the encoder. Surprisingly, though, it already appears to be quite good, as well as works around a lot of other issues with using existing codecs, hence the standalone public release. Expect further development/versions of this library, as well as integration in WaveSabre.

comparisons

An up-to-date listening test matrix can be found here, though it's a good idea to review this blog post section in order to better understand what you're actually listening to before making any judgments.

releases

See releases and changelog for release information.

usage

pulsejet's decoder API is meant to be integrated with software synthesizers (for example, WaveSabre) in size-constrained environments. As such, it only relies on basic C/C++ facilities to allocate/free memory, cast data types, etc. However, it does not rely on existing math functions, as many of these are often unavailable in such environments, and so must be implemented by the user. Luckily, software synthesizers typically already have some or all of the required functions available. Further, sine/cosine functions are often reimplemented for improved performance, rather than to work around artificial limitations.

pulsejet's encoder and meta APIs, on the other hand, are meant to be integrated into authorship tools, which are not size-constrained. As such, they rely on the C/C++ standard libraries to more conveniently implement more complex logic. However, the encoder still relies on user-provided sine/cosine implementations in order to support potential speed optimizations.

Essentially, some or all of the pulsejet library can be used in a number of different ways and in different configurations. For these reasons, pulsejet is a header-only library. By distributing only source code, the user can control the specific compilation flags necessary to build the code appropriately in their existing environment. By distributing only headers, we can provide a mechanism by which the few dependencies that pulsejet has can be configured by the user, and trivially include/exclude some or all of the library, depending on how it will be used.

The include directory should be copied (or otherwise made available somehow) in its entirety to allow the public API header(s) to access the appropriate internal support header(s). From there, one or more of the appropriate header(s) should be #included:

If shims are required (only the encoder and decoder APIs require them), they should be defined in the Pulsejet::Shims namespace before #include'ing the pulsejet header(s). See the included demo application source for how to do this, and the individual doc comments in the source for which shim(s) need to be provided for your use case.

pulsejet's encoder and decoder APIs only accept/output raw, mono floating point PCM sample data, and won't do any sort of mixing/sample rate conversion/etc. This is the job of another library or tool, eg. ffmpeg.

converting .wav <-> .raw

Convert .wav to appropriate raw floating point PCM:

ffmpeg -i  -f f32le -ac 1 -c:a pcm_f32le 

Convert raw floating point PCM to .wav:

ffmpeg -f f32le -ar 44100 -i  

demo

The included demo application, while tiny, is meant to serve as a simple example of how to use the entire pulsejet API, as well as an easy way to test out the codec before actually integrating it into anything. Its basic CLI usage is:

Usage:
  encode: pulsejet_demo -e   
  decode: pulsejet_demo -d  

A typical round-trip test might look like this:

# Convert original .wav sample to .raw (and potentially downmix to mono, if it isn't already)
ffmpeg -i my_sample_original.wav -f f32le -ac 1 -c:a pcm_f32le my_sample_original.raw
# Encode sample
./pulsejet_demo -e 32 my_sample_original.raw my_sample.pulsejet
# Decode sample
./pulsejet_demo -d my_sample.pulsejet my_sample_roundtripped.raw
# Convert decoded sample from .raw to .wav
ffmpeg -f f32le -ar 44100 -i my_sample_roundtripped.raw my_sample_roundtripped.wav

attribution

pulsejet is primarily inspired by Opus, and more specifically, its CELT layer. Additionally, several other articles and writings by the Xiph.Org Foundatation have been incredibly enlightening and inspiring. The work that these folks have done in the open codec space is nothing short of heroic, and without that work, pulsejet would never have been possible. So, huge thanks to them!

FAQ

My encoded pulsejet sample is about half the size of the raw sample, even though the size estimate from the demo said it would only be a fraction of this. What gives?

pulsejet doesn't include an entropy coding stage because in 64k intros, there's typically a very powerful general-purpose compressor already present in the executable packer used (for example, squishy). The size estimate from the pulsejet encoder refers to the final compressed size in the intro, not the encoded size. To check if the estimate is in the right ballpark, a decent compressor like 7-Zip can be used, but bear in mind its ratio is typically a few percent worse than squishy's (which the pulsejet's encoder estimation is tuned to). Additionally, the estimate is still an estimate, and while it tends to be fairly correct on average, no guarantees are made here.

How large is the pulsejet decoder after compression?

About 750 bytes, give or take, depending on what else is in the executable and which packer is used. This can surely be code golfed more, and I expect this will improve in future library versions.

Why not use a better codec that's already included in most target environments like Opus?

There are several reasons, including:

  • On relevant material and at our target bit rates, pulsejet is actually already surprisingly competitive, despite being so crude - so "better" is relative. Listen/compare for yourself here. pulsejet has a lot of room for improvement as well, particularly on the encoder side, which would allow for higher quality at current rates and/or similar quality at lower rates.
  • Because the pulsejet decoder is entirely self-contained (no dependencies on any specific OS features), it works with basically any platform we'd ever want to target, without any fuss or worry about future API breakages.
  • Having an easy-to-integrate encoder library with a permissive license makes tooling integration much easier than it otherwise would be, which can be a real pain for some codecs/encoders (eg. HE-AAC).

Besides, let's be honest: it's just plain rad to have our own codec!

This blog post has more in-depth information behind the codec, its design, and the motivation for building a custom codec in the first place.

license

pulsejet is licensed under the MIT license (see LICENSE or http://opensource.org/licenses/MIT).

You might also like...
gzip (GNU zip) is a compression utility designed to be a replacement for 'compress'

gzip (GNU zip) is a compression utility designed to be a replacement for 'compress'

Advanced DXTc texture compression and transcoding library

crunch/crnlib v1.04 - Advanced DXTn texture compression library Public Domain - Please see license.txt. Portions of this software make use of public d

Better lossless compression than PNG with a simpler algorithm

Zpng Small experimental lossless photographic image compression library with a C API and command-line interface. It's much faster than PNG and compres

Analysing and implementation of lossless data compression techniques like Huffman encoding and LZW was conducted along with JPEG lossy compression technique based on discrete cosine transform (DCT) for Image compression.

PROJECT FILE COMPRESSION ALGORITHMS - Huffman compression LZW compression DCT Aim of the project - Implement above mentioned compression algorithms an

emPOWer your commits. Pointlessly flex on your coworkers with bespoke commit hashes, all with the convenience of a single command.
emPOWer your commits. Pointlessly flex on your coworkers with bespoke commit hashes, all with the convenience of a single command.

git-power emPOWer your commits. Pointlessly flex on your coworkers with bespoke commit hashes, all with the convenience of a single command.

Source code from 068A, our 64k demo presented at Syntax 2017

068A source code dump This is a dump of the source code for the engine, graphics tool and player for 068A, our 64k demo released at Syntax 2017. It's

Lossless data compression codec with LZMA-like ratios but 1.5x-8x faster decompression speed, C/C++

LZHAM - Lossless Data Compression Codec Public Domain (see LICENSE) LZHAM is a lossless data compression codec written in C/C++ (specifically C++03),

Simple Binary Encoding (SBE) - High Performance Message Codec

Simple Binary Encoding (SBE) SBE is an OSI layer 6 presentation for encoding and decoding binary application messages for low-latency financial applic

Open h.265 video codec implementation.
Open h.265 video codec implementation.

libde265 - open h.265 codec implementation libde265 is an open source implementation of the h.265 video codec. It is written from scratch and has a pl

Open Source H.264 Codec

OpenH264 OpenH264 is a codec library which supports H.264 encoding and decoding. It is suitable for use in real time applications such as WebRTC. See

hessian2-codec it is a complete C++ implementation of hessian2 spec

hessian2-codec is a C++ library from Alibaba for hessian2 codec. It is a complete C++ implementation of hessian2 spec. Because it was originally intended to implement the Dubbo Filter of Envoy, it did not provide good support for serialization of user-defined types (there is only one way to implement user-defined types using ADL, but it is not very complete and does not support nested types well). At the moment it is simply deserializing content into some C++ intermediate types.

Lyra: a generative low bitrate speech codec

Lyra is a high-quality, low-bitrate speech codec that makes voice communication available even on the slowest networks.

A free, fast, cross-platform volumetric codec for everyone.

The open source Universal Volumetric (".uvol") compressed interchange format for streaming mesh sequences. This project also includes a cross-platform player implementation using h.264 video for texture.

LFAC - Low Fidelity Audio Codec
LFAC - Low Fidelity Audio Codec

LFAC - Low-Fidelity Audio Codec Copyright 2021 Jari Komppa, http://iki.fi/sol Licensed under Unlicense. Not to be confused with FLAC. What is this? Do

Python bindings of silk codec.

Python silk module. --- pysilk --- APIs See test\test.py. import pysilk as m m.silkEncode(buf , 24000) m.silkDecode(buf , 24000) #the first param is b

Cross-platform silk codec wrap library depends on ploverlake/silk.

libSilkCodec Cross-platform silk codec wrap library depends on ploverlake/silk. Clone & Build Linux/Unix like # clone $ git clone https://github.c

ffmpeg supporting EVC codec and file formats.

ffevc ffmpeg supporting EVC codec and file formats. MPEG-5 Essential Video Coding (EVC) integration with FFmpeg project. It is supported under Linux a

Nuvoton codec/amp driver with different ASoC version

Nuvoton-ASoC Nuvoton codec and amp drivers with different ASoC versions. The Nuvoton-ASoC repository stores the Linux driver for codec and amplifier m

Comments
  • Potential UB in Demo due to unaligned access

    Potential UB in Demo due to unaligned access

    While I was porting pulsejet to Rust (here), I'd some problems while testing original code.

    I've setup C++ code to compile both original and my code to compare output, but I was getting segfaults. My C++ test code was partially copied from Demo.cpp, and I've noticed that here: https://github.com/logicomacorp/pulsejet/blob/ec73d19ccb71ff05b2122e258fe4b7b16e55fb53/demo/Demo.cpp#L102 there is a pointer cast from bytes to floats. I think that in C++ casting pointer to bigger alignment (without checking if it's correctly aligned) is UB, 'tho I haven't thoroughly tested if that was causing the segfaults (I ended up just translating code to safe rust and manually checking if output sounds good).

    It could probably be fixed by adding ReadFileAsFloats function that loads file directly into vector<float>.

    opened by Shadlock0133 0
Owner
logicoma
Demos and demo accessories
logicoma
Brotli compression format

SECURITY NOTE Please consider updating brotli to version 1.0.9 (latest). Version 1.0.9 contains a fix to "integer overflow" problem. This happens when

Google 11.7k Dec 29, 2022
Multi-format archive and compression library

Welcome to libarchive! The libarchive project develops a portable, efficient C library that can read and write streaming archives in a variety of form

null 1.9k Jan 8, 2023
Extremely Fast Compression algorithm

LZ4 - Extremely fast compression LZ4 is lossless compression algorithm, providing compression speed > 500 MB/s per core, scalable with multi-cores CPU

lz4 7.9k Dec 31, 2022
LZFSE compression library and command line tool

LZFSE This is a reference C implementation of the LZFSE compressor introduced in the Compression library with OS X 10.11 and iOS 9. LZFSE is a Lempel-

null 1.7k Jan 4, 2023
Small strings compression library

SMAZ - compression for very small strings ----------------------------------------- Smaz is a simple compression library suitable for compressing ver

Salvatore Sanfilippo 1k Dec 28, 2022
Zstandard - Fast real-time compression algorithm

Zstandard, or zstd as short version, is a fast lossless compression algorithm, targeting real-time compression scenarios at zlib-level and better comp

Facebook 19.2k Jan 1, 2023
A massively spiffy yet delicately unobtrusive compression library.

ZLIB DATA COMPRESSION LIBRARY zlib 1.2.11 is a general purpose data compression library. All the code is thread safe. The data format used by the z

Mark Adler 4.1k Dec 30, 2022
A variation CredBandit that uses compression to reduce the size of the data that must be trasnmitted.

compressedCredBandit compressedCredBandit is a modified version of anthemtotheego's proof of concept Beacon Object File (BOF). This version does all t

Conor Richard 18 Sep 22, 2022
Data compression utility for minimalist demoscene programs.

bzpack Bzpack is a data compression utility which targets retrocomputing and demoscene enthusiasts. Given the artificially imposed size limits on prog

Milos Bazelides 20 Jul 27, 2022
A simple C library implementing the compression algorithm for isosceles triangles.

orvaenting Summary A simple C library implementing the compression algorithm for isosceles triangles. License This project's license is GPL 2 (as of J

Kevin Matthes 0 Apr 1, 2022