2018-06-30 23:15:47 +02:00
|
|
|
(function(){
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
function byteArrayToHex(arrayBuffer){
|
2019-12-16 19:27:28 +01:00
|
|
|
const chunks = [];
|
2018-06-30 23:15:47 +02:00
|
|
|
(new Uint32Array(arrayBuffer)).forEach(function(num){
|
|
|
|
chunks.push(num.toString(16));
|
|
|
|
});
|
|
|
|
return chunks.map(function(chunk){
|
|
|
|
return "0".repeat(8 - chunk.length) + chunk;
|
|
|
|
}).join("");
|
|
|
|
}
|
|
|
|
|
2019-12-16 19:27:28 +01:00
|
|
|
const container = document.getElementById("test");
|
|
|
|
const hashContainer = container.querySelector(".hashes");
|
2020-05-01 01:11:21 +02:00
|
|
|
const sumsContainer = container.querySelector(".sums");
|
2019-12-16 19:27:28 +01:00
|
|
|
let hashSets = Object.create(null);
|
2018-06-30 23:15:47 +02:00
|
|
|
|
2019-02-10 02:50:21 +01:00
|
|
|
function createSet(set){
|
|
|
|
if (!hashSets[set]){
|
2019-12-16 19:27:28 +01:00
|
|
|
const setContainer = document.createElement("tbody");
|
2019-02-10 02:50:21 +01:00
|
|
|
hashContainer.appendChild(setContainer);
|
2019-12-16 19:27:28 +01:00
|
|
|
const nameRow = document.createElement("tr");
|
2019-02-10 02:50:21 +01:00
|
|
|
setContainer.appendChild(nameRow);
|
2019-12-16 19:27:28 +01:00
|
|
|
const nameContainer = document.createElement("th");
|
2019-02-10 02:50:21 +01:00
|
|
|
nameRow.appendChild(nameContainer);
|
|
|
|
nameContainer.colSpan = 2;
|
|
|
|
nameContainer.textContent = set;
|
2020-05-01 01:06:50 +02:00
|
|
|
hashSets[set] = {firstHash: false, failed: false, hashes: [], setContainer};
|
2019-02-10 02:50:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-16 19:27:28 +01:00
|
|
|
async function displayData(data, set, title){
|
2019-02-10 02:50:21 +01:00
|
|
|
createSet(set);
|
2020-05-01 01:06:50 +02:00
|
|
|
const storage = hashSets[set];
|
2019-02-10 02:50:21 +01:00
|
|
|
|
2020-05-01 01:06:50 +02:00
|
|
|
function addLine(title, hash){
|
|
|
|
const container = document.createElement("tr");
|
|
|
|
|
|
|
|
const titleNode = document.createElement("td");
|
|
|
|
titleNode.textContent = title;
|
|
|
|
container.appendChild(titleNode);
|
|
|
|
|
|
|
|
const hashNode = document.createElement("td");
|
|
|
|
hashNode.textContent = hash;
|
|
|
|
container.appendChild(hashNode);
|
|
|
|
|
|
|
|
storage.setContainer.appendChild(container);
|
|
|
|
return container;
|
|
|
|
}
|
|
|
|
const hash = byteArrayToHex(await crypto.subtle.digest("SHA-256", data));
|
|
|
|
storage.hashes.push({title, hash});
|
2019-12-16 19:27:28 +01:00
|
|
|
|
2020-05-01 01:06:50 +02:00
|
|
|
if (!storage.firstHash){
|
|
|
|
storage.firstHash = hash;
|
|
|
|
storage.allLine = addLine("all tests equal", hash);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (storage.failed){
|
|
|
|
addLine(title, hash);
|
|
|
|
}
|
|
|
|
else if (hash !== storage.firstHash){
|
|
|
|
storage.setContainer.removeChild(storage.allLine);
|
|
|
|
storage.hashes.forEach(function(hash){
|
|
|
|
addLine(hash.title, hash.hash);
|
|
|
|
});
|
|
|
|
storage.failed = true;
|
|
|
|
}
|
|
|
|
}
|
2019-02-10 02:50:21 +01:00
|
|
|
}
|
|
|
|
|
2020-05-01 01:06:50 +02:00
|
|
|
function getAudioContext(frequency = 1e4, type = "triangle", useDelayedValues = false){
|
|
|
|
function set(obj, value){
|
|
|
|
if (useDelayedValues){
|
|
|
|
obj.setTargetAtTime(value, 0, 0.01);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
obj.value = value;
|
|
|
|
}
|
|
|
|
}
|
2019-12-16 19:27:28 +01:00
|
|
|
const context = new window.OfflineAudioContext(2, 44100, 44100);
|
2019-02-10 02:50:21 +01:00
|
|
|
|
2018-06-30 23:15:47 +02:00
|
|
|
// Create oscillator
|
2019-12-16 19:27:28 +01:00
|
|
|
const pxi_oscillator = context.createOscillator();
|
2020-05-01 01:06:50 +02:00
|
|
|
pxi_oscillator.type = type;
|
|
|
|
set(pxi_oscillator.frequency, frequency);
|
2018-06-30 23:15:47 +02:00
|
|
|
|
|
|
|
// Create and configure compressor
|
2019-12-16 19:27:28 +01:00
|
|
|
const pxi_compressor = context.createDynamicsCompressor();
|
2020-05-01 01:06:50 +02:00
|
|
|
pxi_compressor.threshold && set(pxi_compressor.threshold, -50);
|
|
|
|
pxi_compressor.knee && set(pxi_compressor.knee, 40);
|
|
|
|
pxi_compressor.ratio && set(pxi_compressor.ratio, 12);
|
|
|
|
pxi_compressor.reduction && set(pxi_compressor.reduction, -20);
|
|
|
|
pxi_compressor.attack && set(pxi_compressor.attack, 0);
|
|
|
|
pxi_compressor.release && set(pxi_compressor.release, .25);
|
2018-06-30 23:15:47 +02:00
|
|
|
|
|
|
|
// Connect nodes
|
|
|
|
pxi_oscillator.connect(pxi_compressor);
|
|
|
|
pxi_compressor.connect(context.destination);
|
2019-02-10 02:50:21 +01:00
|
|
|
|
2018-06-30 23:15:47 +02:00
|
|
|
pxi_oscillator.start(0);
|
2019-02-10 02:50:21 +01:00
|
|
|
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
|
|
|
|
function createEmptyData(){
|
2019-12-16 19:27:28 +01:00
|
|
|
const emptyArray = new Float32Array(44100);
|
2019-02-10 02:50:21 +01:00
|
|
|
displayData(emptyArray, "empty buffer", "no API involved");
|
|
|
|
|
2019-12-16 19:27:28 +01:00
|
|
|
const emptyContext = new OfflineAudioContext(1, 44100, 44100);
|
|
|
|
const emptyBuffer = emptyContext.createBuffer(1, 44100, 44100);
|
2019-02-10 02:50:21 +01:00
|
|
|
|
2019-12-16 19:27:28 +01:00
|
|
|
const emptyCopy = new Float32Array(44100);
|
2019-02-10 02:50:21 +01:00
|
|
|
emptyBuffer.copyFromChannel(emptyCopy, 0);
|
|
|
|
displayData(emptyCopy, "empty buffer", "copyFromChannel - first");
|
|
|
|
|
2019-12-16 19:27:28 +01:00
|
|
|
const emptyData = emptyBuffer.getChannelData(0);
|
2019-02-10 02:50:21 +01:00
|
|
|
displayData(emptyData, "empty buffer", "getChannelData - first");
|
|
|
|
displayData(emptyBuffer.getChannelData(0), "empty buffer", "getChannelData - second");
|
|
|
|
|
2019-12-16 19:27:28 +01:00
|
|
|
const emptyCopy2 = new Float32Array(44100);
|
2019-02-10 02:50:21 +01:00
|
|
|
emptyBuffer.copyFromChannel(emptyCopy2, 0);
|
|
|
|
displayData(emptyCopy2, "empty buffer", "copyFromChannel - second");
|
|
|
|
}
|
|
|
|
|
2019-05-22 23:55:57 +02:00
|
|
|
function getIframeWindow(){
|
2019-12-16 19:27:28 +01:00
|
|
|
const l = window.length;
|
|
|
|
const iframe = document.createElement("iframe");
|
2019-05-22 23:55:57 +02:00
|
|
|
document.body.appendChild(iframe);
|
|
|
|
const iframeWindow = window[l];
|
|
|
|
document.body.removeChild(iframe);
|
|
|
|
return iframeWindow;
|
|
|
|
}
|
|
|
|
|
2020-05-01 01:06:50 +02:00
|
|
|
function createHashData(frequency = 1e4, type = "triangle", useDelayedValues = false){
|
2019-02-10 02:50:21 +01:00
|
|
|
|
2020-05-01 01:06:50 +02:00
|
|
|
const context = getAudioContext(frequency, type, useDelayedValues);
|
2019-02-10 02:50:21 +01:00
|
|
|
|
2020-05-01 01:06:50 +02:00
|
|
|
const setName = type + " (" + frequency + " Hz)" + (useDelayedValues? " delayed": "");
|
2019-02-10 02:50:21 +01:00
|
|
|
createSet(setName);
|
|
|
|
|
2020-05-01 01:06:50 +02:00
|
|
|
const sumRow = document.createElement("tr");
|
|
|
|
const nameCell = document.createElement("td");
|
|
|
|
nameCell.textContent = setName;
|
|
|
|
sumRow.appendChild(nameCell);
|
|
|
|
const sumCell = document.createElement("td");
|
|
|
|
sumRow.appendChild(sumCell);
|
2020-05-01 01:11:21 +02:00
|
|
|
sumsContainer.appendChild(sumRow);
|
2020-05-01 01:06:50 +02:00
|
|
|
|
2019-02-10 02:50:21 +01:00
|
|
|
// Start audio processing
|
2018-06-30 23:15:47 +02:00
|
|
|
context.startRendering();
|
2019-02-10 02:50:21 +01:00
|
|
|
context.oncomplete = function(event){
|
2019-12-16 19:27:28 +01:00
|
|
|
const copyTestIframe = new (getIframeWindow().Float32Array)(44100);
|
2019-05-22 23:55:57 +02:00
|
|
|
getIframeWindow().AudioBuffer.prototype.copyFromChannel.call(event.renderedBuffer, copyTestIframe, 0);
|
|
|
|
displayData(copyTestIframe, setName, "copyFromChannel - iframe");
|
|
|
|
|
2019-12-16 19:27:28 +01:00
|
|
|
const chunkTest = new Float32Array(44100);
|
|
|
|
const number = new Float32Array(100);
|
|
|
|
for (let chunkI = 0; chunkI < 44100; chunkI += number.length){
|
2019-03-12 22:30:37 +01:00
|
|
|
event.renderedBuffer.copyFromChannel(number, 0, chunkI);
|
|
|
|
chunkTest.set(number, chunkI);
|
2019-02-10 02:50:21 +01:00
|
|
|
}
|
|
|
|
displayData(chunkTest, setName, "copyFromChannel - chunks");
|
|
|
|
|
2019-12-16 19:27:28 +01:00
|
|
|
const copyTest = new Float32Array(44100);
|
2018-08-22 22:16:49 +02:00
|
|
|
event.renderedBuffer.copyFromChannel(copyTest, 0);
|
2019-02-10 02:50:21 +01:00
|
|
|
displayData(copyTest, setName, "copyFromChannel - first");
|
|
|
|
|
|
|
|
|
2019-12-16 19:27:28 +01:00
|
|
|
const getTest = event.renderedBuffer.getChannelData(0);
|
2019-02-10 02:50:21 +01:00
|
|
|
displayData(getTest, setName, "getChannelData - first");
|
|
|
|
displayData(event.renderedBuffer.getChannelData(0), setName, "getChannelData - second readout");
|
|
|
|
displayData(event.renderedBuffer.getChannelData(1), setName, "getChannelData - second channel");
|
|
|
|
|
2019-12-16 19:27:28 +01:00
|
|
|
const copyTest2 = new Float32Array(44100);
|
2019-02-10 02:50:21 +01:00
|
|
|
event.renderedBuffer.copyFromChannel(copyTest2, 0);
|
|
|
|
displayData(copyTest2, setName, "copyFromChannel - second");
|
|
|
|
|
2020-05-01 01:06:50 +02:00
|
|
|
let sum = 0;
|
|
|
|
for (let i = 4500; i < 5000; i += 1) {
|
|
|
|
sum += Math.abs(getTest[i]);
|
2018-06-30 23:15:47 +02:00
|
|
|
}
|
2020-05-01 01:06:50 +02:00
|
|
|
sumCell.textContent = sum;
|
2018-06-30 23:15:47 +02:00
|
|
|
};
|
|
|
|
}
|
2019-02-10 02:50:21 +01:00
|
|
|
|
|
|
|
function createAllHashData(){
|
|
|
|
hashContainer.innerHTML = "";
|
2020-05-01 01:11:21 +02:00
|
|
|
sumsContainer.innerHTML = "";
|
2019-02-10 02:50:21 +01:00
|
|
|
hashSets = Object.create(null);
|
|
|
|
createEmptyData();
|
|
|
|
createHashData(1e4);
|
|
|
|
createHashData(2e4);
|
2020-05-01 01:06:50 +02:00
|
|
|
createHashData(1e4, "sine");
|
|
|
|
createHashData(2e4, "sine");
|
|
|
|
createHashData(1e4, undefined, true);
|
|
|
|
createHashData(2e4, undefined, true);
|
|
|
|
createHashData(1e4, "sine", true);
|
|
|
|
createHashData(2e4, "sine", true);
|
2019-02-10 02:50:21 +01:00
|
|
|
}
|
|
|
|
createAllHashData();
|
|
|
|
container.querySelector("button").addEventListener("click", createAllHashData);
|
2018-06-30 23:15:47 +02:00
|
|
|
}());
|