xxxxxxxxxx
<meta charset="utf-8">
<title>lovenote</title>
<style>
g.note rect {
fill:#ccc;
}
g.note.playing rect {
fill:#000;
}
g.note rect.on {
fill:#D900E0;
}
</style>
<body>
<input type='checkbox' id='on' />
<div id='music'></div>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script>
var width = 500,
height = 200;
var svg = d3.select(document.body).append('svg')
.attr('width', width)
.attr('height', height);
var stream_length = 1024;
var ctx = new webkitAudioContext();
var node = ctx.createJavaScriptNode(stream_length, 1, 2);
var volume = ctx.createGainNode();
volume.gain.value = 0.01;
node.connect(volume);
volume.connect(ctx.destination);
var tri = (function(sample_rate) {
var phase = 0,
phaseStep = 110 / sample_rate;
return function(p) {
var w = 2 / p;
if (phase > w) phase -= w;
var r = phase * p;
var ret = 2 * ((r >= 1 ? 2 - r : r) - 0.5);
phase += phaseStep;
return ret;
}
})(ctx.sampleRate);
function next(hz) {
var stream = [], i;
for (i = 0; i < stream_length; i++) {
stream[i] = tri(hz);
}
return stream;
}
var on = false, note = 5;
node.onaudioprocess = function(event) {
var i,
l = event.outputBuffer.getChannelData(0),
r = event.outputBuffer.getChannelData(1);
if (on) {
var wave = next(freq)
for (i = 0; i < l.length; i++) {
l[i] = r[i] = wave[i];
}
} else {
for (i = 0; i < l.length; i++) {
l[i] = r[i] = 0;
}
}
};
d3.select('#on').on('change', function() {
on = this.checked;
});
var board = d3.range(0, 50).reduce(function(mem, time) {
return mem.concat(d3.range(0, 20).map(function(note) {
return {
time: time,
note: note,
on: false
};
}));
}, []);
var scale_note = d3.scale.linear().domain([0, 20]).range([height, 0]);
var scale_time = d3.scale.linear().domain([0, 50]).range([0, width]);
var notes = svg.selectAll('g.note')
.data(board)
.enter()
.append('g')
.attr('class', 'note')
.attr('transform', function(d) {
return 'translate(' +
scale_time(d.time) + ',' +
scale_note(d.note) + ')';
});
notes.append('rect')
.attr({ width: 9, height: 9 });
notes.on('click', function(d) {
d.on = !d.on;
d3.select(this).select('rect').classed('on', d.on);
});
var pos = 0;
window.setInterval(function() {
var note = board.filter(function(d) {
return d.time == pos && d.on;
});
notes.classed('playing', function(d) {
return d.time == pos;
});
if (!note.length) on = false;
else {
on = true;
freq = note[0].note;
}
if (pos++ > 50) pos = 0;
}, 200);
</script>
Modified http://d3js.org/d3.v3.min.js to a secure url
https://d3js.org/d3.v3.min.js