How about generating some noise in JavaScript?
Demo is here: oscillator.
How does this work?
Using HTML Web Audio you can synthesize audio with a given frequency. E.g. 440Hz is A ("la" in solfège)
This means you don't need an <audio>
element or any mp3, ogg, wav, etc, no external files.
Let's see how.
Capable browser?
You need a browser that supports AudioContext
. No such (major) browser at the time of writing, afaik. But there's webkitAudioContext
supported in stable iOS Safari, Safari, Chrome. Also there could be browsers that support AudioContext
but not the oscillator part. So starting off:
// globals var audio_context, oscillator; // hello audio world (function init(g){ try { audio_context = new (g.AudioContext || g.webkitAudioContext); oscillator = audio_context.createOscillator(); } catch (e) { alert('No web audio oscillator support in this browser'); } }(window));
Start/stop playing
Alright, next is a play(frequency /*number*/)
function which makes noise with a given frequency.
function play(freq) { oscillator = audio_context.createOscillator(); oscillator.frequency.value = freq; oscillator.connect(audio_context.destination); oscillator.noteOn(0); fire('play', oscillator.frequency.value); }
(Don't mind fire()
, it's just a poor man's event utility for logging what's going on)
The audio context provides a createOscillator()
. You assign the frequency you need and connect this oscillator node to the audio destination (speaker).
There is a nice analogy going on in the Web Audio: you start with some input noise, say coming from microphone or an audio file, or, in this case, you generate the noise yourself. Then you connect that initial input to the output (destination) which is the system speaker/phones. In between though you can pass the noise through a bunch of nodes that can modify the noise.
In this simple example I only have an oscillator node which is connected directly to the audio destination.
noteOn(0)
starts playing the noise we just generated.
Implementing stop()
to silence the noise is just a question of calling noteOff(0)
on the same oscillator node.
function stop() { oscillator.noteOff(0); fire('stop'); }
That's it, go play with the demo.
The demo plays 440Hz (A on 4th octave of the piano) and 880Hz (A on 5th octave) and also lets you punch in a number and see what happens. Probably nice to play with your dog and with sounds at frequencies you cannot hear.
A chord
Finally, an attempt to play a chord: three frequencies at the same time. C major is C, E and G tones. We have an array of the three frequencies, so loop over the array and create and noteOn
three oscillator nodes.
var cmajor = {}; cmajor.yo = function () { var oscs = [], o, i, freqs = [261.63, 329.63, 392]; freqs.forEach(function(freq) { o = audio_context.createOscillator(); o.frequency.value = freq; o.connect(audio_context.destination); o.noteOn(0); oscs.push(o); }); this.oscs = oscs; fire('play', '\n - ' + freqs.join('Hz\n - ')); }; cmajor.no = function () { this.oscs.forEach(function(o) { o.noteOff(0); }); fire('stop'); };
Thanks
Some links for learning more
Once again the demo is here: oscillator.
Intro: html5rocks.com
Educational demos: webaudiodemos.appspot.com/
Comments? Feedback? Find me on Twitter, Mastodon, Bluesky, LinkedIn, Threads