I have a problem that i want to have a button, that plays random sound after I press it, but the other thing is that i want to spam the button and so does the sound. What I mean is that i dont want to wait for the sound to finish to play it again and like have 5 sounds or more playing depending on your click speed.
for(var i=0;i<1;i++)
{
document.getElementById("MyAudio.mp3")[i].addEventListener("click",function(){});
}
function playAudio()
{
var audio = new Audio("MyAudio.mp3");
audio.play();
}
<button onlick="playAudio()"></button>
That sounds fun and there's many ways to do it. I think the easiest way would be to pre-load the songs ahead of time and randomize it.
// Your sounds
let sounds = [new Audio('https://download.samplelib.com/mp3/sample-3s.mp3'), new Audio('https://download.samplelib.com/mp3/sample-6s.mp3'), new Audio('https://www.soundjay.com/human/fart-01.mp3')];
let lastSound = 0; // Not necessary but we don't want overlapping tracks.
// Listen for click on button (ID soundmachine)
// pointerdown is more suitable so adjusted it.
document.querySelector("#soundmachine1").addEventListener("pointerdown", () => {
// This is a small fix to allow the sound to be spammable and clear last track.
sounds[lastSound].pause();
sounds[lastSound].currentTime = 0;
let random = Math.floor(Math.random() * sounds.length);
sounds[random].play();
lastSound = random; // For the next click we want to cancel this sound if it's playing.
console.log(lastSound); // Just so you can see it count/play
});
document.querySelector("#soundmachine2").addEventListener("pointerdown", () => {
// Play till completed
let random = Math.floor(Math.random() * sounds.length);
sounds[random].play();
});
<button id="soundmachine1">click me ver1</div>
<button id="soundmachine2">click me ver2</div>
Something like this!
There's some odd things going on with this code, so let's rethink it from the beginning. First of all, you want to create an onclick handler on your button that plays your mp3 file. Let's do that first:
let audio = new Audio("MyAudio.mp3");
document.querySelector("button").addEventListener("click", () => {
audio.play()
});
Now, it sounds like you want it to play from the beginning every time when clicked, and not wait till it completes (which is the default behavior). So we need to reset the playback every time you click.
let audio = new Audio("MyAudio.mp3");
document.querySelector("button").addEventListener("click", () => {
audio.currentTime = 0;
audio.play();
});
🎉 🎶
And your HTML can just look like this:
<button>Play</button>
Related
I have function running every second (for clock) .
I wanted to add sound to every tick tick....(second) but as function is running automatic (means no triggering is taking place) and when sound added produces an error
Error showing is :
Uncaught DOMException: play() failed because the user didn't interact with the document first.
Know that it is not possible to play audio automatic .
So tried to create a start sound btn which play the audio but as second time (of clock) and don't match with audio . So there is a mismatch
I am trying to add that function(audio play) inside second(clock time) calculator .
Is this possible or not
Link to similar question but not able to find the solution
The code is as follows
setInterval(clockRunner, 1000);
function clockRunner() {
//Clock code goes here
function trigger() {
var audioElement = document.getElementById('audiotag1');
audioElement.play();
}
}
<audio id="audiotag1" src="https://soundbible.com/mp3/Tick-DeepFrozenApps-397275646.mp3" preload="metadata" controls></audio>
<button onclick="trigger()">Start</button>
Update
Added event listener inside the outer function but this way sound is playing once not every second .
One solution here can be adding another setInterval but this will again create problem of playing sound at different timing of clock's second
Also it shows the same error in the console(mentioned above) until user clicks the btn
setInterval(clockRunner, 1000);
function clockRunner() {
//Clock code goes here
document.getElementById('demo').innerHTML = new Date();
setInterval(trigger, 1000);
document.getElementById("triggerSnd").addEventListener('click', trigger)
function trigger() {
var audioElement = document.getElementById('audiotag1');
audioElement.play();
}
}
<audio id="audiotag1" src="https://soundbible.com/mp3/Tick-DeepFrozenApps-397275646.mp3" preload="metadata" controls></audio>
<button id="triggerSnd">Start</button>
<div id="demo"></div>
Thanks for help in advance
If you make use of some variables, you can control your code to perform like a clock. It's worth noting that there are two possibilities, either the clock has started or it has stopped.
The interval will run when you clicked to start and it will be cleared in stopping it. Here I can't notice any mismatch between the sound and the timer.
var start = document.getElementById("triggerSnd")
var audioElement = document.getElementById('audiotag1')
var demo = document.getElementById('demo')
var interval, isMuted = true
// The second argument of addEventListener should be a function
// that receives an argument 'event'
clockRunner();
clock(); // call firstly
setInterval(() => clock(), 1000)
start.addEventListener('click', clockRunner)
function clock(isMuted){
//Clock code goes here
demo.innerText = new Date();
audioElement.play();
}
function clockRunner() {
audioElement.muted = isMuted
start.innerText = isMuted ? "Start" : "Stop"
isMuted = !isMuted
}
<audio id="audiotag1" src="https://soundbible.com/mp3/Tick-DeepFrozenApps-397275646.mp3" preload="metadata"></audio>
<button id="triggerSnd">Start</button>
<div id="demo"></div>
I've changed my answer completely. Now I didn't need to use an event listener, just the proper API of HTMLMediaElement that audio uses. Note that I've add loop attribute to tick's audio.
var blast = document.getElementById("blast");
var tick = document.getElementById("tick");
var tickDuration, timeDiff, lastTime
tick.onloadedmetadata = () => tickDuration = tick.duration
timeDiff = 0.3 // max difference between sync, dont lower it or it will bug (can explain if u want)
lastTime = 0
blast.addEventListener("timeupdate", () => {
let bct = blast.currentTime
let tct = tick.currentTime
let syncBlastTime = tickDuration - (tickDuration - bct%tickDuration)
let diff = Math.abs(syncBlastTime - tct)
lastTime = bct
console.log(`Blast: ${bct} Tick: ${tct}\nSynced time difference (seconds): ${diff.toFixed(6)}`)
if(diff > timeDiff) { // add this or it will bug the tick audio
tick.currentTime = syncBlastTime
}
})
blast.addEventListener("pause", () => {
tick.pause()
})
blast.addEventListener("playing", () => {
tick.play()
})
<audio id="blast" src="http://stream.arrowcaz.nl/caz64kmp3" controls="loop"></audio>
<audio id="tick" src="https://soundbible.com/mp3/A-Z_Vocalized-Mike_Koenig-197996831.mp3" loop controls='loop'></audio>
<br />
I built a simple matching game and added audio files for several cards like this:
cardList.map((cardItem) => {
var card = document.createElement("li");
card.classList.add("card");
var img = document.createElement("img");
img.src = [cardItem.img]
card.appendChild(img);
//audio starting here
audio = new Audio(cardItem.sound);
card.appendChild(audio);
audio.id += ' ' + cardItem.card;
deck.append(card);
card.className += ' ' + cardItem.name;
});
}
And in my startGame() function I added an eventListener to add audio.play(); on click.
So now, when I open dev tools, I can see audio elements for my cards but when I try and click on them, I'm only ever getting one audio file for all cards and not the audios I actually added to that specific element.
That's my GitHub file: https://github.com/cMikolai/guitar-colour-system-game/blob/master/js/app.js
Could anybody try and help me figure out how I could play the sound I added to the card I am clicking on?
I downloaded your code and played around. The code for playing audio is in the function startGame() in your app.js file.
app.js:
audio = []; // local variable declaration
...
...
// some code
function startGame() {
// some code
for (var i = 0; i < clickedCard.length; i++) {
clickedCard[i].addEventListener("click", function( event ) {
this.classList.add("open", "show");
openCards.push(this.getAttribute("class"));
audio.load();
audio.play(); // this is the line playing the audio
matchCards();
starRating();
}, false);
}
}
As you can see, you are not playing audio from the selected card but from the local variable audio.
So, you have to identify the selected card and play its respective audio instead of playing audio from the local variable.
I want to play a random song in a website. The tunes are short (max a few seconds, they don't need preload or buffering).
This part works, the number of songs may be unlimited, because tunes.length automatically counts all songs.
document.write displays the URL of a random song URL on the screen
tunes = new Array(
'"http://example.net/abcd.ogg"',
'"http://example.net/efgh.ogg"',
'"http://example.net/ijkl.ogg"'
)
var audiopath = (tunes[Math.floor(Math.random() * tunes.length)])
document.write (audiopath)
This part works too, when the URL is defined as a constant.
var song = new audio('http://example.net/abcd.ogg');
song.play();
When I try to replace the constant URL with the variable audiopath, it fails to play.
May it be anything wrong with the syntax?
I tried to run it with and without single quotes in the URL '"http://example.net/ijkl.ogg"' or "http://example.net/ijkl.ogg"
var song = new audio(audiopath);
song.play();
It might be better to handle starting playback once the song has fully loaded. Something like this:
let loaded = false;
const song = new Audio();
song.addEventListener('loadeddata', function()
{
loaded = true;
song.play();
}, false);
song.addEventListener('error' , function()
{
alert('error loading audio');
}, false);
song.src = tunes[Math.floor(Math.random() * tunes.length)];
Note: Exactly this has been asked before here, and here, without satisfactory answers.
I'll try to explain the problem better here, and you can also read TLDR below. Here's a simple fiddle I created using Soundcloud JS sdk v3. I define global variables playerGlobal and playingId. During the first play, both of them are null, and clicking one of play or playNext buttons initializes those variables. Suppose, we click play first, the related track starts playing. When we click pause button soon after, pause() fires and uses the globalPlayer to pause the currently playing track. This works as expected.
When I click playNext, both global variables are updated as they should. The problem arises when I click play again. For some strange reasons, the track associated with play button plays from time starting at when I clicked pause above. When I click pauseagain, nothing happens.
TLDR: Click play -> pause -> playNext(works fine till here) -> play(strange remembering of last position happens) -> pause(nothing happens).
I'm including the snippet here as well.
SC.initialize({
client_id: 'MmZKx4l7fDwXdlL3KJZBiJZ8fLonINga'
});
//Get player
function getPlayer(url) {
return new Promise(function(resolve, reject) {
SC.stream(url)
.then(player => {
if (player.options.protocols[0] === 'rtmp')
player.options.protocols.splice(0, 1);
resolve(player);
});
});
}
//Global players and id to track current playing track
var playerGlobal = null;
var playingId = null;
function play() {
var id = '1';
//Resume playing if the same song is hit
if (playerGlobal !== null && id === playingId) {
console.log("-- using old player");
playerGlobal.play();
return;
}
//New player on a new song
var url = '/tracks/309689093';
getPlayer(url)
.then(player => {
if (playerGlobal) playerGlobal = null;
playerGlobal = player;
console.log("-- new player created");
playerGlobal.play();
playingId = id;
});
}
function pause() {
playerGlobal.pause();
}
function playNext() {
var id = '2';
//Resume playing if the same song is hit
if (playerGlobal !== null && id === playingId) {
console.log("-- using old player");
playerGlobal.play();
return;
}
//New player on a new song
var url = "/tracks/309689082";
getPlayer(url)
.then(player => {
if (playerGlobal) playerGlobal = null;
playerGlobal = player;
console.log("-- new player created");
playerGlobal.play();
playingId = '2';
});
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<button onClick="play()">play</button>
<button onClick="pause()">pause</button>
<button onClick="playNext()">playNext</button>
<script src="https://connect.soundcloud.com/sdk/sdk-3.1.2.js"></script>
</body>
</html>
I'm not sure why this wouldn't work. One of the ways I was able to make this work was by defining separate player, pause and id variables for both tracks. And then when a track is played after another, I set seek to position 0. Here's it. The problem of course is, this is just for reference, my use case involves many more tracks, and I didn't want to define separate variables for them all, until I'm sure why above code doesn't work and that it is the only way. Any hints are appreciated.
I'm tring to provide audio feed back on a button using html5 audio.
It works fine when clicking slowly, but when clicking the button faster it misses some of the clicks.
http://jsfiddle.net/sWsTb/
HTML
<div id="count">0</div>
<button>Click</button>
JS
var snd = new Audio("https://dl.dropbox.com/u/14037764/Development/jsfiddle/click2.mp3");
var count = 0;
$("button").click(function () {
snd.pause();
snd.currentTime = 0;
snd.play();
count++;
$("#count").text(count);
return false;
});
After adding snd.pause(); and snd.currentTime = 0; lines, it's better but still misses some of the fast clicks. Is there any way to fix that?