JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
Input:<br>
<textarea id="input" style="height: 50px;">8000
300
ABCDEFG_GFEDCBA</textarea><br>
<button id="send">
Compute
</button>
<br><br>
<div id="result" style="display: none;">
<span id="res_txt"></span>
<br>
<button id="play">
Play
</button>
<button id="download">
Download
</button>
</div>
<a style="display: none;" id="dummy" target="_blank"></a>
JavaScript
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
function writeString(view, offset, string){
for (var i = 0; i < string.length; i++){
view.setUint8(offset + i, string.charCodeAt(i));
}
}
function floatTo16BitPCM(output, offset, input){
for (var i = 0; i < input.length; i++, offset+=2){
var s = Math.max(-1, Math.min(1, input[i]));
output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
}
}
function encodeWAV(samples, sampleRate){
var buffer = new ArrayBuffer(44 + samples.length * 2);
var view = new DataView(buffer);
writeString(view, 0, 'RIFF');
view.setUint32(4, 32 + samples.length * 2, true);
writeString(view, 8, 'WAVE');
writeString(view, 12, 'fmt ');
view.setUint32(16, 16, true);
view.setUint16(20, 1, true);
view.setUint16(22, 2, true);
view.setUint32(24, sampleRate, true);
view.setUint32(28, sampleRate * 4, true);
view.setUint16(32, 4, true);
view.setUint16(34, 16, true);
writeString(view, 36, 'data');
view.setUint32(40, samples.length * 2, true);
floatTo16BitPCM(view, 44, samples);
return view;
}
var FREQUENCIES = {
A: 440.00,
B: 493.88,
C: 523.25,
D: 587.33,
E: 659.25,
F: 698.46,
G: 783.99,
_: 0
};
var Melody = function(txt, sample_rate, note_duration) {
note_duration = note_duration/1000;
var input = ''; this.sample_rate = sample_rate; this.note_duration = note_duration;
for (var i = 0; i < txt.length; i++) { if (FREQUENCIES[txt.charAt(i)] != null) { input += txt.charAt(i); }}
this.input = input;
var samples_per_note = note_duration * sample_rate;
var myArrayBuffer = audioCtx.createBuffer(2, samples_per_note * input.length, sample_rate), arr = [];
for (var channel = 0; channel < 2; channel++)
{
var nowBuffering = myArrayBuffer.getChannelData(channel);
for (var i = 0; i < input.length; i++)
{
var note = FREQUENCIES[input.charAt(i)] * 2;
for (var j = 0, b = i * samples_per_note; j < samples_per_note; j++, b++)
{
nowBuffering[b] =...