<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Masable</id>
	<title>Expertiza_Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Masable"/>
	<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Special:Contributions/Masable"/>
	<updated>2026-05-27T13:01:44Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124845</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124845"/>
		<updated>2019-05-03T11:42:24Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Completed Work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we did not actually program in JavaScript for this project. This project involved writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
=== Tracking Issues ===&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
=== Useful Resources ===&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Project Steps ==&lt;br /&gt;
&lt;br /&gt;
=== Initial Steps (OSS Project) ===&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
=== Subsequent Steps (Final Project) ===&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
=== OSS Project ===&lt;br /&gt;
&lt;br /&gt;
Our OSS project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final Project ===&lt;br /&gt;
&lt;br /&gt;
For our final project, we had a lot of freedom to design our runnable StereoPannerNode example. For the example, we could have set the pan value to anything between -1 (full left pan) and 1 (full right pan) and then changed it any way we wished. At first, we considered setting the pan value to different values at different times, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
context.message_node(&lt;br /&gt;
        osc,&lt;br /&gt;
        AudioNodeMessage::SetParam(ParamType::Pan, UserAutomationEvent::SetValueAtTime(-1., 2.)),&lt;br /&gt;
    );&lt;br /&gt;
context.message_node(&lt;br /&gt;
        osc,&lt;br /&gt;
        AudioNodeMessage::SetParam(ParamType::Pan, UserAutomationEvent::SetValueAtTime(1., 4.)),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That code would set the pan value to -1 at time = 2 seconds, and then set it to 1 at time = 4 seconds. However, it sounded very weird to have the sound jumping around from place to place.&lt;br /&gt;
&lt;br /&gt;
Eventually, we decided that linearly ramping up the pan value made for the best listening experience. It made the sound continuous but still exemplified what changing the pan value could do.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
context.message_node(&lt;br /&gt;
        pan,&lt;br /&gt;
        AudioNodeMessage::SetParam(&lt;br /&gt;
            ParamType::Pan,&lt;br /&gt;
            UserAutomationEvent::RampToValueAtTime(RampKind::Linear, 0., 4.),&lt;br /&gt;
        ),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our final version of the StereoPannerNode example involved linearly ramping the pan value from -1 to 0 and then from 0 to 1. This meant the sound moved from left to right over time.&lt;br /&gt;
&lt;br /&gt;
The rest of our final project just involved implementing methods and therefore did not involve any design choices.&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
Our Pull Requests:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 OSS Project]&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/242 Final Project Step 1 - Oscillator node message]&lt;br /&gt;
&lt;br /&gt;
The purpose of our first pull request was to implement an audio node message specific to OscillatorNode. This was within the servo/media project. For this pull request, we had to create a new OscillatorNodeMessage within the oscillator_node.rs file. The purpose of the OscillatorNodeMessage is to set the type of the OscillatorNode. We then had to modify node.rs to utilize the new OscillatorNodeMessage.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23282 Final Project Step 2 - Type attribute for OscillatorNode interface]&lt;br /&gt;
&lt;br /&gt;
The purpose of our second pull request was to implement the type attribute for the OscillatorNode interface within the main servo project. This required enabling the setter throws and OscillatorType attribute within the OscillatorNode.webidl file. More importantly, it involved modifying the oscillatornode.rs file to include methods to set and get the type of the OscillatorNode. This was challenging because we did not realize at first that we needed to wrap the oscillator_type in a cell in order to achieve interior mutability. Initially, we were handing references to the setters and getters of the DOM struct members, which did not expose the set and get methods we were calling. We had to wrap the oscillator_type in a cell to give mutable references instead.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/243 Final Project Step 3 - StereoPannerNode backend]&lt;br /&gt;
&lt;br /&gt;
For our third pull request, we had to implement the backend for the StereoPannerNode in servo/media. Then we had to create a runnable example that utilizes the StereoPannerNode. We designed our example so that we would initialize a StereoPannerNode with the default pan value of 0. Then, we would set the pan value to -1. Next, we would linearly ramp up the pan value to 0 and then to 1. A user could run this example and listen to the StereoPannerNode through speakers as its pan value changed over time, causing the sound to move from left to right.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23281 Final Project Step 4 - StereoPannerNode DOM]&lt;br /&gt;
&lt;br /&gt;
For our fourth and last pull request, we created the DOM interface for StereoPannerNode and implemented the createStereoPannerNode API for BaseAudioContext within the main servo project. We had to create a few new files for this, since there was no existing stereopannernode.rs or StereoPannerNode.webidl. We also had to modify audionode.rs to add constraints when creating a StereoPannerNode, such as to ensure that there are not more than two channels and that the channel count mode is not set to max. In that case, we had to return a NotSupported error.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124844</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124844"/>
		<updated>2019-05-03T11:30:05Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we did not actually program in JavaScript for this project. This project involved writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
=== Tracking Issues ===&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
=== Useful Resources ===&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Project Steps ==&lt;br /&gt;
&lt;br /&gt;
=== Initial Steps (OSS Project) ===&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
=== Subsequent Steps (Final Project) ===&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
=== OSS Project ===&lt;br /&gt;
&lt;br /&gt;
Our OSS project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final Project ===&lt;br /&gt;
&lt;br /&gt;
For our final project, we had a lot of freedom to design our runnable StereoPannerNode example. For the example, we could have set the pan value to anything between -1 (full left pan) and 1 (full right pan) and then changed it any way we wished. At first, we considered setting the pan value to different values at different times, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
context.message_node(&lt;br /&gt;
        osc,&lt;br /&gt;
        AudioNodeMessage::SetParam(ParamType::Pan, UserAutomationEvent::SetValueAtTime(-1., 2.)),&lt;br /&gt;
    );&lt;br /&gt;
context.message_node(&lt;br /&gt;
        osc,&lt;br /&gt;
        AudioNodeMessage::SetParam(ParamType::Pan, UserAutomationEvent::SetValueAtTime(1., 4.)),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That code would set the pan value to -1 at time = 2 seconds, and then set it to 1 at time = 4 seconds. However, it sounded very weird to have the sound jumping around from place to place.&lt;br /&gt;
&lt;br /&gt;
Eventually, we decided that linearly ramping up the pan value made for the best listening experience. It made the sound continuous but still exemplified what changing the pan value could do.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
context.message_node(&lt;br /&gt;
        pan,&lt;br /&gt;
        AudioNodeMessage::SetParam(&lt;br /&gt;
            ParamType::Pan,&lt;br /&gt;
            UserAutomationEvent::RampToValueAtTime(RampKind::Linear, 0., 4.),&lt;br /&gt;
        ),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our final version of the StereoPannerNode example involved linearly ramping the pan value from -1 to 0 and then from 0 to 1. This meant the sound moved from left to right over time.&lt;br /&gt;
&lt;br /&gt;
The rest of our final project just involved implementing methods and therefore did not involve any design choices.&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
Our Pull Requests:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 OSS Project]&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/242 Final Project Step 1 - Oscillator node message]&lt;br /&gt;
&lt;br /&gt;
The purpose of our first pull request was to implement an audio node message specific to OscillatorNode. This was within the servo/media project. For this pull request, we had to create a new OscillatorNodeMessage within the oscillator_node.rs file. The purpose of the OscillatorNodeMessage is to set the type of the OscillatorNode. We then had to modify node.rs to utilize the new OscillatorNodeMessage.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23282 Final Project Step 2 - Type attribute for OscillatorNode interface]&lt;br /&gt;
&lt;br /&gt;
The purpose of our second pull request was to implement the type attribute for the OscillatorNode interface within the main servo project. This required enabling the setter throws and OscillatorType attribute within the OscillatorNode.webidl file. More importantly, it involved modifying the oscillatornode.rs file to include methods to set and get the type of the OscillatorNode. This was challenging because we did not realize at first that we needed to wrap the oscillator_type in a cell in order to achieve interior mutability. Initially, we were handing references to the setters and getters of the DOM struct members, which did not expose the set and get methods we were calling. We had to wrap the oscillator_type in a cell to give mutable references instead.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/243 Final Project Step 3 - StereoPannerNode backend]&lt;br /&gt;
&lt;br /&gt;
For our third pull request, we had to implement the backend for the StereoPannerNode in servo/media. Then we had to create a runnable example that utilizes the StereoPannerNode. We designed our example so that we would initialize a StereoPannerNode with the default pan value of 0. Then, we would set the pan value to -1. Next, we would linearly ramp up the pan value to 0 and then to 1. Ideally, someone would be able to run this example and listen to the StereoPannerNode through speakers as its pan value changed over time, causing the sound to move from left to right.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23281 Final Project Step 4 - StereoPannerNode DOM]&lt;br /&gt;
&lt;br /&gt;
For our fourth and last pull request, we created the DOM interface for StereoPannerNode and implemented the createStereoPannerNode API for BaseAudioContext within the main servo project. We had to create a few new files for this, since there was no existing stereopannernode.rs or StereoPannerNode.webidl. We also had to modify audionode.rs to add constraints when creating a StereoPannerNode, such as to ensure that there are not more than two channels and that the channel count mode is not set to max. In that case, we had to return a NotSupported error.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124843</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124843"/>
		<updated>2019-05-03T11:28:44Z</updated>

		<summary type="html">&lt;p&gt;Masable: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
=== Tracking Issues ===&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
=== Useful Resources ===&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Project Steps ==&lt;br /&gt;
&lt;br /&gt;
=== Initial Steps (OSS Project) ===&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
=== Subsequent Steps (Final Project) ===&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
=== OSS Project ===&lt;br /&gt;
&lt;br /&gt;
Our OSS project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final Project ===&lt;br /&gt;
&lt;br /&gt;
For our final project, we had a lot of freedom to design our runnable StereoPannerNode example. For the example, we could have set the pan value to anything between -1 (full left pan) and 1 (full right pan) and then changed it any way we wished. At first, we considered setting the pan value to different values at different times, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
context.message_node(&lt;br /&gt;
        osc,&lt;br /&gt;
        AudioNodeMessage::SetParam(ParamType::Pan, UserAutomationEvent::SetValueAtTime(-1., 2.)),&lt;br /&gt;
    );&lt;br /&gt;
context.message_node(&lt;br /&gt;
        osc,&lt;br /&gt;
        AudioNodeMessage::SetParam(ParamType::Pan, UserAutomationEvent::SetValueAtTime(1., 4.)),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That code would set the pan value to -1 at time = 2 seconds, and then set it to 1 at time = 4 seconds. However, it sounded very weird to have the sound jumping around from place to place.&lt;br /&gt;
&lt;br /&gt;
Eventually, we decided that linearly ramping up the pan value made for the best listening experience. It made the sound continuous but still exemplified what changing the pan value could do.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
context.message_node(&lt;br /&gt;
        pan,&lt;br /&gt;
        AudioNodeMessage::SetParam(&lt;br /&gt;
            ParamType::Pan,&lt;br /&gt;
            UserAutomationEvent::RampToValueAtTime(RampKind::Linear, 0., 4.),&lt;br /&gt;
        ),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our final version of the StereoPannerNode example involved linearly ramping the pan value from -1 to 0 and then from 0 to 1. This meant the sound moved from left to right over time.&lt;br /&gt;
&lt;br /&gt;
The rest of our final project just involved implementing methods and therefore did not involve any design choices.&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
Our Pull Requests:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 OSS Project]&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/242 Final Project Step 1 - Oscillator node message]&lt;br /&gt;
&lt;br /&gt;
The purpose of our first pull request was to implement an audio node message specific to OscillatorNode. This was within the servo/media project. For this pull request, we had to create a new OscillatorNodeMessage within the oscillator_node.rs file. The purpose of the OscillatorNodeMessage is to set the type of the OscillatorNode. We then had to modify node.rs to utilize the new OscillatorNodeMessage.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23282 Final Project Step 2 - Type attribute for OscillatorNode interface]&lt;br /&gt;
&lt;br /&gt;
The purpose of our second pull request was to implement the type attribute for the OscillatorNode interface within the main servo project. This required enabling the setter throws and OscillatorType attribute within the OscillatorNode.webidl file. More importantly, it involved modifying the oscillatornode.rs file to include methods to set and get the type of the OscillatorNode. This was challenging because we did not realize at first that we needed to wrap the oscillator_type in a cell in order to achieve interior mutability. Initially, we were handing references to the setters and getters of the DOM struct members, which did not expose the set and get methods we were calling. We had to wrap the oscillator_type in a cell to give mutable references instead.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/243 Final Project Step 3 - StereoPannerNode backend]&lt;br /&gt;
&lt;br /&gt;
For our third pull request, we had to implement the backend for the StereoPannerNode in servo/media. Then we had to create a runnable example that utilizes the StereoPannerNode. We designed our example so that we would initialize a StereoPannerNode with the default pan value of 0. Then, we would set the pan value to -1. Next, we would linearly ramp up the pan value to 0 and then to 1. Ideally, someone would be able to run this example and listen to the StereoPannerNode through speakers as its pan value changed over time, causing the sound to move from left to right.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23281 Final Project Step 4 - StereoPannerNode DOM]&lt;br /&gt;
&lt;br /&gt;
For our fourth and last pull request, we created the DOM interface for StereoPannerNode and implemented the createStereoPannerNode API for BaseAudioContext within the main servo project. We had to create a few new files for this, since there was no existing stereopannernode.rs or StereoPannerNode.webidl. We also had to modify audionode.rs to add constraints when creating a StereoPannerNode, such as to ensure that there are not more than two channels and that the channel count mode is not set to max. In that case, we had to return a NotSupported error.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124842</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124842"/>
		<updated>2019-05-03T11:28:10Z</updated>

		<summary type="html">&lt;p&gt;Masable: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Project Steps ==&lt;br /&gt;
&lt;br /&gt;
=== Initial Steps (OSS Project) ===&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
=== Subsequent Steps (Final Project) ===&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
=== OSS Project ===&lt;br /&gt;
&lt;br /&gt;
Our OSS project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final Project ===&lt;br /&gt;
&lt;br /&gt;
For our final project, we had a lot of freedom to design our runnable StereoPannerNode example. For the example, we could have set the pan value to anything between -1 (full left pan) and 1 (full right pan) and then changed it any way we wished. At first, we considered setting the pan value to different values at different times, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
context.message_node(&lt;br /&gt;
        osc,&lt;br /&gt;
        AudioNodeMessage::SetParam(ParamType::Pan, UserAutomationEvent::SetValueAtTime(-1., 2.)),&lt;br /&gt;
    );&lt;br /&gt;
context.message_node(&lt;br /&gt;
        osc,&lt;br /&gt;
        AudioNodeMessage::SetParam(ParamType::Pan, UserAutomationEvent::SetValueAtTime(1., 4.)),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That code would set the pan value to -1 at time = 2 seconds, and then set it to 1 at time = 4 seconds. However, it sounded very weird to have the sound jumping around from place to place.&lt;br /&gt;
&lt;br /&gt;
Eventually, we decided that linearly ramping up the pan value made for the best listening experience. It made the sound continuous but still exemplified what changing the pan value could do.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
context.message_node(&lt;br /&gt;
        pan,&lt;br /&gt;
        AudioNodeMessage::SetParam(&lt;br /&gt;
            ParamType::Pan,&lt;br /&gt;
            UserAutomationEvent::RampToValueAtTime(RampKind::Linear, 0., 4.),&lt;br /&gt;
        ),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our final version of the StereoPannerNode example involved linearly ramping the pan value from -1 to 0 and then from 0 to 1. This meant the sound moved from left to right over time.&lt;br /&gt;
&lt;br /&gt;
The rest of our final project just involved implementing methods and therefore did not involve any design choices.&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
Our Pull Requests:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 OSS Project]&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/242 Final Project Step 1 - Oscillator node message]&lt;br /&gt;
&lt;br /&gt;
The purpose of our first pull request was to implement an audio node message specific to OscillatorNode. This was within the servo/media project. For this pull request, we had to create a new OscillatorNodeMessage within the oscillator_node.rs file. The purpose of the OscillatorNodeMessage is to set the type of the OscillatorNode. We then had to modify node.rs to utilize the new OscillatorNodeMessage.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23282 Final Project Step 2 - Type attribute for OscillatorNode interface]&lt;br /&gt;
&lt;br /&gt;
The purpose of our second pull request was to implement the type attribute for the OscillatorNode interface within the main servo project. This required enabling the setter throws and OscillatorType attribute within the OscillatorNode.webidl file. More importantly, it involved modifying the oscillatornode.rs file to include methods to set and get the type of the OscillatorNode. This was challenging because we did not realize at first that we needed to wrap the oscillator_type in a cell in order to achieve interior mutability. Initially, we were handing references to the setters and getters of the DOM struct members, which did not expose the set and get methods we were calling. We had to wrap the oscillator_type in a cell to give mutable references instead.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/243 Final Project Step 3 - StereoPannerNode backend]&lt;br /&gt;
&lt;br /&gt;
For our third pull request, we had to implement the backend for the StereoPannerNode in servo/media. Then we had to create a runnable example that utilizes the StereoPannerNode. We designed our example so that we would initialize a StereoPannerNode with the default pan value of 0. Then, we would set the pan value to -1. Next, we would linearly ramp up the pan value to 0 and then to 1. Ideally, someone would be able to run this example and listen to the StereoPannerNode through speakers as its pan value changed over time, causing the sound to move from left to right.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23281 Final Project Step 4 - StereoPannerNode DOM]&lt;br /&gt;
&lt;br /&gt;
For our fourth and last pull request, we created the DOM interface for StereoPannerNode and implemented the createStereoPannerNode API for BaseAudioContext within the main servo project. We had to create a few new files for this, since there was no existing stereopannernode.rs or StereoPannerNode.webidl. We also had to modify audionode.rs to add constraints when creating a StereoPannerNode, such as to ensure that there are not more than two channels and that the channel count mode is not set to max. In that case, we had to return a NotSupported error.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124841</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124841"/>
		<updated>2019-05-03T11:26:19Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Design Choices */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
=== OSS Project ===&lt;br /&gt;
&lt;br /&gt;
Our OSS project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final Project ===&lt;br /&gt;
&lt;br /&gt;
For our final project, we had a lot of freedom to design our runnable StereoPannerNode example. For the example, we could have set the pan value to anything between -1 (full left pan) and 1 (full right pan) and then changed it any way we wished. At first, we considered setting the pan value to different values at different times, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
context.message_node(&lt;br /&gt;
        osc,&lt;br /&gt;
        AudioNodeMessage::SetParam(ParamType::Pan, UserAutomationEvent::SetValueAtTime(-1., 2.)),&lt;br /&gt;
    );&lt;br /&gt;
context.message_node(&lt;br /&gt;
        osc,&lt;br /&gt;
        AudioNodeMessage::SetParam(ParamType::Pan, UserAutomationEvent::SetValueAtTime(1., 4.)),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That code would set the pan value to -1 at time = 2 seconds, and then set it to 1 at time = 4 seconds. However, it sounded very weird to have the sound jumping around from place to place.&lt;br /&gt;
&lt;br /&gt;
Eventually, we decided that linearly ramping up the pan value made for the best listening experience. It made the sound continuous but still exemplified what changing the pan value could do.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
context.message_node(&lt;br /&gt;
        pan,&lt;br /&gt;
        AudioNodeMessage::SetParam(&lt;br /&gt;
            ParamType::Pan,&lt;br /&gt;
            UserAutomationEvent::RampToValueAtTime(RampKind::Linear, 0., 4.),&lt;br /&gt;
        ),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our final version of the StereoPannerNode example involved linearly ramping the pan value from -1 to 0 and then from 0 to 1. This meant the sound moved from left to right over time.&lt;br /&gt;
&lt;br /&gt;
The rest of our final project just involved implementing methods and therefore did not involve any design choices.&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
Our Pull Requests:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 OSS Project]&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/242 Final Project Step 1 - Oscillator node message]&lt;br /&gt;
&lt;br /&gt;
The purpose of our first pull request was to implement an audio node message specific to OscillatorNode. This was within the servo/media project. For this pull request, we had to create a new OscillatorNodeMessage within the oscillator_node.rs file. The purpose of the OscillatorNodeMessage is to set the type of the OscillatorNode. We then had to modify node.rs to utilize the new OscillatorNodeMessage.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23282 Final Project Step 2 - Type attribute for OscillatorNode interface]&lt;br /&gt;
&lt;br /&gt;
The purpose of our second pull request was to implement the type attribute for the OscillatorNode interface within the main servo project. This required enabling the setter throws and OscillatorType attribute within the OscillatorNode.webidl file. More importantly, it involved modifying the oscillatornode.rs file to include methods to set and get the type of the OscillatorNode. This was challenging because we did not realize at first that we needed to wrap the oscillator_type in a cell in order to achieve interior mutability. Initially, we were handing references to the setters and getters of the DOM struct members, which did not expose the set and get methods we were calling. We had to wrap the oscillator_type in a cell to give mutable references instead.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/243 Final Project Step 3 - StereoPannerNode backend]&lt;br /&gt;
&lt;br /&gt;
For our third pull request, we had to implement the backend for the StereoPannerNode in servo/media. Then we had to create a runnable example that utilizes the StereoPannerNode. We designed our example so that we would initialize a StereoPannerNode with the default pan value of 0. Then, we would set the pan value to -1. Next, we would linearly ramp up the pan value to 0 and then to 1. Ideally, someone would be able to run this example and listen to the StereoPannerNode through speakers as its pan value changed over time, causing the sound to move from left to right.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23281 Final Project Step 4 - StereoPannerNode DOM]&lt;br /&gt;
&lt;br /&gt;
For our fourth and last pull request, we created the DOM interface for StereoPannerNode and implemented the createStereoPannerNode API for BaseAudioContext within the main servo project. We had to create a few new files for this, since there was no existing stereopannernode.rs or StereoPannerNode.webidl. We also had to modify audionode.rs to add constraints when creating a StereoPannerNode, such as to ensure that there are not more than two channels and that the channel count mode is not set to max. In that case, we had to return a NotSupported error.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124840</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124840"/>
		<updated>2019-05-03T11:24:57Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Final Project */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
=== OSS Project ===&lt;br /&gt;
&lt;br /&gt;
Our OSS project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final Project ===&lt;br /&gt;
&lt;br /&gt;
For our final project, we had a lot of freedom to design our runnable StereoPannerNode example. For the example, we could have set the pan value to anything between -1 (full left pan) and 1 (full right pan) and then changed it any way we wished. At first, we considered setting the pan value to different values at different times, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
context.message_node(&lt;br /&gt;
        osc,&lt;br /&gt;
        AudioNodeMessage::SetParam(ParamType::Pan, UserAutomationEvent::SetValueAtTime(-1., 2.)),&lt;br /&gt;
    );&lt;br /&gt;
context.message_node(&lt;br /&gt;
        osc,&lt;br /&gt;
        AudioNodeMessage::SetParam(ParamType::Pan, UserAutomationEvent::SetValueAtTime(1., 4.)),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That code would set the pan value to -1 at time = 2 seconds, and then set it to 1 at time = 4 seconds. However, it sounded very weird to have the sound jumping around from place to place.&lt;br /&gt;
&lt;br /&gt;
Eventually, we decided that linearly ramping up the pan value made for the best listening experience. It made the sound continuous but still exemplified what changing the pan value could do.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
context.message_node(&lt;br /&gt;
        pan,&lt;br /&gt;
        AudioNodeMessage::SetParam(&lt;br /&gt;
            ParamType::Pan,&lt;br /&gt;
            UserAutomationEvent::RampToValueAtTime(RampKind::Linear, 0., 4.),&lt;br /&gt;
        ),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our final version of the StereoPannerNode example involved linearly ramping the pan value from -1 to 0 and then from 0 to 1. This meant the sound moved from left to right over time.&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
Our Pull Requests:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 OSS Project]&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/242 Final Project Step 1 - Oscillator node message]&lt;br /&gt;
&lt;br /&gt;
The purpose of our first pull request was to implement an audio node message specific to OscillatorNode. This was within the servo/media project. For this pull request, we had to create a new OscillatorNodeMessage within the oscillator_node.rs file. The purpose of the OscillatorNodeMessage is to set the type of the OscillatorNode. We then had to modify node.rs to utilize the new OscillatorNodeMessage.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23282 Final Project Step 2 - Type attribute for OscillatorNode interface]&lt;br /&gt;
&lt;br /&gt;
The purpose of our second pull request was to implement the type attribute for the OscillatorNode interface within the main servo project. This required enabling the setter throws and OscillatorType attribute within the OscillatorNode.webidl file. More importantly, it involved modifying the oscillatornode.rs file to include methods to set and get the type of the OscillatorNode. This was challenging because we did not realize at first that we needed to wrap the oscillator_type in a cell in order to achieve interior mutability. Initially, we were handing references to the setters and getters of the DOM struct members, which did not expose the set and get methods we were calling. We had to wrap the oscillator_type in a cell to give mutable references instead.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/243 Final Project Step 3 - StereoPannerNode backend]&lt;br /&gt;
&lt;br /&gt;
For our third pull request, we had to implement the backend for the StereoPannerNode in servo/media. Then we had to create a runnable example that utilizes the StereoPannerNode. We designed our example so that we would initialize a StereoPannerNode with the default pan value of 0. Then, we would set the pan value to -1. Next, we would linearly ramp up the pan value to 0 and then to 1. Ideally, someone would be able to run this example and listen to the StereoPannerNode through speakers as its pan value changed over time, causing the sound to move from left to right.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23281 Final Project Step 4 - StereoPannerNode DOM]&lt;br /&gt;
&lt;br /&gt;
For our fourth and last pull request, we created the DOM interface for StereoPannerNode and implemented the createStereoPannerNode API for BaseAudioContext within the main servo project. We had to create a few new files for this, since there was no existing stereopannernode.rs or StereoPannerNode.webidl. We also had to modify audionode.rs to add constraints when creating a StereoPannerNode, such as to ensure that there are not more than two channels and that the channel count mode is not set to max. In that case, we had to return a NotSupported error.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124839</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124839"/>
		<updated>2019-05-03T11:24:40Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Final Project */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
=== OSS Project ===&lt;br /&gt;
&lt;br /&gt;
Our OSS project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final Project ===&lt;br /&gt;
&lt;br /&gt;
For our final project, we had a lot of freedom to design our runnable StereoPannerNode example. For the example, we could have set the pan value to anything between -1 (full left pan) and 1 (full right pan) and then changed it any way we wished. At first, we considered setting the pan value to different values at different times, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
context.message_node(&lt;br /&gt;
        osc,&lt;br /&gt;
        AudioNodeMessage::SetParam(ParamType::Pan, UserAutomationEvent::SetValueAtTime(-1., 2.)),&lt;br /&gt;
    );&lt;br /&gt;
context.message_node(&lt;br /&gt;
        osc,&lt;br /&gt;
        AudioNodeMessage::SetParam(ParamType::Pan, UserAutomationEvent::SetValueAtTime(1., 4.)),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That code would set the pan value to -1 at time = 2 seconds, and then set it to 1 at time = 4 seconds. However, it sounded very weird to have the sound jumping around from place to place.&lt;br /&gt;
&lt;br /&gt;
Eventually, we decided that linearly ramping up the pan value made for the best listening experience. It made the sound continuous but still exemplified what changing the pan value could do.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
context.message_node(&lt;br /&gt;
        pan,&lt;br /&gt;
        AudioNodeMessage::SetParam(&lt;br /&gt;
            ParamType::Pan,&lt;br /&gt;
            UserAutomationEvent::RampToValueAtTime(RampKind::Linear, 0., 4.),&lt;br /&gt;
        ),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our final version of the StereoPannerNode example involved linearly ramping the pan value from -1 to 0 and then from 0 to 1. This meant that the sound would move from left to right over time.&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
Our Pull Requests:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 OSS Project]&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/242 Final Project Step 1 - Oscillator node message]&lt;br /&gt;
&lt;br /&gt;
The purpose of our first pull request was to implement an audio node message specific to OscillatorNode. This was within the servo/media project. For this pull request, we had to create a new OscillatorNodeMessage within the oscillator_node.rs file. The purpose of the OscillatorNodeMessage is to set the type of the OscillatorNode. We then had to modify node.rs to utilize the new OscillatorNodeMessage.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23282 Final Project Step 2 - Type attribute for OscillatorNode interface]&lt;br /&gt;
&lt;br /&gt;
The purpose of our second pull request was to implement the type attribute for the OscillatorNode interface within the main servo project. This required enabling the setter throws and OscillatorType attribute within the OscillatorNode.webidl file. More importantly, it involved modifying the oscillatornode.rs file to include methods to set and get the type of the OscillatorNode. This was challenging because we did not realize at first that we needed to wrap the oscillator_type in a cell in order to achieve interior mutability. Initially, we were handing references to the setters and getters of the DOM struct members, which did not expose the set and get methods we were calling. We had to wrap the oscillator_type in a cell to give mutable references instead.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/243 Final Project Step 3 - StereoPannerNode backend]&lt;br /&gt;
&lt;br /&gt;
For our third pull request, we had to implement the backend for the StereoPannerNode in servo/media. Then we had to create a runnable example that utilizes the StereoPannerNode. We designed our example so that we would initialize a StereoPannerNode with the default pan value of 0. Then, we would set the pan value to -1. Next, we would linearly ramp up the pan value to 0 and then to 1. Ideally, someone would be able to run this example and listen to the StereoPannerNode through speakers as its pan value changed over time, causing the sound to move from left to right.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23281 Final Project Step 4 - StereoPannerNode DOM]&lt;br /&gt;
&lt;br /&gt;
For our fourth and last pull request, we created the DOM interface for StereoPannerNode and implemented the createStereoPannerNode API for BaseAudioContext within the main servo project. We had to create a few new files for this, since there was no existing stereopannernode.rs or StereoPannerNode.webidl. We also had to modify audionode.rs to add constraints when creating a StereoPannerNode, such as to ensure that there are not more than two channels and that the channel count mode is not set to max. In that case, we had to return a NotSupported error.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124838</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124838"/>
		<updated>2019-05-03T11:23:44Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Final Project */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
=== OSS Project ===&lt;br /&gt;
&lt;br /&gt;
Our OSS project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final Project ===&lt;br /&gt;
&lt;br /&gt;
For our final project, we had a lot of freedom to design our runnable StereoPannerNode example. For the example, we could have set the pan value to anything between -1 (full left pan) and 1 (full right pan) and then changed it any way we wished. At first, we considered setting the pan value to different values at different times, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
context.message_node(&lt;br /&gt;
        osc,&lt;br /&gt;
        AudioNodeMessage::SetParam(ParamType::Pan, UserAutomationEvent::SetValueAtTime(-1., 2.)),&lt;br /&gt;
    );&lt;br /&gt;
context.message_node(&lt;br /&gt;
        osc,&lt;br /&gt;
        AudioNodeMessage::SetParam(ParamType::Pan, UserAutomationEvent::SetValueAtTime(1., 4.)),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That code would set the pan value to -1 at time = 2 seconds, and then set it to 1 at time = 4 seconds. However, it sounded very weird to have the sound jumping around from place to place.&lt;br /&gt;
&lt;br /&gt;
Eventually, we decided that linearly ramping up the pan value made for the best listening experience. It made the sound continuous but still exemplified what changing the pan value could do.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
context.message_node(&lt;br /&gt;
        pan,&lt;br /&gt;
        AudioNodeMessage::SetParam(&lt;br /&gt;
            ParamType::Pan,&lt;br /&gt;
            UserAutomationEvent::RampToValueAtTime(RampKind::Linear, 0., 4.),&lt;br /&gt;
        ),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our final version of the StereoPannerNode example involved linearly ramping the pan value from -1 to 0 and then from 0 to 1.&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
Our Pull Requests:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 OSS Project]&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/242 Final Project Step 1 - Oscillator node message]&lt;br /&gt;
&lt;br /&gt;
The purpose of our first pull request was to implement an audio node message specific to OscillatorNode. This was within the servo/media project. For this pull request, we had to create a new OscillatorNodeMessage within the oscillator_node.rs file. The purpose of the OscillatorNodeMessage is to set the type of the OscillatorNode. We then had to modify node.rs to utilize the new OscillatorNodeMessage.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23282 Final Project Step 2 - Type attribute for OscillatorNode interface]&lt;br /&gt;
&lt;br /&gt;
The purpose of our second pull request was to implement the type attribute for the OscillatorNode interface within the main servo project. This required enabling the setter throws and OscillatorType attribute within the OscillatorNode.webidl file. More importantly, it involved modifying the oscillatornode.rs file to include methods to set and get the type of the OscillatorNode. This was challenging because we did not realize at first that we needed to wrap the oscillator_type in a cell in order to achieve interior mutability. Initially, we were handing references to the setters and getters of the DOM struct members, which did not expose the set and get methods we were calling. We had to wrap the oscillator_type in a cell to give mutable references instead.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/243 Final Project Step 3 - StereoPannerNode backend]&lt;br /&gt;
&lt;br /&gt;
For our third pull request, we had to implement the backend for the StereoPannerNode in servo/media. Then we had to create a runnable example that utilizes the StereoPannerNode. We designed our example so that we would initialize a StereoPannerNode with the default pan value of 0. Then, we would set the pan value to -1. Next, we would linearly ramp up the pan value to 0 and then to 1. Ideally, someone would be able to run this example and listen to the StereoPannerNode through speakers as its pan value changed over time, causing the sound to move from left to right.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23281 Final Project Step 4 - StereoPannerNode DOM]&lt;br /&gt;
&lt;br /&gt;
For our fourth and last pull request, we created the DOM interface for StereoPannerNode and implemented the createStereoPannerNode API for BaseAudioContext within the main servo project. We had to create a few new files for this, since there was no existing stereopannernode.rs or StereoPannerNode.webidl. We also had to modify audionode.rs to add constraints when creating a StereoPannerNode, such as to ensure that there are not more than two channels and that the channel count mode is not set to max. In that case, we had to return a NotSupported error.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124837</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124837"/>
		<updated>2019-05-03T11:23:23Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Design Choices */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
=== OSS Project ===&lt;br /&gt;
&lt;br /&gt;
Our OSS project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final Project ===&lt;br /&gt;
&lt;br /&gt;
For our final project, we had a lot of freedom to design our runnable StereoPannerNode example. For the example, we could have set the pan value to anything between -1 (full left pan) and 1 (full right pan) and then changed it any way we wished. At first, we considered setting the pan value to different values at different times, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&lt;br /&gt;
context.message_node(&lt;br /&gt;
        osc,&lt;br /&gt;
        AudioNodeMessage::SetParam(ParamType::Pan, UserAutomationEvent::SetValueAtTime(-1., 2.)),&lt;br /&gt;
    );&lt;br /&gt;
context.message_node(&lt;br /&gt;
        osc,&lt;br /&gt;
        AudioNodeMessage::SetParam(ParamType::Pan, UserAutomationEvent::SetValueAtTime(1., 4.)),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That code would set the pan value to -1 at time = 2 seconds, and then set it to 1 at time = 4 seconds. However, it sounded very weird to have the sound jumping around from place to place.&lt;br /&gt;
&lt;br /&gt;
Eventually, we decided that linearly ramping up the pan value made for the best listening experience. It made the sound continuous but still exemplified what changing the pan value could do.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
context.message_node(&lt;br /&gt;
        pan,&lt;br /&gt;
        AudioNodeMessage::SetParam(&lt;br /&gt;
            ParamType::Pan,&lt;br /&gt;
            UserAutomationEvent::RampToValueAtTime(RampKind::Linear, 0., 4.),&lt;br /&gt;
        ),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our final version of the StereoPannerNode example involved linearly ramping the pan value from -1 to 0 and then from 0 to 1.&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
Our Pull Requests:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 OSS Project]&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/242 Final Project Step 1 - Oscillator node message]&lt;br /&gt;
&lt;br /&gt;
The purpose of our first pull request was to implement an audio node message specific to OscillatorNode. This was within the servo/media project. For this pull request, we had to create a new OscillatorNodeMessage within the oscillator_node.rs file. The purpose of the OscillatorNodeMessage is to set the type of the OscillatorNode. We then had to modify node.rs to utilize the new OscillatorNodeMessage.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23282 Final Project Step 2 - Type attribute for OscillatorNode interface]&lt;br /&gt;
&lt;br /&gt;
The purpose of our second pull request was to implement the type attribute for the OscillatorNode interface within the main servo project. This required enabling the setter throws and OscillatorType attribute within the OscillatorNode.webidl file. More importantly, it involved modifying the oscillatornode.rs file to include methods to set and get the type of the OscillatorNode. This was challenging because we did not realize at first that we needed to wrap the oscillator_type in a cell in order to achieve interior mutability. Initially, we were handing references to the setters and getters of the DOM struct members, which did not expose the set and get methods we were calling. We had to wrap the oscillator_type in a cell to give mutable references instead.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/243 Final Project Step 3 - StereoPannerNode backend]&lt;br /&gt;
&lt;br /&gt;
For our third pull request, we had to implement the backend for the StereoPannerNode in servo/media. Then we had to create a runnable example that utilizes the StereoPannerNode. We designed our example so that we would initialize a StereoPannerNode with the default pan value of 0. Then, we would set the pan value to -1. Next, we would linearly ramp up the pan value to 0 and then to 1. Ideally, someone would be able to run this example and listen to the StereoPannerNode through speakers as its pan value changed over time, causing the sound to move from left to right.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23281 Final Project Step 4 - StereoPannerNode DOM]&lt;br /&gt;
&lt;br /&gt;
For our fourth and last pull request, we created the DOM interface for StereoPannerNode and implemented the createStereoPannerNode API for BaseAudioContext within the main servo project. We had to create a few new files for this, since there was no existing stereopannernode.rs or StereoPannerNode.webidl. We also had to modify audionode.rs to add constraints when creating a StereoPannerNode, such as to ensure that there are not more than two channels and that the channel count mode is not set to max. In that case, we had to return a NotSupported error.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124836</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124836"/>
		<updated>2019-05-03T11:16:17Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* OSS Project */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
=== OSS Project ===&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
Our Pull Requests:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 OSS Project]&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/242 Final Project Step 1 - Oscillator node message]&lt;br /&gt;
&lt;br /&gt;
The purpose of our first pull request was to implement an audio node message specific to OscillatorNode. This was within the servo/media project. For this pull request, we had to create a new OscillatorNodeMessage within the oscillator_node.rs file. The purpose of the OscillatorNodeMessage is to set the type of the OscillatorNode. We then had to modify node.rs to utilize the new OscillatorNodeMessage.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23282 Final Project Step 2 - Type attribute for OscillatorNode interface]&lt;br /&gt;
&lt;br /&gt;
The purpose of our second pull request was to implement the type attribute for the OscillatorNode interface within the main servo project. This required enabling the setter throws and OscillatorType attribute within the OscillatorNode.webidl file. More importantly, it involved modifying the oscillatornode.rs file to include methods to set and get the type of the OscillatorNode. This was challenging because we did not realize at first that we needed to wrap the oscillator_type in a cell in order to achieve interior mutability. Initially, we were handing references to the setters and getters of the DOM struct members, which did not expose the set and get methods we were calling. We had to wrap the oscillator_type in a cell to give mutable references instead.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/243 Final Project Step 3 - StereoPannerNode backend]&lt;br /&gt;
&lt;br /&gt;
For our third pull request, we had to implement the backend for the StereoPannerNode in servo/media. Then we had to create a runnable example that utilizes the StereoPannerNode. We designed our example so that we would initialize a StereoPannerNode with the default pan value of 0. Then, we would set the pan value to -1. Next, we would linearly ramp up the pan value to 0 and then to 1. Ideally, someone would be able to run this example and listen to the StereoPannerNode through speakers as its pan value changed over time, causing the sound to move from left to right.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23281 Final Project Step 4 - StereoPannerNode DOM]&lt;br /&gt;
&lt;br /&gt;
For our fourth and last pull request, we created the DOM interface for StereoPannerNode and implemented the createStereoPannerNode API for BaseAudioContext within the main servo project. We had to create a few new files for this, since there was no existing stereopannernode.rs or StereoPannerNode.webidl. We also had to modify audionode.rs to add constraints when creating a StereoPannerNode, such as to ensure that there are not more than two channels and that the channel count mode is not set to max. In that case, we had to return a NotSupported error.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124835</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124835"/>
		<updated>2019-05-03T11:16:05Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Design Choices */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
= OSS Project =&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
Our Pull Requests:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 OSS Project]&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/242 Final Project Step 1 - Oscillator node message]&lt;br /&gt;
&lt;br /&gt;
The purpose of our first pull request was to implement an audio node message specific to OscillatorNode. This was within the servo/media project. For this pull request, we had to create a new OscillatorNodeMessage within the oscillator_node.rs file. The purpose of the OscillatorNodeMessage is to set the type of the OscillatorNode. We then had to modify node.rs to utilize the new OscillatorNodeMessage.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23282 Final Project Step 2 - Type attribute for OscillatorNode interface]&lt;br /&gt;
&lt;br /&gt;
The purpose of our second pull request was to implement the type attribute for the OscillatorNode interface within the main servo project. This required enabling the setter throws and OscillatorType attribute within the OscillatorNode.webidl file. More importantly, it involved modifying the oscillatornode.rs file to include methods to set and get the type of the OscillatorNode. This was challenging because we did not realize at first that we needed to wrap the oscillator_type in a cell in order to achieve interior mutability. Initially, we were handing references to the setters and getters of the DOM struct members, which did not expose the set and get methods we were calling. We had to wrap the oscillator_type in a cell to give mutable references instead.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/243 Final Project Step 3 - StereoPannerNode backend]&lt;br /&gt;
&lt;br /&gt;
For our third pull request, we had to implement the backend for the StereoPannerNode in servo/media. Then we had to create a runnable example that utilizes the StereoPannerNode. We designed our example so that we would initialize a StereoPannerNode with the default pan value of 0. Then, we would set the pan value to -1. Next, we would linearly ramp up the pan value to 0 and then to 1. Ideally, someone would be able to run this example and listen to the StereoPannerNode through speakers as its pan value changed over time, causing the sound to move from left to right.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23281 Final Project Step 4 - StereoPannerNode DOM]&lt;br /&gt;
&lt;br /&gt;
For our fourth and last pull request, we created the DOM interface for StereoPannerNode and implemented the createStereoPannerNode API for BaseAudioContext within the main servo project. We had to create a few new files for this, since there was no existing stereopannernode.rs or StereoPannerNode.webidl. We also had to modify audionode.rs to add constraints when creating a StereoPannerNode, such as to ensure that there are not more than two channels and that the channel count mode is not set to max. In that case, we had to return a NotSupported error.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124834</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124834"/>
		<updated>2019-05-03T11:14:43Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Completed Work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
Our Pull Requests:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 OSS Project]&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/242 Final Project Step 1 - Oscillator node message]&lt;br /&gt;
&lt;br /&gt;
The purpose of our first pull request was to implement an audio node message specific to OscillatorNode. This was within the servo/media project. For this pull request, we had to create a new OscillatorNodeMessage within the oscillator_node.rs file. The purpose of the OscillatorNodeMessage is to set the type of the OscillatorNode. We then had to modify node.rs to utilize the new OscillatorNodeMessage.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23282 Final Project Step 2 - Type attribute for OscillatorNode interface]&lt;br /&gt;
&lt;br /&gt;
The purpose of our second pull request was to implement the type attribute for the OscillatorNode interface within the main servo project. This required enabling the setter throws and OscillatorType attribute within the OscillatorNode.webidl file. More importantly, it involved modifying the oscillatornode.rs file to include methods to set and get the type of the OscillatorNode. This was challenging because we did not realize at first that we needed to wrap the oscillator_type in a cell in order to achieve interior mutability. Initially, we were handing references to the setters and getters of the DOM struct members, which did not expose the set and get methods we were calling. We had to wrap the oscillator_type in a cell to give mutable references instead.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/243 Final Project Step 3 - StereoPannerNode backend]&lt;br /&gt;
&lt;br /&gt;
For our third pull request, we had to implement the backend for the StereoPannerNode in servo/media. Then we had to create a runnable example that utilizes the StereoPannerNode. We designed our example so that we would initialize a StereoPannerNode with the default pan value of 0. Then, we would set the pan value to -1. Next, we would linearly ramp up the pan value to 0 and then to 1. Ideally, someone would be able to run this example and listen to the StereoPannerNode through speakers as its pan value changed over time, causing the sound to move from left to right.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23281 Final Project Step 4 - StereoPannerNode DOM]&lt;br /&gt;
&lt;br /&gt;
For our fourth and last pull request, we created the DOM interface for StereoPannerNode and implemented the createStereoPannerNode API for BaseAudioContext within the main servo project. We had to create a few new files for this, since there was no existing stereopannernode.rs or StereoPannerNode.webidl. We also had to modify audionode.rs to add constraints when creating a StereoPannerNode, such as to ensure that there are not more than two channels and that the channel count mode is not set to max. In that case, we had to return a NotSupported error.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124833</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124833"/>
		<updated>2019-05-03T11:13:39Z</updated>

		<summary type="html">&lt;p&gt;Masable: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
Our Pull Requests:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 OSS Project]&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/242 Step 1 of the Final Project - Oscillator node message]&lt;br /&gt;
&lt;br /&gt;
The purpose of our first pull request was to implement an audio node message specific to OscillatorNode. This was within the servo/media project. For this pull request, we had to create a new OscillatorNodeMessage within the oscillator_node.rs file. The purpose of the OscillatorNodeMessage is to set the type of the OscillatorNode. We then had to modify node.rs to utilize the new OscillatorNodeMessage.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23282 Step 2 of the Final Project - Type attribute for OscillatorNode interface]&lt;br /&gt;
&lt;br /&gt;
The purpose of our second pull request was to implement the type attribute for the OscillatorNode interface within the main servo project. This required enabling the setter throws and OscillatorType attribute within the OscillatorNode.webidl file. More importantly, it involved modifying the oscillatornode.rs file to include methods to set and get the type of the OscillatorNode. This was challenging because we did not realize at first that we needed to wrap the oscillator_type in a cell in order to achieve interior mutability. Initially, we were handing references to the setters and getters of the DOM struct members, which did not expose the set and get methods we were calling. We had to wrap the oscillator_type in a cell to give mutable references instead.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/243 Step 3 of the Final Project - StereoPannerNode backend]&lt;br /&gt;
&lt;br /&gt;
For our third pull request, we had to implement the backend for the StereoPannerNode in servo/media. Then we had to create a runnable example that utilizes the StereoPannerNode. We designed our example so that we would initialize a StereoPannerNode with the default pan value of 0. Then, we would set the pan value to -1. Next, we would linearly ramp up the pan value to 0 and then to 1. Ideally, someone would be able to run this example and listen to the StereoPannerNode through speakers as its pan value changed over time, causing the sound to move from left to right.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23281 Step 4 of the Final Project - StereoPannerNode DOM]&lt;br /&gt;
&lt;br /&gt;
For our fourth and last pull request, we created the DOM interface for StereoPannerNode and implemented the createStereoPannerNode API for BaseAudioContext within the main servo project. We had to create a few new files for this, since there was no existing stereopannernode.rs or StereoPannerNode.webidl. We also had to modify audionode.rs to add constraints when creating a StereoPannerNode, such as to ensure that there are not more than two channels and that the channel count mode is not set to max. In that case, we had to return a NotSupported error.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124832</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124832"/>
		<updated>2019-05-03T11:11:39Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Completed Work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
Our Pull Requests:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 OSS Project]&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/242 Step 1 of the Final Project - Oscillator node message]&lt;br /&gt;
&lt;br /&gt;
The purpose of our first pull request was to implement an audio node message specific to OscillatorNode. This was within the servo/media project. For this pull request, we had to create a new OscillatorNodeMessage within the oscillator_node.rs file. The purpose of the OscillatorNodeMessage is to set the type of the OscillatorNode. We then had to modify node.rs to utilize the new OscillatorNodeMessage.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23282 Step 2 of the Final Project - Type attribute for OscillatorNode interface]&lt;br /&gt;
&lt;br /&gt;
The purpose of our second pull request was to implement the type attribute for the OscillatorNode interface within the main servo project. This required enabling the setter throws and OscillatorType attribute within the OscillatorNode.webidl file. More importantly, it involved modifying the oscillatornode.rs file to include methods to set and get the type of the OscillatorNode. This was challenging because we did not realize at first that we needed to wrap the oscillator_type in a cell in order to achieve interior mutability. Initially, we were handing references to the setters and getters of the DOM struct members, which did not expose the set and get methods we were calling. We had to wrap the oscillator_type in a cell to give mutable references instead.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/243 Step 3 of the Final Project - StereoPannerNode backend]&lt;br /&gt;
&lt;br /&gt;
For our third pull request, we had to implement the backend for the StereoPannerNode in servo/media. Then we had to create a runnable example that utilizes the StereoPannerNode. We designed our example so that we would initialize a StereoPannerNode with the default pan value of 0. Then, we would set the pan value to -1. Next, we would linearly ramp up the pan value to 0 and then to 1. Ideally, someone would be able to run this example and listen to the StereoPannerNode through speakers as its pan value changed over time, causing the sound to move from left to right.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23281 Step 4 of the Final Project - StereoPannerNode DOM]&lt;br /&gt;
&lt;br /&gt;
For our fourth and last pull request, we created the DOM interface for StereoPannerNode and implemented the createStereoPannerNode API for BaseAudioContext within the main servo project. We had to create a few new files for this, since there was no existing stereopannernode.rs or StereoPannerNode.webidl. We also had to modify audionode.rs to add constraints when creating a StereoPannerNode, such as to ensure that there are not more than two channels and that the channel count mode is not set to max. In that case, we had to return a NotSupported error.&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:OscillatorNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Exposed=Window,&lt;br /&gt;
Constructor (BaseAudioContext context, optional OscillatorOptions options)]&lt;br /&gt;
interface OscillatorNode : AudioScheduledSourceNode {&lt;br /&gt;
//  utilize the new OscillatorType audio node message &lt;br /&gt;
    attribute OscillatorType type;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:ConstantSourceNodeDOMResized.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNodeDOMResized.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:BaseAudioContext.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124831</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124831"/>
		<updated>2019-05-03T11:10:53Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Completed Work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
Our Pull Requests:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 OSS Project]&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/242 Step 1 of the Final Project - Oscillator node message]&lt;br /&gt;
&lt;br /&gt;
The purpose of the first pull request was to implement an audio node message specific to OscillatorNode. This was within the servo/media project. For this pull request, we had to create a new OscillatorNodeMessage within the oscillator_node.rs file. The purpose of the OscillatorNodeMessage is to set the type of the OscillatorNode. We then had to modify node.rs to utilize the new OscillatorNodeMessage.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23282 Step 2 of the Final Project - Type attribute for OscillatorNode interface]&lt;br /&gt;
&lt;br /&gt;
The purpose of our second pull request was to implement the type attribute for the OscillatorNode interface within the main servo project. This required enabling the setter throws and OscillatorType attribute within the OscillatorNode.webidl file. More importantly, it involved modifying the oscillatornode.rs file to include methods to set and get the type of the OscillatorNode. This was challenging because we did not realize at first that we needed to wrap the oscillator_type in a cell in order to achieve interior mutability. Initially, we were handing references to the setters and getters of the DOM struct members, which did not expose the set and get methods we were calling. We had to wrap the oscillator_type in a cell to give mutable references instead.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/243 Step 3 of the Final Project - StereoPannerNode backend]&lt;br /&gt;
&lt;br /&gt;
For our third pull request, we had to implement the backend for the StereoPannerNode in servo/media. Then we had to create a runnable example that utilizes the StereoPannerNode. We designed our example so that we would initialize a StereoPannerNode with the default pan value of 0. Then, we would set the pan value to -1. Next, we would linearly ramp up the pan value to 0 and then to 1. Ideally, someone would be able to run this example and listen to the StereoPannerNode through speakers as its pan value changed over time, causing the sound to move from left to right.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23281 Step 4 of the Final Project - StereoPannerNode DOM]&lt;br /&gt;
&lt;br /&gt;
For our fourth and last pull request, we created the DOM interface for StereoPannerNode and implemented the createStereoPannerNode API for BaseAudioContext within the main servo project. We had to create a few new files for this, since there was no existing stereopannernode.rs or StereoPannerNode.webidl. We also had to modify audionode.rs to add constraints when creating a StereoPannerNode, such as to ensure that there are not more than two channels and that the channel count mode is not set to max. In that case, we had to return a NotSupported error.&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:OscillatorNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Exposed=Window,&lt;br /&gt;
Constructor (BaseAudioContext context, optional OscillatorOptions options)]&lt;br /&gt;
interface OscillatorNode : AudioScheduledSourceNode {&lt;br /&gt;
//  utilize the new OscillatorType audio node message &lt;br /&gt;
    attribute OscillatorType type;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:ConstantSourceNodeDOMResized.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNodeDOMResized.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:BaseAudioContext.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124830</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124830"/>
		<updated>2019-05-03T11:10:24Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Completed Work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
Here, each of our pull requests is described in greater detail.&lt;br /&gt;
&lt;br /&gt;
Our Pull Requests:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 OSS Project]&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/242 Step 1 of the Final Project - Oscillator node message]&lt;br /&gt;
&lt;br /&gt;
The purpose of the first pull request was to implement an audio node message specific to OscillatorNode. This was within the servo/media project. For this pull request, we had to create a new OscillatorNodeMessage within the oscillator_node.rs file. The purpose of the OscillatorNodeMessage is to set the type of the OscillatorNode. We then had to modify node.rs to utilize the new OscillatorNodeMessage.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23282 Step 2 of the Final Project - Type attribute for OscillatorNode interface]&lt;br /&gt;
&lt;br /&gt;
The purpose of our second pull request was to implement the type attribute for the OscillatorNode interface within the main servo project. This required enabling the setter throws and OscillatorType attribute within the OscillatorNode.webidl file. More importantly, it involved modifying the oscillatornode.rs file to include methods to set and get the type of the OscillatorNode. This was challenging because we did not realize at first that we needed to wrap the oscillator_type in a cell in order to achieve interior mutability. Initially, we were handing references to the setters and getters of the DOM struct members, which did not expose the set and get methods we were calling. We had to wrap the oscillator_type in a cell to give mutable references instead.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/243 Step 3 of the Final Project - StereoPannerNode backend]&lt;br /&gt;
&lt;br /&gt;
For our third pull request, we had to implement the backend for the StereoPannerNode in servo/media. Then we had to create a runnable example that utilizes the StereoPannerNode. We designed our example so that we would initialize a StereoPannerNode with the default pan value of 0. Then, we would set the pan value to -1. Next, we would linearly ramp up the pan value to 0 and then to 1. Ideally, someone would be able to run this example and listen to the StereoPannerNode through speakers as its pan value changed over time, causing the sound to move from left to right.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23281 Step 4 of the Final Project - StereoPannerNode DOM]&lt;br /&gt;
&lt;br /&gt;
For our fourth and last pull request, we created the DOM interface for StereoPannerNode and implemented the createStereoPannerNode API for BaseAudioContext within the main servo project. We had to create a few new files for this, since there was no existing stereopannernode.rs or StereoPannerNode.webidl. We also had to modify audionode.rs to add constraints when creating a StereoPannerNode, such as to ensure that there are not more than two channels and that the channel count mode is not set to max. In that case, we had to return a NotSupported error.&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:OscillatorNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Exposed=Window,&lt;br /&gt;
Constructor (BaseAudioContext context, optional OscillatorOptions options)]&lt;br /&gt;
interface OscillatorNode : AudioScheduledSourceNode {&lt;br /&gt;
//  utilize the new OscillatorType audio node message &lt;br /&gt;
    attribute OscillatorType type;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:ConstantSourceNodeDOMResized.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNodeDOMResized.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:BaseAudioContext.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124829</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124829"/>
		<updated>2019-05-03T11:06:19Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Completed Work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
Our Pull Requests:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 OSS Project]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/242 Step 1 of the Final Project - Oscillator node message]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23282 Step 2 of the Final Project - Type attribute for OscillatorNode interface]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/media/pull/243 Step 3 of the Final Project - StereoPannerNode backend]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23281 Step 4 of the Final Project - StereoPannerNode DOM]&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:OscillatorNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Exposed=Window,&lt;br /&gt;
Constructor (BaseAudioContext context, optional OscillatorOptions options)]&lt;br /&gt;
interface OscillatorNode : AudioScheduledSourceNode {&lt;br /&gt;
//  utilize the new OscillatorType audio node message &lt;br /&gt;
    attribute OscillatorType type;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:ConstantSourceNodeDOMResized.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNodeDOMResized.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:BaseAudioContext.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124016</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124016"/>
		<updated>2019-04-13T02:16:05Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:OscillatorNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Exposed=Window,&lt;br /&gt;
Constructor (BaseAudioContext context, optional OscillatorOptions options)]&lt;br /&gt;
interface OscillatorNode : AudioScheduledSourceNode {&lt;br /&gt;
//  utilize the new OscillatorType audio node message &lt;br /&gt;
    attribute OscillatorType type;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:ConstantSourceNodeDOMResized.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNodeDOMResized.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:BaseAudioContext.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:ConstantSourceNodeDOMResized.png&amp;diff=124014</id>
		<title>File:ConstantSourceNodeDOMResized.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:ConstantSourceNodeDOMResized.png&amp;diff=124014"/>
		<updated>2019-04-13T02:15:45Z</updated>

		<summary type="html">&lt;p&gt;Masable: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:StereoPannerNodeDOMResized.png&amp;diff=124011</id>
		<title>File:StereoPannerNodeDOMResized.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:StereoPannerNodeDOMResized.png&amp;diff=124011"/>
		<updated>2019-04-13T02:14:23Z</updated>

		<summary type="html">&lt;p&gt;Masable: uploaded a new version of &amp;amp;quot;File:StereoPannerNodeDOMResized.png&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124009</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124009"/>
		<updated>2019-04-13T02:13:00Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:OscillatorNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Exposed=Window,&lt;br /&gt;
Constructor (BaseAudioContext context, optional OscillatorOptions options)]&lt;br /&gt;
interface OscillatorNode : AudioScheduledSourceNode {&lt;br /&gt;
//  utilize the new OscillatorType audio node message &lt;br /&gt;
    attribute OscillatorType type;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNodeDOMResized.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:BaseAudioContext.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:StereoPannerNodeDOMResized.png&amp;diff=124008</id>
		<title>File:StereoPannerNodeDOMResized.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:StereoPannerNodeDOMResized.png&amp;diff=124008"/>
		<updated>2019-04-13T02:12:53Z</updated>

		<summary type="html">&lt;p&gt;Masable: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124007</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124007"/>
		<updated>2019-04-13T02:11:30Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:OscillatorNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Exposed=Window,&lt;br /&gt;
Constructor (BaseAudioContext context, optional OscillatorOptions options)]&lt;br /&gt;
interface OscillatorNode : AudioScheduledSourceNode {&lt;br /&gt;
//  utilize the new OscillatorType audio node message &lt;br /&gt;
    attribute OscillatorType type;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNodeDOM.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:BaseAudioContext.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:StereoPannerNodeDOM.png&amp;diff=124006</id>
		<title>File:StereoPannerNodeDOM.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:StereoPannerNodeDOM.png&amp;diff=124006"/>
		<updated>2019-04-13T02:11:15Z</updated>

		<summary type="html">&lt;p&gt;Masable: uploaded a new version of &amp;amp;quot;File:StereoPannerNodeDOM.png&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124005</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124005"/>
		<updated>2019-04-13T02:10:22Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:OscillatorNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Exposed=Window,&lt;br /&gt;
Constructor (BaseAudioContext context, optional OscillatorOptions options)]&lt;br /&gt;
interface OscillatorNode : AudioScheduledSourceNode {&lt;br /&gt;
//  utilize the new OscillatorType audio node message &lt;br /&gt;
    attribute OscillatorType type;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNodeDOM.png|400 px]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:BaseAudioContext.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124004</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124004"/>
		<updated>2019-04-13T02:10:07Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:OscillatorNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Exposed=Window,&lt;br /&gt;
Constructor (BaseAudioContext context, optional OscillatorOptions options)]&lt;br /&gt;
interface OscillatorNode : AudioScheduledSourceNode {&lt;br /&gt;
//  utilize the new OscillatorType audio node message &lt;br /&gt;
    attribute OscillatorType type;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNodeDOM.png|200 px]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:BaseAudioContext.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124003</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=124003"/>
		<updated>2019-04-13T02:09:15Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:OscillatorNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Exposed=Window,&lt;br /&gt;
Constructor (BaseAudioContext context, optional OscillatorOptions options)]&lt;br /&gt;
interface OscillatorNode : AudioScheduledSourceNode {&lt;br /&gt;
//  utilize the new OscillatorType audio node message &lt;br /&gt;
    attribute OscillatorType type;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNodeDOM.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:BaseAudioContext.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:StereoPannerNodeDOM.png&amp;diff=124002</id>
		<title>File:StereoPannerNodeDOM.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:StereoPannerNodeDOM.png&amp;diff=124002"/>
		<updated>2019-04-13T02:08:31Z</updated>

		<summary type="html">&lt;p&gt;Masable: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:ConstantSourceNodeDOM.png&amp;diff=124001</id>
		<title>File:ConstantSourceNodeDOM.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:ConstantSourceNodeDOM.png&amp;diff=124001"/>
		<updated>2019-04-13T02:08:13Z</updated>

		<summary type="html">&lt;p&gt;Masable: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123994</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123994"/>
		<updated>2019-04-13T02:03:11Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:OscillatorNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Exposed=Window,&lt;br /&gt;
Constructor (BaseAudioContext context, optional OscillatorOptions options)]&lt;br /&gt;
interface OscillatorNode : AudioScheduledSourceNode {&lt;br /&gt;
//  utilize the new OscillatorType audio node message &lt;br /&gt;
    attribute OscillatorType type;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:BaseAudioContext.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123991</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123991"/>
		<updated>2019-04-13T02:02:33Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:OscillatorNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Exposed=Window,&lt;br /&gt;
 Constructor (BaseAudioContext context, optional OscillatorOptions options)]&lt;br /&gt;
interface OscillatorNode : AudioScheduledSourceNode {&lt;br /&gt;
//  utilize the new OscillatorType audio node message &lt;br /&gt;
    attribute OscillatorType type;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:BaseAudioContext.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123990</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123990"/>
		<updated>2019-04-13T02:02:09Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:OscillatorNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Exposed=Window,&lt;br /&gt;
 Constructor (BaseAudioContext context, optional OscillatorOptions options)]&lt;br /&gt;
interface OscillatorNode : AudioScheduledSourceNode {&lt;br /&gt;
//  [SetterThrows]&lt;br /&gt;
//  line below utilizes the new OscillatorType audio node message &lt;br /&gt;
    attribute OscillatorType type;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:BaseAudioContext.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123988</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123988"/>
		<updated>2019-04-13T02:00:48Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:OscillatorNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Exposed=Window,&lt;br /&gt;
 Constructor (BaseAudioContext context, optional OscillatorOptions options)]&lt;br /&gt;
interface OscillatorNode : AudioScheduledSourceNode {&lt;br /&gt;
//  [SetterThrows]&lt;br /&gt;
//  attribute OscillatorType type;&lt;br /&gt;
//  attributes such as frequency, gain, etc. go here&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:BaseAudioContext.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123987</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123987"/>
		<updated>2019-04-13T02:00:18Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:OscillatorNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Exposed=Window,&lt;br /&gt;
 Constructor (BaseAudioContext context, optional OscillatorOptions options)]&lt;br /&gt;
interface OscillatorNode : AudioScheduledSourceNode {&lt;br /&gt;
//  [SetterThrows]&lt;br /&gt;
//  attribute OscillatorType type;&lt;br /&gt;
//  attributes such as frequency, gain, etc. go here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:BaseAudioContext.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123986</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123986"/>
		<updated>2019-04-13T01:58:28Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:OscillatorNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Exposed=Window,&lt;br /&gt;
 Constructor (BaseAudioContext context, optional OscillatorOptions options)]&lt;br /&gt;
interface OscillatorNode : AudioScheduledSourceNode {&lt;br /&gt;
//  [SetterThrows]&lt;br /&gt;
attribute OscillatorType type;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:BaseAudioContext.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123985</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123985"/>
		<updated>2019-04-13T01:57:50Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:OscillatorNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
&lt;br /&gt;
[Exposed=Window,&lt;br /&gt;
 Constructor (BaseAudioContext context, optional OscillatorOptions options)]&lt;br /&gt;
interface OscillatorNode : AudioScheduledSourceNode {&lt;br /&gt;
//  [SetterThrows]&lt;br /&gt;
//  attribute OscillatorType type;&lt;br /&gt;
&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:BaseAudioContext.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123981</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123981"/>
		<updated>2019-04-13T01:54:52Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:OscillatorNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:BaseAudioContext.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:OscillatorNode.png&amp;diff=123980</id>
		<title>File:OscillatorNode.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:OscillatorNode.png&amp;diff=123980"/>
		<updated>2019-04-13T01:54:28Z</updated>

		<summary type="html">&lt;p&gt;Masable: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123979</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123979"/>
		<updated>2019-04-13T01:50:16Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:BaseAudioContext.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:BaseAudioContext.png&amp;diff=123978</id>
		<title>File:BaseAudioContext.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:BaseAudioContext.png&amp;diff=123978"/>
		<updated>2019-04-13T01:49:48Z</updated>

		<summary type="html">&lt;p&gt;Masable: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123970</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123970"/>
		<updated>2019-04-13T01:41:06Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123968</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123968"/>
		<updated>2019-04-13T01:38:28Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123967</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123967"/>
		<updated>2019-04-13T01:38:09Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123966</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123966"/>
		<updated>2019-04-13T01:38:00Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;center&amp;quot; style=&amp;quot;width: auto; margin-left: auto; margin-right: auto;&amp;quot;&amp;gt;[[File:StereoPannerNode.png]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:StereoPannerNode.png]]&lt;br /&gt;
&lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123965</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123965"/>
		<updated>2019-04-13T01:34:57Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
&lt;br /&gt;
[[File:StereoPannerNode.png]]&lt;br /&gt;
&lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:StereoPannerNode.png&amp;diff=123963</id>
		<title>File:StereoPannerNode.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:StereoPannerNode.png&amp;diff=123963"/>
		<updated>2019-04-13T01:33:58Z</updated>

		<summary type="html">&lt;p&gt;Masable: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123961</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123961"/>
		<updated>2019-04-13T01:31:29Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
&lt;br /&gt;
[[File:ECE517 M1900 StereoPannerNode.png|ECE517 M1900 StereoPannerNode]]&lt;br /&gt;
&lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123960</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123960"/>
		<updated>2019-04-13T01:30:14Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
&lt;br /&gt;
[[File:ECE517_M1900_StereoPannerNode.png]]&lt;br /&gt;
&lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123959</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123959"/>
		<updated>2019-04-13T01:29:49Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
&lt;br /&gt;
[[File:Example.jpg]]&lt;br /&gt;
[[File:ECE517 M1900 StereoPannerNode.png]]&lt;br /&gt;
&lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123957</id>
		<title>M1900: Implement missing WebAudio node support</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=M1900:_Implement_missing_WebAudio_node_support&amp;diff=123957"/>
		<updated>2019-04-13T01:28:52Z</updated>

		<summary type="html">&lt;p&gt;Masable: /* Planned Work (Design Document) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Major browsers support the WebAudio standard which can be used to create complex media playback applications from low-level building blocks. [https://github.com/servo/servo Servo] is a new, experimental browser that supports some of these building blocks (called audio nodes); the goal of [https://github.com/servo/servo/wiki/WebAudio-JS-interfaces-student-project this project] is to improve compatibility with web content that relies on the WebAudio API by implementing missing pieces of incomplete node types (OscillatorNode) along with entire missing nodes (ConstantSourceNode and StereoPannerNode).&lt;br /&gt;
&lt;br /&gt;
Although the GitHub description for our project is titled &amp;quot;Implement JS support for several missing WebAudio node types&amp;quot;, we are not actually programming in JavaScript for this project. This project involves writing Rust code to implement the backend functionality of the WebAudio API, which the end user can then write JavaScript code to utilize. Therefore, the code snippets on this page are entirely in the Rust language. The only portion of our project written in JavaScript/HTML are the tests; however, the tests are not the main focus of this project (feature implementation is).&lt;br /&gt;
&lt;br /&gt;
== Tracking Issues ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21803 ConstantSourceNode]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/issues/21797 StereoPannerNode]&lt;br /&gt;
&lt;br /&gt;
== Useful Resources ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/servo/media#servo-media Setup] for modifying the standalone media backend implementation&lt;br /&gt;
* [https://github.com/servo/media/tree/master/audio/src Implementation] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/media/tree/master/examples Runnable examples] of audio node processing algorithms&lt;br /&gt;
* [https://github.com/servo/servo/pull/21750 Example] pull request implementing a missing node type in Servo (another example)&lt;br /&gt;
* [https://github.com/servo/media/pull/131 Example] pull request implementing the processing backend for a missing node type&lt;br /&gt;
* [https://github.com/servo/servo/#the-servo-parallel-browser-engine-project Setup] for making changes to Servo's code&lt;br /&gt;
* [https://doc.servo.org/script/dom/index.html#adding-a-new-dom-interface Documentation] for introducing new WebIDL-based DOM interfaces to Servo&lt;br /&gt;
* [https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#overriding-dependencies Documentation] for integrating a version of servo-media that contains your local changes into your local Servo build&lt;br /&gt;
&lt;br /&gt;
== Initial Steps (OSS Project) ==&lt;br /&gt;
* Email the mozilla.dev.servo mailing list (be sure to subscribe to it first!) introducing your group and asking any necessary questions.&lt;br /&gt;
* Create the DOM interface for ConstantSourceNode and implement the createConstantSource API for BaseAudioContext.&lt;br /&gt;
* Connect the DOM interface to the underlying backend node by processing the unimplemented message type.&lt;br /&gt;
* Update the expected test results for the relevant tests.&lt;br /&gt;
&lt;br /&gt;
== Subsequent Steps (Final Project) ==&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
&lt;br /&gt;
== Design Choices ==&lt;br /&gt;
&lt;br /&gt;
Our project did not involve any design patterns since we were just implementing methods.&lt;br /&gt;
&lt;br /&gt;
However, we faced multiple options of how to create and implement the ConstantSourceNode. Initially, we tried to model it on the OscillatorNode implementation, but faced a build error. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.parent&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We eventually learned that the ConstantSourceNode should not have a parent field because it does not inherit from anything.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let node_options =&lt;br /&gt;
options&lt;br /&gt;
.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We faced other design choices that we had to adjust from the OscillatorNode implementation. For example, we encountered errors with this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then realized that ConstantSourceNodeOptions needed to be cast as a different type in order to function correctly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Completed Work ==&lt;br /&gt;
&lt;br /&gt;
We created the DOM interface for ConstantSourceNode and implemented the CreateConstantSource API for BaseAudio Context. The connection between the DOM interface and the underlying backend node was already [https://github.com/servo/media/pull/164 implemented by other contributors] before we started the project.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/servo/servo/pull/23152 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
DOM implementation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	use crate::dom::audioparam::AudioParam;&lt;br /&gt;
	use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode;&lt;br /&gt;
	use crate::dom::baseaudiocontext::BaseAudioContext;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{&lt;br /&gt;
	    ChannelCountMode, ChannelInterpretation,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::ConstantSourceNodeMethods;&lt;br /&gt;
	use crate::dom::bindings::codegen::Bindings::ConstantSourceNodeBinding::{&lt;br /&gt;
	    self, ConstantSourceOptions,&lt;br /&gt;
	};&lt;br /&gt;
	use crate::dom::bindings::error::Fallible;&lt;br /&gt;
	use crate::dom::bindings::reflector::reflect_dom_object;&lt;br /&gt;
	use crate::dom::bindings::root::{Dom, DomRoot};&lt;br /&gt;
	use crate::dom::window::Window;&lt;br /&gt;
	use dom_struct::dom_struct;&lt;br /&gt;
	use servo_media::audio::node::AudioNodeInit;&lt;br /&gt;
	use servo_media::audio::constant_source_node::ConstantSourceNodeOptions as ServoMediaConstantSourceOptions;&lt;br /&gt;
	use servo_media::audio::param::ParamType;&lt;br /&gt;
	use std::f32;&lt;br /&gt;
	&lt;br /&gt;
	#[dom_struct]&lt;br /&gt;
	pub struct ConstantSourceNode {&lt;br /&gt;
	    source_node: AudioScheduledSourceNode,&lt;br /&gt;
	    offset: Dom&amp;lt;AudioParam&amp;gt;,&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNode {&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new_inherited(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;ConstantSourceNode&amp;gt; {&lt;br /&gt;
	        let node_options =&lt;br /&gt;
	            options&lt;br /&gt;
	                .parent&lt;br /&gt;
	                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);&lt;br /&gt;
	        let source_node = AudioScheduledSourceNode::new_inherited(&lt;br /&gt;
	            AudioNodeInit::ConstantSourceNode(options.into()),&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_options,&lt;br /&gt;
	            0, /* inputs */&lt;br /&gt;
	            1, /* outputs */&lt;br /&gt;
	        )?;&lt;br /&gt;
	        let node_id = source_node.node().node_id();&lt;br /&gt;
	        let offset = AudioParam::new(&lt;br /&gt;
	            window,&lt;br /&gt;
	            context,&lt;br /&gt;
	            node_id,&lt;br /&gt;
	            ParamType::Offset,&lt;br /&gt;
	            AutomationRate::A_rate,&lt;br /&gt;
	            1.,&lt;br /&gt;
	            f32::MIN,&lt;br /&gt;
	            f32::MAX,&lt;br /&gt;
	        );&lt;br /&gt;
	&lt;br /&gt;
	        Ok(ConstantSourceNode {&lt;br /&gt;
	            source_node,&lt;br /&gt;
	            offset: Dom::from_ref(&amp;amp;offset),&lt;br /&gt;
	        })&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    #[allow(unrooted_must_root)]&lt;br /&gt;
	    pub fn new(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        let node = ConstantSourceNode::new_inherited(window, context, options)?;&lt;br /&gt;
	        Ok(reflect_dom_object(&lt;br /&gt;
	            Box::new(node),&lt;br /&gt;
	            window,&lt;br /&gt;
	            ConstantSourceNodeBinding::Wrap,&lt;br /&gt;
	        ))&lt;br /&gt;
	    }&lt;br /&gt;
	&lt;br /&gt;
	    pub fn Constructor(&lt;br /&gt;
	        window: &amp;amp;Window,&lt;br /&gt;
	        context: &amp;amp;BaseAudioContext,&lt;br /&gt;
	        options: &amp;amp;ConstantSourceOptions,&lt;br /&gt;
	    ) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
	        ConstantSourceNode::new(window, context, options)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl ConstantSourceNodeMethods for ConstantSourceNode {&lt;br /&gt;
	    fn Offset(&amp;amp;self) -&amp;gt; DomRoot&amp;lt;AudioParam&amp;gt; {&lt;br /&gt;
	        DomRoot::from_ref(&amp;amp;self.offset)&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	impl&amp;lt;'a&amp;gt; From&amp;lt;&amp;amp;'a ConstantSourceOptions&amp;gt; for ServoMediaConstantSourceOptions {&lt;br /&gt;
	    fn from(options: &amp;amp;'a ConstantSourceOptions) -&amp;gt; Self {&lt;br /&gt;
	        Self {&lt;br /&gt;
	            offset: *options.offset,&lt;br /&gt;
	        }&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Constant Source Node Webidl DOM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        dictionary ConstantSourceOptions: AudioNodeOptions {&lt;br /&gt;
            float offset = 1;&lt;br /&gt;
        };&lt;br /&gt;
	&lt;br /&gt;
        [Exposed=Window, Constructor (BaseAudioContext context, optional ConstantSourceOptions options)]&lt;br /&gt;
        interface ConstantSourceNode : AudioScheduledSourceNode {&lt;br /&gt;
            readonly attribute AudioParam offset;&lt;br /&gt;
        };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateConstantSource API for BaseAudio Context:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        use crate::dom::constantsourcenode::ConstantSourceNode;&lt;br /&gt;
        fn CreateConstantSource(&amp;amp;self) -&amp;gt; Fallible&amp;lt;DomRoot&amp;lt;ConstantSourceNode&amp;gt;&amp;gt; {&lt;br /&gt;
            ConstantSourceNode::new( &amp;amp;self.global().as_window(), &amp;amp;self, &amp;amp;ConstantSourceOptions::empty())&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connection between the DOM interface and the underlying backend node (implemented by other contributors):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        AudioNodeInit::ConstantSourceNode(options) =&amp;gt; {&lt;br /&gt;
            Box::new(ConstantSourceNode::new(options, ch))&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Planned Work (Design Document) ==&lt;br /&gt;
&lt;br /&gt;
As we continue our project, it will likely not involve any design patterns since we will just be implementing methods. Here is what we must do and our plan for how do it:&lt;br /&gt;
&lt;br /&gt;
* Implement an audio node message that is specific to OscillatorNode (use BiquadFilterNode as a model) which updates the node's oscillator type.&lt;br /&gt;
** The audio node message specification is in servo/media/audio/src/node.rs. We will use this specification for guidance.&lt;br /&gt;
* Implement the type attribute setter for the OscillatorNode interface which uses the new oscillator node message.&lt;br /&gt;
** We will accomplish this by modifying servo/components/script/dom/webidls/OscillatorNode.webidl.&lt;br /&gt;
* Implement the backend for StereoPannerNode in the media crate by creating a new node implementation using PannerNode as a guide. The processing algorithm is described in the specification. Create a runnable example based on the example for PannerNode.&lt;br /&gt;
** The goal for the StereoPannerNode implementation is that the user should be able to specify a pan value between -1 (full left pan) and 1 (full right pan) and the StereoPannerNode will adjust the gain on each of the two speakers accordingly. &lt;br /&gt;
&lt;br /&gt;
[[File:ECE517 M1900 StereoPannerNode.png|thumb|StereoPannerNode diagram for ECE 517 (M1900).]]&lt;br /&gt;
&lt;br /&gt;
** We will follow the example in servo/media/examples/panner.rs to create our runnable example.&lt;br /&gt;
* Create the DOM interface for StereoPannerNode and implement the createStereoPannerNode API for BaseAudioContext.&lt;br /&gt;
** We already created the DOM interface for ConstantSourceNode and implemented the createConstantSourceNode API for BaseAudioContext, so we will follow the same procedure when creating the DOM interface for StereoPannerNode and implementing the createStereoPannerNode API.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
'''Testing from Command Line'''&lt;br /&gt;
&lt;br /&gt;
After following the setup instructions in the [https://github.com/servo/servo#the-servo-parallel-browser-engine-project Servo readme], cloning the repository, and changing directories into it, you can build the project with the following command from the terminal (the readme includes the different build commands to use depending on your OS). Note that it may take a long time to build the project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach build --release&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After building, you can run the relevant tests with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mach test-wpt tests/wpt/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice that all tests pass as expected.&lt;br /&gt;
&lt;br /&gt;
'''Testing from UI'''&lt;br /&gt;
&lt;br /&gt;
Our project cannot be tested from a UI since it involves the Servo project.&lt;/div&gt;</summary>
		<author><name>Masable</name></author>
	</entry>
</feed>