And then the user listening can indicate support for various elements.
So the program "learns" what the user likes in realtime, and we can explore a deeper set of concepts in techno music. then after interactive session, upload to e.g. soundcloud.
e.g. auto-generate the expression tree, then slowly tweak different components.
because every music can be constructed from functions, like this:
Code:
<!doctype html>
<meta charset="utf-8">
<style>
.f {
text-align: center;
padding: 1em;
box-sizing: border-box;
background-color: #cfc;
}
.example {
padding: 1em;
margin: 1em;
border: 1px solid black;
}
canvas {
box-sizing: border-box;
padding: 0;
margin: 1em auto;
display: block;
}
button {
padding: 1em;
margin: 0 auto;
display: block;
}
#f {
width: 60em;
text-align: center;
height: 10em;
box-sizing: border-box;
padding: 1em;
margin: 1em auto;
display: block;
}
</style>
<!--div id="addFunction">
<canvas id="canvas" height="200"></canvas>
<input id="f" placeholder="a.sin(b.x)"/>
<button id="play">Play</button>
</div-->
<body></body>
<script>
let add = (f, g) => (t) => (f(t) + g(t))
let mul = (f, g) => (t) => (f(t) * g(t))
let div = (f, g) => (t) => (f(t) / g(t))
let apply = (f, g) => (t) => f(g(t))
let pi = Math.PI;
let sin = (frequency) => (t) => Math.sin(frequency * 2 * pi * t)
let pow = (frequency) => (t) => Math.pow(2, frequency * t);
let square = (frequency) => (t) => Math.sign(sin(frequency)(t))
let saw = (frequency) => (t) => 2 * (frequency * t - Math.floor(0.5 + frequency * t))
let triangle = (frequency) => (t) => 2 * Math.abs(saw(frequency)(t)) - 1
let constant = (a) => (t) => a
let linear = (start, end) => (t) => (end - start) * t + start
let inverse = (a) => (t) => (1.0/t)
let repeat = (f, a) => (t) => f(t % (1/a))
let normalize = (f) => { let max = 0; for (let t = 0; t < 1; t += 0.001) max = Math.max(max, Math.abs(f(t))); return (t) => f(t) / max; }
let random_wave = () => [sin, square, saw, triangle][Math.floor(Math.random() * 4)];
let f = mul(mul(square(162.62413278270736), square(83.16190555748766)), mul(sin(21.945119968409998), square(162.78247470082357)));
let g = mul(mul(square(162.62413278270736), square(83.16190555748766)), mul(sin(21.945119968409998), square(162.78247470082357)));
f = div(f, pow(10));
g = div(g, pow(10));
f = add(f, (t) => t >= 1 ? g(t-1) : 0);
/*
saw()
saw()
59.42011391658839 101.86210294520923 198.7362955259255 44.16287968187087 manual.js:66:67
function triangle()
function triangle()
function triangle()
function square()
37.64853009526994 197.1292484244233 194.982529682227 195.58191638702692 manual.js:66:67
function triangle()
function triangle()
function sin()
function square()
71.09632010892695 2.027127754841862 171.13064469415832 50.53797347482516 manual.js:66:67
function square()
function square()
function sin()
function square()
162.62413278270736 83.16190555748766 21.945119968409998 162.78247470082357 manual.js:66:67
function sin()
function square()
function sin()
function sin()
170.5469423775594 133.51553198794136 131.8228173251929 189.75443429593506 manual.js:66:67
function sin()
function sin()
function sin()
function triangle() 2.8052721802001246 73.90683485785048 188.52057012564111 71.13760882126476
*/
let interval = null;
let draw = function(f, exampleId) {
f = new Function("return function (x) { return " + f + "(x); }")();
let canvas = document.getElementById("canvas" + exampleId);
canvas.width = window.innerWidth * 0.9; // 90% to account for border
let ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, 1000, 200);
ctx.beginPath();
ctx.moveTo(0, 100);
ctx.lineTo(canvas.width, 100);
ctx.moveTo(0, 0);
ctx.lineTo(0, 200);
let lasty = 0;
let lastx = 0;
for (let x = 1; x < canvas.width; x+=1) {
let y = f(x / canvas.width);
ctx.moveTo(x-1, 100 - 100 * lasty);
ctx.lineTo(x, 100 - 100 * y);
lasty = y;
}
ctx.stroke();
}
let play = function(f, exampleId, count) {
f = new Function("return function (x) { return " + f + "(x); }")();
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var buffer = audioCtx.createBuffer(1, count * audioCtx.sampleRate, audioCtx.sampleRate);
var nowBuffering = buffer.getChannelData(0);
for (var i = 0; i < buffer.length; i++) {
nowBuffering[i] = Math.min(Math.max(-1, f(i / audioCtx.sampleRate)), 1);
}
var source = audioCtx.createBufferSource();
source.buffer = buffer;
source.connect(audioCtx.destination);
source.start();
};
let exampleId = 0;
let examples = [];
function add_example(s, f, count) {
if (count === undefined) count = 1;
if (f === undefined) f = s;
document.body.innerHTML = document.body.innerHTML + '<div class="example"><div class="f">' + s + '</div><canvas id="canvas' + exampleId + '" height="200"></canvas><button onclick="play(\'' + f + '\', ' + exampleId + ', ' + count + ')">Play</button></div>';
examples.push(f);
for (let i = 0; i <= exampleId; i++)
draw(examples[i], i);
exampleId++;
}
document.body.innerHTML += '<center><big><br/><strong>Turn the volume down since these examples are quite loud.</strong></big></center>';
add_example('sin(1000 * x)', 'sin(1000)');
document.body.innerHTML += '<center><big><strong>Turn the volume down since these examples are quite loud.</strong></big></center>';
add_example('sin(1200 * x)', 'sin(1200)');
add_example('(sin(1000 * x) + sin(1200 * x)) / 2', 'mul(constant(0.5), add(sin(1000), sin(1200)))');
add_example('(sin(1000 * x) + sin(1200 * x)) / 2 * 2^(-10 * x)', 'mul(mul(constant(0.5), add(sin(1000), sin(1200))), pow(-10))');
add_example('(sin(250 * x) + sin(600 * x)) / 2 * 2^(-10 * (x % 0.25))', 'mul(mul(constant(0.5), add(sin(250), sin(600))), (t) => pow(-10)(t%0.25))');
add_example('(sin(25 * x) + sin(60 * x)) / 2 * 2^(-10 * (x % 0.25))', 'mul(mul(constant(0.5), add(sin(25*4), sin(60*4))), (t) => pow(-10)(t%0.25))');
add_example('square(162.624 * x)', 'square(162.624)');
add_example('square(83.16190)');
add_example('sin(21.945119968409998)');
add_example('square(83.16190)');
let s = 'mul(mul(square(162.62413278270736), square(83.16190555748766)), mul(sin(21.945119968409998), square(162.78247470082357)))';
add_example('the above four combined<br/>' + s, s);
add_example('mul by sin(4 * x) again..','mul(sin(4), ' + s + ')');
add_example('mul by sin(4 * x * x) this time..','mul((t) => sin(4 * t)(t), ' + s + ')', 4);
add_example('square(600)');
add_example('triangle(600)');
add_example('saw(600)');
</script>
<!--script src="functions.js"></script-->
<!--script src="events.js"></script-->
what's the best way to achieve funding for something like this?