Skip to content

Commit

Permalink
Adding copyFromChannel for audio fingerprinting
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathanKingston committed Feb 26, 2021
1 parent c2a57df commit 4afd4bd
Showing 1 changed file with 120 additions and 36 deletions.
156 changes: 120 additions & 36 deletions privacy-protections/fingerprinting/helpers/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -994,50 +994,91 @@ const tests = [
{
id: 'audio',
category: 'full-fingerprints',
getValue: () => {
let resolve;
const promise = new Promise((res, rej) => { resolve = res; });
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 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;
}
},
{
id: 'audio-analyserNode-getByteTimeDomainData',
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 analyser = context.createAnalyser();
const dataArray = new Uint8Array(analyser.fftSize);

await applyFpExampleDataToAudio(context, analyser);

// still pefixed in Safari
analyser.getByteTimeDomainData(dataArray);
return dataArray.reduce((acc, val) => { return acc + Math.abs(val); }, 0);
}
},
{
id: 'audio-analyserNode-getFloatTimeDomainData',
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 analyser = context.createAnalyser();
const dataArray = new Float32Array(analyser.fftSize);

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);
}
});
await applyFpExampleDataToAudio(context, analyser);

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();
analyser.getFloatTimeDomainData(dataArray);
return dataArray.reduce((acc, val) => { return acc + Math.abs(val); }, 0);
}
},
{
id: 'audio-analyserNode-getByteFrequencyData',
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 analyser = context.createAnalyser();
const dataArray = new Uint8Array(analyser.frequencyBinCount);

resolve(fingerprint);
};
await applyFpExampleDataToAudio(context, analyser);

oscillator.connect(compressor);
compressor.connect(context.destination);
oscillator.start(0);
context.startRendering();
analyser.getByteFrequencyData(dataArray);
return dataArray.reduce((acc, val) => { return acc + Math.abs(val); }, 0);
}
},
{
id: 'audio-analyserNode-getFloatFrequencyData',
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 analyser = context.createAnalyser();
const dataArray = new Float32Array(analyser.frequencyBinCount);

return promise;
await applyFpExampleDataToAudio(context, analyser);

analyser.getFloatFrequencyData(dataArray);
return dataArray.reduce((acc, val) => { return acc + Math.abs(val); }, 0);
}
},
{
Expand Down Expand Up @@ -1365,3 +1406,46 @@ function applyFpExampleDataToCanvas (canvas) {
ctx.arc(75, 75, 25, 0, Math.PI * 2, true);
ctx.fill('evenodd');
}

function applyFpExampleDataToAudio (context, analyzerNode) {
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);
if (analyzerNode) {
compressor.connect(analyzerNode);
analyzerNode.connect(context.destination);
} else {
compressor.connect(context.destination);
}
oscillator.start(0);
context.startRendering();

return promise;
}

0 comments on commit 4afd4bd

Please sign in to comment.