Why does js oscillators stop playing sound after some use? - javascript

I'm trying to make a simple piano with js but I don't want to use audio samples, instead I want to generate sound programmatically. To play single sound I am using this code from this blog https://marcgg.com/blog/2016/11/01/javascript-audio/
var context = new AudioContext()
var o = context.createOscillator()
var g = context.createGain()
o.connect(g)
g.connect(context.destination)
o.start(0)
g.gain.exponentialRampToValueAtTime(0.00001, context.currentTime + 5)
I found that after playing it more than about 50 times this method stops working. No sound plays when running this code, context.currentTime does not change and stays 0. How can I fix it without stopping already playing sound?

Don't create a new AudioContext for each note; create one and use it for all of them. This will not only save resources; it will also help with playing multiple notes at precise times if you decide you want to do that.
You're also accumulating oscillators that are still playing, just extremely quietly. You need to stop them sometime. The good news is, the Web Audio API is designed to make it easy to do this:
// stop after 5 seconds from now
o.stop(context.currentTime + 5);

Related

How can two audioplayer play at same time?

I like to install two audioplayer on my WordPress page so that both players will playing at same time. So how is it possible to tell each player not to stop playing if an other player is running?
Thanks for helping out.
I just started to look for a plugin player.
As per your description you have not mentioned about how do you want that page to load the audio. (For example to load those 2 audio on page load or user input/interactions with them.)
On WordPress you can add custom JS code or some hook to those elements or interaction event.
For easy go if you use on page load(as you have not described the way to interact with them) see if this helps you or if it leads you to any idea about way you want it to implement:
// just for example
function playAudio() {
var audio1 = document.getElementById('audio1');
var audio2 = document.getElementById('audio2');
audio1.play();
audio2.play();
}

does new Audio preload the sound file?

I get an audio element and play the sound like so:
let audio = document.querySelector(`audio[data-key="${e.key}"]`);
audio.play();
However sometimes (I use Chrome) there is initially a delay when I play a sound, so I also added this code:
let audioElems = document.querySelectorAll('audio');
audioElems.forEach(function (audio) {
new Audio(`./sounds/${audio.dataset.key}.mp3`);
});
It seemed to make a difference at first but now again sometimes I get the delay. Does the extra code make a difference, will using new Audio actually preload the sound file?
It doesn't necessarily preload it, but it creates an HTMLAudioElement with the preload attribute set to auto.
This means that UAs are told that they should preload the resource if they dim it appropriate, e.g, they could ignore it if on mobile data.
console.log(new Audio)
Now to your issue, Chrome is known to not accept more than 6 simultaneous requests. So if your audioElems NodeList contains more than 6 elements, that would be the cause for some of them to be delayed until the first ones are fetched.
Also, there will always be at least a little delay, since all in MediaElement is asynchronous. Depending on what you are after, you may get better results using the Web Audio API.
HTML5 audio/video tags have an optional preload attribute. Is this attribute currently enabled on your audio tag?
https://www.w3schools.com/tags/av_prop_preload.asp
Using the new Audio() constructor defaults to preload="auto", so that does make a difference.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLAudioElement

Playing MediaStream using AudioContext.createMediaStreamSource vs HTMLAudioElement.srcObject

I'm trying to play MediaStream from remote peer (WebRTC) using Web Audio API. When i attach the stream to audio element using audio.srcObject = stream it plays ok, but when i try to use AudioContext it does not play any sound at all (I need to avoid audio/video HTML tag).
This piece works:
<audio controls>
<script>
const audioEl = document.getElementsByTagName('audio')[0];
audioEl.srcObject = MY_STREAM;
audioEl.play();
</script>
This one does not:
const audioContext = new AudioContext();
const sourceNode = audioContext.createMediaStreamSource(MY_STREAM);
sourceNode.connect(audioContext.destination);
// Trying even 'audioContext.resume()' after user gesture with no luck
What is weird about that is that when MY_STREAM is my micriphone then it plays nicely for Web Audio API (i hear the feedback from my mic).
So it would suggest that there is something different between microphone MediaStream and the one i get from WebRTC connection but why DOES it play for simple HTML audio tag?
As demonstrated by #jib, this is a Chrome bug.
I have opened a new issue to let them know about it.
I thought I found a workaround by simply assigning this MediaStream to the srcObject of a dummy HTMLAudioElement,
new Audio().srcObject = mediaStream;
but somehow, while testing on my localhost it didn't persist in time, while in this fiddle it does.
I also encountered a lot of other weird behavior while playing around, like different tabs having incidence on others and things like that.
Add to that other non-fixed bugs in the area that make me think of false positives and all-in-all, I fear there is no proper solution than waiting for them to fix it...

HTML5 audio stops working after a while (leak)

So im working on a HTML5 / javascript rts game. Obv there are several sounds playing all the time. So what happens for me is after a while the sounds kinda "crashes" and all sound from this browser tab stops working. I can only bring back sound by restarting the browser, restarting the tab (= reloading the game) doesnt fix it. This is what i use to play sounds:
// play sound
soundToPlay.load();
soundToPlay.play();
soundToPlay.volume = volume;
Im on win7 and FF. What also happens when i play the game is that the windows process "audiodg" increases in memory usage, and when the sound stops working its usually up at something like 2,5 gb. When i close the browser, most of the time it will go back down to a couple of MB, where it should be normally. This audiodg thing is a known bug (not with my game, but in general), but i do not havy any issues with audiodg outside of my game. Most users of my game seem to not have this problem, only relatively few, but im definetly not the only one, also its definetly not a FF thing only, ive seen it happen on chrome, too.
so, my guess is that you're creating the new Audio(filename) every time it must be played.
so, even creating these with javascript, you end up with an HTML template anyway.
var a = new Audio('file.mp3');
// <audio preload=​"auto">​</audio>​
In light of that you should call new Audio(filename) only once, and store it in a variable that can be referenced when the sound should play:
var clone = $(a).clone()[0];
clone.play();
clone.volume = volume;
clone.onended = function() {
$(clone).remove();
}

HTML5 Audio Plays Randomly

I am implementing sound effects in HTML5 audio but after a while, it just stops playing any audio. The file type is correct because it starts fine but then seems to give up.
var sound = new Audio(url);
function play() {
sound.play();
}
Is there a better way to do this so it consistently plays sound?
Here is a link to my implementation. Easy to reproduce by pressing spacebar a lot until it eventually gives up (also shoot the lights for added sounds). http://craftyjs.com/elevatoraction/
This occurs for me in the latest version of Chrome (8.0)
Edit: I did as Gaurav suggested and only played the same instance of each sound file, but the same sort of problems are present. It will arbitrarily stop playing.
Edit 2: I just noticed that whenever I try to play the sound, the networkState is always 1 which according to this means it hasn't fully loaded. That is odd seeing as it still plays sometimes and even when it plays the networkState is always 1
Don't create a new audio object each time you want to play a sound, reuse the same resource.
var sound1 = new Audio(url);
function playSound1() {
sound1.play();
}
I think this is related to the bug http://code.google.com/p/chromium/issues/detail?id=57070

Categories

Resources