I’ve put together a sine waveform generator that generates .wav files on the fly in pure JavaScript and plays the .wav file using whatever plugin your browser has installed. It works under Firefox, Opera, Safari, and Google Chrome, but I haven’t tested it in Internet Explorer. You can increase the size of the generated .wav file by changing around the parameters, but be aware that it will stop working if the size of the .wav file grows too large. Most likely, the plugin that you will need is Quicktime, since that seems to register itself as the default player on many systems.
If you missed the link in my post:
http://www.sk89q.com/experiments/jswav/
In addition, I’ve made a JavaScript song player that generates each note individually and plays them in order. However, a new .wav is generated for every note due to the length limit of data URIs.

I'm on Twitter!
I’m porting your example code into my Chiron library. I’m breaking it into a struct.js and wav.js module with more discrete functions so people can make unit tests. I’ve added the base64 code you found to my list of base64 encoders for the upcoming deathmatch.
In the mean time, I think you could make use of this function, perhaps to generate your lookup table on the fly, or to memoize, whatever you like:
/*** notes
*/
exports.notes = {
‘Ab’: -1, ‘A’: 0, ‘A#’: 1, ‘Bb’: 1, ‘B’: 2, ‘C’: 3, ‘C#’: 4, ‘Db’: 4, ‘D’: 5,
‘D#’: 6, ‘Eb’: 6, ‘E’: 7, ‘F’: 8, ‘F#’: 9, ‘Gb’: 9, ‘G’: 10, ‘G#’: 11
};
/*** frequency
*/
exports.frequency = function (octave, note) {
if (typeof note == ‘string’) note = notes[note];
return 440 * Math.pow(2, (octave – 4) + note / 12);
};
What would it take to create polyphony or other wave forms?
Yeah, that’s a better way to do it. I copied the list of note frequencies from an old piece of Python code that I wrote (or generated, I think), so I didn’t bother with creating the lookup table on the fly.
As for other wave forms or more complicated sounds, you’d have to consult an audio engineer. I don’t have any substantial knowledge in audio signals. The only other simple waveform that I know of that you can do is the sawtooth wave, but it’s only emulation (it doesn’t sound as nice). The function for that is floor(x) – x.
Wikipedia has great articles on the basic waveforms:
http://en.wikipedia.org/wiki/Sine_wave
http://en.wikipedia.org/wiki/Sawtooth_wave
http://en.wikipedia.org/wiki/Triangle_wave
http://en.wikipedia.org/wiki/Square_wave
i extend your code to integrate other waves form
Oscilator 1 Shape
Sinus
Square
Saw tooth
Spike
White Noise
Ramp
function genSignal(shape,value)
{
var signal = 0;
if (shape == 1)
{
signal = Math.sin((2 * Math.PI) * value);
}
else if (shape == 2)
{
if (value < -0.5)
{
signal = 1.0;
}
else
{
signal = -1.0;
}
}
else if (shape == 3)
{
if ( value < -0.5 )
{
signal = -1 + ( value + 1 )*4;
}
else
{
signal = 1 – (value + .5)*4;
}
}
else if (shape == 4)
{
if ( value -0.47)
{
signal = 1;
}
else
{
signal = -1;
}
}
else if (shape == 5)
{
signal = Math.random();
}
else if (shape == 6)
{
signal = 1 + value*2;
}
return signal;
}
we also can insert ADSR envelope, lfo modulation and ocsilateur composition.
Are you losing your mind?
Very cool!
If you need extra performance generating the wavs you may try the following.
Firefox and Safari (and I’m guessing Chrome also) have native base64 encoder/decoder functions; btoa (encode) and atob (decode).
dec2hex seems very quirky. The native Number method toString() with a radix seems a bit more solid: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Number/toString
String.fromCharCode accepts multiple arguments so instead of:
case “V”:
output += String.fromCharCode(arg & 255) +
String.fromCharCode((arg >> 8) & 255) +
String.fromCharCode((arg >> 16) & 255) +
String.fromCharCode((arg >> 24) & 255);
break;
you could do:
case “V”:
output += String.fromCharCode(
arg & 255,
(arg >> 8) & 255,
(arg >> 16) & 255,
(arg >> 24) & 255
);
break;
Ah, thanks for the comment. I’ll update the code accordingly.
That’s fantastic! If only there wasn’t such a strict size limitation this would be a great way to generate tunes on the fly.
Do you think there is a way to save that data to a file and then play it back? I suppose it could be AJAXed back to the server, saved, then retrieved, but then one might as well generate it on the server to start with.
Doing separate WAV files is ok, but doesn’t give quite enough control.
Great job! I’m going to start playing around with this.
I’m not aware of any way to save the files to the computer.
Very good job!!
When we see that web2 success is partly due to music community. It’s very strange that standard web technology (xHTML …) deals so bad with sounds management where text, image and even vector graphics are so easily accessible thru javascript/svg/canvas
It is simple, most of web browser use plugin to play music and no one integrate sounds génerator (synthesis).
Does it exist an example of generating any complex type of image (like GIF, BMP or JPG and not XBM) in Javascript?
Yes. Check Google.
I’ve got a hack for generating pngs in javascript here: http://thebends.googlecode.com/svn/trunk/jspng/
This is really interesting. I wonder if we could apply this idea to .mid files as well.
As a side note. This generator works with Skyfire on a Symbian mobile phone.
I believe that someone already has done it with MIDI files.
It would be better if we use audio element added in HTML 5. Unfortunately, it seems that WAV playback in audio element is not available in Google Chrome — so we have to generate simple Ogg Vorbis file instead. I have personally tried it, but with no success yet.
I have tried it with the audio element (Firefox), but I ran into some issues at the time, but it might have only affected the song player — I don’t recall.
Works great with HTML 5 and doesn’t have the same file size limitations. Just replace the embed part with
var audio = new Audio(dataURI);
audio.play();
Great work! Very simple to understand and use as opposed to other libraries!