Creating an Oscillator Node in Scala.js using js.Dynamic - javascript

I'm using the online version of Scala-js-fiddle. So far, I've been able to successfully declare an Audio Context:
val ctx = js.Dynamic.newInstance(js.Dynamic.global.AudioContext)()
Now, I want to create an oscillator node. I tried (unsuccessfully):
val oscillator = ctx.js.Dynamic.global.createOscillator()
When I saved this, the Scala-js-fiddle said compilation was successful. However, I also had error messages. The main one was:
TypeError: Cannot read property 'Dynamic' of undefined
How can I properly create an oscillator node and set the value of its frequency using js.Dynamic?
In regular Javascript, I would simply write something like this:
var oscillator = ctx.createOscillator();
oscillator.frequency.value = 400;
Would I have to use js.Global.Function(...)? How would that work?

Solved! As it turns out, after creating an AudioContext like this
val ctx = js.Dynamic.newInstance(js.Dynamic.global.AudioContext)()
you can call the JavaScript methods normally:
val o = ctx.createOscillator()

Related

<video>.playbackRate not working on firefox when using HTMLMediaElementSourceNode

As stated in the title, I have been running in an issue regarding the HTMLVideoElement when connected to the WebAudioAPI inside Firefox.
The following sample gives a minimal example reproducing the issue:
var video = document.getElementById('video');
var ctx = new AudioContext();
var sourceNode = ctx.createMediaElementSource(video);
sourceNode.connect(ctx.destination);
video.playbackRate = 3;
video.play();
As soon as the video element is connected to the audio pipeline, I cannot get the playbackRate setter to work anymore.
I've been looking for a way to set this value somewhere inside the AudioContext or the HTMLMediaElementSourceNode objects but those classes do not seem to handle playback-rate on their own.
Please note that this sample works fine on Chrome. And I don't really see what seems to be the problem here.
Thanks
Already reported over the Firefox's bug tracker: https://bugzilla.mozilla.org/show_bug.cgi?id=966247

Web Audio API: discover a node's connections

With the Web Audio API, is there a way to discover a node's connections?
For example, given
ctx = new AudioContext();
g1 = ctx.createGain();
g2 = ctx.createGain();
g1.connect(g2);
is there a method I can call on g1 that will return [g2]?
I'm interested in writing a javascript library to visualize the current audio graph, similar to the Firefox Web Audio Editor.
You could potentially do something like this:
var connect = AudioNode.prototype.connect;
var disconnect = AudioNode.prototype.disconnect;
AudioNode.prototype.connect = function( dest ) {
this._connections || ( this._connections = [] );
if ( this._connections.indexOf( dest ) === -1 ) {
this._connections.push( dest );
}
return connect.apply( this, arguments );
};
AudioNode.prototype.disconnect = function() {
this._connections = [];
return disconnect.apply( this, arguments );
};
This is a quick example, and it doesn't account for disconnect arguments. But something along those lines could work, I think.
There are good reasons not to do something like this. But
it would allow you to keep the application code generic, which is really what you need if you want to be able to visualize arbitrary audio graphs.
The short answer is no - there is no such method. You'll have to keep track of your connections yourself.

Web Audio API Analyzer Node not working as expected

I'm simply trying to read the FFT values of a 1000Hz sine wave in this code. However the console output displays '-128' a 1000 times. Why doesn't the analyzer node work in this?
window.onload = init;
var sourceNode;
function init(){
var context = new AudioContext();
var osc = context.createOscillator();
var analyser = context.createAnalyser();
var gain = context.createGain();
sourceNode = context.createBufferSource();
var amplitudeArray = new Float32Array(analyser.frequencyBinCount);
osc.frequency.value=1000;
osc.start();
gain.gain.value=0.07;
osc.connect(analyser);
analyser.connect(gain);
gain.connect(context.destination);
analyser.getFloatFrequencyData(amplitudeArray);
for(var i=0;i<amplitudeArray.length;i++){
console.log(amplitudeArray[i]);
}
}
You are basically asking the analyser for the FFT data right when the oscillator starts. At this point, the internal buffers are full of zeroes, so the output is -128 dB. That is, everything is zero.
Try waiting for a second before calling analyser.getFloatFrequencyData. You'll see that the output is not a constant -128.
In this particular case, because you're IMMEDIATELY requesting the data; although you've called osc.start(), the audio system hasn't processed any data yet, so when you call getFloatFrequencyData() it's full of empty data. (FloatFrequencyData is in decibels, so -128 is the noise floor - aka "zero").
If you had enough of a time gap between start() and the getFloatFrequencyData() call for some audio to be processed, I expect you'd see some data.

Buffered Audio For Generating Sounds

I have an oscillator to generate the frequencies of a keyboard. It all works when I output to speakers, but as well as outputting to speakers I would like to buffer it so that I can turn it into base 64 and use again later. The only examples of this I have seen use xhr which I do not need as obviously I want to be able to just add a node into the modular routing to take input, store it in an array, then output to the hardware.
Something like this:
var osc = ctx.createOscillator();
osc.type = 3;
osc.frequency.value = freq;
osc.connect(buffer);
buffer.connect(ctx.destination);
Is this possible?
Have you considered utilizing a ScriptProcessorNode?
See: http://www.w3.org/TR/webaudio/#ScriptProcessorNode
You would attach an eventListener to this node, allowing you to capture arrays of audio samples as they pass through. You could then save these buffers and manipulate them as you wish.
Have you checked out RecorderJs? https://github.com/mattdiamond/Recorderjs. I think it does what you need.
I have solved my problem by using Matt's Recorder.js https://github.com/mattdiamond/Recorderjs and connecting it to a GainNode which acts as an intermediary from a number of oscillators to the ctx.destination. I will be using localStorage but here is an example using an array (this does not include the oscillator setup).
var recorder;
recorder = new Recorder(gainNode, { workerPath: "../recorderWorker.js"});
recorder.record();
var recordedSound = [];
function recordSound() {
recorder.exportWAV(function(blob) {
recordedSound.push(blob);
});
}
function play(i) {
var audio = new Audio(window.URL.createObjectURL(recordedSound[i]));
audio.play();
}

Toggle One And Off - JavaScript - Web Audio API

I am an Audio Engineer and just started JavaScript and HTML5, Specifically WEB Audio API.
I have this oscillator code which is connected to destination(output).
here is the code
I want to have a buttons to connect and disconnect the oscillator to destination
I managed to make it start but I can't disconnect it.
<html>
<head>
<script>
//creating the context
context = new webkitAudioContext(); //allways the first code for audio API
function osc1(frequency){ // Creating a function that has an oscillator going to gainNode and then going to the destination
//creating AudioNodes and AudioParams
//creating OscillatorNode
var oscillator = context.createOscillator(); //creating Node's as Variables
oscillator.type = 0; //0 is a sine wave
oscillator.noteOn(0); // turning on the oscillator
oscillator.frequency.value = frequency;// telling that frequency in () of the function equals to what
//creating GainNode
var gain = context.createGainNode(); // creating the Gain node
gain.gain.value = 1; // setting up the value for gain node
//Making the connections
oscillator.connect(gain); // connecting oscillator to gain
gain.connect(context.destination); // connecting gain to destination (speakers)
}; // now we have a function called osc1(we can put frequency in here) then we can re call
</script>
</head>
<body>
<input type="button" value="on" onClick="osc1(500);" />
</body>
</html>
I know that the code for disconnecting it is oscillator.disconnect();, but I don't know how to to execute it.
Maybe you want declare the oscillator variable outside the function:
var context = new webkitAudioContext();
var oscillator = context.createOscillator();
function osc1(frequency){
var button = document.getElementsByTagName('input')[0];
if (button.value === 'off') {
button.value = 'on';
oscillator.disconnect();
} else {
button.value = 'off';
// same as your original code (connect, noteOn...)
I'm working on this too.
You do oscillator.disconnect(0) where zero represents the output number.
I think that means if you connect the oscillator to a gain node and a filter node separately, gain would be disconnect(0) and filter would be disconnect(1).
I think keeping track of what outputs are what is our job, since there doesn't look like a built in way.
I would hope the spec changes so that we can pass disconnect() the actual node we want disconnected.
It's been mentioned already, but you need to expose the oscillator variable (possibly to the global scope) so that your off function can disconnect it (make sure you don't redeclare the oscillator variable inside the onclick handler).
Here's a working example: http://jsbin.com/iwetiy/1/edit

Categories