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] =...