Problem: Finding an efficient function for Muting and Unmuting Audio (w/o VideoPlayer) in HTML5 automatically until a defined time is past.
I set the gain of an oscillator to increase gradually from 0 to 1 (interrupted by a bunch of 1second of silence in each unit of gain's increase) until 30s are reached. For this purpose the setValueAtTime function (I added increments to both values of gain and time) was called.
It doesn't seem efficient, however, because the iterations don't follow an accurate real-life-corresponding time, even if the arguments are set individually to change values in a particular time -> this demanded a dummy effort to test. More interesting would be setValueCurveAtTime and setLinearRampAtTime, but they don't seem to allow a distribution of "silences" during the increasing tone.
The only references found regarded UserInteraction with a custom button, which is not automatic; and JQuery functions. I found no documentation precise enough. The function "document.getElementById(id).setVolume(0);" for example doesn't offer neither an option of defining the duration of the silence, nor the option to insert this 1s of silence homogeneously along the 30seconds of an increasing tone.
Once the function is defined, I would call setTimeout so that it played immediately and then setInterval("function()", 30000).
Snippet of code
context=new AudioContext();
var oscillator = context.createOscillator();
var gainR = context.createGain();
oscillator.connect(gainR);
gainR.connect(context.destination);
gainR.gain.setValueAtTime(0,currenttime);
loudnessup = function (){
var c = currenttime;
var Loud=0.2;
gainR.gain.setValueAtTime(Loud, c+2);
gainR.gain.setValueAtTime(0, c+3);
gainR.gain.setValueAtTime(Loud+0.05, c+3.5);
gainR.gain.setValueAtTime(0, c+4.5);
//...continues iterations
gainR.gain.setValueAtTime(Loud+0.8, c+28);
gainR.gain.setValueAtTime(0, c+30);};
setTimeout("loudnessup()",currenttime);
setInterval(function(){
n=n+1; //after 30s the freq value should arise accordingly to an array
oscillator.frequency.value = frequencies[n];},30000);}
After the 30s, the loop w/ a higher freq doesn't seem to go any further
Here is an example using the built-in high-resolution timer to set the volume over a short segment relative to the start time.
It will create two events for each segment to ramp volume quickly. Each segment is toggled so the first time it will ramp up the volume, the second time ramp it down. Using a slight ramp will also prevent clicks in the sound.
Using a toggle state you can create two events defining a short ramp for each segment. If the toggle is true if will go from current volume to 0, otherwise from 0 to current volume:
var toggle = true;
var now = actx.currentTime;
...
for(var i = 0; i < duration; i += step) {
var volume = i / duration;
g.gain.linearRampToValueAtTime(toggle ? volume : 0, now + i);
g.gain.linearRampToValueAtTime(toggle ? 0 : volume, now + i + 0.012);
toggle = !toggle;
}
document.querySelector("button").onclick = function() {
this.style.display = "none";
playSound(); // first play
setInterval(playSound, 30000); // next play, after and every 30 sec.
};
function playSound() {
var duration = 30, step = 1, toggle = false,
actx = new (AudioContext || webkitAudioContext)(),
osc = actx.createOscillator(),
g = actx.createGain();
osc.frequency.value = 440;
g.gain.value = 0;
osc.connect(g);
g.connect(actx.destination);
var now = actx.currentTime;
for(var i = 0; i < duration; i += step) {
// volume for this segment when toggled on
var volume = i / duration;
// create a short ramp using two events 12ms appart
g.gain.linearRampToValueAtTime(toggle ? volume : 0, now + i);
g.gain.linearRampToValueAtTime(toggle ? 0 : volume, now + i + 0.012);
toggle = !toggle;
}
osc.start();
osc.stop(now + duration);
};
button {font:bold 20px sans-serif}
<button>Start</button>