JSFiddle - React, Tailwind, and code Playground

HTML

wav, mp3などの音声ファイル<br>
<input type="file" onchange="onChange(event);"><br><br>
<input type="button" value="play" onclick="play();"><br><br>
<a id="anchor" download="xacalite.dat">xacalite.dat</a><br>
<canvas id="canvas"></canvas>
<pre id="output"></pre>

CSS

canvas {
	border: 1px solid green;
}

JavaScript

"use strict";

const MAG = 1000;
const FREQ = 4181.7;
//const FREQ = 8363.4;

let ac;		// AudioContext
let abuf;	// AudioBuffer
let abuf2;	// AudioBuffer
let pcm;
let dpcm;

onload = function() {
	ac = new AudioContext();
};

function onChange(e) {
	let file = e.target.files[0];

	let fr = new FileReader();
	fr.onload = function(e) {

		// wav, mp3などの音声ファイルをデコードする
		ac.decodeAudioData(e.target.result)
		.then(decodedData => {

			// リサンプリングする
			let sr = FREQ;
			let oac = new OfflineAudioContext(1, sr * 9, sr);
			let src = oac.createBufferSource();
			src.buffer = decodedData;
			src.connect(oac.destination);
			src.start();

			oac.startRendering()
			.then(renderedBuffer => {
				abuf = renderedBuffer;
				check();
				encode();
				draw();
				decode();
				download();
			});
		});
	};
	fr.readAsArrayBuffer(file);
}

function play() {
	// AudioBufferSourceNode
	let src = ac.createBufferSource();
	src.connect(ac.destination);
	src.buffer = abuf2;
	src.start();
}

function check() {
	let log = "";
	log += `${abuf.sampleRate.toFixed(1)} Hz\n`;
	log += `${abuf.length}\n`;
	log += `${abuf.duration.toFixed(2)} s\n`;
	log += `${abuf.numberOfChannels} ch\n`;

	let data = abuf.getChannelData(0);
	let min = data[0];
	let max = data[0];
	let sum = data[0];

	for (let i = 1; i < data.length; i++) {
		if (min > data[i]) min = data[i];
		if (max < data[i]) max = data[i];
		sum += data[i];
	}
	let avg = sum / data.length;

	log += `len: ${data.length}\n`;
	log += `min: ${min}\n`;
	log += `max: ${max}\n`;
	log += `avg: ${avg}\n`;
	output.textContent = log;
}

function encode() {
	let data = abuf.getChannelData(0);
	let len = 32768;
	pcm = new Uint8Array(len);
	dpcm = new Uint8Array(len);

	for (let i = 0; i < len; i++) {
		pcm[i] = Math.min(Math.max(Math.floor(64+data[1000+i]*MAG), 0), 127);
	}

	let v = 64;
	for (let i = 0; i < len; i++) {
		if (v < pcm[i]) {
			v++;
			dpcm[i] = 1;
		} else {
			v--;
			dpcm[i] = 0;
		}
	}
}

function decode() {
	abuf2 =...