new synthesis

This commit is contained in:
gauthiier 2015-08-17 10:25:09 +02:00
parent eccdb21264
commit 11a906f725
6 changed files with 647 additions and 0 deletions

17
synthesis/index.html Normal file
View File

@ -0,0 +1,17 @@
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>http micro tempo</title>
<script src="https://code.jquery.com/jquery-1.8.2.js"></script>
<script src="https://jquery-csv.googlecode.com/git/src/jquery.csv.js"></script>
<script src="https://raw.githubusercontent.com/mbostock/d3/master/d3.min.js"></script>
<script src="lib/ssss.js"></script> <!-- data -->
<script src="lib/yyyy.js"></script> <!-- audio -->
<script src="lib/nnnn.js"></script> <!-- svg -->
<script src="lib/tttt.js"></script> <!-- main -->
<script src="lib/hhhh.js"></script> <!-- synth defs -->
</head>
<body>
<svg id="track"></svg>
</body>
</html>

55
synthesis/lib/hhhh.js Normal file
View File

@ -0,0 +1,55 @@
var modfactor = 750.0;
var modfactor_gain = 10750.0;
function create_none_synth() {
var s = new FMSynth('triangle', 100, 'saw', 2, 300);
s.add_filter(new LowPassFilter());
s.update = function(val) {
this.modulator_freq(val / modfactor);
};
return s;
}
function create_ad_synth() {
var s = new SimpleOscillator('square', 100);
s.add_filter(new NoiseConvolver());
s.update = function(val) {
this.modulator_freq(val / 25);
};
return s;
}
function create_tracker_synth() {
var s = new PinkNoiseGenerator();
//s.add_filter(new NoiseConvolver());
s.update = function(val) {
this.modulator_gain(val / modfactor_gain);
};
return s;
}
function create_analytics_synth() {
var s = new WhiteNoiseGenerator();
//s.add_filter(new DistortionShaper(55));
s.update = function(val) {
this.modulator_gain(val / modfactor_gain);
};
return s;
}
function create_widget_synth() {
var s = new PinkNoiseGenerator();
s.update = function(val) {
this.modulator_gain(val / modfactor_gain);
};
return s;
}
function create_privacy_synth() {
var s = new WhiteNoiseGenerator();
s.update = function(val) {
this.modulator_gain(val / modfactor_gain);
};
return s;
}

60
synthesis/lib/nnnn.js Normal file
View File

@ -0,0 +1,60 @@
var refresh_rate_ms = 4;
var bb;
function draw(url) {
if(/csv$/.test(url)) {
url = url + '.svg';
} else {
return;
}
d3.xml(url, function(xml) {
svg_node = document.importNode(xml.documentElement, true);
svg = d3.select('#track');
svg.style('width', svg_node.width.baseVal.value);
svg.style('height', svg_node.height.baseVal.value);
svg.node().appendChild(svg_node);
d3.select(svg_node)
.attr('id', 'svg_track');
// <input type="button" value="wwwwwwaaavves" onclick="start('wpt_05_[NY Times]_[Amsterdam]_object__filtered.csv')">
var g = d3.select(svg_node).append('g');
var b = g.append('foreignObject')
.attr('x', '85')
.attr('y', '350')
.attr('width', '100')
.attr('height', '100')
.append('xhtml:body');
bb = b.append('input')
.attr('type', 'button')
.attr('value', 'synthesise')
.attr('onclick', 'go()');
var line = svg.append('svg:line')
.attr('x1', 0)
.attr('y1', 0)
.attr('x2', 0)
.attr('y1', svg_node.height.baseVal.value)
.style('stroke', 'rgb(255,0,0)')
.style('stroke-width', 1);
window.setInterval( function() {
line.attr('x1', tick_cnt); //var tick_cnt = 0; // from ssss.js
line.attr('x2', tick_cnt);
}, refresh_rate_ms);
});
}
function go() {
if(bb.attr('value') == 'pause') {
bb.attr('value', 'synthesise');
stop_all_synths();
} else {
bb.attr('value', 'pause');
start_all_synths();
}
}

193
synthesis/lib/ssss.js Normal file
View File

@ -0,0 +1,193 @@
var data = [];
var start_times_dict = {};
var end_times_dict = {};
var start_times = [];
var end_times = [];
var next_start = 0;
var next_end = 0;
var processing_data = [];
// timer parameters
var tick_cnt = 0; /// this is passed to the drawing
var time_incr_ms = 2;
var time_end = 0;
var interval_id = 0;
var p = true;
var params = {
"-" : {'bytes': 0, 'synth': null, 'active': 0},
"ad" : {'bytes': 0, 'synth': null, 'active': 0},
"tracker" : {'bytes': 0, 'synth': null, 'active': 0},
"analytics" : {'bytes': 0, 'synth': null, 'active': 0},
"widget" : {'bytes': 0, 'synth': null, 'active': 0},
"privacy" : {'bytes': 0, 'synth': null, 'active': 0}
};
function synthesise(csv_input_file_url) {
$.ajax({
type: 'GET',
url: csv_input_file_url,
dataType: 'text',
success: function(resp) {
data = $.csv.toObjects(resp);
start_times = {};
end_times = {};
for(var i = 0; i < data.length; i++) {
var start = +data[i]['Start Time (ms)'];
var end = +data[i]['End Time (ms)'];
var size = +data[i]['Object Size'];
if(!(start in start_times_dict)) {
start_times_dict[start] = [];
}
start_times_dict[start].push(i);
if(!(end in end_times_dict)) {
end_times_dict[end] = [];
}
end_times_dict[end].push(i);
data[i].incr = linear_increment(start, end, size);
data[i].incr_tick = 0;
if(end > time_end) time_end = end;
}
$('#end').html(time_end);
start_times = Object.keys(start_times_dict);
end_times = Object.keys(end_times_dict);
start_times.sort(function(a, b){
return a - b;
});
end_times.sort(function(a, b) {
return a - b;
});
// create synths
params['-'].synth = create_none_synth();
params['ad'].synth = create_ad_synth();
params['tracker'].synth = create_tracker_synth();
params['analytics'].synth = create_analytics_synth();
params['widget'].synth = create_widget_synth();
params['privacy'].synth = create_privacy_synth();
stop_all_synths();
interval_id = window.setInterval(tick, time_incr_ms);
},
error: function(xhr, status, error) {
console.log("error loading -- " + csv_input_file);
}
});
}
function linear_increment(start_ms, end_ms, size_bytes) {
return size_bytes / (end_ms - start_ms);
}
function start_all_synths() {
p = false;
params['-'].synth.start();
params['ad'].synth.start();
params['tracker'].synth.start();
params['analytics'].synth.start();
params['widget'].synth.start();
params['privacy'].synth.start();
}
function stop_all_synths() {
p = true;
params['-'].synth.stop();
params['ad'].synth.stop();
params['tracker'].synth.stop();
params['analytics'].synth.stop();
params['widget'].synth.stop();
params['privacy'].synth.stop();
}
function tick() {
if(p) return;
$('#time').html(tick_cnt);
if(tick_cnt >= time_end + 1) {
window.clearInterval(interval_id);
stop_all_synths();
} else if(tick_cnt == 0) {
start_all_synths();
}
if(start_times[next_start] == tick_cnt) {
var start_indices = start_times_dict[tick_cnt];
processing_data = processing_data.concat(start_indices)
for(var i = 0; i < start_indices.length; i++) {
var d = data[start_indices[i]]
params[d.bug_type].active = params[d.bug_type].active + 1;
}
next_start++;
}
if(end_times[next_end] == tick_cnt) {
var end_indices = end_times_dict[tick_cnt];
for(var i = 0; i < end_indices.length; i++) {
var processing_indx = processing_data.indexOf(end_indices[i]);
if(processing_indx != -1) {
var d = data[end_indices[i]]
processing_data.splice(processing_indx, 1);
params[d.bug_type].bytes -= parseInt(d['Object Size']);
params[d.bug_type].active = params[d.bug_type].active - 1;
} else {
console.log('not proccesed -- ' + end_indices[i]);
}
}
next_end++;
}
for(var i = 0; i < processing_data.length; i++) {
var d = data[processing_data[i]];
params[d.bug_type].bytes += d.incr;
d.incr_tick = d.incr_tick + 1;
}
params['-'].synth.update(params['-'].bytes);
params['ad'].synth.update(params['ad'].bytes);
params['tracker'].synth.update(params['tracker'].bytes);
params['analytics'].synth.update(params['analytics'].bytes);
params['widget'].synth.update(params['widget'].bytes);
params['privacy'].synth.update(params['privacy'].bytes);
// $('#none').html(params['-'].active);
// $('#none_bytes').html(Math.ceil(params['-'].bytes));
// $('#ad').html(params['ad'].active);
// $('#ad_bytes').html(Math.ceil(params['ad'].bytes));
// $('#tracker').html(params['tracker'].active);
// $('#tracker_bytes').html(Math.ceil(params['tracker'].bytes));
// $('#analytics').html(params['analytics'].active);
// $('#analytics_bytes').html(Math.ceil(params['analytics'].bytes));
// $('#widget').html(params['widget'].active);
// $('#widget_bytes').html(Math.ceil(params['widget'].bytes));
// $('#privacy').html(params['privacy'].active);
// $('#privacy_bytes').html(Math.ceil(params['privacy'].bytes));
tick_cnt++;
}

20
synthesis/lib/tttt.js Normal file
View File

@ -0,0 +1,20 @@
var svg_repo_url = "http://gauthiier.github.io/www-micro-temporalities/img/scores/";
var csv_repo_url = "https://raw.githubusercontent.com/gauthiier/www-micro-temporalities/master/webpagetest/filtered/";
var data_ref = get_param('ref');
if(data_ref === "") {
console.log('no ref aborting...');
} else {
console.log('ref: ' + data_ref);
draw(svg_repo_url + data_ref);
synthesise(csv_repo_url + data_ref);
}
function get_param(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}

302
synthesis/lib/yyyy.js Normal file
View File

@ -0,0 +1,302 @@
////////////
////////////////////////////
////////////
var AudioContext = window.AudioContext || window.webkitAudioContext;
var audioCtx = new AudioContext();
function Modulator(waveform, freq, gain) {
// actual modulating freq
this.osc = audioCtx.createOscillator();
this.osc.type = waveform;
this.osc.frequency.value = freq;
// not sure about this -- but the gain is what modulates
this.gain = audioCtx.createGain();
this.gain.gain.value = gain;
// connect
this.osc.connect(this.gain);
}
function Carrier(waveform, freq) {
this.osc = audioCtx.createOscillator();
this.osc.type = waveform;
this.osc.frequency.value = freq;
this.gain = audioCtx.createGain();
this.osc.connect(this.gain);
}
function FMSynth(waveform_c, freq_c, waveform_m, freq_m, gain_m) {
this.carrier = new Carrier(waveform_c, freq_c);
this.modulator = new Modulator(waveform_m, freq_m, gain_m);
this.bitcrusher_filter = new BitCrusherFilter();
this.modulator.gain.connect(this.carrier.osc.frequency);
this.carrier.gain.connect(audioCtx.destination);
this.started = false;
this.start = function() {
if(!this.started) {
this.carrier.osc.start();
this.modulator.osc.start();
this.started = true;
} else {
this.carrier.gain.gain.value = 1.0;
}
}
this.stop = function() {
this.carrier.gain.gain.value = 0.0;
}
this.modulator_freq_incr = function(incr) {
this.modulator.osc.frequency.value = this.modulator.osc.frequency.value + incr;
}
this.modulator_freq = function(freq) {
this.modulator.osc.frequency.value = freq;
}
this.add_filter = function (filter) {
this.filter = filter;
this.carrier.osc.disconnect(this.carrier.gain);
this.carrier.osc.connect(this.filter);
this.filter.connect(this.carrier.gain);
}
}
function SimpleOscillator(waveform, freq) {
this.oscillator = new Carrier(waveform, freq);
this.oscillator.gain.connect(audioCtx.destination);
this.started = false;
this.start = function() {
if(!this.started) {
this.oscillator.osc.start();
this.started = true;
} else {
this.oscillator.gain.gain.value = 1.0;
}
}
this.stop = function() {
this.oscillator.gain.gain.value = 0.0;
}
this.modulator_freq_incr = function(incr) {
this.oscillator.osc.frequency.value = this.modulator.osc.frequency.value + incr;
}
this.modulator_freq = function(freq) {
this.oscillator.osc.frequency.value = freq;
}
this.add_filter = function (filter) {
this.filter = filter;
this.oscillator.osc.disconnect(this.oscillator.gain);
this.oscillator.osc.connect(this.filter);
this.filter.connect(this.oscillator.gain);
}
}
function WhiteNoiseGenerator() {
// generates 2 sec noise buffer
var bufferSize = audioCtx.sampleRate * 2;
var noiseBuffer = audioCtx.createBuffer(1, bufferSize, audioCtx.sampleRate);
var out = noiseBuffer.getChannelData(0);
for(var i = 0; i < bufferSize; i++) {
out[i] = Math.random() * 2 - 1;
}
this.whitenoise = audioCtx.createBufferSource();
this.whitenoise.buffer = noiseBuffer;
this.whitenoise.loop = true;
this.gain = audioCtx.createGain();
this.whitenoise.connect(this.gain);
this.gain.connect(audioCtx.destination);
this.started = false;
this.start = function() {
if(!this.started)
this.whitenoise.start(0);
this.started = true;
}
this.stop = function() {
this.gain.gain.value = 0.0;
this.started = false;
}
this.modulator_gain_incr = function(incr) {
this.gain.gain.value = this.gain.gain.value + incr;
}
this.modulator_gain = function(gain) {
this.gain.gain.value = gain;
}
this.add_filter = function(filter) {
this.filter = filter;
this.whitenoise.disconnect(this.gain);
this.whitenoise.connect(this.filter);
this.filter.connect(this.gain);
}
}
function PinkNoiseGenerator() {
var bufferSize = 4096;
this.pinknoise = audioCtx.createScriptProcessor(bufferSize, 1, 1);
var b0, b1, b2, b3, b4, b5, b6;
b0 = b1 = b2 = b3 = b4 = b5 = b6 = 0.0;
this.pinknoise.onaudioprocess = function(e) {
var out = e.outputBuffer.getChannelData(0);
for(var i = 0; i < bufferSize; i++) {
var white = Math.random() * 2 - 1;
b0 = 0.99886 * b0 + white * 0.0555179;
b1 = 0.99332 * b1 + white * 0.0750759;
b2 = 0.96900 * b2 + white * 0.1538520;
b3 = 0.86650 * b3 + white * 0.3104856;
b4 = 0.55000 * b4 + white * 0.5329522;
b5 = -0.7616 * b5 - white * 0.0168980;
out[i] = b0 + b1 + b2 + b3 + b4 + b5 + b6 + white * 0.5362;
out[i] *= 0.11; // (roughly) compensate for gain
b6 = white * 0.115926;
}
};
this.gain = audioCtx.createGain();
this.pinknoise.connect(this.gain);
this.gain.connect(audioCtx.destination);
this.started = false;
this.start = function() {
}
this.stop = function() {
this.gain.gain.value = 0.0;
this.started = false;
}
this.modulator_gain_incr = function(incr) {
this.gain.gain.value = this.gain.gain.value + incr;
}
this.modulator_gain = function(gain) {
this.gain.gain.value = gain;
}
this.add_filter = function(filter) {
this.filter = filter;
this.pinknoise.disconnect(this.gain);
this.pinknoise.connect(this.filter);
this.filter.connect(this.gain);
}
}
//////////// Filters
function BitCrusherFilter() {
var bufferSize = 4096;
var node = audioCtx.createScriptProcessor(bufferSize, 1, 1);
node.bits = 14; // between 1 and 16
node.normfreq = 0.1; // between 0.0 and 1.0
var step = Math.pow(1/2, node.bits);
var phaser = 0;
var last = 0;
node.onaudioprocess = function(e) {
var input = e.inputBuffer.getChannelData(0);
var output = e.outputBuffer.getChannelData(0);
for (var i = 0; i < bufferSize; i++) {
phaser += node.normfreq;
if (phaser >= 1.0) {
phaser -= 1.0;
last = step * Math.floor(input[i] / step + 0.5);
}
output[i] = last;
}
};
return node;
}
function LowPassFilter() {
var bufferSize = 4096;
var node = audioCtx.createScriptProcessor(bufferSize, 1, 1);
var prev = 0;
node.onaudioprocess = function(e) {
var input = e.inputBuffer.getChannelData(0);
var out = e.outputBuffer.getChannelData(0);
for (var i = 0; i < bufferSize; i++) {
out[i] = (input[i] + prev) / 2.0;
prev = out[i];
}
};
return node;
}
//////////// Convolvers
function NoiseConvolver() {
var convolver = audioCtx.createConvolver();
var noiseBuffer = audioCtx.createBuffer(2, 0.5 * audioCtx.sampleRate, audioCtx.sampleRate);
var left = noiseBuffer.getChannelData(0);
var rigth = noiseBuffer.getChannelData(1);
for(var i = 0; i < noiseBuffer.length; i++) {
left[i] = Math.random() * 2 - 1;
rigth[i] = Math.random() * 2 - 1;
}
convolver.buffer = noiseBuffer;
return convolver;
}
//////////// WaveShapers
function DistortionShaper(distortion_val) {
this.waveshaper = audioCtx.createWaveShaper();
this.makeDistortionCurve = function(amount) {
var k = typeof amount === 'number' ? amount : 50,
n_samples = 44100,
curve = new Float32Array(n_samples),
deg = Math.PI / 180,
i = 0,
x;
for ( ; i < n_samples; ++i ) {
x = i * 2 / n_samples - 1;
curve[i] = ( 3 + k ) * x * 20 * deg / ( Math.PI + k * Math.abs(x) );
}
return curve;
}
this.distortion = function(amount) {
this.waveshaper.curve = this.makeDistortionCurve(amount);
}
this.waveshaper.curve = this.makeDistortionCurve(distortion_val);
return this.waveshaper;
}