How to play an audio file in a infinite loop using jQuery - javascript

Right now I have a piece of code (below) which allows me to play audio files on button click. However, I would like to have the file playing in a infinite loop until I click click the button "Stop" button.
How can I achieve that?
var audiotypes={
"mp3": "audio/mpeg",
"mp4": "audio/mp4",
"ogg": "audio/ogg",
"wav": "audio/wav"
}
function ss_soundbits(sound){
var audio_element = document.createElement('audio')
if (audio_element.canPlayType){
for (var i=0; i<arguments.length; i++){
var source_element = document.createElement('source')
source_element.setAttribute('src', arguments[i])
if (arguments[i].match(/\.(\w+)$/i))
source_element.setAttribute('type', audiotypes[RegExp.$1])
audio_element.appendChild(source_element)
}
audio_element.load()
audio_element.playclip=function(){
audio_element.pause()
audio_element.currentTime=0
audio_element.play()
}
return audio_element
}
}
var audio = ss_soundbits('audio/file.mp3');
var start_audio= function() {
audio.playclip();
};

Capture the ended event on the audio element, and then make it play again.
audio_element.addEventListener('ended', function() {
this.currentTime = 0;
this.play();
}, false);
This should be sufficient for you.
edit
As pointed out by #A. Wolff, I made an oversight wherein clicking stop would fire the ended event. Setting a global boolean flag will resolve this.
var stopped = false;
audio_element.addEventListener('ended', function() {
if(!stopped){
this.currentTime = 0;
this.play();
}
}, false);
var stop_button = document.getElementByID('stop');
stop.addEventListener('click', function(){
stopped = true
audio_element.stop();
});

Sorry for my comment - only addition: audio_element.play() may not work on mobile browsers without manual click

Related

Tone.js app - audio won't start until second click

I'm aware that I need a user action to start Web Audio on mobile. However I have followed the recommendation to resume (in the case of Tone.js call Tone.start()) on user action but it still don't work.
Here are the relevant parts of my code:
keyElement.addEventListener("touchstart", notePressed, false);
keyElement.addEventListener("touchend", noteReleased, false);
function notePressed(event) {
let dataset = event.target.dataset;
if (!dataset["pressed"]) {
let octave = +dataset["octave"];
oscList[octave][dataset["note"]] = playTone(dataset["frequency"]);
dataset["pressed"] = "yes";
}
event.preventDefault(); event.stopPropagation();
}
function noteReleased(event) {
let dataset = event.target.dataset;
if (dataset && dataset["pressed"]) {
let octave = +dataset["octave"];
oscList[octave][dataset["note"]].triggerRelease();
delete oscList[octave][dataset["note"]];
delete dataset["pressed"];
}
}
function playTone(freq) {
let synth = new Tone.Synth().toDestination();
let now = Tone.now();
Tone.start();
synth.triggerAttack(freq, now);
return synth;
}
It works fine on the second touch, but after the first touch I get a warning about the audio context being suspended, even though the standard is that it is resumed when start() is called by a user action. I'm stumped here.
That Tone code looks correct. I simplified it in a CodePen and it worked on mobile on first click (iOS).
var keyElement = document.getElementById("play");
keyElement.addEventListener("touchstart", notePressed, false);
keyElement.addEventListener("touchend", noteReleased, false);
// Added mouse ELs to test on non-mobile.
keyElement.addEventListener("mousedown", notePressed, false);
keyElement.addEventListener("mouseup", noteReleased, false);
var pressedTone;
function notePressed(event) {
console.log("notePressed");
pressedTone = playTone(440);
event.preventDefault();
event.stopPropagation();
}
function noteReleased(event) {
pressedTone.triggerRelease();
}
function playTone(freq) {
console.log("playTone", freq);
let synth = new Tone.Synth().toDestination();
let now = Tone.now();
Tone.start();
synth.triggerAttack(freq, now);
return synth;
}
Here's the link to the CodePen: https://codepen.io/joeweiss/pen/gOmeQVW

Playing array of audio in sequence not working even if I have ended function

I'm trying to play all my audio files in sequence with the duration between each audio. Right now, I can play the first audio, but I have to click the play button again in order to play the second audio. ended function should handle this, shouldn't it? Appreciate your kindness and help.
var playList = [{
"duration": 1000,
"value": "0_silence"
}, {
"duration": 4000,
"value": "1_hello"
}, {
"duration": 6000,
"value": "2_how_old"
}];
$(document).ready(function() {
var audioElement = document.createElement('audio');
var i = 0;
$("#play").on("click", function(){
audioElement.addEventListener("ended", playAudio(playList));
function playAudio() {
if(i < playList.length) {
audioElement.setAttribute('src', 'sound/' + playList[i].value + '.wav');
setTimeout(function (){audioElement.play(); playAudio, playList[i].duration;});
i++;
} else {
i = 0;
}
}
});
// playAudio(playList);
// });
//
// function playAudio() {
// var audioElement = document.createElement('audio');
// audioElement.addEventListener("ended", playAudio(playList));
// if (i < playList.length) {
//
// var audioElement = document.createElement('audio');
// audioElement.addEventListener("ended", playAudio(playList));
// audioElement.setAttribute('src', 'sound/' + playList[i].value + '.wav');
// audioElement.play();
// setTimeout(playAudio, playList[i].duration);
// i++;
// } else {
// i = 0; // reset i to zero to start over if button clicked again
// }
// }
}
The first error is in this line:
audioElement.addEventListener("ended", playAudio(playList));
Here the function playAudio() is called and the result from it (undefined in this case) is handed to the addEventListener() as argument, which of course won't work. If the playList is global simply change it to:
audioElement.addEventListener("ended", playAudio); // function is now referenced
In addition, the handler is called every time the play button is clicked. Only add it once when the element is created.
There is also an error in the setTimeout() call, as shown in the post, as it misses a time argument and contains invalid statements inside the function block.
However, it shouldn't be necessary to use this call as calling play() on the element will, in newer browsers, cue up the call. For older browsers you may need to use the canplay event. setTimeout() is not recommended here in either case.
You should also call load() before play() to reset and cleanup the element, and to start loading the new source.
And finally, if the intention is to play the list in a loop the list will fail when last track has been played as i is reset in a separate else-block which does not invoke play.
You might want to consider how the play button behaves in order to prevent it from loading samples while playing (ie. toggle pause/play). I wrapped up the fixes above except from the play-button (I rewired it to share the playAudio() function) here using random short samples:
var playList = [{
"duration": 1000,
"value": "http://sampleswap.org/samples-ghost/SFX%20and%20UNUSUAL%20SOUNDS/ELECTRO%20and%20SYNTHETIC/257[kb]50s_space_telemetry.aif.mp3"
}, {
"duration": 4000,
"value": "http://sampleswap.org/samples-ghost/SFX%20and%20UNUSUAL%20SOUNDS/ELECTRO%20and%20SYNTHETIC/85[kb]analog_alarm_up.aif.mp3"
}, {
"duration": 6000,
"value": "http://sampleswap.org/samples-ghost/SFX%20and%20UNUSUAL%20SOUNDS/ELECTRO%20and%20SYNTHETIC/42[kb]alien_alarm.aif.mp3"
}];
$(document).ready(function() {
var audioElement = document.createElement('audio');
// reference function instead of calling it. Also, only set it once.
audioElement.addEventListener("ended", playAudio);
var i = 0;
$("#play").on("click", playAudio); // rewired to share playAudio()
function playAudio() {
var entry = playList[i++]; // get current entry, increment i
if (i >= playList.length) i = 0; // if i=> length, reset
audioElement.src = entry.value; // <- for demo samples only. 'sound/' + entry.value + '.wav';
audioElement.load(); // cleanup old fun, invoke loading of new
audioElement.play(); // cue up play
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id=play>Play</button>

HTMLMediaElement.duration returning NaN for audio file

I have the following JavaScript to play a sound when a button is clicked on the screen, however I'm only getting NaN for the duration.
$(document).ready(function() {
function play_sound() {
var audio = new Audio("assets/sound.ogg");
audio.play();
var duration = audio.duration;
console.log(duration);
}
$(document).on("click", ".box", function(e) {
play_sound();
});
});
In my research I found this answer which uses the "loadeddata" event, however I'm not sure how to incorporate that into my code. Should I use an <audio> element in my HTML?
Here's my shot at it:
$(document).ready(function() {
function play_sound() {
var audio = new Audio("assets/sound.ogg");
audio.addEventListener("loadedmetadata", function(_event) {
var duration = audio.duration;
console.log(duration);
});
audio.play();
}
$(document).on("click", ".box", function(e) {
play_sound();
});
});
http://jsfiddle.net/x2pe6hcf/1/
Added the eventListener and it works perfectly.

How do I keep the <video> and the <canvas> duplicate at same frame?

I have the following code setup to display the canvas duplicate of the video when paused so it can display a greyscale version of the paused image. As you'll notice the paused frame is always behind the video.
I've tried setting pixelScan() to only happen when the video is paused or ended, and I've experimented with the setTimeout() and requestAnimationFrame() all with no luck. But, that's most likely due to my own lack of skill with JavaScript haha
I just seem to keep getting caught up with this issue and I know there has to be plenty fixes to this simple issue
http://coreytegeler.com/ethan/
var processes={
timerCallback:function() {
if (this.v2.paused || this.v2.ended) {
return;
}
this.ctxIn.drawImage(this.v2,0,0,this.width,this.height);
this.pixelScan();
var self=this;
},
doLoad:function(){
this.v2=document.getElementById("video");
this.cIn=document.getElementById("cIn");
this.ctxIn=this.cIn.getContext("2d");
this.cOut=document.getElementById("cOut");
this.ctxOut=this.cOut.getContext("2d");
var self=this;
setTimeout(function() {
self.timerCallback();
}, 34);
this.v2.addEventListener("playing", function() {
self.width=v.videoWidth;
self.height=v.videoHeight;
cIn.width=v.videoWidth;
cIn.height=v.videoHeight;
cOut.width=v.videoWidth;
cOut.height=v.videoHeight;
self.timerCallback();
}, false);
this.v2.addEventListener('ended', function() {
openInfo();
v2.pause();
v2.loop = true;
stateAnimate.animate({path: playBtn, fill:"white"}, 300, "ease-in-out");
loopAnimate.animate({path: loopOn, fill:"white"}, 200, "back-in");
});
},
pixelScan: function() {
var frame = this.ctxIn.getImageData(0,0,this.width,this.height);
for(var i=0; i<frame.data.length;i+=4) {
var grayscale=frame.data[i]*.3+frame.data[i+1]*.59+frame.data[i+2]*.11;
frame.data[i]=grayscale;
frame.data[i+1]=grayscale;
frame.data[i+2]=grayscale;
}
this.ctxOut.putImageData(frame,0,0);
return;
}
}
You can use the pause event:
this.v2.addEventListener('pause', function() {
// process frame here
}, false);

Running text: Pause, Stop

I have <p> element:
<p id="news_title">Text goes here</p>
Which I have made to run text with help this JavaScript:
(function(){
var j = 0;
var el = document.getElementById("news_title");
var interval;
function runEngine(){
interval = setInterval(function(){
if (j===200){
j=-200;
}
el.style.left = j + "px";
j++;
},20);
}
window.onload = function(){
runEngine();
};
})();
Marked script working nicely, but I want to pause the text onmouseover and onmouseout let it continue running. Also, onclick I want to stop it for good.
el.onmouseover = function(){
clearInterval(interval);
}; // pausing , working nicely
el.onmouseout = function(){
runEngine();
}; // also working
The onclick is not working however. Even though I clear the interval, the onmouseout handler causes the text to run again. How can I prevent this?
On click, set a flag. Then check the flag in the onmouseout handler:
var clicked = false;
el.onclick = function() {
clicked = true;
};
el.onmouseout = function() {
if (!clicked) {
runEngine();
}
};

Categories

Resources