Last active
April 15, 2017 21:59
-
-
Save sevaa/2d84822540bf1fc8b8deab255d6209eb to your computer and use it in GitHub Desktop.
Generating a simple musical tone purely from JavaScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function GenerateTone(frequency, duration, volume, rate) | |
{ | |
if (!volume) | |
volume = 30000; | |
if (!rate) | |
rate = 8000; | |
var nSamples = rate * duration, | |
i, w = (2 * Math.PI * frequency) / rate, | |
wav = new ArrayBuffer(44 + nSamples*2); | |
(new Int32Array(wav, 0, 11)).set( | |
[0x46464952, 36 + nSamples*2, 0x45564157, | |
0x20746d66, 16, 0x10001, rate, rate*2, 0x100002, | |
0x61746164, nSamples*2], 0); | |
var samples = new Int16Array(wav, 44, nSamples); | |
for (i = 0; i < nSamples; i++) | |
samples[i] = volume * Math.sin(w * i); | |
return "data:audio/wav;base64," + ToBase64(wav); | |
} | |
function ToBase64(arrayBuffer) | |
{ | |
var s = "", a, b, c, d, chunk; | |
var alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
var bytes = new Uint8Array(arrayBuffer) | |
var byteLength = bytes.byteLength; | |
var byteRemainder = byteLength % 3; | |
var mainLength = byteLength - byteRemainder; | |
for (var i = 0; i < mainLength; i += 3) | |
{ | |
chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]; | |
a = (chunk & 16515072) >> 18; | |
b = (chunk & 258048) >> 12; | |
c = (chunk & 4032) >> 6; | |
d = chunk & 63; | |
s += alpha[a] + alpha[b] + alpha[c] + alpha[d]; | |
} | |
if (byteRemainder == 1) | |
{ | |
chunk = bytes[mainLength]; | |
a = (chunk & 252) >> 2; | |
b = (chunk & 3) << 4; | |
s += alpha[a] + alpha[b] + "=="; | |
} | |
else if (byteRemainder == 2) | |
{ | |
chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]; | |
a = (chunk & 64512) >> 10; | |
b = (chunk & 1008) >> 4; | |
c = (chunk & 15) << 2; | |
s += alpha[a] + alpha[b] + alpha[c] + "="; | |
} | |
return s; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Today's snippet: generating a simple musical tone purely from JavaScript. I saw some online samples for doing it on a server (e. g. in PHP) and sending to the client, but that's a waste of bandwidth.
The ingredients are twofold:
There's a concise description of the WAV format here. My implementation limits the format to 16-bit mono PCM.
The GenerateTone() function returns a data: URI with a WAV file in it. The parameters are:
That's it. All that remains is feeding that data to an element. Assuming you have an
<audio id="MyAudio">
element on the page:The ToBase64 function here is one of many JavaScript-only implementations of the Base64 format. If your project already has one, feel free to substitute.