1
0
mirror of https://github.com/kkapsner/CanvasBlocker synced 2024-12-23 05:10:27 +01:00
CanvasBlocker/lib/modifiedAudioAPI.js

278 lines
8.1 KiB
JavaScript
Raw Normal View History

2018-06-16 00:22:31 +02:00
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
(function(){
"use strict";
2019-11-28 01:26:35 +01:00
let scope;
2018-06-16 00:22:31 +02:00
if ((typeof exports) !== "undefined"){
scope = exports;
}
else {
2019-03-12 22:24:23 +01:00
scope = require.register("./modifiedAudioAPI", {});
2018-06-16 00:22:31 +02:00
}
2018-06-30 00:34:20 +02:00
const {sha256String: hashing} = require("./hash");
2019-12-10 15:07:22 +01:00
const {checkerWrapper, setFunctionProperties, getStatusByFlag} = require("./modifiedAPIFunctions");
2018-06-16 00:22:31 +02:00
2019-11-28 01:26:35 +01:00
let randomSupply = null;
2018-06-16 00:22:31 +02:00
2018-06-21 00:20:41 +02:00
const getAudioFakeRate = function(){
const audioFakeRate = {
2019-11-28 01:26:35 +01:00
"1": function(){return 1;},
"10": function(){return 10;},
"100": function(){return 100;},
"1000": function(){return 1000;},
2018-06-21 00:20:41 +02:00
"0.1%": function(array){return array.length / 1000;},
"1%": function(array){return array.length / 100;},
"10%": function(array){return array.length / 10;},
"100%": function(array){return array.length;},
2018-06-21 00:20:41 +02:00
};
return function getAudioFakeRate(array, prefs){
2019-11-28 01:26:35 +01:00
const func = audioFakeRate[prefs("audioFakeRate")];
2018-06-21 00:20:41 +02:00
if (typeof func === "function"){
return func(array);
}
else {
return 10;
}
};
}();
const getAudioNoiseLevel = function(){
const audioNoiseLevel = {
"minimal": 0.0001,
"low": 0.0005,
"medium": 0.001,
"high": 0.005,
"maximal": 0.01
};
return function getAudioNoiseLevel(prefs){
return audioNoiseLevel[prefs("audioNoiseLevel")] || 0.0001;
};
}();
function forEachFixedIndex(prefs, callback){
if (prefs("audioUseFixedIndices")){
prefs("audioFixedIndices")
.split(",")
.map(function(str){
return parseInt(str, 10);
}).filter(function(num){
return !isNaN(num);
}).filter(function(num, i, array){
return array.indexOf(num) === i;
}).forEach(callback);
2018-06-16 00:22:31 +02:00
}
}
2018-06-21 00:20:41 +02:00
function forEachIndex(array, prefs, callback){
2019-11-28 01:26:35 +01:00
const length = array.length;
const rate = getAudioFakeRate(array, prefs);
let start = 0;
2018-06-21 00:20:41 +02:00
forEachFixedIndex(prefs, function(index){
callback(index, start);
start += 1;
});
if (start < rate){
2019-11-28 01:26:35 +01:00
const delta = Math.floor(length / (rate - start));
const indexRng = randomSupply.getIndexRng(1, length - delta * (rate - start - 1), window);
let offset = indexRng(0);
for (let i = start; i < rate; i += 1){
callback(offset, i);
offset += delta;
}
2018-06-21 00:20:41 +02:00
}
2018-06-16 00:22:31 +02:00
}
2018-06-30 00:34:20 +02:00
const floatCache = Object.create(null);
const intCache = Object.create(null);
function arrayHasAnyNonZero(array){
2019-11-28 01:26:35 +01:00
for (let i = 0, l = array.length; i < l; i += 1){
if (array[i]){
return true;
}
}
return false;
}
2018-06-16 00:22:31 +02:00
function fakeFloat32Array(array, window, prefs){
if (arrayHasAnyNonZero(array)){
2018-06-30 00:34:20 +02:00
let cached = false;
let hash;
if (prefs("useAudioCache")){
hash = hashing(array);
cached = floatCache[hash];
}
if (!cached){
2019-11-28 01:26:35 +01:00
const rate = getAudioFakeRate(array, prefs);
const noiseLevel = getAudioNoiseLevel(prefs);
const rng = randomSupply.getRng(rate, window);
2018-06-30 00:34:20 +02:00
forEachIndex(array, prefs, function(index, i){
let value;
if (array[index] !== 0){
value = array[index] * (1 + (rng(i) / 0xffffffff - 0.5) * noiseLevel);
}
else {
value = Number.EPSILON * (rng(i) / 0xffffffff - 0.5) * noiseLevel;
}
array[index] = value;
});
if (prefs("useAudioCache")){
2019-05-22 10:06:11 +02:00
floatCache[hash] = new array.constructor(array);
floatCache[hashing(array)] = floatCache[hash];
}
2018-06-30 00:34:20 +02:00
}
else {
array.set(cached);
}
2018-06-16 00:22:31 +02:00
}
}
function fakeUint8Array(array, window, prefs){
if (arrayHasAnyNonZero(array)){
2018-06-30 00:34:20 +02:00
let cached = false;
let hash;
if (prefs("useAudioCache")){
hash = hashing(array);
cached = intCache[hash];
}
if (!cached){
2019-11-28 01:26:35 +01:00
const rate = getAudioFakeRate(array, prefs);
const rng = randomSupply.getValueRng(rate, window);
forEachIndex(array, prefs, function(index, i){
2018-06-30 00:34:20 +02:00
array[index] = rng(array[index], i);
});
if (prefs("useAudioCache")){
2019-05-22 10:06:11 +02:00
intCache[hash] = new array.constructor(array);
intCache[hashing(array)] = intCache[hash];
2018-06-30 00:34:20 +02:00
}
}
else {
array.set(cached);
}
2018-06-16 00:22:31 +02:00
}
}
scope.setRandomSupply = function(supply){
randomSupply = supply;
};
const getChannelDataAlreadyFakedArrays = new WeakMap();
2018-06-16 00:22:31 +02:00
// changed functions and their fakes
scope.changedFunctions = {
getFloatFrequencyData: {
object: ["AnalyserNode"],
2018-07-13 16:58:13 +02:00
fakeGenerator: function(checker){
2018-06-16 00:22:31 +02:00
return function getFloatFrequencyData(array){
2018-07-13 16:58:13 +02:00
return checkerWrapper(checker, this, arguments, function(args, check){
2019-11-28 01:26:35 +01:00
const {prefs, notify, window, original} = check;
2018-09-16 12:09:48 +02:00
notify("fakedAudioReadout");
2019-11-28 01:26:35 +01:00
const ret = original.apply(this, window.Array.from(args));
2018-07-13 16:58:13 +02:00
fakeFloat32Array(array, window, prefs);
return ret;
});
2018-06-16 00:22:31 +02:00
};
}
},
getByteFrequencyData: {
object: ["AnalyserNode"],
2018-07-13 16:58:13 +02:00
fakeGenerator: function(checker){
2018-06-16 00:22:31 +02:00
return function getByteFrequencyData(array){
2018-07-13 16:58:13 +02:00
return checkerWrapper(checker, this, arguments, function(args, check){
2019-11-28 01:26:35 +01:00
const {prefs, notify, window, original} = check;
2018-09-16 12:09:48 +02:00
notify("fakedAudioReadout");
2019-11-28 01:26:35 +01:00
const ret = original.apply(this, window.Array.from(args));
2018-07-13 16:58:13 +02:00
fakeUint8Array(array, window, prefs);
return ret;
});
2018-06-16 00:22:31 +02:00
};
}
},
getFloatTimeDomainData: {
object: ["AnalyserNode"],
2018-07-13 16:58:13 +02:00
fakeGenerator: function(checker){
2018-06-16 00:22:31 +02:00
return function getFloatTimeDomainData(array){
2018-07-13 16:58:13 +02:00
return checkerWrapper(checker, this, arguments, function(args, check){
2019-11-28 01:26:35 +01:00
const {prefs, notify, window, original} = check;
2018-09-16 12:09:48 +02:00
notify("fakedAudioReadout");
2019-11-28 01:26:35 +01:00
const ret = original.apply(this, window.Array.from(args));
2018-07-13 16:58:13 +02:00
fakeFloat32Array(array, window, prefs);
return ret;
});
2018-06-16 00:22:31 +02:00
};
}
},
getByteTimeDomainData: {
object: ["AnalyserNode"],
2018-07-13 16:58:13 +02:00
fakeGenerator: function(checker){
2018-06-16 00:22:31 +02:00
return function getByteTimeDomainData(array){
2018-07-13 16:58:13 +02:00
return checkerWrapper(checker, this, arguments, function(args, check){
2019-11-28 01:26:35 +01:00
const {prefs, notify, window, original} = check;
2018-09-16 12:09:48 +02:00
notify("fakedAudioReadout");
2019-11-28 01:26:35 +01:00
const ret = original.apply(this, window.Array.from(args));
2018-07-13 16:58:13 +02:00
fakeUint8Array(array, window, prefs);
return ret;
});
2018-06-16 00:22:31 +02:00
};
}
},
getChannelData: {
object: ["AudioBuffer"],
2018-07-13 16:58:13 +02:00
fakeGenerator: function(checker){
2019-11-28 01:26:35 +01:00
// eslint-disable-next-line no-unused-vars
2018-06-16 00:22:31 +02:00
return function getChannelData(channel){
2018-07-13 16:58:13 +02:00
return checkerWrapper(checker, this, arguments, function(args, check){
2019-11-28 01:26:35 +01:00
const {prefs, notify, window, original} = check;
const ret = original.apply(this, window.Array.from(args));
if (!getChannelDataAlreadyFakedArrays.get(ret)){
notify("fakedAudioReadout");
fakeFloat32Array(ret, window, prefs);
getChannelDataAlreadyFakedArrays.set(ret, true);
}
2018-07-13 16:58:13 +02:00
return ret;
});
2018-06-16 00:22:31 +02:00
};
}
},
copyFromChannel: {
object: ["AudioBuffer"],
2018-07-13 16:58:13 +02:00
fakeGenerator: function(checker){
2019-11-28 01:26:35 +01:00
// eslint-disable-next-line no-unused-vars
2018-06-16 00:22:31 +02:00
return function copyFromChannel(destination, channelNumber, startInChannel){
2018-07-13 16:58:13 +02:00
return checkerWrapper(checker, this, arguments, function(args, check){
2019-11-28 01:26:35 +01:00
const {prefs, notify, window, original} = check;
const channelData = this.getChannelData(channelNumber);
if (!getChannelDataAlreadyFakedArrays.get(channelData)){
notify("fakedAudioReadout");
fakeFloat32Array(channelData, window, prefs);
getChannelDataAlreadyFakedArrays.set(channelData, true);
}
2019-11-28 01:26:35 +01:00
const ret = original.apply(this, window.Array.from(args));
2018-07-13 16:58:13 +02:00
return ret;
});
2018-06-16 00:22:31 +02:00
};
}
},
getFrequencyResponse: {
object: ["BiquadFilterNode", "IIRFilterNode"],
2018-07-13 16:58:13 +02:00
fakeGenerator: function(checker){
2019-11-28 01:26:35 +01:00
// eslint-disable-next-line no-unused-vars
2018-06-16 00:22:31 +02:00
return function getFrequencyResponse(frequencyArray, magResponseOutput, phaseResponseOutput){
2018-07-13 16:58:13 +02:00
return checkerWrapper(checker, this, arguments, function(args, check){
2019-11-28 01:26:35 +01:00
const {prefs, notify, window, original} = check;
2018-09-16 12:09:48 +02:00
notify("fakedAudioReadout");
2019-11-28 01:26:35 +01:00
const ret = original.apply(this, window.Array.from(args));
2018-07-13 16:58:13 +02:00
fakeFloat32Array(magResponseOutput, window, prefs);
fakeFloat32Array(phaseResponseOutput, window, prefs);
return ret;
});
2018-06-16 00:22:31 +02:00
};
}
},
};
2019-12-10 15:07:22 +01:00
setFunctionProperties(scope.changedFunctions, {
type: "readout",
getStatus: getStatusByFlag("protectAudio"),
api: "audio"
});
2018-06-16 00:22:31 +02:00
}());