Skip to content

Commit

Permalink
Add bindings for AudioListener
Browse files Browse the repository at this point in the history
  • Loading branch information
orottier committed Nov 30, 2023
1 parent ce30937 commit edad866
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 0 deletions.
4 changes: 4 additions & 0 deletions examples/iir-filter.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import { AudioContext } from '../index.mjs';
const latencyHint = process.env.WEB_AUDIO_LATENCY === 'playback' ? 'playback' : 'interactive';
const audioContext = new AudioContext({ latencyHint });

console.log(audioContext.listener.position_x.value);
audioContext.listener.position_x.set_value(1.);
console.log(audioContext.listener.position_x.value);

const pathname = path.join(process.cwd(), 'samples', 'think-stereo-48000.wav');
const arrayBuffer = fs.readFileSync(pathname).buffer;
const buffer = await audioContext.decodeAudioData(arrayBuffer);
Expand Down
24 changes: 24 additions & 0 deletions examples/panner.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { AudioContext } from '../index.mjs';

const latencyHint = process.env.WEB_AUDIO_LATENCY === 'playback' ? 'playback' : 'interactive';
const audioContext = new AudioContext({ latencyHint });

audioContext.listener.positionZ.value = 1;
audioContext.listener.positionX.value = -10;
audioContext.listener.positionX.linearRampToValueAtTime(10, 4);

const osc = audioContext.createOscillator();
const panner = audioContext.createPanner();
osc.connect(panner);
panner.connect(audioContext.destination);
osc.start();

let direction = 1;
setInterval(function loop() {
console.log(audioContext.listener.positionX.value);
if (Math.abs(audioContext.listener.positionX.value) >= 10.) {
direction *= -1;
const now = audioContext.currentTime;
audioContext.listener.positionX.linearRampToValueAtTime(10 * direction, now + 4);
}
}, 500);
7 changes: 7 additions & 0 deletions generator/templates/audio_context.tmpl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ fn constructor(ctx: CallContext) -> Result<JsUndefined> {
};

let audio_context = AudioContext::new(audio_context_options);
let native_listener = audio_context.listener();
let napi_audio_context = NapiAudioContext(audio_context);
ctx.env.wrap(&mut js_this, napi_audio_context)?;

Expand All @@ -134,6 +135,12 @@ fn constructor(ctx: CallContext) -> Result<JsUndefined> {
let js_obj = ctor.new_instance(&[&js_this])?;
js_this.set_named_property("destination", &js_obj)?;

// Audio Listener
let napi_listener = NapiAudioListener::new(native_listener);
let mut js_obj = NapiAudioListener::create_js_object(ctx.env)?;
ctx.env.wrap(&mut js_obj, napi_listener)?;
js_this.set_named_property("listener", &js_obj)?;

ctx.env.get_undefined()
}

Expand Down
3 changes: 3 additions & 0 deletions generator/templates/lib.tmpl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ use napi_derive::module_exports;
#[macro_use]
mod audio_node;

mod audio_listener;
use audio_listener::NapiAudioListener;

mod audio_param;
use crate::audio_param::{NapiAudioParam};
// public
Expand Down
7 changes: 7 additions & 0 deletions src/audio_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ fn constructor(ctx: CallContext) -> Result<JsUndefined> {
};

let audio_context = AudioContext::new(audio_context_options);
let native_listener = audio_context.listener();
let napi_audio_context = NapiAudioContext(audio_context);
ctx.env.wrap(&mut js_this, napi_audio_context)?;

Expand All @@ -155,6 +156,12 @@ fn constructor(ctx: CallContext) -> Result<JsUndefined> {
let js_obj = ctor.new_instance(&[&js_this])?;
js_this.set_named_property("destination", &js_obj)?;

// Audio Listener
let napi_listener = NapiAudioListener::new(native_listener);
let mut js_obj = NapiAudioListener::create_js_object(ctx.env)?;
ctx.env.wrap(&mut js_obj, napi_listener)?;
js_this.set_named_property("listener", &js_obj)?;

ctx.env.get_undefined()
}

Expand Down
156 changes: 156 additions & 0 deletions src/audio_listener.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// @TODO
// This should be generated as any other AudioNode

use crate::*;
use napi::*;
use napi_derive::js_function;
use web_audio_api::AudioListener;

pub struct NapiAudioListener(AudioListener);

impl NapiAudioListener {
pub fn new(audio_listener: AudioListener) -> Self {
Self(audio_listener)
}

pub fn create_js_object(env: &Env) -> Result<JsObject> {
let mut obj = env.create_object()?;
obj.define_properties(&[
Property::new("Symbol.toStringTag")?
.with_value(&env.create_string("AudioListener")?)
.with_property_attributes(PropertyAttributes::Static),
Property::new("positionX")?.with_getter(get_position_x),
Property::new("positionY")?.with_getter(get_position_y),
Property::new("positionZ")?.with_getter(get_position_z),
Property::new("forwardX")?.with_getter(get_forward_x),
Property::new("forwardY")?.with_getter(get_forward_y),
Property::new("forwardZ")?.with_getter(get_forward_z),
Property::new("upX")?.with_getter(get_up_x),
Property::new("upY")?.with_getter(get_up_y),
Property::new("upZ")?.with_getter(get_up_z),
])?;

Ok(obj)
}

pub fn unwrap(&self) -> &AudioListener {
&self.0
}
}

#[js_function]
fn get_position_x(ctx: CallContext) -> Result<JsObject> {
let js_this = ctx.this_unchecked::<JsObject>();
let napi_node = ctx.env.unwrap::<NapiAudioListener>(&js_this)?;
let node = napi_node.unwrap();

let native_param = node.position_x().clone();
let napi_param = NapiAudioParam::new(native_param);
let mut js_obj = NapiAudioParam::create_js_object(ctx.env)?;
ctx.env.wrap(&mut js_obj, napi_param)?;
Ok(js_obj)
}

#[js_function]
fn get_position_y(ctx: CallContext) -> Result<JsObject> {
let js_this = ctx.this_unchecked::<JsObject>();
let napi_node = ctx.env.unwrap::<NapiAudioListener>(&js_this)?;
let node = napi_node.unwrap();

let native_param = node.position_y().clone();
let napi_param = NapiAudioParam::new(native_param);
let mut js_obj = NapiAudioParam::create_js_object(ctx.env)?;
ctx.env.wrap(&mut js_obj, napi_param)?;
Ok(js_obj)
}

#[js_function]
fn get_position_z(ctx: CallContext) -> Result<JsObject> {
let js_this = ctx.this_unchecked::<JsObject>();
let napi_node = ctx.env.unwrap::<NapiAudioListener>(&js_this)?;
let node = napi_node.unwrap();

let native_param = node.position_z().clone();
let napi_param = NapiAudioParam::new(native_param);
let mut js_obj = NapiAudioParam::create_js_object(ctx.env)?;
ctx.env.wrap(&mut js_obj, napi_param)?;
Ok(js_obj)
}

#[js_function]
fn get_forward_x(ctx: CallContext) -> Result<JsObject> {
let js_this = ctx.this_unchecked::<JsObject>();
let napi_node = ctx.env.unwrap::<NapiAudioListener>(&js_this)?;
let node = napi_node.unwrap();

let native_param = node.forward_x().clone();
let napi_param = NapiAudioParam::new(native_param);
let mut js_obj = NapiAudioParam::create_js_object(ctx.env)?;
ctx.env.wrap(&mut js_obj, napi_param)?;
Ok(js_obj)
}

#[js_function]
fn get_forward_y(ctx: CallContext) -> Result<JsObject> {
let js_this = ctx.this_unchecked::<JsObject>();
let napi_node = ctx.env.unwrap::<NapiAudioListener>(&js_this)?;
let node = napi_node.unwrap();

let native_param = node.forward_y().clone();
let napi_param = NapiAudioParam::new(native_param);
let mut js_obj = NapiAudioParam::create_js_object(ctx.env)?;
ctx.env.wrap(&mut js_obj, napi_param)?;
Ok(js_obj)
}

#[js_function]
fn get_forward_z(ctx: CallContext) -> Result<JsObject> {
let js_this = ctx.this_unchecked::<JsObject>();
let napi_node = ctx.env.unwrap::<NapiAudioListener>(&js_this)?;
let node = napi_node.unwrap();

let native_param = node.forward_z().clone();
let napi_param = NapiAudioParam::new(native_param);
let mut js_obj = NapiAudioParam::create_js_object(ctx.env)?;
ctx.env.wrap(&mut js_obj, napi_param)?;
Ok(js_obj)
}

#[js_function]
fn get_up_x(ctx: CallContext) -> Result<JsObject> {
let js_this = ctx.this_unchecked::<JsObject>();
let napi_node = ctx.env.unwrap::<NapiAudioListener>(&js_this)?;
let node = napi_node.unwrap();

let native_param = node.up_x().clone();
let napi_param = NapiAudioParam::new(native_param);
let mut js_obj = NapiAudioParam::create_js_object(ctx.env)?;
ctx.env.wrap(&mut js_obj, napi_param)?;
Ok(js_obj)
}

#[js_function]
fn get_up_y(ctx: CallContext) -> Result<JsObject> {
let js_this = ctx.this_unchecked::<JsObject>();
let napi_node = ctx.env.unwrap::<NapiAudioListener>(&js_this)?;
let node = napi_node.unwrap();

let native_param = node.up_y().clone();
let napi_param = NapiAudioParam::new(native_param);
let mut js_obj = NapiAudioParam::create_js_object(ctx.env)?;
ctx.env.wrap(&mut js_obj, napi_param)?;
Ok(js_obj)
}

#[js_function]
fn get_up_z(ctx: CallContext) -> Result<JsObject> {
let js_this = ctx.this_unchecked::<JsObject>();
let napi_node = ctx.env.unwrap::<NapiAudioListener>(&js_this)?;
let node = napi_node.unwrap();

let native_param = node.up_z().clone();
let napi_param = NapiAudioParam::new(native_param);
let mut js_obj = NapiAudioParam::create_js_object(ctx.env)?;
ctx.env.wrap(&mut js_obj, napi_param)?;
Ok(js_obj)
}
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ use napi_derive::module_exports;
#[macro_use]
mod audio_node;

mod audio_listener;
use audio_listener::NapiAudioListener;

mod audio_param;
use crate::audio_param::NapiAudioParam;
// public
Expand Down

0 comments on commit edad866

Please sign in to comment.