xxxxxxxxxx
332
/*
This script can render avi's and gifs. Setup recording in setup().
Press enter to start and stop recording.
Will also stop recording after recording 'FRAMES' frames. Use this for perfect loops :)
libraries used:
Video Builder: https://github.com/theshock/VideoBuilder
download: https://github.com/rndme/download
*/
const LOOPS = 8;
const FRAMES = 1000;
const FPS = 60;
// const RECORD = true;
const MANUAL = false;
const PLAY_AUDIO = false;
const RECORD_AUDIO = false;
const QUALITY = 1;
const DIST = 3;
const TRIGGER_T_DIST_MAX = 0.05; //0.1;
const TRIGGER_T_DIST_MIN = 0.05; //0.025;
const AA = 2 * QUALITY;
let OUTPUT_SIZE = QUALITY * 1080;
let SIZE, SCALE, TEX, SYNTHS;
let recorder, soundFile;
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,
]
let rec;
let size;
function setup() {
frameRate(FPS);
OUTPUT_SIZE = OUTPUT_SIZE;
SIZE = OUTPUT_SIZE * AA;
SCALE = SIZE / 1080;
const canvas = createCanvas(OUTPUT_SIZE, OUTPUT_SIZE);
TEX = createGraphics(OUTPUT_SIZE * AA, SIZE);
rec = setupRecording("noise field audio reactive", canvas, FRAMES * LOOPS, {
avi: {
fps: 60,
quality: 0.92
},
});
colorMode(RGB, 1);
TEX.colorMode(RGB, 1);
TEX.noFill();
// TEX.strokeCap(PROJECT);
// noLoop();
noiseSeed(100);
SYNTHS = [
new p5.PolySynth(),
new p5.PolySynth(),
new p5.PolySynth(),
new p5.PolySynth(),
new p5.PolySynth(),
]
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);
}
}
function keyPressed(evt) {
if (evt.key == "Enter") {
if (!rec.recording) {
rec.start();
frameCount = 0; // reset time
} else
rec.stop();
}
}
let t;
function draw() {
drawScene();
if (rec.recording)
rec.recordFrame();
}
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,
midi_v: map(midi - oct, -4, 20, 0, 1)
});
}
}
});
}
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 drawScene() {
t = (frameCount / FRAMES);
TEX.background(.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 index_f = index / TRIGGERS.length;
const trigger_t_dist = lerp(TRIGGER_T_DIST_MAX, TRIGGER_T_DIST_MIN, index_f);
const t_vals = TRIGGERS[index].filter(({t: _t}) => abs(t - _t) < TRIGGER_T_DIST_MAX);
const val_f = (1 - fract(TRIGGERS.length * f));
const val_line = t_vals.reduce((tot, {t: _t, amp_v}) => {
const d = 1 * (t - _t) / TRIGGER_T_DIST_MAX
const v = constrain(d + val_f, 0, 1);
const val = pow(invCosn(v), 2 + index * 2)
// (v < 0.5
// ? pow(invCosn(v), 5)
// : invCosn(v)
// )
* val_f * amp_v
return max(tot, val);
// return 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),
);
// const midi_v = t_vals[0]?.midi_v ?? 0;
// const val = pow(invCosn(constrain(x - midi_v, 0, 1)), 1) * val_line * 2;
positions.push({ x, y, val: val_line });
}
}
const col2 = TEX.color(1, 0.5, 0);
const col1 = TEX.color(0.5, 0, 1);
lines.forEach((positions, i) => {
const drawLine = (weight, step) => {
TEX.beginShape();
const { x, y } = positions[0];
TEX.vertex(spaceX(x), spaceY(y));
const inc = 3;
for (let i=0; i<positions.length - inc; i += inc) {
const { x: x1, y: y1, val } = positions[i];
const { x: x2, y: y2 } = positions[i + 1];
const { x: x3, y: y3 } = positions[i + 2];
// const { x: x4, y: y4 } = positions[i + 3];
TEX.bezierVertex(
spaceX(x1), spaceY(y1),
spaceX(x2), spaceY(y2),
spaceX(x3), spaceY(y3),
// spaceX(x4), spaceY(y4),
)
// line(spaceX(x1), spaceY(y1), spaceX(x2), spaceY(y2));
}
TEX.endShape();
}
const { val } = positions[0];
const val_weight = SCALE * val * 50
const f = i / lines.length;
const col = lerpColor(col1, col2, f);
TEX.stroke(col);
TEX.strokeWeight(outline_weight / QUALITY + val_weight);
drawLine(outline_weight / QUALITY, "outline");
const col_fill = lerpColor(color("white"), color("rgba(255,255,255,0)"), val);
TEX.stroke(col_fill);
TEX.strokeWeight(weight / QUALITY + val_weight);
drawLine(weight / QUALITY, "stroke");
});
background(0.9);
image(TEX, 0, 0, OUTPUT_SIZE, OUTPUT_SIZE);
}
function spaceX(v) {
const pad = 0.25 / 1;
return lerp(pad, 1 - pad, v) * SIZE;
}
function spaceY(v) {
const pad = 0.33 / 1;
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)
}