From 38dc3e8d189727255f77f0363fb938655e248e26 Mon Sep 17 00:00:00 2001 From: Jonathan Kingston Date: Tue, 23 Feb 2021 00:13:14 +0000 Subject: [PATCH] Adding copyFromChannel for audio fingerprinting --- .../fingerprinting/helpers/tests.js | 103 +++++++++++------- 1 file changed, 61 insertions(+), 42 deletions(-) diff --git a/privacy-protections/fingerprinting/helpers/tests.js b/privacy-protections/fingerprinting/helpers/tests.js index e86e1ef..1110729 100644 --- a/privacy-protections/fingerprinting/helpers/tests.js +++ b/privacy-protections/fingerprinting/helpers/tests.js @@ -994,50 +994,31 @@ const tests = [ { id: 'audio', category: 'full-fingerprints', - getValue: () => { - let resolve; - const promise = new Promise((res, rej) => { resolve = res; }); - - // still pefixed in Safari + getValue: async () => { // eslint-disable-next-line new-cap const context = window.OfflineAudioContext ? new OfflineAudioContext(1, 44100, 44100) : new webkitOfflineAudioContext(1, 44100, 44100); - - const oscillator = context.createOscillator(); - oscillator.type = 'triangle'; - oscillator.frequency.setValueAtTime(10000, context.currentTime); - - const compressor = context.createDynamicsCompressor(); - - [ - ['threshold', -50], - ['knee', 40], - ['ratio', 12], - ['reduction', -20], - ['attack', 0], - ['release', 0.25] - ].forEach(function (item) { - if (compressor[item[0]] !== undefined && typeof compressor[item[0]].setValueAtTime === 'function') { - compressor[item[0]].setValueAtTime(item[1], context.currentTime); - } - }); - - context.oncomplete = (event) => { - const fingerprint = event.renderedBuffer.getChannelData(0) - .slice(4500, 5000) - .reduce(function (acc, val) { return acc + Math.abs(val); }, 0) - .toString(); - oscillator.disconnect(); - compressor.disconnect(); - - resolve(fingerprint); - }; - - oscillator.connect(compressor); - compressor.connect(context.destination); - oscillator.start(0); - context.startRendering(); - - return promise; + const renderedBuffer = await applyFpExampleDataToAudio(context); + const fingerprint = renderedBuffer.getChannelData(0) + .slice(4500, 5000) + .reduce(function (acc, val) { return acc + Math.abs(val); }, 0) + .toString(); + return fingerprint; + } + }, + { + id: 'audio-copyFromChannel', + category: 'full-fingerprints', + getValue: async () => { + // eslint-disable-next-line new-cap + const context = window.OfflineAudioContext ? new OfflineAudioContext(1, 44100, 44100) : new webkitOfflineAudioContext(1, 44100, 44100); + const renderedBuffer = await applyFpExampleDataToAudio(context); + const copiedData = new Float32Array(renderedBuffer.length); + renderedBuffer.copyFromChannel(copiedData, 0, 0); + + const fingerprint = copiedData.slice(4500, 5000) + .reduce(function (acc, val) { return acc + Math.abs(val); }, 0) + .toString(); + return fingerprint; } }, { @@ -1365,3 +1346,41 @@ function applyFpExampleDataToCanvas (canvas) { ctx.arc(75, 75, 25, 0, Math.PI * 2, true); ctx.fill('evenodd'); } + +function applyFpExampleDataToAudio (context) { + let resolve; + const promise = new Promise((res, rej) => { resolve = res; }); + + const oscillator = context.createOscillator(); + oscillator.type = 'triangle'; + oscillator.frequency.setValueAtTime(10000, context.currentTime); + + const compressor = context.createDynamicsCompressor(); + + [ + ['threshold', -50], + ['knee', 40], + ['ratio', 12], + ['reduction', -20], + ['attack', 0], + ['release', 0.25] + ].forEach(function (item) { + if (compressor[item[0]] !== undefined && typeof compressor[item[0]].setValueAtTime === 'function') { + compressor[item[0]].setValueAtTime(item[1], context.currentTime); + } + }); + + context.oncomplete = (event) => { + oscillator.disconnect(); + compressor.disconnect(); + + resolve(event.renderedBuffer); + }; + + oscillator.connect(compressor); + compressor.connect(context.destination); + oscillator.start(0); + context.startRendering(); + + return promise; +}