settimeout while audio.duration - javascript

I try to read an array of sentence asynchronously by audio; but i want to wait the duration of current audio before reading another sentence.
I'm trying to settimeout while audio duration, i onloadmetadata but it does not work. i think audio.duration work only in onloadedmetadata. when i debug i got the right duration in onloadedmetadata and NaN out of it
Here is what i have done.
Excuse my english
var j = 0, texte = "";
function listen(callback) {
var sentence = texte[j];
if (j < texte.length) {
j++;
} else {
j = 0;
texte = "";
return;
}
callback(sentence, listen);
}
function play (sentence, callback) {
// Play the received speech
googleTTS(sentence, 'fr', 1) // speed normal = 1 (default), slow = 0.24
.then(function (url) {
console.log(url); // https://translate.google.com/translate_tts?...
var audio = new Audio(url);
var duration;
audio.onloadedmetadata = function(){
duration = audio.duration;
}
audio.play();
setTimeout(function(){
callback(play);
}, duration);
});
}

Try adding and ended event handler to your audio object:
audio.addEventListener('ended', function() {
callback(play);
});
audio.play();
This event will trigger when the current audio has finished playing.

audio.play() probably doesn't pause to load metadata. That's why the callback is there. Therefore duration isn't being set before you're calling setTimeout.
Instead of
var duration;
audio.onloadedmetadata = function(){
duration = audio.duration;
}
audio.play();
setTimeout(function(){
callback(play);
}, duration);
Try
var duration;
audio.onloadedmetadata = function(){
duration = audio.duration;
setTimeout(function(){
callback(play);
}, duration);
}
audio.play();

Related

Run the function only once if its been called 50 times in 1 second

This is the function and what is does, is playing a sound when new order is coming. So there be 50 orders coming all at once, now it play the sound 50 times, where only 1 time is enough. Any idea how I can achieve this?
function playSound() {
var audio = new Audio('/audio/short_notification.mp3');
audio.play()
}
Found some similar questions but they did not provide a much of help on this.
Use setTimeout function to reset variable that controls the audio play.
let isPlaying = true;
const silentTimeOutCounter = 1000;
function playSound() {
if(isPlaying){
var audio = new Audio('/audio/short_notification.mp3');
audio.play();
isPlaying = false;
setTimeout(() => {isPlaying = true;} ,silentTimeOutCounter);
}
}
playSound();
You can set timer and check if the function was called in the last second.
let timer = 0;
function playSound() {
if (Date.now() - timer < 1000) return;
timer = Date.now();
var audio = new Audio('/audio/short_notification.mp3');
audio.play();
}
You can use a global variable var to check if it is played once.
var isPlayedOnce = false;
function playSound() {
if(!isPlayedOnce){
var audio = new Audio('/audio/short_notification.mp3');
audio.play();
isPlayedOnce = true;
}
}

Shuffle song when it ends - javascript html5

I have this code that randomizes and play a song from a list of them:
var sounds = [
"sounds/royksopp.mp3",
"sounds/9thwonder.mp3",
"sounds/thisbeat.mp3",
"sounds/mosdef.mp3",
"sounds/bewater.mp3",
"sounds/boutdre.mp3",
"sounds/masterflash.mp3",
"sounds/2ep.mp3",
"sounds/drewestcoast.mp3",
"sounds/poetry.mp3",
"sounds/mfdoom.mp3",
"sounds/dreams.mp3",
"sounds/oizo.mp3", ];
function StartOrStop(audioFile) {
srcAudio = sounds[Math.floor(Math.random() * sounds.length)];
var audie = document.getElementById("myAudio");
audie.addEventListener('ended', function() {
this.currentTime = 0;
this.play();
}, false);
if (audie.paused == false) {
audie.pause();
} else {
audie.src = srcAudio;
audie.play();
}
}
When the song stops playing, it restarts with th same one. How can I make it so when the music ends, it will grab a new song from my list and automatically play it?
The problem is that you are simply calling this.play() in your ended event listener. Instead, you should be updating the src attribute with the random choice of song with this.src = srcAudio, similar to how you are for the initial selection:
function StartOrStop(audioFile) {
srcAudio = sounds[Math.floor(Math.random() * sounds.length)];
var audie = document.getElementById("myAudio");
audie.addEventListener('ended', function() {
this.currentTime = 0;
this.src = srcAudio;
this.play();
}, false);
if (audie.paused == false) {
audie.pause();
} else {
audie.src = srcAudio;
audie.play();
}
}
Hope this helps! :)

Change the sound in WebAudioAPI with no user interaction on iOS

I'm using this function to create a sound, which works well on desktop and Android, and works initially on iOS when I use a touchevent to start it. I need to later replace the sound with another sound file, however on iOS it doesn't start - I'm assuming because it needs another user interaction to play the sound.
This is a VR app in a headset so this kind of user interaction isn't possible. Is there another way of replacing the sound or another non-click user interaction I can use like movement?
I've seen this http://matt-harrison.com/perfect-web-audio-on-ios-devices-with-the-web-audio-api/
Which seems to have another solution, but I don't want to pre-load all of the files (they're reasonably big and there's 10 of them) which seems to be a requirement here - plus I use the pause function in the code I have. Are there any easy ways round this?
var AudioContext = AudioContext || webkitAudioContext, context = new AudioContext();
function createSound(filename) {
console.log('createSound()');
var url = cdnPrefix + '/' + filename;
var buffer;
context = new AudioContext();
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
// Decode asynchronously
request.onload = function() {
context.decodeAudioData(request.response, function(b) {
buffer = b;
play();
});
}
request.send();
var sourceNode = null,
startedAt = 0,
pausedAt = 0,
playing = false,
volume = context.createGain();
var play = function() {
if(playing || !buffer)
return;
var offset = pausedAt;
sourceNode = context.createBufferSource();
sourceNode.connect(context.destination);
sourceNode.connect(volume);
volume.gain.value = 1;
sourceNode.buffer = buffer;
sourceNode.start(0, offset);
sourceNode.onended = onEnded;
sourceNode.onstatechange = onStateChange;
sourceNode.onloaded = onLoaded;
//sourceNode.loop = true;
startedAt = context.currentTime - offset;
pausedAt = 0;
playing = true;
$(document).trigger("voiceoverPlay");
if(isPaused == true)
pause();
};
function onEnded(event){
$(document).trigger("voiceoverEnded");
play();
}
function onStateChange(event){
console.log('onStateChange',event);
}
function onLoaded(event){
console.log('onLoaded',event);
}
var pause = function() {
var elapsed = context.currentTime - startedAt;
stop();
pausedAt = elapsed;
$(document).trigger("voiceoverPause");
};
var stop = function() {
if (sourceNode) {
sourceNode.disconnect();
if(playing === true)
sourceNode.stop(0);
sourceNode = null;
}
pausedAt = 0;
startedAt = 0;
playing = false;
};
var getPlaying = function() {
return playing;
};
var getCurrentTime = function() {
if(pausedAt) {
return pausedAt;
}
if(startedAt) {
return context.currentTime - startedAt;
}
return 0;
};
var setCurrentTime = function(time) {
pausedAt = time;
};
var getDuration = function() {
return buffer.duration;
};
return {
getCurrentTime: getCurrentTime,
setCurrentTime: setCurrentTime,
getDuration: getDuration,
getPlaying: getPlaying,
play: play,
pause: pause,
stop: stop
};
}
You need a touch event for each sound.
I ended up using SoundJS which is much better.

Stop setInterval until action not performed?

Is it possible that we could stop setInterval means next interval will call only when first event completed.
I want to load next image only when previous image loaded.This event should work only after mouse over.But if next image is large in size then next interval is calling in my case..i want to stop interval until last image not loaded.
This is my code:
jQuery('.product').on('mouseover', function(){
timer = setInterval(function() {
if (counter === product_images.length) {
counter = 0;
}
// selector.addClass('hidden');
loading_image.removeClass('hidden');
selector.attr('src', 'localhost/product/' + product_images[counter]);
var loadImage = new Image();
loadImage.src = selector.attr('src');
loadImage.onload = function() {console.log('after load');
loading_image.addClass('hidden');
// selector.removeClass('hidden');
selector.show();
};
counter = counter + 1;
}, 1000);
How we can stop setInterval or prevent it to go next interval even task of last interval is not completed.Not for clearInterval,It should be continue(setInterval) if first task completed.
Please help me.
try the below code. this may work,
var flag = 1;
jQuery('.product').on('mouseover', function(){
if(typeof timer != "undefined")
clearInterval(timer);
timer = setInterval(function() {
if(flag){
if (counter === product_images.length) {
counter = 0;
}
loading_image.removeClass('hidden');
selector.attr('src', 'localhost/product/' + product_images[counter]);
flag = 0;
var loadImage = new Image();
loadImage.src = selector.attr('src');
loadImage.onload = function() {
console.log('after load');
loading_image.addClass('hidden');
selector.show();
flag = 1;
};
counter = counter + 1;
}
}, 1000);
NOTE: I have not tested this code.

play sound & run timer using jquery

i try to play sound with the below code, but it does not play sound, so i feel sad and finally felt to ask here for your help.
Script
$(function() {
$('#btn_start').on('click', function(event){
event.preventDefault();
play_sound('mp3');
return false;
});
//------------------------
function play_sound(sound)
{
// This next line will get the audio element
// that is adjacent to the link that was clicked.
var song = $(this).next('audio').get(0);
if (song.paused)
song.play();
else
song.pause();
}
});
I suggest you to create a little class like this :
The duration cannot be get in Javascript (actually not implemented on every browsers, you must set this value for each "songs")
Fiddle: http://jsfiddle.net/XYevE/4/
(nota: this is just an example, developped very fast...:))
HTML:
PLAY
<div id="timer"><span>click play</span></div>
<div id="ms">
Before callback:
<span id="mins"></span>:
<span id="secs"></span>
</div>
<audio id="audiosource">
<source src="http://www.cumfortitudine.com/vvdemo/assets/js/actions/vquery.vdemo/scenes/assets/sound/hans-zimmer-injection.mp3" type="audio/mpeg" />
</audio>
Javascript:
function myApp() {
this.paused = false;
this.paused = true // set pause to true (stop)
this.isactive = false; // countdown is active
this.duration = 0; // set duration to 0 (get via audio DOM)
return this.observer(); // call and return the "observer" method of the "myApp" class
}
myApp.prototype.observer = function() { // observer method
var self = this; // set this to self (this is the current instance of this class)
$('#btn_start').on('click', function(event){ // where an user click on "btn_start"
event.preventDefault();
self.play('mp3'); // call the play method and store the state in a public var
self.countdown(self.onEnd); //parameter is the callback when the audio is finished
self.isactive = true;
});
return this; // return this instance
};
myApp.prototype.play = function() { // play method
var song = document.getElementById('audiosource');
this.duration = song.duration;
if (this.paused === true)
{
$('#btn_start').html('PAUSE');
console.log('set play song');
song.play();
this.paused = false;
}
else
{
$('#btn_start').html('PLAY');
console.log('set pause song');
song.pause();
this.paused = true;
}
return this;
};
myApp.prototype.countdown = function(duration, callback) { // countdown method
var self = this, // class instance
countdown = null, // countdown
ctx = null; // setIntervall clearer
timer = this.duration * 1000; // timer in milliseconds
if (this.isactive === true) // if this method yet called
{
return false;
}
countdown = function() {
if (timer <= 0)
{
self.isactive = false; // reset
clearInterval(ctx);
callback.call(this);
return false;
}
if (self.paused === false) // if not in pause
{
timer -= 250;
var mins = parseInt((timer / 1000) / 60);
var secs = parseInt((timer / 1000) - mins * 60);
$('#mins').html(mins);
$('#secs').html(secs);
$('#timer > span').html(timer.toFixed(2));
}
};
ctx = setInterval(countdown, 250);
};
myApp.prototype.onEnd = function() {
// when the audio is finish..
alert ('end of the song');
};
;$(function() {
new myApp();
});

Categories