All Projects → AnthumChris → Opus Stream Decoder

AnthumChris / Opus Stream Decoder

Instantly decode Ogg Opus audio streams in chunks with JavaScript & WebAssembly (Wasm)

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to Opus Stream Decoder

Wasmjit
Small Embeddable WebAssembly Runtime
Stars: ✭ 1,063 (+1228.75%)
Mutual labels:  emscripten, webassembly, wasm
Webassembly Examples
From Simple To Complex. A complete collection of webassembly examples.
Stars: ✭ 177 (+121.25%)
Mutual labels:  emscripten, webassembly, wasm
Assortedwidgets
OpenGL GUI library
Stars: ✭ 92 (+15%)
Mutual labels:  emscripten, webassembly, wasm
Dcmjs
dcmjs is a javascript cross-compile of dcmtk (dcmtk.org).
Stars: ✭ 92 (+15%)
Mutual labels:  emscripten, webassembly, wasm
Wac
WebAssembly interpreter in C
Stars: ✭ 372 (+365%)
Mutual labels:  emscripten, webassembly, wasm
Emscripten Docker
Docker image with Emscripten to compile ASM.js and WebAssembly
Stars: ✭ 92 (+15%)
Mutual labels:  emscripten, webassembly, wasm
Modern Wasm Starter
🛸 Run C++ code on web and create blazingly fast websites! A starter template to easily create WebAssembly packages using type-safe C++ bindings with automatic TypeScript declarations.
Stars: ✭ 140 (+75%)
Mutual labels:  emscripten, webassembly, wasm
Wasmer
🚀 The leading WebAssembly Runtime supporting WASI and Emscripten
Stars: ✭ 11,047 (+13708.75%)
Mutual labels:  emscripten, webassembly, wasm
Wasm Git
GIT for nodejs and the browser using https://libgit2.org compiled to WebAssembly with https://emscripten.org
Stars: ✭ 261 (+226.25%)
Mutual labels:  emscripten, webassembly, wasm
koder
QR/bar code scanner for the Browser
Stars: ✭ 73 (-8.75%)
Mutual labels:  webassembly, wasm, emscripten
TypeScriptXX
🧷 Stay safe! Type-safe scripting for C++ using TypeScriptToLua and CMake with auto-generated declarations.
Stars: ✭ 33 (-58.75%)
Mutual labels:  webassembly, wasm, emscripten
Camaro
camaro is an utility to transform XML to JSON, using Node.js binding to native XML parser pugixml, one of the fastest XML parser around.
Stars: ✭ 438 (+447.5%)
Mutual labels:  emscripten, webassembly, wasm
Rustynes
👾 An NES emulator by Rust and WebAssembly
Stars: ✭ 399 (+398.75%)
Mutual labels:  emscripten, webassembly, wasm
Cppwasm Book
📚 WebAssembly friendly programming with C/C++ -- Emscripten practice
Stars: ✭ 956 (+1095%)
Mutual labels:  emscripten, webassembly, wasm
Wagi
Write HTTP handlers in WebAssembly with a minimal amount of work
Stars: ✭ 75 (-6.25%)
Mutual labels:  webassembly, wasm
Proxy Wasm Cpp Sdk
WebAssembly for Proxies (C++ SDK)
Stars: ✭ 55 (-31.25%)
Mutual labels:  webassembly, wasm
Pulsefft
A WebAssembly implementation of the C Fast Fourier Transform library kissFFT
Stars: ✭ 76 (-5%)
Mutual labels:  webassembly, wasm
Vxformgenerator
The library contains a component, that nests itself into the Blazor EditForm instead of a wrapper around the EditForm. The component is able to generate a form based on a POCO or a ExpandoObject. Because of this architecture the library provides the developer flexibility and direct usage of the EditForm.
Stars: ✭ 60 (-25%)
Mutual labels:  webassembly, wasm
Sql.js
A javascript library to run SQLite on the web.
Stars: ✭ 9,594 (+11892.5%)
Mutual labels:  emscripten, wasm
Blazor Wasm Identity Grpc
Blazor WASM, IdentityServer4, Kestrel Web Server, Entity Framework Code First SQLite Database with Multiple Roles, Additional User Claims & gRPC with Roles Authorization.
Stars: ✭ 61 (-23.75%)
Mutual labels:  webassembly, wasm

OpusStreamDecoder is an Emscripten JavaScript WebAssembly (Wasm) library for immediately decoding Ogg Opus audio streams (URLs or files) in chunks without waiting for the complete file to download, copy, or read. libopusfile is the underlying C library used for decoding. OpusStreamDecoder provides a lightweight JavaScript API for decoding Opus audio streams at near-native speeds.

Note: This repository was forked from AnthumChris/fetch-stream-audio to decouple OpusStreamDecoder as a standalone Wasm decoder. It will be integrated back into demo as a git submodule for fetch-stream-audio #4.

Usage

Pre-compiled binaries and full examples are included in the dist/ folder. The OpusStreamDecoder API was designed to be simple and the pseudocode below explains its complete usage:

If using a front-end build system, you can obtain OpusStreamDecoder via require or import syntaxes:

const { OpusStreamDecoder } = require('opus-stream-decoder');
import { OpusStreamDecoder } from 'opus-stream-decoder';

Otherwise, include the script bfore you instantiate OpusStreamDecoder.

<script src="opus-stream-decoder.js"></script>
<script>
  // instantiate with onDecode callback that fires when OggOpusFile data is decoded
  const decoder = new OpusStreamDecoder({onDecode});

  // Loop through your Opusdata callingdecode() multiple times. Pass a Uint8Array
  try {
    while(...) {
      decoder.ready.then(_ => decoder.decode(UINT8_DATA_TO_DECODE));
    }
  } catch (e) {
    decoder.ready.then(_ => decoder.free());
  }

  // free up the decoder's memory in WebAssembly (also resets decoder for reuse)
  decoder.ready.then(_ => decoder.free());

  // after free() is called, you could reuse the decoder for another file
  try { ... decoder.ready.then(_ => decoder.decode(UINT8_DATA_TO_DECODE) } ...

  /* Receives decoded Float32Array PCM audio in left/right arrays.
   * sampleRate is always 48000 and both channels would always contain data if
   * samplesDecoded > 0.  Mono Opus files would decoded identically into both
   * left/right channels and multichannel Opus files would be downmixed to 2 channels.
   */
  function onDecode({left, right, samplesDecoded, sampleRate}) {
    console.log(`Decoded ${samplesDecoded} samples`);
    // play back the left/right audio, write to a file, etc
  }
</script>

After instantiating OpusStreamDecoder, decode() should be called repeatedly until you're done reading the stream. You must start decoding from the beginning of the file. Otherwise, a valid Ogg Opus file will not be discovered by libopusfile for decoding. decoder.ready is a Promise that resolves once the underlying WebAssembly module is fetched from the network and instantiated, so ensure you always wait for it to resolve. free() should be called when done decoding, when decode() throws an error, or if you wish to "reset" the decoder and begin decoding a new file with the same instance. free() releases the allocated Wasm memory.

Performance

To achieve optimum decoding performance, OpusStreamDecoder should ideally be run in a Web Worker to keep CPU decoding computations on a sepearate browser thread. (TODO: provide web worker example.)

Additionally, onDecode will be called thousands of times while decoding Opus files. Keep your onDecode callbacks lean. The multiple calls result intentionally because of Opus' unmatched low-latency decoding advantage (read more)—audio is decoded as soon as possible . For example, a 60-second Opus file encoded with a 20ms frame/packet size would yield 3,000 onDecode calls (60 * 1000 / 20), because the underlying libopusfile C decoding function op_read_float_stereo() currently decodes one frame at a time during my tests.

Building

The dist/ folder will contain all required files, tests, and examples after building.

Download Ogg, Opus, and Opusfile C libraries:

$ git submodule update --init

TODO: consider moving this to Makefile

Install Emscripten

Emscripten is used to compile the C libraries to be compatible with WebAssembly. This repo was tested with 1.39.5.

Run the Build

$ make clean dist

The Emscripten module builds in a few seconds, but most of the work will be spent configuring the dependencies libopus, libogg, and libopusfile. You may see the warnings (not errors) below, which don't prevent the build from succeeding. It is not known whether these warnings adversly affect runtime use.

  • Don't have the functions lrint() and lrintf ()
  • Replacing these functions with a standard C cast
  • implicit conversion from 'unsigned int' to 'float'

Build Errors

Error: "autoreconf: command not found"

$ brew install automake

"./autogen.sh: No such file or directory"

$ brew install autogen

Tests & Examples

Two tests exist that will decode an Ogg Opus File with OpusStreamDecoder. Both tests output "decoded N samples." on success.

NodeJS Test

This test writes two decoded left/right PCM audio data to files in tmp/. Install NodeJS and run:

$ make test-wasm-module

HTML Browser Test

This test uses fetch() to decode a URL file stream in chunks. Serve the dist/ folder from a web server and open test-opus-stream-decoder.html in the browser. HTTP/HTTPS schemes are required for Wasm to load—opening it directly with file:// probably won't work.

You can also run SimpleHTTPServer and navigate to http://localhost:8000/test-opus-stream-decoder.html

$ cd dist
$ python -m SimpleHTTPServer 8000

Developing

Emscripten Wasm Module

See files src/*.{js,html} and use $ make and $ make clean to build into dist/

OpusChunkDecoder C interface

See C files src/opus_chunkdecoder* and use $ make native-decode-test, which allows you to compile and test almost instantly. native-decode-test is a fast workflow that ensures things work properly independently of Emscripten and Wasm before you integrate it.

You'll need to install libopusfile binaries natively on your system (on Mac use $ brew install opusfile). Then, declare environment variables with the locations of the installed libopusfile dependencies required by native-decode-test before running:

$ export OPUS_DIR=/usr/local/Cellar/opus/1.2.1
$ export OPUSFILE_DIR=/usr/local/Cellar/opusfile/0.10
$ make native-decode-test

Note: If you see error "fatal error: 'stdarg.h' file not found", try running from a new terminal window that does not have Emscripten initialized.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].