audio-player: corrected indentation and comments

This commit is contained in:
Trek H 2019-09-24 17:15:58 +09:30
parent 1a8493853e
commit 1de5438565
4 changed files with 142 additions and 140 deletions

View File

@ -29,24 +29,24 @@ LICENSE
// Table of index changes (see spec).
const indexTable = [
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8
];
// Quantize step size table (see spec).
const stepTable = [
7, 8, 9, 10, 11, 12, 13, 14,
16, 17, 19, 21, 23, 25, 28, 31,
34, 37, 41, 45, 50, 55, 60, 66,
73, 80, 88, 97, 107, 118, 130, 143,
157, 173, 190, 209, 230, 253, 279, 307,
337, 371, 408, 449, 494, 544, 598, 658,
724, 796, 876, 963, 1060, 1166, 1282, 1411,
1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
32767
7, 8, 9, 10, 11, 12, 13, 14,
16, 17, 19, 21, 23, 25, 28, 31,
34, 37, 41, 45, 50, 55, 60, 66,
73, 80, 88, 97, 107, 118, 130, 143,
157, 173, 190, 209, 230, 253, 279, 307,
337, 371, 408, 449, 494, 544, 598, 658,
724, 796, 876, 963, 1060, 1166, 1282, 1411,
1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
32767
];
const byteDepth = 2; // We are working with 16-bit samples. TODO(Trek): make configurable.
@ -59,89 +59,89 @@ let step = 0;
// decodeSample takes 4 bits which represents a single ADPCM nibble, and returns a 16 bit decoded PCM sample.
function decodeSample(nibble) {
let diff = 0;
if ((nibble & 4) != 0) {
diff += step;
}
if ((nibble & 2) != 0) {
diff += step >> 1;
}
if ((nibble & 1) != 0) {
diff += step >> 2;
}
diff += step >> 3;
let diff = 0;
if ((nibble & 4) != 0) {
diff += step;
}
if ((nibble & 2) != 0) {
diff += step >> 1;
}
if ((nibble & 1) != 0) {
diff += step >> 2;
}
diff += step >> 3;
if ((nibble & 8) != 0) {
diff = -diff;
}
est += diff;
idx += indexTable[nibble];
if ((nibble & 8) != 0) {
diff = -diff;
}
est += diff;
idx += indexTable[nibble];
if (idx < 0) {
idx = 0;
} else if (idx > stepTable.length - 1) {
idx = stepTable.length - 1;
}
if (idx < 0) {
idx = 0;
} else if (idx > stepTable.length - 1) {
idx = stepTable.length - 1;
}
step = stepTable[idx];
step = stepTable[idx];
result = est;
return result;
result = est;
return result;
}
// decode takes an array of bytes of arbitrary length representing adpcm and decodes it into pcm.
function decode(b) {
// Iterate over each chunk and decode it.
let chunkLen;
var result = [];
for (var off = 0; off + headSize <= b.length; off += chunkLen) {
// Read length of chunk and check if whole chunk exists.
chunkLen = bytesToInt32(b.slice(off, off + chunkLenSize))
if (off + chunkLen > b.length) {
break;
}
// Iterate over each chunk and decode it.
let chunkLen;
var result = [];
for (var off = 0; off + headSize <= b.length; off += chunkLen) {
// Read length of chunk and check if whole chunk exists.
chunkLen = bytesToInt32(b.slice(off, off + chunkLenSize))
if (off + chunkLen > b.length) {
break;
}
// Initialize Decoder with first 4 bytes of b.
est = bytesToInt16(b.slice(off + chunkLenSize, off + chunkLenSize + byteDepth));
idx = b[off + chunkLenSize + byteDepth];
step = stepTable[idx];
// Initialize Decoder with first 4 bytes of b.
est = bytesToInt16(b.slice(off + chunkLenSize, off + chunkLenSize + byteDepth));
idx = b[off + chunkLenSize + byteDepth];
step = stepTable[idx];
result.push(...b.slice(off + chunkLenSize, off + chunkLenSize + byteDepth));
result.push(...b.slice(off + chunkLenSize, off + chunkLenSize + byteDepth));
for (var i = off + headSize; i < off + chunkLen - b[off + chunkLenSize + 3]; i++) {
var twoNibs = b[i];
var nib2 = twoNibs >> 4;
var nib1 = (nib2 << 4) ^ twoNibs;
for (var i = off + headSize; i < off + chunkLen - b[off + chunkLenSize + 3]; i++) {
var twoNibs = b[i];
var nib2 = twoNibs >> 4;
var nib1 = (nib2 << 4) ^ twoNibs;
var sample1 = int16ToBytes(decodeSample(nib1));
result.push(...sample1);
var sample1 = int16ToBytes(decodeSample(nib1));
result.push(...sample1);
var sample2 = int16ToBytes(decodeSample(nib2));
result.push(...sample2);
}
if (b[off + chunkLenSize + 3] == 1) {
var padNib = b[off + chunkLen - 1];
var sample = int16ToBytes(decodeSample(padNib));
result.push(...sample);
}
}
return result;
var sample2 = int16ToBytes(decodeSample(nib2));
result.push(...sample2);
}
if (b[off + chunkLenSize + 3] == 1) {
var padNib = b[off + chunkLen - 1];
var sample = int16ToBytes(decodeSample(padNib));
result.push(...sample);
}
}
return result;
}
// int16ToBytes takes a number assumed to be an int 16 and converts it to an array containing bytes (Little Endian).
function int16ToBytes(num) {
return [(num & 0x00ff), (num & 0xff00) >> 8];
return [(num & 0x00ff), (num & 0xff00) >> 8];
}
// bytesToInt16 takes an array of bytes (assumed to be values between 0 and 255), interprates them as little endian and converts it to an int16.
function bytesToInt16(b) {
return (b[0] | (b[1] << 8));
return (b[0] | (b[1] << 8));
}
// bytesToInt32 takes an array of bytes (assumed to be values between 0 and 255), interprates them as little endian and converts it to an int32.
function bytesToInt32(b) {
return (b[0] |
(b[1] << 8) |
(b[2] << 16) |
(b[3] << 24));
return (b[0] |
(b[1] << 8) |
(b[2] << 16) |
(b[3] << 24));
}

View File

@ -23,7 +23,7 @@
</div>
<div class="container-fluid">
<div class="form-group">
<input class="form-control-file" type="file" id="fileinput" onchange="processData();">
<input class="form-control-file" type="file" id="fileinput" onchange="playFile();">
</div>
</div>
<div class="container-fluid">

View File

@ -23,82 +23,84 @@ LICENSE
If not, see [GNU licenses](http://www.gnu.org/licenses).
*/
function processData() {
const input = event.target.files[0]
const reader = new FileReader()
// playFile will process and play the chosen target file.
function playFile() {
const input = event.target.files[0]
const reader = new FileReader()
reader.onload = event => {
bytes = new Uint8Array(event.target.result)
reader.onload = event => {
bytes = new Uint8Array(event.target.result)
// decode adpcm to pcm
var decoded = decode(Array.from(bytes))
// Decode adpcm to pcm.
var decoded = decode(Array.from(bytes))
// convert raw pcm to wav TODO(Trek): make these configurable.
var wav = pcmToWav(decoded, 48000, 1, 16);
// Convert raw pcm to wav TODO(Trek): make these configurable.
var wav = pcmToWav(decoded, 48000, 1, 16);
// play wav data in player
const blob = new Blob([Uint8Array.from(wav)], {
type: 'audio/wav'
});
const url = URL.createObjectURL(blob);
// Play wav data in player.
const blob = new Blob([Uint8Array.from(wav)], {
type: 'audio/wav'
});
const url = URL.createObjectURL(blob);
const audio = document.getElementById('audio');
const source = document.getElementById('source');
const audio = document.getElementById('audio');
const source = document.getElementById('source');
source.src = url;
audio.load();
audio.play();
}
reader.onerror = error => reject(error)
reader.readAsArrayBuffer(input)
source.src = url;
audio.load();
audio.play();
}
reader.onerror = error => reject(error)
reader.readAsArrayBuffer(input)
}
// getQuery gets everything after the question mark in the URL.
function getQuery() {
var regex = new RegExp("\\?(.*)");
var match = regex.exec(window.location.href);
if (match == null) {
return '';
} else {
return decodeURIComponent(match[1].replace(/\+/g, " "));
}
var regex = new RegExp("\\?(.*)");
var match = regex.exec(window.location.href);
if (match == null) {
return '';
} else {
return decodeURIComponent(match[1].replace(/\+/g, " "));
}
}
// load gets the file from the given url and displays a link for download.
function load() {
var url = document.getElementById('url').value;
if (url == "") {
url = getQuery()
document.getElementById('url').value = url;
}
if (url[0] == '/') {
url = window.location.protocol + '//' + window.location.host + url;
}
if (url == "") {
return;
}
var url = document.getElementById('url').value;
if (url == "") {
url = getQuery()
document.getElementById('url').value = url;
}
if (url[0] == '/') {
url = window.location.protocol + '//' + window.location.host + url;
}
if (url == "") {
return;
}
var request = new XMLHttpRequest();
request.responseType = "blob";
request.onreadystatechange = function () {
if (request.readyState === XMLHttpRequest.DONE) {
if (request.status === 200) {
console.log("request received");
var request = new XMLHttpRequest();
request.responseType = "blob";
request.onreadystatechange = function () {
if (request.readyState === XMLHttpRequest.DONE) {
if (request.status === 200) {
console.log("request received");
data = request.response;
data = request.response;
dataURL = URL.createObjectURL(data);
dataURL = URL.createObjectURL(data);
var link = document.getElementById("link");
link.href = dataURL;
link.download = "media.ts";
link.innerHTML = "Download";
var link = document.getElementById("link");
link.href = dataURL;
link.download = "media.ts";
link.innerHTML = "Download";
} else {
console.log('There was a problem with the request. Status: ' + request.status);
}
}
}
request.open("GET", url, true);
request.send();
} else {
console.log('There was a problem with the request. Status: ' + request.status);
}
}
}
request.open("GET", url, true);
request.send();
}

View File

@ -24,24 +24,24 @@ LICENSE
// pcmToWav takes raw pcm data along with the sample rate, number of channels and bit-depth,
// and adds a WAV header to it so that it can be read and played by common players.
// input and output data bytes are represented as arrays of 8 bit integers.
// Input and output data bytes are represented as arrays of 8 bit integers.
// WAV spec.: http://soundfile.sapp.org/doc/WaveFormat/
function pcmToWav(data, rate, channels, bitdepth) {
subChunk2ID = [100, 97, 116, 97]; // "data"
subChunk2ID = [100, 97, 116, 97]; // "data".
subChunk2Size = int32ToBytes(data.length);
subChunk1ID = [102, 109, 116, 32]; // "fmt "
subChunk1ID = [102, 109, 116, 32]; // "fmt ".
subChunk1Size = int32ToBytes(16);
audioFmt = int16ToBytes(1); // 1 = PCM
audioFmt = int16ToBytes(1); // 1 = PCM.
numChannels = int16ToBytes(channels);
sampleRate = int32ToBytes(rate);
byteRate = int32ToBytes(rate * channels * bitdepth / 8);
blockAlign = int16ToBytes(channels * bitdepth / 8);
bitsPerSample = int16ToBytes(bitdepth)
chunkID = [82, 73, 70, 70]; // "RIFF"
chunkID = [82, 73, 70, 70]; // "RIFF".
chunkSize = int32ToBytes(36 + data.length);
format = [87, 65, 86, 69]; // "WAVE"
format = [87, 65, 86, 69]; // "WAVE".
result = chunkID;
result.push(...chunkSize, ...format, ...subChunk1ID, ...subChunk1Size, ...audioFmt, ...numChannels, ...sampleRate, ...byteRate, ...blockAlign, ...bitsPerSample, ...subChunk2ID, ...subChunk2Size);