Oscillator value does not change in safari? - javascript

I am trying to make use of web audio api with NexusUI JS for dial/knobs?
In chrome the dial is changing the oscillator frequency but in safari its playing i think the default 440hz.
Can someone please direct me what am I missing or doing wrong ? It seems like I am in the right direction since I am getting output in chrome as safari is super strict some basic mistake is been overlooked by me.
Reason for using nexusUI: It was the most minimalist dial/knob I found. I only need a super basic knob. Toggle switch I can easily replace with a play / pause button.
Example of what I am trying to do. (Same on codepen)
document.body.style.backgroundColor = "#2a2c2d";
var power = new Nexus.Toggle("#power", {
state: false
});
Nexus.colors.accent = "#16e1ff";
Nexus.colors.fill = "#2a2c2d";
Nexus.colors.accent = "#16e1ff";
var dial = new Nexus.Dial("#dial");
dial.value = 0;
dial.min = 20;
dial.max = 6000;
dial.on("change", function (v) {
knb1.frequency.value = v;
console.log(v);
return v;
});
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
var knb1 = context.createOscillator();
var knb1Gain = context.createGain();
var breath1 = context.createOscillator();
var breathGain1 = context.createGain();
knb1.type = "sine";
knb1Gain.gain.value = 0.1 / 8;
knb1.connect(knb1Gain);
knb1Gain.connect(context.destination);
breath1.connect(breathGain1);
breath1.type = "sine";
breath1.frequency.value = 0.01;
breathGain1.gain.value = (0.2 + 0.01) / 8;
knb1.start();
context.onstatechange = function () {
console.log(context.state);
};
power.on("change", function (v) {
v ? context.resume() : context.suspend();
});
<script src="https://cdn.jsdelivr.net/npm/nexusui#latest/dist/NexusUI.js"></script>
<div id="power"><div>
<div id="dial"></div>

my code was wrong.
knb1.frequency.value = v; is wrong!
correct line is knb1.frequency.setValueAtTime(v, context.currentTime);
changing this line solved my issue.

Related

Why does my second audio file not play using the currentTime property?

I would like my audio2 file to play when audio1.currentTime is 3 seconds, but I'm not able to make it work. I'm a newbie in javascript, what am I missing?. This is my current javascript code:
function initAudioPlayer(){
var audio1, audio2, ext, agent;
ext = ".mp3";
agent = navigator.userAgent.toLocaleLowerCase();
if(agent.indexOf('firefox') != -1 || agent.indexOf('opera') != -1) { ext = ".ogg";}
//Audio Objects: audio1 and audio2
audio1 = new Audio();
audio1.src = "folder/Audio1"+ext;
audio1.loop = false;
audio1.play();
audio2 = new Audio();
audio2.src = "folder/Audio2"+ext;
audio2.loop = false;
audio2.play();
//Function that reproduces the second audio file at second 3 of the first audio file
function audio2(){
if(audio1.currentTime == 3) {audio2.play();}
};
}
window.addEventListener("load", initAudioPlayer);
You Must use Audio Api and fetch buffers of your files.
Then you must plus each byte and copy to another new buffer.
this code can help you:
let idnex=0;
samples.forEach(buufer => {
if (index === 0) {
tempBuf = buufer;
} else {
tempBuf = this.appendBuffer(tempBuf, buufer);
}
index++;
});
and by thi method you can append two buffer:
private appendBuffer(buffer1, buffer2) {
const numberOfChannels = Math.min(buffer1.numberOfChannels, buffer2.numberOfChannels);
const tmp = this.audioContextService.createBuffer(Math.max(buffer1.numberOfChannels, buffer2.numberOfChannels),
Math.max(buffer1.length, buffer2.length), buffer1.sampleRate);
for (let i = 0; i < numberOfChannels; i++) {
const channel = tmp.getChannelData(i);
let finallArray = [];
let d = [];
const chanelTemp = buffer1.getChannelData(i);
if (buffer2.numberOfChannels <= i) {
finallArray = chanelTemp;
} else {
const c = buffer2.getChannelData(i);
if (chanelTemp.length > c.length) {
finallArray = chanelTemp;
d = c;
} else {
finallArray = c;
d = chanelTemp;
}
for (let j = 0; j < d.length; j++) {
finallArray[j] += d[j] / 2;
}
}
channel.set(finallArray, i);
}
you can see my demo here
Also You Can See this Answer
If you truly want this to be accurate in time, you can't use Audio() - that's the HTML5 <audio> element, which is not sample-accurate. Javascript is also not accurate enough in event delivery to use a callback to do this (to be fair, neither are most general-purpose native OS APIs). You need to schedule the playback in advance, which is where Web Audio (https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API) comes in. You need to load both samples, decode them into AudioBuffers, and then schedule playing back each of them with an AudioBufferSourceNode.

WebCL doesn't fill global table

I started using Nokia WebCL implementation for Mozilla Firefox.
I'm testing my application on Firefox version 32.0 (which is version for which Nokia binding was implemented).
This is my code (for simplicity and to show you what my issue is I've simplified the kernel code to minimum):
Kernel code:
<script id="julia_set" type="text/x-opencl">
__kernel void julia_set(__global int* pix)
{
pix[0]=5;
}
</script>
My Javascript code:
function loadKernel(id){
var kernelElement = document.getElementById(id);
var kernelSource = kernelElement.text;
if (kernelElement.src != "") {
var mHttpReq = new XMLHttpRequest();
mHttpReq.open("GET", kernelElement.src, false);
mHttpReq.send(null);
kernelSource = mHttpReq.responseText;
}
return kernelSource;
}
var platforms = webcl.getPlatforms();
var width = 2;
var height = 2;
var ctx = webcl.createContext(platforms[2],WebCL.DEVICE_TYPE_GPU);
var length = 4*width*height;
var bufSize = 4*length;
var bufferC = ctx.createBuffer (WebCL.MEM_WRITE_ONLY, bufSize);
var kernelSrc = loadKernel("julia_set");
var program = ctx.createProgram(kernelSrc);
var device = ctx.getInfo(WebCL.CONTEXT_DEVICES)[0];
try {
program.build ([device], "");
} catch(e) {
alert ("Failed to build WebCL program. Error "
+ program.getBuildInfo (device,
WebCL.PROGRAM_BUILD_STATUS)
+ ": "
+ program.getBuildInfo (device,
WebCL.PROGRAM_BUILD_LOG));
throw e;
}
var kernel = program.createKernel ("julia_set");
kernel.setArg (0, bufferC);
var cmdQueue = ctx.createCommandQueue (device);
var local = [16,16];
var global = [32,32];
cmdQueue.enqueueNDRangeKernel(kernel, 2, null,global, local);
var outBuffer = new Uint32Array(length);
cmdQueue.enqueueReadBuffer (bufferC, false, 0, bufSize, outBuffer);
cmdQueue.finish ();
console.log(outBuffer);
It's the most simple OpenCL application I could imagine. I expect my outBuffer to be filled with 0's and first element to be 5, but all the elements are 0. Whatever I try to do in kernel, my array seems untouched.
The device I'm using is NVidia GeForce GT 750M.
What can be possibly wrong in my code?
if(get_global_id(0)==0 && get_global_id(1)==0)
pix[0]=5;
should fix the issue, without race condition.

Is it possible to post process HTML5 video elements audio output with Web Audio Api?

I have an html5 video element and I need to apply different processing realtime on the video's output audio. On desktop I made it work with the WebAudio API. The Api is seemingly present on iOS also. I am able to inspect the created objects, but it doesn't modify the video's output signal.
Here's my example code:
$(function () {
window.AudioContext = window.AudioContext||window.webkitAudioContext;
var audioContext = new AudioContext();
var bufferSize = 1024;
var selectedChannel = 0;
var effect = (function() {
var node = audioContext.createScriptProcessor(bufferSize, 2, 2);
node.addEventListener('audioprocess', function(e) {
var input = e.inputBuffer.getChannelData(selectedChannel);
var outputL = e.outputBuffer.getChannelData(0);
var outputR = e.outputBuffer.getChannelData(1);
for (var i = 0; i < bufferSize; i++) {
outputL[i] = selectedChannel==0? input[i] : 0.0;
outputR[i] = selectedChannel==1? input[i] : 0.0;
}
});
return node;
})();
var streamAttached = false;
function attachStream(video) {
if (streamAttached) {
return;
}
var source = audioContext.createMediaElementSource(video);
source.connect(effect);
effect.connect(audioContext.destination);
streamAttached = true;
}
function iOS_video_touch_start() {
var video = $('#vid')[0];
video.play();
attachStream(video);
}
var needtouch = false;
$('#vid').on('play', function () {
attachStream(this);
}).on('loadedmetadata', function () {
this.play();
this.volume=1.0;
if (this && this.paused) {
if (needtouch == false) {
needtouch = true;
this.addEventListener("touchstart", iOS_video_touch_start, true);
}
}
});
window.panToRight = function(){
selectedChannel = 1;
};
window.panToLeft = function(){
selectedChannel = 0;
};
});
You can also check it on CP:
http://codepen.io/anon/pen/pgeJQG
With the buttons you are able to toggle between the left and the right channels. On desktop browsers (Chrome, Firefox, Safari tested) it works fine.
I have also tried the older createJavaScriptNode() instead of createScriptProcessor(). I have also tried it with an alternative effect chain, which was looking like this:
var audioContext = new (window.AudioContext||window.webkitAudioContext)();
audioContext.createGain = audioContext.createGain||audioContext.createGainNode;
var gainL = audioContext.createGain();
var gainR = audioContext.createGain();
gainL.gain.value = 1;
gainR.gain.value = 1;
var merger = audioContext.createChannelMerger(2);
var splitter = audioContext.createChannelSplitter(2);
//Connect to source
source = audioContext.createMediaElementSource(video);
//Connect the source to the splitter
source.connect(splitter, 0, 0);
//Connect splitter' outputs to each Gain Nodes
splitter.connect(gainL, 0);
splitter.connect(gainR, 1);
//Connect Left and Right Nodes to the Merger Node inputs
//Assuming stereo as initial status
gainL.connect(merger, 0, 0);
gainL.connect(merger, 0, 1);
//Connect Merger output to context destination
merger.connect(audioContext.destination, 0, 0);
As you probably noticed this code was using the built in nodes only. But no luck.
So my questions are: Is this even possible on mobile? If it is, than what am I missing? If it is not, than any possible workaround? Thanks
With Chrome on Android, MediaElementSource is not currently routed to WebAudio. This is a known issue and is planned to be fixed eventually.

Animate XML data in Flash with Actionscript 3

I have a question about getting a specific animation added to some xml data I'm pulling. I need some advice on how to make the data move from left to right or vise versa.Just for example I downloaded a rss feed from BBC world news, so it's just an xml file. Both the flash and xml are saved in the same folder and I can get in flash and display the data. Here's are the code so far:
import flash.text.TextField;
import flash.sampler.StackFrame;
import flash.display.MovieClip;
var yPlacement:int = 20;
var xPlacement:int = 30;
var distance:int = 60;
var loader:URLLoader = new URLLoader();
loader.load(new URLRequest("bbc-worldnews-rss.xml"));
loader.addEventListener(Event.COMPLETE, handleComplete);
function handleComplete(event:Event):void
{
var rawXML:XML = new XML(loader.data);
rawXML.ignoreWhite = true;
//trace(rawXML.channel.image.url);
var items:XMLList = rawXML.channel.item;
//trace("Total new items", items.length());
for each (var item:XML in items)
{
//trace(item.title);
var feedTitle:String = item.title.toString();
var myText:TextField = new TextField();
myText.text = feedTitle;
myText.autoSize = TextFieldAutoSize.LEFT;
myText.x = 2;
myText.y = 2;
var clip_mc = new MovieClip();
clip_mc.addChild(myText);
addChild(clip_mc);
clip_mc.y = yPlacement;
clip_mc.x = xPlacement;
yPlacement = yPlacement + distance;
}
//trace("First item title:", item[0].title);
}
I also know the code that makes text move side to side but I don't know how to incorporate it my codes above:
onClipEvent ( load ) {
startPoint = 1280; //this is where the clip will start
endPoint = -1080; //this is where the clip will end, and restart to the startPoint.
speed = 5; //this is how many pixels the text will move each frame.
}
onClipEvent ( enterFrame ) {
this._x -= speed; //you are telling the MC to move to the left 5 pixels each frame.
if (this._x <= endPoint ) { //if your clip goes beyond the end point.
this._x = startPoint; //go back to the starting point.
}
}
I hope I'm not confusing anyone, I just need to get the data I get from xml file to move side to side... I may be complete off course but I would GREATLY appreciate anyone's help!
Thank you,
For starters, the second snippet of code you posted is actually ActionScript 2, not 3.
You'd need to update that snippet to AS3 in order for this to work. Try something like this:
var startPoint:int = 1280;
var endPoint:int = -1080;
var speed:int = 5;
function moveMC(mc:MovieClip):void {
mc.addEventListener(Event.ENTER_FRAME, tick);
}
function tick(e:Event):void {
e.currentTarget.x -= speed;
if (e.currentTarget.x <= endPoint) {
e.currentTarget.x = startPoint;
}
}
You could then call moveMC() after you've added your newly created MovieClip to the stage.
Edit: You can use that snippet right in your for each loop like this:
for each (var item:XML in items)
{
//trace(item.title);
var feedTitle:String = item.title.toString();
var myText:TextField = new TextField();
myText.text = feedTitle;
myText.autoSize = TextFieldAutoSize.LEFT;
myText.x = 2;
myText.y = 2;
var clip_mc = new MovieClip();
clip_mc.addChild(myText);
addChild(clip_mc);
clip_mc.y = yPlacement;
clip_mc.x = xPlacement;
yPlacement = yPlacement + distance;
//takes in reference to MovieClip, start point, end point and speed
moveMC(clip_mc, 1280, -1080, 5);
}
function moveMC(mc:MovieClip, startPoint:int, endPoint:int, speed:int):void {
mc.startPoint = startPoint;
mc.endPoint = endPoint;
mc.speed = speed;
mc.addEventListener(Event.ENTER_FRAME, tick);
}
function tick(e:Event):void {
var mc:MovieClip = e.currentTarget as MovieClip;
mc.x -= mc.speed;
if (mc.x <= mc.endPoint) {
mc.x = mc.startPoint;
}
}

How do I make JavaScript beep?

I want my web page to beep whenever a user exceeds the maximum character limit of my <textarea>.
Solution
You can now use base64 files to produce sounds when imported as data URI. The solution is almost the same as the previous ones, except you do not need to import an external audio file.
function beep() {
var snd = new Audio("data:audio/wav;base64,//uQRAAAAWMSLwUIYAAsYkXgoQwAEaYLWfkWgAI0wWs/ItAAAGDgYtAgAyN+QWaAAihwMWm4G8QQRDiMcCBcH3Cc+CDv/7xA4Tvh9Rz/y8QADBwMWgQAZG/ILNAARQ4GLTcDeIIIhxGOBAuD7hOfBB3/94gcJ3w+o5/5eIAIAAAVwWgQAVQ2ORaIQwEMAJiDg95G4nQL7mQVWI6GwRcfsZAcsKkJvxgxEjzFUgfHoSQ9Qq7KNwqHwuB13MA4a1q/DmBrHgPcmjiGoh//EwC5nGPEmS4RcfkVKOhJf+WOgoxJclFz3kgn//dBA+ya1GhurNn8zb//9NNutNuhz31f////9vt///z+IdAEAAAK4LQIAKobHItEIYCGAExBwe8jcToF9zIKrEdDYIuP2MgOWFSE34wYiR5iqQPj0JIeoVdlG4VD4XA67mAcNa1fhzA1jwHuTRxDUQ//iYBczjHiTJcIuPyKlHQkv/LHQUYkuSi57yQT//uggfZNajQ3Vmz+Zt//+mm3Wm3Q576v////+32///5/EOgAAADVghQAAAAA//uQZAUAB1WI0PZugAAAAAoQwAAAEk3nRd2qAAAAACiDgAAAAAAABCqEEQRLCgwpBGMlJkIz8jKhGvj4k6jzRnqasNKIeoh5gI7BJaC1A1AoNBjJgbyApVS4IDlZgDU5WUAxEKDNmmALHzZp0Fkz1FMTmGFl1FMEyodIavcCAUHDWrKAIA4aa2oCgILEBupZgHvAhEBcZ6joQBxS76AgccrFlczBvKLC0QI2cBoCFvfTDAo7eoOQInqDPBtvrDEZBNYN5xwNwxQRfw8ZQ5wQVLvO8OYU+mHvFLlDh05Mdg7BT6YrRPpCBznMB2r//xKJjyyOh+cImr2/4doscwD6neZjuZR4AgAABYAAAABy1xcdQtxYBYYZdifkUDgzzXaXn98Z0oi9ILU5mBjFANmRwlVJ3/6jYDAmxaiDG3/6xjQQCCKkRb/6kg/wW+kSJ5//rLobkLSiKmqP/0ikJuDaSaSf/6JiLYLEYnW/+kXg1WRVJL/9EmQ1YZIsv/6Qzwy5qk7/+tEU0nkls3/zIUMPKNX/6yZLf+kFgAfgGyLFAUwY//uQZAUABcd5UiNPVXAAAApAAAAAE0VZQKw9ISAAACgAAAAAVQIygIElVrFkBS+Jhi+EAuu+lKAkYUEIsmEAEoMeDmCETMvfSHTGkF5RWH7kz/ESHWPAq/kcCRhqBtMdokPdM7vil7RG98A2sc7zO6ZvTdM7pmOUAZTnJW+NXxqmd41dqJ6mLTXxrPpnV8avaIf5SvL7pndPvPpndJR9Kuu8fePvuiuhorgWjp7Mf/PRjxcFCPDkW31srioCExivv9lcwKEaHsf/7ow2Fl1T/9RkXgEhYElAoCLFtMArxwivDJJ+bR1HTKJdlEoTELCIqgEwVGSQ+hIm0NbK8WXcTEI0UPoa2NbG4y2K00JEWbZavJXkYaqo9CRHS55FcZTjKEk3NKoCYUnSQ0rWxrZbFKbKIhOKPZe1cJKzZSaQrIyULHDZmV5K4xySsDRKWOruanGtjLJXFEmwaIbDLX0hIPBUQPVFVkQkDoUNfSoDgQGKPekoxeGzA4DUvnn4bxzcZrtJyipKfPNy5w+9lnXwgqsiyHNeSVpemw4bWb9psYeq//uQZBoABQt4yMVxYAIAAAkQoAAAHvYpL5m6AAgAACXDAAAAD59jblTirQe9upFsmZbpMudy7Lz1X1DYsxOOSWpfPqNX2WqktK0DMvuGwlbNj44TleLPQ+Gsfb+GOWOKJoIrWb3cIMeeON6lz2umTqMXV8Mj30yWPpjoSa9ujK8SyeJP5y5mOW1D6hvLepeveEAEDo0mgCRClOEgANv3B9a6fikgUSu/DmAMATrGx7nng5p5iimPNZsfQLYB2sDLIkzRKZOHGAaUyDcpFBSLG9MCQALgAIgQs2YunOszLSAyQYPVC2YdGGeHD2dTdJk1pAHGAWDjnkcLKFymS3RQZTInzySoBwMG0QueC3gMsCEYxUqlrcxK6k1LQQcsmyYeQPdC2YfuGPASCBkcVMQQqpVJshui1tkXQJQV0OXGAZMXSOEEBRirXbVRQW7ugq7IM7rPWSZyDlM3IuNEkxzCOJ0ny2ThNkyRai1b6ev//3dzNGzNb//4uAvHT5sURcZCFcuKLhOFs8mLAAEAt4UWAAIABAAAAAB4qbHo0tIjVkUU//uQZAwABfSFz3ZqQAAAAAngwAAAE1HjMp2qAAAAACZDgAAAD5UkTE1UgZEUExqYynN1qZvqIOREEFmBcJQkwdxiFtw0qEOkGYfRDifBui9MQg4QAHAqWtAWHoCxu1Yf4VfWLPIM2mHDFsbQEVGwyqQoQcwnfHeIkNt9YnkiaS1oizycqJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=");
snd.play();
}
beep();
Compatibility
Data URI is supported on almost every browser now. More information on http://caniuse.com/datauri
Demo
http://jsfiddle.net/7EAgz/
Conversion Tool
And here is where you can convert mp3 or wav files into Data URI format:
https://dopiaza.org/tools/datauri/index.php
It's not possible to do directly in JavaScript. You'll need to embed a short WAV file in the HTML, and then play that via code.
An Example:
<script>
function PlaySound(soundObj) {
var sound = document.getElementById(soundObj);
sound.Play();
}
</script>
<embed src="success.wav" autostart="false" width="0" height="0" id="sound1"
enablejavascript="true">
You would then call it from JavaScript code as such:
PlaySound("sound1");
This should do exactly what you want - you'll just need to find/create the beep sound yourself, which should be trivial.
/*if you want to beep without using a wave file*/
var context = new AudioContext();
var oscillator = context.createOscillator();
oscillator.type = "sine";
oscillator.frequency.value = 800;
oscillator.connect(context.destination);
oscillator.start();
// Beep for 500 milliseconds
setTimeout(function () {
oscillator.stop();
}, 100);
The top answer was correct at the time but is now wrong; you can do it in pure javascript. But the one answer using javascript doesn't work any more, and the other answers are pretty limited or don't use pure javascript.
I made my own solution that works well and lets you control the volume, frequency, and wavetype.
//if you have another AudioContext class use that one, as some browsers have a limit
var audioCtx = new (window.AudioContext || window.webkitAudioContext || window.audioContext);
//All arguments are optional:
//duration of the tone in milliseconds. Default is 500
//frequency of the tone in hertz. default is 440
//volume of the tone. Default is 1, off is 0.
//type of tone. Possible values are sine, square, sawtooth, triangle, and custom. Default is sine.
//callback to use on end of tone
function beep(duration, frequency, volume, type, callback) {
var oscillator = audioCtx.createOscillator();
var gainNode = audioCtx.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);
if (volume){gainNode.gain.value = volume;}
if (frequency){oscillator.frequency.value = frequency;}
if (type){oscillator.type = type;}
if (callback){oscillator.onended = callback;}
oscillator.start(audioCtx.currentTime);
oscillator.stop(audioCtx.currentTime + ((duration || 500) / 1000));
};
Someone suggested I edit this to note it only works on some browsers. However Audiocontext seems to be supported on all modern browsers, as far as I can tell. It isn't supported on IE, but that has been discontinued by Microsoft. If you have any issues with this on a specific browser please report it.
I wrote a function to beep with the new Audio API.
var beep = (function () {
var ctxClass = window.audioContext ||window.AudioContext || window.AudioContext || window.webkitAudioContext
var ctx = new ctxClass();
return function (duration, type, finishedCallback) {
duration = +duration;
// Only 0-4 are valid types.
type = (type % 5) || 0;
if (typeof finishedCallback != "function") {
finishedCallback = function () {};
}
var osc = ctx.createOscillator();
osc.type = type;
//osc.type = "sine";
osc.connect(ctx.destination);
if (osc.noteOn) osc.noteOn(0); // old browsers
if (osc.start) osc.start(); // new browsers
setTimeout(function () {
if (osc.noteOff) osc.noteOff(0); // old browsers
if (osc.stop) osc.stop(); // new browsers
finishedCallback();
}, duration);
};
})();
jsFiddle.
Using Houshalter's suggestion, I made this simple tone synthesizer demo.
Screenshot
Here is a screenshot. Try the live demo further down in this Answer (click Run code snippet).
Demo code
audioCtx = new(window.AudioContext || window.webkitAudioContext)();
show();
function show() {
frequency = document.getElementById("fIn").value;
document.getElementById("fOut").innerHTML = frequency + ' Hz';
switch (document.getElementById("tIn").value * 1) {
case 0: type = 'sine'; break;
case 1: type = 'square'; break;
case 2: type = 'sawtooth'; break;
case 3: type = 'triangle'; break;
}
document.getElementById("tOut").innerHTML = type;
volume = document.getElementById("vIn").value / 100;
document.getElementById("vOut").innerHTML = volume;
duration = document.getElementById("dIn").value;
document.getElementById("dOut").innerHTML = duration + ' ms';
}
function beep() {
var oscillator = audioCtx.createOscillator();
var gainNode = audioCtx.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);
gainNode.gain.value = volume;
oscillator.frequency.value = frequency;
oscillator.type = type;
oscillator.start();
setTimeout(
function() {
oscillator.stop();
},
duration
);
};
frequency
<input type="range" id="fIn" min="40" max="6000" oninput="show()" />
<span id="fOut"></span><br>
type
<input type="range" id="tIn" min="0" max="3" oninput="show()" />
<span id="tOut"></span><br>
volume
<input type="range" id="vIn" min="0" max="100" oninput="show()" />
<span id="vOut"></span><br>
duration
<input type="range" id="dIn" min="1" max="5000" oninput="show()" />
<span id="dOut"></span>
<br>
<button onclick='beep();'>Play</button>
You can clone and tweak the code here:
Tone synthesizer demo on JS Bin
Have fun!
Compatible browsers:
Chrome mobile & desktop
Firefox mobile & desktop
Opera mobile, mini & desktop
Android browser
Microsoft Edge browser
Safari on iPhone or iPad
Not Compatible
Internet Explorer version 11 (but does work on the Edge browser)
This will enable you to play the sound multiple times, in contrast to the top-voted answer:
var playSound = (function beep() {
var snd = new Audio("data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=");
return function() {
snd.play();
}
})();
playSound(); // Play first time
playSound(); // Play second time
As we read in this answer, HTML5 will solve this for you if you're open to that route. HTML5 audio is supported in all modern browsers.
Here's a copy of the example:
var snd = new Audio("file.wav"); // buffers automatically when created
snd.play();
Now it easy enough with JavaScript AudioContext API. It fully supported by major desktop and mobile web browsers...
let context = null;
const beep = (freq = 520, duration = 200, vol = 100) => {
const oscillator = context.createOscillator();
const gain = context.createGain();
oscillator.connect(gain);
oscillator.frequency.value = freq;
oscillator.type = "square";
gain.connect(context.destination);
gain.gain.value = vol * 0.01;
oscillator.start(context.currentTime);
oscillator.stop(context.currentTime + duration * 0.001);
}
document.querySelector('button').addEventListener('click', function () {
context = new AudioContext();
beep();
});
I wrote a small application that plays music from the Mario game without any audio file, just runtime. In my opinion it’s interesting, you can see the source code and listen it.
Using CSS you can do it if you add the following style to a tag, but you will need a wav file:
<style type="text/css">
.beep {cue: url("beep.wav") }
</style>
var body=document.getElementByTagName("body");
body.className=body.className + " " + "beep";
Here's how I get it to beep using HTML5:
First I copy and convert the windows wav file to mp3, then I use this code:
var _beep = window.Audio("Content/Custom/Beep.mp3")
function playBeep() { _beep.play()};
It's faster to declare the sound file globally and refer to it as needed.
This code supports sequencing of multiple beeps, as well as gradual change in frequency ('ramp' flag). Both examples are given below.
<script>
var audioContext = null;
var oscillatorNode = null;
var stopTime = 0;
function beep (frequency, durationSec, ramp=false)
{
if (oscillatorNode == null) {
audioContext = new (window.AudioContext || window.webkitAudioContext) ();
stopTime = audioContext.currentTime;
oscillatorNode = audioContext.createOscillator();
oscillatorNode.type = "sine";
oscillatorNode.connect (audioContext.destination);
if (ramp) {
oscillatorNode.frequency.setValueAtTime (frequency, stopTime);
}
oscillatorNode.start ();
oscillatorNode.onended = function() {
oscillatorNode = null;
audioContext = null;
}
}
if (ramp) {
oscillatorNode.frequency.linearRampToValueAtTime (frequency, stopTime); // value in hertz
} else {
oscillatorNode.frequency.setValueAtTime (frequency, stopTime); // value in hertz
}
stopTime += durationSec;
oscillatorNode.stop (stopTime);
}
function test1()
{
beep (250, 0.5);
beep (1000, 0.2);
beep (550, 0.5);
}
function test2()
{
beep (50, 2, true);
beep (5000, 2, true);
beep (50, 0, true);
}
</script>
<button onclick='test1()'>Beep!</button>
<button onclick='test2()'>Beep(ramped)!</button>
There's no crossbrowser way to achieve this with pure javascript. Instead you could use a small .wav file that you play using embed or object tags.
function beep(wavFile){
wavFile = wavFile || "beep.wav"
if (navigator.appName == 'Microsoft Internet Explorer'){
var e = document.createElement('BGSOUND');
e.src = wavFile;
e.loop =1;
document.body.appendChild(e);
document.body.removeChild(e);
}else{
var e = document.createElement('AUDIO');
var src1 = document.createElement('SOURCE');
src1.type= 'audio/wav';
src1.src= wavFile;
e.appendChild(src1);
e.play();
}
}
Works on Chrome,IE,Mozilla using Win7 OS.
Requires a beep.wav file on the server.
function Sound(url, vol, autoplay, loop)
{
var that = this;
that.url = (url === undefined) ? "" : url;
that.vol = (vol === undefined) ? 1.0 : vol;
that.autoplay = (autoplay === undefined) ? true : autoplay;
that.loop = (loop === undefined) ? false : loop;
that.sample = null;
if(that.url !== "")
{
that.sync = function(){
that.sample.volume = that.vol;
that.sample.loop = that.loop;
that.sample.autoplay = that.autoplay;
setTimeout(function(){ that.sync(); }, 60);
};
that.sample = document.createElement("audio");
that.sample.src = that.url;
that.sync();
that.play = function(){
if(that.sample)
{
that.sample.play();
}
};
that.pause = function(){
if(that.sample)
{
that.sample.pause();
}
};
}
}
var test = new Sound("http://mad-hatter.fr/Assets/projects/FreedomWings/Assets/musiques/freedomwings.mp3");
test.play();
http://jsfiddle.net/sv9j638j/
Note:put this code in your javascript at the point you want the beep to occur.
and remember to specify the directory or folder where the beep sound is stored(source).
<script>
//Appending HTML5 Audio Tag in HTML Body
$('<audio id="chatAudio"><source src="sound/notify.ogg" type="audio/ogg"><source src="sound/notify.mp3" type="audio/mpeg"><source src="sound/notify.wav" type="audio/wav"></audio>').appendTo('body');
$('#chatAudio')[0].play();
</script>
Reference:http://www.9lessons.info/2013/04/play-notification-sound-using-jquery.html.
I implemented this in a social media i am developing and it works find, a notification like that of facebook when chatting, notifying you that you have a new chat message
<html>
<head>
<script src='https://surikov.github.io/webaudiofont/npm/dist/WebAudioFontPlayer.js'></script>
<script src='https://surikov.github.io/webaudiofontdata/sound/0000_JCLive_sf2_file.js'></script>
<script>
var selectedPreset=_tone_0000_JCLive_sf2_file;
var AudioContextFunc = window.AudioContext || window.webkitAudioContext;
var audioContext = new AudioContextFunc();
var player=new WebAudioFontPlayer();
player.loader.decodeAfterLoading(audioContext, '_tone_0000_JCLive_sf2_file');
</script>
</head>
<body>
<p>Play a note</p>
<hr/>
<p>source</p>
</body>
listen here
https://jsbin.com/lamidog/1/edit?html,output
function beep(freq = 660, duration = 90, vol = 50) {
var context = new(window.AudioContext || window.webkitAudioContext);
const oscillator = context.createOscillator();
const gain = context.createGain();
gain.gain.setValueAtTime(0, context.currentTime);
gain.gain.linearRampToValueAtTime(1, context.currentTime + 0.002);
oscillator.connect(gain);
oscillator.frequency.value = freq;
oscillator.type = "square";
gain.connect(context.destination);
oscillator.start(context.currentTime);
oscillator.stop(context.currentTime + duration * .001);
oscillator.onended = () => context.close();
}
<br>
<center><button onclick="beep()">Beep!</button></center>
You need a sound file to be served from somewhere. Here's the code from Scriptaculous's Sound library:
//Default:
<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>
//For Gecko:
if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>');
else if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('Windows Media') != -1 }))
Sound.template = new Template('<object id="sound_#{track}_#{id}" type="application/x-mplayer2" data="#{url}"></object>');
else if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('RealPlayer') != -1 }))
Sound.template = new Template('<embed type="audio/x-pn-realaudio-plugin" style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>');
else
Sound.play = function(){};
}

Categories