xxxxxxxxxx
307
const musicScale = new teoria.note("A3").scale("major");
let toolSelectRadio;
let rectHalfWidth = 10;
let c = null;
let activeChordRoot = 1;
const walkers = [];
let xSlider;
let ySlider;
let magnitudeSlider;
const waveTypes = {
circle: "sine",
square: "square",
triangle: "triangle",
sawtooth: "sawtooth",
};
const OUTPUT_NODE = new Tone.Gain(0.3);
const outputLimiter = new Tone.Limiter(-1);
const outputFilter = new Tone.Filter({
type: "lowpass",
frequency: 15000
});
const outputReverb = new Tone.Reverb({
wet: 0.2
});
const outputDistortion = new Tone.Distortion({
wet: 1,
distortion: 0,
});
OUTPUT_NODE.chain(outputFilter, outputDistortion, outputReverb, outputLimiter, Tone.Master);
function Walker(startX, startY, type) {
const pos = createVector(startX, startY);
let velocity = createVector();
const noiseOffset = random(5000);
const detune = random(-20, 20);
const synth = new Tone.Synth({
volume: type === "square" ? -30 : -20,
portamento: 0.1,
envelope: {
attack: 1,
decay: 15,
sustain: 0.5,
release: 1,
},
oscillator: {
detune,
type: waveTypes[type],
},
});
const panner = new Tone.Panner(map(pos.x, 0, width, -1, 1));
const filter = new Tone.Filter({
type: "lowpass",
Q: 20,
frequency: 15000
});
const limiter = new Tone.Limiter(-20);
synth.chain(filter, limiter, panner, OUTPUT_NODE);
const noteOptions = [-7, 0, 2, 4, 6];
const getNote = () =>
activeChordRoot + noteOptions[Math.floor(random(0, noteOptions.length))];
let startingNote = getNote();
synth.triggerAttack(musicScale.get(startingNote).toString());
this.updateNote = () => {
setTimeout(() => {
startingNote = getNote();
synth.triggerAttack(musicScale.get(startingNote).toString());
}, random(0, 1000));
};
this.update = () => {
const positionNoise = noise(pos.x / 100, pos.y / 100);
const filterFreqPow = map(positionNoise, 0, 1, 6, 14)
filter.Q.rampTo(map(positionNoise, 0, 1, 0, 30), 0.1);
filter.frequency.rampTo(Math.pow(2, filterFreqPow), 0.2);
panner.pan.rampTo(constrain(map(pos.x, 0, width, -1, 1), -1, 1), 0.2);
let hue = positionNoise * 360 + activeChordRoot * 80;
hue = hue % 360;
const frameNoise = noise((frameCount + noiseOffset) / 50);
synth.volume.rampTo(map(frameNoise, 0, 1, -40, 0), 0.1);
colorMode(HSL);
rectMode(CENTER);
noStroke();
let w = frameNoise * 90 + 20;
let a = frameNoise * 0.03 + 0.01;
const r = floor(random(4));
const r2 = floor(random(100));
/* Sometimes draw bigger shapes */
if (r2 < 15) {
w = random(100, 200);
a = 0.01;
}
if (r2 < 5) {
w = random(200, 400);
a = 0.01;
}
if (r2 < 2) {
w = random(400, 800);
a = 0.01;
}
push();
translate(pos.x, pos.y);
scale(xSlider.value() / 20 + 1, ySlider.value() / 20 + 1);
if (type === "circle") {
fill(hue, random(45), frameNoise * 10 + 50, a);
ellipse(0, 0, w, w);
}
if (type === "square") {
fill(hue, 20, frameNoise * 3 + 50, a);
rect(0, 0, w, w);
}
if (type === "triangle") {
fill(hue, 30, frameNoise * 100, a);
rotate((frameNoise / 50) * PI * 2);
beginShape();
vertex(0, w);
vertex(-w, -5);
vertex(w, 5);
endShape(CLOSE);
}
if (type === "sawtooth") {
fill(hue, 30, frameNoise * 10 + 50, a + 0.1);
beginShape();
vertex(0, 0);
vertex(0, w);
vertex(25, w);
endShape(CLOSE);
}
pop();
const velocity = p5.Vector.random2D();
velocity.mult(magnitudeSlider.value() / 20);
const drift = createVector(xSlider.value(), ySlider.value());
pos.add(velocity);
pos.add(drift);
// Stay on screen
if (pos.x < 0) {
pos.x = width + pos.x;
}
if (pos.x > width) {
pos.x = pos.x % width;
}
if (pos.y < 0) {
pos.y = height + pos.y;
}
if (pos.y > height) {
pos.y = pos.y % height;
}
};
}
const isInSquare = () => {
const px = mouseX - width / 2;
const py = mouseY - height / 2
return Math.abs(px) < rectHalfWidth && Math.abs(py) < rectHalfWidth;
}
const changeChord = () => {
activeChordRoot = Math.floor(random(0, 7));
walkers.forEach((walker) => {
walker.updateNote();
});
}
function setup() {
c = createCanvas(600, 600);
c.mouseClicked(function() {
const c = {
x: width / 2,
y: height / 2
};
if (isInSquare()) {
changeChord();
} else {
walkers.push(new Walker(mouseX, mouseY, toolSelectRadio.value()));
}
})
toolSelectRadio = createRadio();
Object.keys(waveTypes).forEach(type => {
toolSelectRadio.option(type);
})
toolSelectRadio.selected("triangle");
// createButton('Change Chord').mousePressed(changeChord)
createDiv('Wiggle');
magnitudeSlider = createSlider(1, 100, 5);
createDiv('Horizontal Drift')
xSlider = createSlider(-10, 10, 0).doubleClicked(function() {
this.value(0)
});
createDiv('Vertical Drift')
ySlider = createSlider(-10, 10, 0).doubleClicked(function() {
this.value(0)
});
background(255);
frameRate(60);
}
let rectNoiseCount = 0;
function draw() {
push()
rectMode(CENTER);
const noiseVal = noise((rectNoiseCount + 2345) / 120);
if (rectHalfWidth > width / 2) {
rectHalfWidth = 10;
}
stroke(255, 0.03);
strokeWeight(random(14 * noiseVal));
fill(255, 0.01 * noiseVal)
translate(width / 2, height / 2);
if (isInSquare()) {
cursor('pointer');
fill(255, 0);
scale(1 + random(-0.1, 0.1) * noiseVal)
stroke(255, 0.5 * noiseVal);
rectNoiseCount++;
if (mouseIsPressed) {
rectHalfWidth += 0.5;
fill(255, 0);
stroke(255, 0.15 * noiseVal);
}
} else {
cursor('default');
}
// blendMode(SCREEN)
rect(0, 0, rectHalfWidth * 2, rectHalfWidth * 2);
background(0, 0.001);
rect(0, 0, rectHalfWidth * 2, rectHalfWidth * 2);
pop()
// outputDistortion.distortion.value = map(rectHalfWidth, 0, width /2, 0, 0.99)
walkers.forEach((walker) => {
walker.update();
});
}
function keyPressed() {
const activeShape = toolSelectRadio.value();
if (key === "1") {
toolSelectRadio.selected("circle");
}
if (key === "2") {
toolSelectRadio.selected("square");
}
if (key === "3") {
toolSelectRadio.selected("triangle");
}
if (key === "4") {
toolSelectRadio.selected("sawtooth");
}
}