Fed Reggiardo Fed Reggiardo - 4 months ago 15
Javascript Question

AudioContext.currentTime + variable time

Using the Web Audio API to generate basic tones using oscillators and having an issue varying the duration (in secs) of notes played.

The issue is with the "sustain" variable not working as expected to stop the oscillator. The variable works as expected for one note played and then the remaining notes play unlimited duration. If I remove the variable and hardcode the duration instead of using a variable it works fine. Logs of context.currentTime show no difference between variable or hard coded duration. Over thinking something. What am I missing??

JS:

//start new audio session. Do this only once


var context = new window.webkitAudioContext();

function playSound(note) {
oscillator = context.createOscillator();

//create volume controller
var gainNode = context.createGain();

//connect signal to audio output(speakers by default)
oscillator.connect(gainNode);
gainNode.connect(context.destination);

//adjusts frequency played by 50%, 100% or 200%
var octave = document.getElementById('octave').value;

//sets oscillator frequency
oscillator.frequency.value = frequencies[note] * octave;

//oscillator wave type
oscillator.type = document.getElementById('waveSelect').value;

//starts oscillator. Delayed start can be achieved by adding time(in secs) after currentTime
oscillator.start(context.currentTime + 0.01);

//determines note duration
var sustain = document.getElementById('sustain').value;

//stops oscillator by exponentially ramping down sound over .015 seconds to avoid audible click
gainNode.gain.setTargetAtTime(0, context.currentTime + sustain, 0.0015);


//for testing
console.log("Hz:" + frequencies[note] * octave + " octave:" + octave + " wave:" + oscillator.type + "duration: " + sustain + " time:" + context.currentTime);


}

HTML:

<select class="lists" id="sustain">
<option value="0.5">EIGHTH NOTE</option>
<option value="1.0">QUARTER NOTE</option>
<option value="2.0">HALF NOTE</option>
<option value="4.0">WHOLE NOTE</option>
</select>


Thanks for the help!

Answer

You need to parse the resulting value of the sustain select-element to a floating point number, because it's returning a string value. And if you combine a string with a number in javascript, it evaluates to a string. Have a look at this jsbin for a pratical example:

http://jsbin.com/qexusoyida/edit?html,js,console,output

Just edit this line

var sustain = document.getElementById('sustain').value;

like this

var sustain = parseFloat(document.getElementById('sustain').value);