The Sound of Thinking
About This Sketch
A visualization exploring attention, silence, and the space where thinking happens. The sketch shows information waves constantly bombarding from all edges, trying to penetrate a protected center where thoughts can actually form. The chaotic input from the periphery contrasts sharply with the calm, pulsing particles at the center—representing the insights that can only emerge in silence.
The post this accompanies examines how we've filled every cognitive gap with stimulus, eliminating the very conditions under which understanding develops.
Algorithm
The visualization explores the tension between constant information input and the protected space needed for genuine thinking.
Input waves spawn continuously from all four edges of the canvas, representing the barrage of notifications, articles, podcasts, and stimuli that bombard us throughout the day. These waves move toward the center with an oscillating motion that creates a sense of chaos and urgency. As they approach the protected center zone, they quickly fade and dissipate—symbolizing how real thinking requires filtering out the noise.
At the center sits a calm, glowing zone—the "quiet center" where thinking actually happens. Within this protected space, thought particles orbit slowly, pulsing gently and drifting in contemplative patterns. These particles represent the organic emergence of ideas when given space to form without interruption.
The contrast between the chaotic waves from the edges and the serene particles in the center visualizes the core insight of the post: thinking requires silence and protected attention. The waves can't penetrate the center, just as true understanding can't happen when we're constantly consuming inputs.
This sketch accompanies the blog post "The Sound of Thinking" and explores how modern life has filled every silence with stimulus, eliminating the cognitive space where real thinking emerges.
Pseudocode
SETUP:
Create canvas (400x300)
Initialize empty arrays for waves and center particles
Spawn 30 thought particles in center zone (radius 60)
Each particle has random orbit parameters
DRAW (every frame):
Get current theme colors
Fade background (creates trail effect)
Draw protected center circle with glowing inner gradient
SPAWN INPUT WAVES (every 8 frames):
Choose random edge (top/right/bottom/left)
Create wave pointing toward center
Give wave oscillation parameters
UPDATE AND DRAW INPUT WAVES:
For each wave:
Move toward center along angle
Add perpendicular oscillation for chaotic feel
If approaching center (within 40px of radius):
Rapidly fade out (suppressed by protected space)
Otherwise fade slowly
Draw as elongated ellipse with trail
Remove if dead
UPDATE AND DRAW THOUGHT PARTICLES:
For each particle in center:
Orbit around center point
Drift radius in/out slowly
Bounce off inner boundaries
Pulse opacity gently
Draw as soft glowing circles (multiple layers)
DRAW CENTER FOCAL POINT:
Small bright circle at exact center
Represents the self/consciousness
LABELS:
Title, annotations about input vs. quiet center
PULSE EFFECT (every 180 frames):
Expanding ring from center
Represents moments of insight emerging
Source Code
let sketch = function(p) {
// The Sound of Thinking
// Visualization: Input waves overwhelming a quiet center
// Shows the constant barrage of information (waves from edges)
// versus the still center where thinking happens (protected space)
// As waves penetrate less, clarity emerges in the center
let waves = [];
let centerParticles = [];
let time = 0;
let centerRadius = 60;
class InputWave {
constructor() {
// Waves come from all edges
let side = p.floor(p.random(4));
if (side === 0) { // top
this.x = p.random(400);
this.y = 0;
this.angle = p.HALF_PI;
} else if (side === 1) { // right
this.x = 400;
this.y = p.random(300);
this.angle = p.PI;
} else if (side === 2) { // bottom
this.x = p.random(400);
this.y = 300;
this.angle = -p.HALF_PI;
} else { // left
this.x = 0;
this.y = p.random(300);
this.angle = 0;
}
// Angle toward center with some variance
let angleToCenter = p.atan2(150 - this.y, 200 - this.x);
this.angle = angleToCenter + p.random(-0.3, 0.3);
this.speed = p.random(1, 2.5);
this.amplitude = p.random(8, 15);
this.frequency = p.random(0.1, 0.2);
this.offset = p.random(p.TWO_PI);
this.life = 255;
this.size = p.random(2, 4);
}
update() {
// Move toward center
this.x += p.cos(this.angle) * this.speed;
this.y += p.sin(this.angle) * this.speed;
// Oscillate perpendicular to direction
let perpAngle = this.angle + p.HALF_PI;
let oscillation = p.sin(time + this.offset) * this.amplitude;
this.x += p.cos(perpAngle) * oscillation * 0.05;
this.y += p.sin(perpAngle) * oscillation * 0.05;
// Fade as it approaches center
let distToCenter = p.dist(this.x, this.y, 200, 150);
if (distToCenter < centerRadius + 40) {
this.life -= 8;
}
this.life -= 0.5;
}
display(colors) {
// Draw as chaotic, energetic marks
p.noStroke();
p.fill(...colors.accent2, this.life * 0.6);
p.push();
p.translate(this.x, this.y);
p.rotate(this.angle);
p.ellipse(0, 0, this.size * 3, this.size);
p.pop();
// Trailing dots
p.fill(...colors.accent2, this.life * 0.3);
p.circle(this.x, this.y, this.size * 0.5);
}
isDead() {
return this.life <= 0;
}
}
class ThoughtParticle {
constructor() {
// Start at center
let angle = p.random(p.TWO_PI);
let r = p.random(centerRadius * 0.3);
this.x = 200 + p.cos(angle) * r;
this.y = 150 + p.sin(angle) * r;
this.angle = angle;
this.orbitSpeed = p.random(-0.01, 0.01);
this.orbitRadius = r;
this.radiusVelocity = p.random(-0.1, 0.1);
this.size = p.random(1.5, 3);
this.pulse = p.random(p.TWO_PI);
this.baseAlpha = p.random(150, 220);
}
update() {
// Orbit around center with slow drift
this.angle += this.orbitSpeed;
this.orbitRadius += this.radiusVelocity;
this.orbitRadius = p.constrain(this.orbitRadius, 5, centerRadius * 0.8);
// If at edges, bounce back
if (this.orbitRadius >= centerRadius * 0.8 || this.orbitRadius <= 5) {
this.radiusVelocity *= -0.8;
}
this.x = 200 + p.cos(this.angle) * this.orbitRadius;
this.y = 150 + p.sin(this.angle) * this.orbitRadius;
this.pulse += 0.05;
}
display(colors) {
let alpha = this.baseAlpha + p.sin(this.pulse) * 50;
// Draw soft glowing particle
p.noStroke();
p.fill(...colors.accent1, alpha * 0.2);
p.circle(this.x, this.y, this.size * 4);
p.fill(...colors.accent1, alpha * 0.6);
p.circle(this.x, this.y, this.size * 2);
p.fill(...colors.accent1, alpha);
p.circle(this.x, this.y, this.size);
}
}
p.setup = function() {
p.createCanvas(400, 300);
p.colorMode(p.RGB);
// Initialize thought particles in center
for (let i = 0; i < 30; i++) {
centerParticles.push(new ThoughtParticle());
}
};
p.draw = function() {
const colors = getThemeColors();
// Fade background for trails
p.fill(...colors.bg, 40);
p.noStroke();
p.rect(0, 0, 400, 300);
time += 0.1;
// Draw protected center (the silence where thinking happens)
p.noFill();
p.stroke(...colors.accent3, 60);
p.strokeWeight(1);
p.circle(200, 150, centerRadius * 2);
// Inner glow of center
for (let r = centerRadius * 2; r > 0; r -= 10) {
let alpha = p.map(r, 0, centerRadius * 2, 40, 0);
p.fill(...colors.accent1, alpha);
p.noStroke();
p.circle(200, 150, r);
}
// Spawn input waves (information bombardment)
if (p.frameCount % 8 === 0) {
waves.push(new InputWave());
}
// Update and draw input waves
for (let i = waves.length - 1; i >= 0; i--) {
waves[i].update();
waves[i].display(colors);
if (waves[i].isDead()) {
waves.splice(i, 1);
}
}
// Update and draw thought particles (what emerges in silence)
for (let particle of centerParticles) {
particle.update();
particle.display(colors);
}
// Draw center point (the self)
p.noStroke();
p.fill(...colors.accent1, 200);
p.circle(200, 150, 4);
p.fill(...colors.accent1, 80);
p.circle(200, 150, 8);
// Labels
p.textFont('Georgia');
p.textAlign(p.CENTER);
p.fill(...colors.accent2, 200);
p.textSize(10);
p.text('The Sound of Thinking', 200, 20);
p.textSize(8);
p.fill(...colors.accent2, 180);
p.text('Input noise', 200, 40);
p.fill(...colors.accent1, 180);
p.text('The quiet center: where thoughts form', 200, 280);
// Pulse effect on center every few seconds
if (p.frameCount % 180 < 20) {
let pulse = p.frameCount % 180;
let alpha = p.map(pulse, 0, 20, 40, 0);
p.noFill();
p.stroke(...colors.accent1, alpha);
p.strokeWeight(2);
let size = centerRadius * 2 + pulse * 3;
p.circle(200, 150, size);
}
};
};