Skip to content

Marcel-G/waw-rs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

waw-rs

waw-rs helps you create Web Audio Worklets using Rust, without crying.

See WebAssembly/Rust Tutorial: Pitch-perfect Audio Processing

This is all very experimental.

Requirements

This crate requires WebAssembly target features +atomics and +bulk-memory to function properly. These features are necessary for the underlying web-thread dependency that enables Audio Worklet support with shared memory and threading.

Minimal Configuration

If you want a minimal setup (though the full configuration above is recommended), you can use:

[target.wasm32-unknown-unknown]
rustflags = [
  "-C", "target-feature=+atomics,+bulk-memory",
]

Usage

Add waw-rs to your Cargo.toml:

waw = { git = "https://github.com/Marcel-G/waw-rs" }

Implement the Processor trait and register your audio node:

use wasm_bindgen::prelude::*;
use waw::{register, ParameterValuesRef, Processor};

#[derive(Clone)]
pub struct MyData {
    pub frequency: f32,
}

pub struct MyProcessor {
    phase: f32,
    frequency: f32,
}

impl Processor for MyProcessor {
    type Data = MyData;

    fn new(data: Self::Data) -> Self {
        Self { phase: 0.0, frequency: data.frequency }
    }

    fn process(
        &mut self,
        _inputs: &[&[f32]],
        outputs: &mut [&mut [f32]],
        sample_rate: f32,
        params: &ParameterValuesRef,
    ) {
        // ... your audio processing logic
    }
}

#[wasm_bindgen]
pub struct MyNode {
    node: web_sys::AudioWorkletNode,
}

#[wasm_bindgen]
impl MyNode {
    #[wasm_bindgen(constructor)]
    pub fn new(ctx: &web_sys::AudioContext, frequency: f32) -> Result<MyNode, JsValue> {
        let data = MyData { frequency };
        
        // Configure input/output ports via AudioWorkletNodeOptions
        let options = web_sys::AudioWorkletNodeOptions::new();
        options.set_number_of_inputs(0);  // Generator: no inputs
        options.set_number_of_outputs(1); // Mono output
        
        let node = MyProcessor::create_node(ctx, data, Some(&options))?;
        Ok(MyNode { node })
    }

    #[wasm_bindgen(getter)]
    pub fn node(&self) -> web_sys::AudioWorkletNode {
        self.node.clone()
    }
}

register!(MyProcessor, "my-processor");

Build with wasm-pack:

wasm-pack build --target web

Use in JavaScript:

import init, { MyNode, register_all } from './pkg/your_project';

const main = async () => {
  await init();
  const context = new AudioContext();
  
  // Register all audio worklet processors
  await register_all(context);

  const node = new MyNode(context, 440.0);
  node.node.connect(context.destination);

  document.addEventListener('click', () => context.resume(), { once: true });
};

main();

See the demo for a complete example.

Links

About

Rust Web Audio Worklets without crying

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages