How to play a group of wav files with javascript - javascript

Let's say I have an Html file that look like this:
<div name="piano">
<div name="a.wav"></div>
<div name="b.wav"></div>
<div name="c.wav"></div>
</div>
How would I play all the .wav files mentioned in the piano div simultaneously (when a button is pressed)?
Edit: For clarification, eventually the user will be able to select what notes are played and at what time. This is just a simplified example.

The normal audio element (<audio> or new Audio()) is not appropriate for this use case, as it leaves no method for precise timing. You need to use the Web Audio API.
Use a BufferSourceNode for each note you want to play:
const buffer = await audioContext.decodeAudioData(... audio data ...);
const bufferSourceNode = audioContext.createBufferSource();
bufferSourceNode.buffer = buffer;
bufferSourceNode.connect(audioContext.destination);
bufferSourceNode.start(/* you can use a start time here */);
See also:
JSFiddle I made for a mini sampler: https://jsfiddle.net/bradisbell/sc9jpxvn/1/
AudioBufferSourceNode documentation: https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode

If you would like to play it randomly use:
<audio src="..." id="song1"></audio>
<audio src="..." id="song2"></audio>
<audio src="..." id="song2"></audio>
for(var i = 1; i <= 3; i++){
document.querySelector("#song" + i)[0].play();
}

With html5, you should use the <audio> tag. It have javascript hooks for 'play', 'pause', etc.
You can add the following html;
<button onclick="playA();playB();playC()">Play Audio</button>
with corresponding javascript
var audioA = new Audio('a.wav');
var audioB = new Audio('b.wav');
var audioC = new Audio('c.wav');
function playA() {
audioA.play();
}
function playB() {
audioB.play();
}
function playC() {
audioC.play();
}

Related

I can't make a new Audio(url).play() to stop by new Audio(url).pause()

What I want to achieve: To stop a previously started sound when a new is started. What I have now: The sounds plays simultanously, none of them is stopping. The probably reason: Wrong logic statement in a line if (audio.played && audio.paused){. Before you judge me for not trying hard enough - I am trying to solve this from 3 days, I am a beginner. It should take me a few minutes, even an hour. I tried in several combinations.At the end I listed several websites which I tried and I still haven't solved it. In all answers is something similar but still I can't made a browser to chose, always only one part is executed either audio.play() or audio.pause() in the log. It works but not as I want and these logical statements are like on other informations on the forum. At the end of the message you can see all similar topics I already tried several times. I kept just as clear code as possible and I want to do it this way, in vanilla javascript because I won't deal for now with anything more complicated. An audio url is taken from modified id on click, the audios are on my disk. It works, I made some mistake in line if (audio.played && audio.paused){ Any ideas except giving up and changing a hobby?
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Timeout</title>
</head>
<script>
function playAudio3(clicked_id) {
var OriginalID = (clicked_id);
var res = OriginalID.slice(5,-1);
var audioID=res+'.mp3';
var url =audioID;
var audio = new Audio(url);
if (audio.played && audio.paused){
audio.play();
console.log('audio.play was used.');
}else {
audio.currentTime = 0
audio.pause();
console.log('audio.pause was used.');
}
}
</script>
<body>
<span id="guita2x"onclick="playAudio3(this.id);"> Guitar. </span>
<span id="piano2x" onclick="playAudio3(this.id);"> Piano. </span>
<span id="basse15x" onclick="playAudio3(this.id);"> Basse. </span>
</body>
</html>
how do i stop a sound when a key is released in JavaScript
Javascript Audio Play on click
Javascript to stop playing sound when another starts
HTML5 Audio stop function
cancel an if statement if another statement comes true
Stopping audio when another audio file is clicked using jQuery while obscuring link
https://www.w3schools.com/jsref/dom_obj_audio.asp
HTML5 Audio pause not working
Never give up, and don't change a hobby. :)
Possible solution from one hobbyist, too:
files = ['guitar', 'piano', 'bass']; // name of your files in array. You can get this array from looping through your html/spans id's too, but, this is basic logic
audios = []; //empty audios object array
for (i = 0; i < files.length; i++) {
var audioID = files[i] + '.mp3';
var url = audioID;
var audio = new Audio(url);
audios.push(audio); //place all audio objects into array
}
console.log(audios);
//now - basic logic to check which audio element to play, and to stop others
function playAudio3(clicked_id) {
for (i = 0; i < audios.length; i++) {
if (audios[i].src.includes(clicked_id)) {
audios[i].play();
} else {
audios[i].currentTime = 0
audios[i].pause();
}
}
}
So, you are creating all audio objects at the page load, and then choose which one to play. Of course, this will play all audio files from the start. If you want to keep the track of the audio progress, and play it from the last pause, you will need some additions, but, this could be the start, i hope.
OK, updated, i kept some of your code, and slightly changed some things in HTML.
Your complete code now should look like this: (HTML)
<span class='aud' id="guita1x" onclick="playAudio3(this.id);"> Guitar. </span>
<span class='aud' id="piano2x" onclick="playAudio3(this.id);"> Piano. </span>
<span class='aud' id="basse3x" onclick="playAudio3(this.id);"> Basse. </span>
Js:
spans=document.querySelectorAll('.aud');
console.log(spans);
audios = []; //empty audios object array
for (i = 0; i < spans.length; i++) {
var OriginalID = spans[i].id;
var res = OriginalID.slice(5,-1);
var audioID=res+'.mp3';
var url =audioID;
var audio = new Audio(url);
audios.push(audio); //place all audio objects into array
}
console.log(audios);
//now - basic logic to check which audio element to play, and to stop others
function playAudio3(clicked_id) {
for (i = 0; i < audios.length; i++) {
clickid=clicked_id.replace(/[A-Za-z]/g,'')+'.mp3';
if (audios[i].src.includes(clickid)) {
audios[i].play();
} else {
audios[i].currentTime = 0
audios[i].pause();
}
}
}
Now, i have just added class 'aud' to your spans, for easier targeting.
Then, i have collected id's from the spans and placed it in the audios array. (Not sure why you are slicing names/ids, you can simplify things by adding just numbers: 1, 2, 3 and so on).
NOW, this MUST work, IF
you have 3 .mp3 files in the same folder as your html/js file, called: 1.mp3, 2.mp3, 3.mp3.
if you place your javascript bellow HTML, BEFORE closing 'body' tag.

How to force a media to be loaded at run time, without playing it now?

I am making a web app that can be open for a long time. I don't want to load audio at load time (when the HTML gets downloaded and parsed) to make the first load as fast as possible and to spare precious resources for mobile users. Audio is disabled by default.
Putting the audio in CSS or using preload is not appropriate here because I don't want to load it at load time with the rest.
I am searching for the ideal method to load audio at run time, (after a checkbox has been checked, this can be after 20 minutes after opening the app) given a list of audio elements.
The list is already in a variable allSounds. I have the following audio in a webpage (there are more):
<audio preload="none">
<source src="sound1.mp3">
</audio>
I want to keep the same HTML because after second visit I can easily change it to (this works fine with my server-side HTML generation)
<audio preload="auto">
<source src="sound1.mp3">
</audio>
and it works.
Once the option is turned on, I want to load the sounds, but not play them immediately. I know that .play() loads the sounds. But I want to avoid the delay between pressing a button and the associated feedback sound.
It is better to not play sound than delayed (in my app).
I made this event handler to load sounds (it works) but in the chrome console, it says that download was cancelled, and then restarted I don't know exactly what I am doing wrong.
Is this is the correct way to force load sounds? What are the other ways? If possible without changing the HTML.
let loadSounds = function () {
allSounds.forEach(function (sound) {
sound.preload = "auto";
sound.load();
});
loadSounds = function () {}; // Execute once
};
here is playSound function, but not very important for the questions
const playSound = function (sound) {
// PS
/* only plays ready sound to avoid delays between fetching*/
if (!soundEnabled)) {
return;
}
if (sound.readyState < sound.HAVE_ENOUGH_DATA) {
return;
}
sound.play();
};
Side question: Should there be a preload="full" in the HTML spec?
See also:
Preload mp3 file in queue to avoid any delay in playing the next file in queue
how we can Play Audio with text highlight word by word in angularjs
To cache the audio will need to Base64 encode your MP3 files, and start the Base64 encoded MP3 file with data:audio/mpeg;base64,
Then you can pre-load/cache the file with css using something like:
body::after {
content:url(myfile.mp3);
display:none;
}
I think I would just use the preloading functionality without involving audio tag at all...
Example:
var link = document.createElement('link')
link.rel = 'preload'
link.href = 'sound1.mp3'
link.as = 'audio'
link.onload = function() {
// Done loading the mp3
}
document.head.appendChild(link)
I'm quite sure that I've found a solution for you. As far as I'm concerned, your sounds are additional functionality, and are not required for everybody. In that case I would propose to load the sounds using pure javascript, after user has clicked unmute button.
A simple sketch of solution is:
window.addEventListener('load', function(event) {
var audioloaded = false;
var audioobject = null;
// Load audio on first click
document.getElementById('unmute').addEventListener('click', function(event) {
if (!audioloaded) { // Load audio on first click
audioobject = document.createElement("audio");
audioobject.preload = "auto"; // Load now!!!
var source = document.createElement("source");
source.src = "sound1.mp3"; // Append src
audioobject.appendChild(source);
audioobject.load(); // Just for sure, old browsers fallback
audioloaded = true; // Globally remember that audio is loaded
}
// Other mute / unmute stuff here that you already got... ;)
});
// Play sound on click
document.getElementById('playsound').addEventListener('click', function(event) {
audioobject.play();
});
});
Of course, button should have id="unmute", and for simplicity, body id="body" and play sound button id="playsound. You can modify that of course to suit your needs. After that, when someone will click unmute, audio object will be generated and dynamically loaded.
I didn't try this solution so there may be some little mistakes (I hope not!). But I hope this will get you an idea (sketch) how this can be acomplished using pure javascript.
Don't be afraid that this is pure javascript, without html. This is additional functionality, and javascript is the best way to implement it.
You can use a Blob URL representation of the file
let urls = [
"https://upload.wikimedia.org/wikipedia/commons/b/be/Hidden_Tribe_-_Didgeridoo_1_Live.ogg"
, "https://upload.wikimedia.org/wikipedia/commons/6/6e/Micronesia_National_Anthem.ogg"
];
let audioNodes, mediaBlobs, blobUrls;
const request = url => fetch(url).then(response => response.blob())
.catch(err => {throw err});
const handleResponse = response => {
mediaBlobs = response;
blobUrls = mediaBlobs.map(blob => URL.createObjectURL(blob));
audioNodes = blobUrls.map(blobURL => new Audio(blobURL));
}
const handleMediaSelection = () => {
const select = document.createElement("select");
document.body.appendChild(select);
const label = new Option("Select audio to play");
select.appendChild(label);
select.onchange = () => {
audioNodes.forEach(audio => {
audio.pause();
audio.currentTime = 0;
});
audioNodes[select.value].play();
}
select.onclick = () => {
const media = audioNodes.find(audio => audio.currentTime > 0);
if (media) {
media.pause();
media.currentTime = 0;
select.selectedIndex = 0;
}
}
mediaBlobs.forEach((blob, index) => {
let option = new Option(
new URL(urls[index]).pathname.split("/").pop()
, index
);
option.onclick = () => console.log()
select.appendChild(option);
})
}
const handleError = err => {
console.error(err);
}
Promise.all(urls.map(request))
.then(handleResponse)
.then(handleMediaSelection)
.catch(handleError);

Linking audio elements together HTML/AngularJS

I'm not entirely sure how to run a function that syncs up with the updating of a webpage.
I have a checkbox that runs a function if checked.
Html:
<input type="checkbox" value="data.id" id="status" ng-model="data.status" class="Form-label-checkbox" ng-change="IfCheck(data.Url)">
The IfCheck function adds the url into an array, $scope.ids
JavaScript: //kind of psuedocode
$scope IfCheck(url){
$scope.ids.push(object);}
$scope.Playall = function(){
var audioElements = document.getElementsByTagName("audio");
for(var i = 0; i < audioElements.length; i++){
audioElements[i].play();
}
}
This seems to work well so far. The array ids gets populated with the URLs on the fly. Afterwards, I run ng-repeat on this array, and create an element with the source as the url. This works as well.
HTML:
<div ng-repeat="data in ids">
<audio controls>
<source src="{{data.Url | trustUrl}}" id = "Synth.wav" type="audio/mpeg">
Your browser does not support the audio element.
</audio> </div>
My problem is this now. Lets say I check two boxes, and create two audio players on the fly. They play music if I click the play button. Is there a way to somehow make a button so that it will play both of them at the same time? I thought of something like
<button ng-click = "Playall()"> Playall </button>
but I'm not sure how to write the function to "link" to the created elements.
The Playall() function can look something like this:
$scope.Playall = function(){
Array.from(document.getElementsByTagName("audio")).forEach(audio => audio.play());
}
OR:
$scope.Playall = function(){
var audioElements = document.getElementsByTagName("audio");
for(var i = 0; i < audioElements.length; i++){
audioElements[i].play();
}
}

Javascript play sound on hover. stop and reset on hoveroff

function EvalSound(soundobj) {
var thissound=document.getElementById(soundobj);
thissound.currentTime = 0;
thissound.Play();
}
function StopSound(soundobj) {
var thissound=document.getElementById(soundobj);
thissound.Stop();
}
This is my code to play a audio file,
onmouseover="EvalSound('sound1')" onmouseout="StopSound('sound1')"
It is currently working on hover, however when i go back to the image that it plays under it doesnt go back to the beginning, it continues playing
The <embed> tag is the old way to embed multimedia. You really ought to be using the new HTML5 <audio> or <video> tags as they are the preferred and standardized way to embed multimedia objects. You can use the HTMLMediaElement interface to play, pause, and seek through the media (and lots more).
Here is a simple example that plays an audio file on mouseover and stops it on mouseout.
HTML:
<p onmouseover="PlaySound('mySound')"
onmouseout="StopSound('mySound')">Hover Over Me To Play</p>
<audio id='mySound' src='http://upload.wikimedia.org/wikipedia/commons/6/6f/Cello_Live_Performance_John_Michel_Tchaikovsky_Violin_Concerto_3rd_MVT_applaused_cut.ogg'/>
Javascript:
function PlaySound(soundobj) {
var thissound=document.getElementById(soundobj);
thissound.play();
}
function StopSound(soundobj) {
var thissound=document.getElementById(soundobj);
thissound.pause();
thissound.currentTime = 0;
}
For more information, check out the MDN guide for embedding audio and video
I had the same question, about starting and stopping audio. I use jQuery without any other plugins. My code is for mousedown and mouseup, but could be changed to other actions.
HTML
<div class="soundbutton">
cool wind sound
</div>
<audio id="wind-sound" src="wind-sound/wind.mp3">
Javascript
$('.soundbutton').on('mousedown', function () {
playWind(); //start wind sound
})
.on('mouseup', function () {
stopWind(); //stops the wind sound
});
// my full functions to start and stop
function playWind () { //start wind audio
$('#wind-sound')[0].volume = 0.7;
$('#wind-sound')[0].load();
$('#wind-sound')[0].play();
}
function stopWind () { //stop the wind audio
$('#wind-sound')[0].pause();
$('#wind-sound')[0].currentTime = 0; //resets wind to zero/beginning
}
<html>
<script>
function stopAudio() {
player.pause();
player.currentTime = 0;
}
</script>
<body>
<audio id="player" src="(place audio here)"></audio>
<div>
<button onclick=" stopAudio()">Stop</button>
</div>
</body>
</html>
//End Note: you must look at your audio id as mine is named "player"
this is the reason it is not working look at your css and your html
very closely in your lines. The other thing you must be careful about
is your call function as mine is stated as stopAudio() yours could be
named different. The function only works with css if you use your call
method properly.

Playing sound notifications using Javascript?

How can I do that, so whenever a user clicks a link we play a sound? Using javascript and jquery here.
Use this plugin: https://github.com/admsev/jquery-play-sound
$.playSound('http://example.org/sound.mp3');
Put an <audio> element on your page.
Get your audio element and call the play() method:
document.getElementById('yourAudioTag').play();
Check out this example: http://www.storiesinflight.com/html5/audio.html
This site uncovers some of the other cool things you can do such as load(), pause(), and a few other properties of the audio element.
When exactly you want to play this audio element is up to you. Read the text of the button and compare it to "no" if you like.
Alternatively
http://www.schillmania.com/projects/soundmanager2/
SoundManager 2 provides a easy to use API that allows sound to be played in any modern browser, including IE 6+. If the browser doesn't support HTML5, then it gets help from flash. If you want stricly HTML5 and no flash, there's a setting for that, preferFlash=false
It supports 100% Flash-free audio on iPad, iPhone (iOS4) and other HTML5-enabled devices + browsers
Use is as simple as:
<script src="soundmanager2.js"></script>
<script>
// where to find flash SWFs, if needed...
soundManager.url = '/path/to/swf-files/';
soundManager.onready(function() {
soundManager.createSound({
id: 'mySound',
url: '/path/to/an.mp3'
});
// ...and play it
soundManager.play('mySound');
});
Here's a demo of it in action: http://www.schillmania.com/projects/soundmanager2/demo/christmas-lights/
Found something like that:
//javascript:
function playSound( url ){
document.getElementById("sound").innerHTML="<embed src='"+url+"' hidden=true autostart=true loop=false>";
}
Using the html5 audio tag and jquery:
// appending HTML5 Audio Tag in HTML Body
$('<audio id="chatAudio">
<source src="notify.ogg" type="audio/ogg">
<source src="notify.mp3" type="audio/mpeg">
</audio>').appendTo('body');
// play sound
$('#chatAudio')[0].play();
Code from here.
In my implementation I added the audio embed directly into the HTML without jquery append.
JavaScript Sound Manager:
http://www.schillmania.com/projects/soundmanager2/
$('a').click(function(){
$('embed').remove();
$('body').append('<embed src="/path/to/your/sound.wav" autostart="true" hidden="true" loop="false">');
});
I wrote a small function that can do it, with the Web Audio API...
var beep = function(duration, type, finishedCallback) {
if (!(window.audioContext || window.webkitAudioContext)) {
throw Error("Your browser does not support Audio Context.");
}
duration = +duration;
// Only 0-4 are valid types.
type = (type % 5) || 0;
if (typeof finishedCallback != "function") {
finishedCallback = function() {};
}
var ctx = new (window.audioContext || window.webkitAudioContext);
var osc = ctx.createOscillator();
osc.type = type;
osc.connect(ctx.destination);
osc.noteOn(0);
setTimeout(function() {
osc.noteOff(0);
finishedCallback();
}, duration);
};
New emerger... seems to be compatible with IE, Gecko browsers and iPhone so far...
http://www.jplayer.org/
Following code might help you to play sound in a web page using javascript only. You can see further details at http://sourcecodemania.com/playing-sound-javascript-flash-player/
<script>
function getPlayer(pid) {
var obj = document.getElementById(pid);
if (obj.doPlay) return obj;
for(i=0; i<obj.childNodes.length; i++) {
var child = obj.childNodes[i];
if (child.tagName == "EMBED") return child;
}
}
function doPlay(fname) {
var player=getPlayer("audio1");
player.play(fname);
}
function doStop() {
var player=getPlayer("audio1");
player.doStop();
}
</script>
<form>
<input type="button" value="Play Sound" onClick="doPlay('texi.wav')">
[Play]
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
width="40"
height="40"
id="audio1"
align="middle">
<embed src="wavplayer.swf?h=20&w=20"
bgcolor="#ffffff"
width="40"
height="40"
allowScriptAccess="always"
type="application/x-shockwave-flash"
pluginspage="http://www.macromedia.com/go/getflashplayer"
/>
</object>
<input type="button" value="Stop Sound" onClick="doStop()">
</form>
First things first, i'd not like that as a user.
The best way to do is probably using a small flash applet that plays your sound in the background.
Also answered here: Cross-platform, cross-browser way to play sound from Javascript?

Categories