Skip to content

MartinEricsson/qoa-wasm

Repository files navigation

QOA Decoder in WebAssembly

A WebAssembly decoder for the QOA (Quite OK Audio) format, implemented in WebAssembly Text (WAT) format for use in web browsers and Node.js.

🎵 Try the Live Demo

Overview

This is a decoder-only implementation. The encoder is not included in this project.

Note: This library assumes that the input is well formed, no validation of the data is performed when decoding. There are no checks for

  • Magic number verification
  • Minimum file size requirements
  • Zero or invalid values for channels, sample rate, or sample counts
  • Frame header consistency checks

The goal for this projects is size of the decoder, currently sitting at

  • Original: 1.17 KB (1195 bytes)
  • Gzipped: 887 bytes (887 bytes)

Installation

npm install qoa-wasm

or

pnpm add qoa-wasm

or

yarn add qoa-wasm

Building from Source

Prerequisites

  • Node.js
  • pnpm

Build instructions

pnpm install
pnpm build

Usage

In Node.js

const { QOADecoder } = require('qoa-wasm');
const fs = require('fs');
const path = require('path');

// Initialize the decoder once
await QOADecoder.init();

// Load and decode a QOA file
const qoaBuffer = fs.readFileSync(path.join(__dirname, 'audio.qoa'));
const decoded = QOADecoder.decode(qoaBuffer);

console.log('Channels:', decoded.channels);
console.log('Sample Rate:', decoded.sampleRate);
console.log('Samples per channel:', decoded.samplesPerChannel);
console.log('PCM samples:', decoded.samples); // Int16Array

In the Browser

Note that the Wasm runtime must support multi value.

import { QOADecoder, decodeToAudioBuffer } from 'qoa-wasm';

// Initialize the decoder once
await QOADecoder.init();

// Load and decode a QOA file
const response = await fetch('audio.qoa');
const qoaBuffer = await response.arrayBuffer();
const decoded = QOADecoder.decode(qoaBuffer);

console.log('Channels:', decoded.channels);
console.log('Sample Rate:', decoded.sampleRate);
console.log('Samples per channel:', decoded.samplesPerChannel);
console.log('PCM samples:', decoded.samples); // Int16Array

Using with Web Audio API

import { QOADecoder, decodeToAudioBuffer } from 'qoa-wasm';

await QOADecoder.init();

const audioContext = new AudioContext();
const response = await fetch('audio.qoa');
const qoaBuffer = await response.arrayBuffer();
const decoded = QOADecoder.decode(qoaBuffer);

// Decode to AudioBuffer using the utility helper
const audioBuffer = decodeToAudioBuffer(decoded, audioContext);

// Play the audio
const source = audioContext.createBufferSource();
source.buffer = audioBuffer;
source.connect(audioContext.destination);
source.start();

Using Script Tags (UMD)

<script src="node_modules/qoa-wasm/src/qoa-decoder.js"></script>
<script src="node_modules/qoa-wasm/src/utils/decode-to-audio-buffer.js"></script>
<script>
  // Initialize the decoder
  QOADecoder.init().then(() => {
    // Load and decode
    fetch('audio.qoa')
      .then(response => response.arrayBuffer())
      .then(qoaBuffer => {
        const decoded = QOADecoder.decode(qoaBuffer);
        console.log('Decoded:', decoded);
        
        // Convert to AudioBuffer
        const audioContext = new AudioContext();
        const audioBuffer = QOAUtils.decodeToAudioBuffer(decoded, audioContext);
        
        // Play
        const source = audioContext.createBufferSource();
        source.buffer = audioBuffer;
        source.connect(audioContext.destination);
        source.start();
      });
  });
</script>

Demo

🎵 Try the Live Demo

Or run it locally:

pnpm serve

Then open http://localhost:8080 in your browser.

Contributing

See PUBLISHING.md for information about the release process and how to create changesets.

License

ISC License - see LICENSE file for details.

About

A QOA decoder written in the WebAssembly text format

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Contributors