{
const size = 150;
const fMin = 80;
const fMax = 1300;
const synth = new Tone.Synth();
synth.toDestination();
function mapLinear(mouseY) {
return d3.scaleLinear([0, size], [fMax, fMin])(mouseY);
}
function mapLogarithmic(mouseY) {
const steps = d3.scaleLinear([0, size], [1, 0])(mouseY);
return fMin * Math.pow(2, steps);
}
function onMousedown(mapLinear, e) {
const [mouseX, mouseY] = mouseof(e);
const frequency = mapLinear(mouseY);
const velocity = mouseX / size;
synth.triggerAttack(frequency, Tone.now(), velocity);
}
function onMouseup() {
synth.triggerRelease();
}
const app = cm.render({
width: size * 2 + 10,
height: size,
draw: [
cm.svg("rect", {
x: 0,
y: 0,
width: size,
height: size,
fill: "black",
onMouseup,
onMousedown: onMousedown.bind(null, mapLinear)
}),
cm.svg("rect", {
x: size + 10,
y: 0,
width: size,
height: size,
fill: "black",
onMouseup,
onMousedown: onMousedown.bind(null, mapLogarithmic)
})
]
});
invalidation.then(() => app.dispose());
return app.node();
}