Need simplified function for onclick button sounds - javascript

This is my first question here sorry if I make any mistake.
I want to know how to simplify an action (function), I have a drumkit with different buttons and sounds, I'm using this code: FIDDLE
JS
function play() {
var audio = document.getElementById('audio1');
if (audio.paused) {
audio.play();
} else {
audio.currentTime = 0
}
}
How can I write just one function and play different sounds for every button?

You could try firing multiple functions from one function. Something like:
<button onClick="play()">song1</button>
<button onClick="play()">song2</button>
<button onClick="play()">song3</button>
function someFunc() {
function audioOne() {
var audio = document.getElementById('audio1');
if (audio.paused) {
audio.play();
}
else{
audio.currentTime = 0
};
function audioTwo() {
var audio = document.getElementById('audio2');
if (audio.paused) {
audio.play();
}
else{
audio.currentTime = 0
};
function audioThree() {
var audio = document.getElementById('audio3');
if (audio.paused) {
audio.play();
}
else{
audio.currentTime = 0
};
}
Alternatively you could also try something like:
var audio = document.getElementById("id");
audio.addEventListener("click", function(){alert("audio1 triggered")}, false);
audio.addEventListener("click", function(){alert("audio2 triggered")}, false);

function play(id) {
var audio = document.getElementById(id);
if (audio.paused) {
audio.play();
}else{
audio.currentTime = 0
}
call it like this:
play('audio1');
play('audio2');
If i understand your question correctly this should work for your use-case. You basically just pass the elements id as parameter. Everytime you call the function the logic will apply to the element you specified as parameter in your function call.

Related

call function (audio playing) in order

I hava a function that playing audios in order. But there may be a case where the function is called almost at the same time, and all audios playing is mixed. How can I call the same function where audios order of the second call is played after the audios order of the first call.
function playSound() {
$('#content').append('<audio id="ding" src="ding.wav" preload="auto"></audio>');
$('#ding')[0].play();
$('#ding')[0].onended = function() {
$('#content').append('<audio id="number" src="sound/voice/number.wav" preload="auto"></audio>');
$('#number')[0].play();
$('#number')[0].onended = function() {
$('#content').append('<audio id="goToCounter" src="sound/voice/goToCounter.wav" preload="auto"></audio>');
$('#goToCounter')[0].play();
}
}
}
One possible way is to have a counter that counts the number of times the playSound function is called. If it is still in the middle of playing sounds, increase the counter, but return from the function. Only after the playing of the three sounds is finished, you call playSound again if there are still calls in the queue.
var numberOfTimesAudioHasStarted = 0;
function playSound(buttonClicked) {
if(buttonClicked === true){
numberOfTimesAudioHasStarted++;
}
if(numberOfTimesAudioHasStarted > 1 && buttonClicked === true){
return;
}
$('#content').append(
'<audio id="ding" src="https://thumbs.dreamstime.com/audiothumb_22779/227796222.mp3" preload="auto"></audio>');
$('#ding')[0].play();
$('#ding')[0].onended = function() {
$('#content')
.append(
'<audio id="number" src="https://thumbs.dreamstime.com/audiothumb_22779/227796222.mp3" preload="auto"></audio>');
$('#number')[0].play();
$('#number')[0].onended = function() {
$('#content')
.append(
'<audio id="goToCounter" src="https://thumbs.dreamstime.com/audiothumb_11413/114136296.mp3" preload="auto"></audio>');
$('#goToCounter')[0].play();
$('#goToCounter')[0].onended = function() {
numberOfTimesAudioHasStarted--;
if(numberOfTimesAudioHasStarted > 0){
playSound(false);
}
}
}
}
}
$('button').click(function() {
playSound(true);
});
<div id="content"></div>
<button>play</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Note that this function keeps adding audio elements to the page every time the function runs. This is bad practice, since no two elements with the same id should be present on a page.

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

How to play more video on the same player with Vimeo player.js

I'm trying to play videos one after the other in the same Vimeo player, without success.
This is the code I'm working on. I can't find any example on how to do that.
I'm sure I'm wrong but I don't know how to go further...
var iframe = document.querySelector('iframe.main-player');
var player = new Vimeo.Player(iframe);
var video_ids = ['123456789', '987654321'];
video_ids.forEach(function(item, index) {
player.pause();
player.loadVideo(item);
player.on('loaded', function() {
player.play();
});
})
I'm not sure about this, because can't test it right now , but you can try something like this:
var iframe = document.querySelector('iframe.main-player');
var player = new Vimeo.Player(iframe);
var video_ids = ['123456789', '987654321'];
var index = 0;
var playNext = function(data){
player.pause();
if(index<=video_ids.length)
player.loadVideo(video_ids[index++])
}
player.pause();
player.loadVideo(video_ids[index++]);
player.on('loaded', function() {
player.play();
});
player.on('ended', playNext);
The idea is pretty simple by listen to the ended event then moving to the next item.
First of all, we just create a class to hold some information such as the list & current playing index:
import Player from "#vimeo/player";
class Playlist {
constructor(playlist) {
this.playlist = playlist;
this.currentIdx = 0;
}
init() {
this.player = new Player("app", {
id: this.currentItem,
width: 640
});
this.player.on("ended", this.onEnded.bind(this));
}
onEnded() {
if (this.currentIdx < this.playlist.length) {
this.currentIdx++;
const nextId = this.currentItem;
this.player.loadVideo(nextId);
// Check next item has loaded then play it automatically
// you might not receive any error in case of having to interact with document
this.player.on("loaded", () => {
this.player.play();
});
}
}
get currentItem() {
return this.playlist[this.currentIdx];
}
}
// Try to run 2 items
const pl = new Playlist([59777392, 28582484]);
pl.init();
NOTE: I also created a codesandbox link for you here https://codesandbox.io/s/focused-firefly-ej0fd?file=/src/index.js

Clicking multiple time on Button, Multiple audio play (Older sounds overlap new) in JavaScript

When I click on button, audio start. But when I click the button multiple times, multiple audio playing simultaneously.
HTML CODE
<button id = 'bt'> Click Me </button>
JavaScript Code
<script type="text/javascript">
url = 'song.mp3';
var btn =document.getElementById('bt');
btn.addEventListener('click', function(){
var audioElement = document.createElement('audio');
audioElement.setAttribute('src', url);
playFunc(my, 3);
});
function PlayFunc(target, RepeatCount) {
var soundFunc = function(){
RepeatCount--;
target.currentTime = 0;
if (RepeatCount>0)
target.play();
else
target.removeEventListener('ended', soundFunc);
}
target.addEventListener('ended', soundFunc)
target.play();
}
</script>
What I'm thinking as solution-
Before creating new click event, destroy last event fist then create new one.
When user click second, it check if cureentTime == 0, then play audio else start again or nothing happen.
Thanks to Gurpreet, your solution work.
On each click I'm creating a new audio element thats why multiple audio are playing.
Simply I saved my audio to a variable and passed to playFunc.
url = 'song.mp3'
const myAudio = new Audio(url);
var btn =document.getElementById('bt');
btn.addEventListener('click', function(){
playFunc(myAudio, 3);
});
function PlayFunc(target, RepeatCount) {
var soundFunc = function(){
RepeatCount--;
target.currentTime = 0;
if (RepeatCount>0)
target.play();
else
target.removeEventListener('ended', soundFunc);
}
target.addEventListener('ended', soundFunc)
target.play();
}
Just de-register the click event handler in the click event handler. In order to do this, you'll need a named function.
btn.addEventListener('click', doPlay);
function doPlay(){
var audioElement = document.createElement('audio');
audioElement.setAttribute('src', url);
playFunc(audioElement, 3);
btn.removeEventListener('click', doPlay); // <-- de-register the handler
}
You can disable the button until the audio clip is over.
const url = 'http://www.noiseaddicts.com/samples_1w72b820/4927.mp3';
const my = new Audio(url);
var btn =document.getElementById('bt');
btn.addEventListener('click', function(){
var audioElement = document.createElement('audio');
audioElement.setAttribute('src', url);
playFunc(audioElement, 3);
});
function playFunc(target, RepeatCount) {
btn.disabled=true;
var soundFunc = function(){
RepeatCount--;
target.currentTime = 0;
if (RepeatCount>0)
target.play();
else{
target.removeEventListener('ended', soundFunc);
btn.disabled=false;
}
}
target.addEventListener('ended', soundFunc)
target.play();
}

How can I detect whether my audio stream is: playing, paused or finished?

I'm working on an online radio website and am trying to detect what state the audio player is currently in for the user.
The current setup I've got is often wrong in knowing this and if I'm on iOS and I pause from the lock screen player instead, it will still think it's playing because I never clicked the html pause button.
Finally how is it possible to detect when my stream has fully ended. I've tried: onstalled="", onwaiting="", onerror="", onended="". But none of them work 100% of the time. The closest one to work would be: onstalled="", but even that only had a 60% success rate or so (occasionally when I'm loading the site it would tell me it has ended).
HTML:
<audio autoplay="" id="player" title="" oncanplay="radioLoaded()">
<source src="...">
</audio>
Javascript:
function radioLoaded() {
if (player.paused) {
document.getElementById('radioplaypause').innerHTML = varRadioResume;
} else if (player.play) {
document.getElementById('radioplaypause').innerHTML = varRadioPause;
} else {
document.getElementById('radioplaypause').innerHTML = varRadioLoading;
}
window.player = document.getElementById('player');
document.getElementById('radioplaypause').onclick = function () {
if (player.paused) {
player.play();
this.innerHTML = varRadioPause;
} else {
player.pause();
this.innerHTML = varRadioResume;
}
}
};
function radioEnded() {
document.getElementById('radiolivetext').innerHTML = 'OFFLINE';
document.getElementById('radioplayer').style.display = 'none';
document.getElementById('radioinformation').style.display = 'none';
};
Try this, with some corrections/notes to the code in general:
function radioLoaded() {
// move this line to the top
window.player = document.getElementById('player'); // !!! <-- name too generic, possibility of global collisions
var playPauseButton = document.getElementById('radioplaypause');
if (player.paused) {
playPauseButton.innerHTML = varRadioResume;
} else if (player.play) {
playPauseButton.innerHTML = varRadioPause;
} else {
playPauseButton.innerHTML = varRadioLoading;
}
playPauseButton.onclick = function () {
if (player.paused) {
player.play();
this.innerHTML = varRadioPause;
} else {
player.pause();
this.innerHTML = varRadioResume;
}
};
player.onended = function () {
console.log('ended');
};
// other helpful events
player.onpause = function () {
console.log('paused...');
}
player.onplay = function () {
console.log('playing...');
}
player.onprogress = function (e) {
console.log(e.loaded + ' of ' + e.total + ' loaded');
}
};

Categories

Resources