xxxxxxxxxx
320
const FRAMES = 1000;
const RECORD = true;
const MANUAL = false;
const PLAY_AUDIO = false;
const RECORD_AUDIO = false;
const QUALITY = .5;
const DIST = 3;
const TRIGGER_T_DIST_MAX = 0.05;
const TRIGGER_T_DIST_MIN = 0.05;
const AA = 1;
let OUTPUT_SIZE = QUALITY * 1080;
let SIZE, SCALE, TEX, SYNTHS;
function setup() {
OUTPUT_SIZE = RECORD ? OUTPUT_SIZE : min(windowWidth, windowHeight);
SIZE = OUTPUT_SIZE * AA;
SCALE = SIZE / 1080;
createCanvas(OUTPUT_SIZE, OUTPUT_SIZE);
TEX = createGraphics(SIZE, SIZE);
TEX.colorMode(RGB, 1);
TEX.noFill();
// TEX.strokeCap(PROJECT);
// noLoop();
noiseSeed(100);
SYNTHS = [
// new Tone.Synth().toDestination(),
// new Tone.Synth().toDestination(),
// new Tone.Synth().toDestination(),
// new TfSynth().toDestination(),
// new Tone.Synth().toDestination(),
new p5.PolySynth(),
new p5.PolySynth(),
new p5.PolySynth(),
new p5.PolySynth(),
new p5.PolySynth(),
// osc = new p5.SinOsc(),
// osc = new p5.TriOsc(),
// osc = new p5.SinOsc(),
// osc = new p5.TriOsc(),
// osc = new p5.SinOsc(),
]
SYNTHS.forEach((synth, i) => {
const f = i / SYNTHS.length;
const rev = new p5.Reverb();
rev.drywet(f);
synth.disconnect()
synth.connect(rev)
});
if (RECORD_AUDIO) {
recorder = new p5.SoundRecorder();
// console.log();
recorder.setInput(p5.soundOut.output);
soundFile = new p5.SoundFile();
recorder.record(soundFile);
}
playSynths();
if (RECORD_AUDIO) {
setTimeout(() => {
recorder.stop();
console.log(soundFile);
setTimeout(() => {
// console.log(soundFile);
saveSound(soundFile, 'mySound.wav');
}, 3000);
}, 1000 * LENGTH * LOOPS);
}
}
let recorder, soundFile;
function keyPressed() {
if (key == 'Enter') {
save("noise field " + Date.now());
}
if (key == 'r') {
noiseSeed(random() * 1000);
draw();
}
// if (key == ' ') {
// }
}
const LENGTH = FRAMES / 60;
const NOTES = [
// 0, 3, 5, 8
0, 5, 7, 8
];
const CHORDS = [
0, 0, 0, 0,
-4, -4, -4, -4,
3, 3, 3, 3,
2, 2, 12, 0,
]
const LOOPS = 8;
let TRIGGERS=[];
function playSynths() {
randomSeed(0);
SYNTHS.forEach((synth, i) => {
const f = i / SYNTHS.length;
TRIGGERS[min(i, 2)] = TRIGGERS[min(i, 2)] ?? [];
let prev_midi = null;
const count = 13 * 8;
for (let j=0; j<count * LOOPS; j++) {
const t = j / count;
const oct = 12 * (4 + min(i, 2) * 1);
const v = lerp(
getNoise(0.5, f, t),
getNoise(0.5 - DIST, f - DIST, t),
invCosn(t * 0.5)
) * (1 + i * 2) + oct;
const midi = NOTES[floor(v) % NOTES.length]
+ CHORDS[floor(fract(t) * CHORDS.length)]
+ floor(v / 12) * 12;
const freq = midiToFreq(midi);
// const amp = env(v, 1 + f * 10) / SYNTHS.length;
if (prev_midi != midi || i == 0 && j % 3 == 0) {
const len = i == 0
? 15 * LENGTH / FRAMES / 4
: 0.5 * random(1 - f) * 30 * LENGTH / FRAMES;
// const len = 0.5 * random(1 - f) * 30 * LENGTH / FRAMES;
const amp_v = random(.25, 1);
const amp = 3 * amp_v / SYNTHS.length;
const time = max(0, t * LENGTH - i / 3);
if (PLAY_AUDIO) synth.play(freq, amp, time, len);
prev_midi = midi;
TRIGGERS[min(i, 2)].push({t, amp_v});
}
}
});
}
function env(v, p) {
// return invCosn(v - 0.5);
v = fract(v / 2);
return v < 0.5
? pow(invCosn(v), p)
: pow(1 - v * 2, 5)
}
function getNoise(x, y, t) {
const noise_f = 3;
const noise_scale = 1;
const noise_offset = t * DIST;
const noise_offset_x = noise_offset; //cos(TAU * noise_offset);
const noise_offset_y = noise_offset; //sin(TAU * noise_offset);
const noise_offset_z = 0; //sin(TAU * noise_offset);
noiseDetail(4, .5);
return (noise(
(x + noise_offset_x) * noise_scale,
(y + noise_offset_y) * noise_scale,
noise_offset_z * noise_scale,
) - 0.5) * noise_f * invCosn(x); // * lerp(0.25, 1, invCosn(y));
}
function draw() {
if (RECORD && frameCount === 1 && typeof P5Capture !== 'undefined') {
const capture = P5Capture.getInstance();
capture.start({
format: "webm",
duration: FRAMES * LOOPS,
quality: 1,
framerate: 60,
});
}
t = (frameCount / FRAMES);
TEX.background(0.9);
// translate(-width / 2, 0ght / 2);
const count = 150 * QUALITY;
const segments = 150 * QUALITY;
const weight = 3 * SCALE;
const outline_weight = 6 * SCALE;
const m_x = mouseX / width;
const m_y = mouseY / width;
if (MANUAL) t = fract(m_x) * LOOPS;
const lines = [];
for (let i=0; i<count; i++) {
const positions = [];
lines[i] = positions;
const f = i / count;
const index = floor(TRIGGERS.length * f);
const trigger_t_dist = lerp(TRIGGER_T_DIST_MAX, TRIGGER_T_DIST_MIN, index / TRIGGERS.length);
const t_vals = TRIGGERS[index].filter(({t: _t}) => abs(t - _t) < trigger_t_dist);
const val_f = (1 - fract(TRIGGERS.length * f));
const val = t_vals.reduce((tot, {t: _t, amp_v}) => {
const d = 1 * (t - _t) / trigger_t_dist
const v = constrain(d + val_f - 0.5, 0, 1);
const val = (v < 0.5
? pow(invCosn(v), 5)
: invCosn(v)
) * val_f * amp_v
return max(tot, val);
}, 0)
for (let j=0; j<segments; j++) {
let x = j / (segments - 1);
let y = i / (count - 1);
y -= lerp(
getNoise(x, y, t),
getNoise(x - DIST, y - DIST, t),
invCosn(t * 0.5),
);
positions.push({ x, y, val });
}
}
const col2 = TEX.color(1, 0.5, 0);
const col1 = TEX.color(0.5, 0, 1);
lines.forEach((positions, i) => {
const drawLine = () => {
TEX.beginShape();
const { x, y } = positions[0];
TEX.vertex(spaceX(x), spaceY(y));
const inc = 3;
for (let i=1; i<positions.length - inc; i += inc) {
const { x: x1, y: y1 } = positions[i];
const { x: x2, y: y2 } = positions[i + 1];
const { x: x3, y: y3 } = positions[i + 2];
TEX.bezierVertex(
spaceX(x1), spaceY(y1),
spaceX(x2), spaceY(y2),
spaceX(x3), spaceY(y3)
)
// line(spaceX(x1), spaceY(y1), spaceX(x2), spaceY(y2));
}
TEX.endShape();
}
const f = i / lines.length;
const { val } = positions[0];
const val_weight = SCALE * val * 50
col = lerpColor(col1, col2, f);
TEX.stroke(col);
TEX.strokeWeight(outline_weight / QUALITY + val_weight);
drawLine();
const col_fill = lerpColor(color("white"), color("rgba(255,255,255,0)"), val);
TEX.stroke(col_fill);
TEX.strokeWeight(weight / QUALITY + val_weight);
drawLine();
});
image(TEX, 0, 0, OUTPUT_SIZE, OUTPUT_SIZE);
}
function spaceX(v) {
const pad = 0.25;
return lerp(pad, 1 - pad, v) * SIZE;
}
function spaceY(v) {
const pad = 0.33;
return lerp(pad, 1 - pad, v) * SIZE;
}
function invCosn(v) {
return 1 - (cos(v * TAU) * 0.5 + 0.5)
}
function tri(v) {
return 1 - abs(1 - fract(v) * 2)
}