AI Bongo Drums - Tribal Percussion Instrument Tap the bongos to play! Left drum plays low tone, rig

52 views Β· Dec 16, 2025

Create a Bongo Drums instrument! Draw two round drums side by side. Click left drum for low tone, ri

#xelsedia#xelsedai#xelsedp5flashalpha6
πŸ”€ Remix This πŸ“– View Docs β›Ά Full Screen ← Back to Gallery
πŸ“‹ Embed Code

Copy this code to embed this sketch on your website:

<iframe src="https://p5js.ai/embed/01b51a85-e913-4e2d-a141-8eb0cc756ef7" width="400" height="400" frameborder="0" allow="autoplay" title="AI Bongo Drums - Tribal Percussion Instrument Tap the bongos to play! Left drum plays low tone, rig"></iframe>

Adjust width and height as needed. Preview embed β†’

❓ About This Sketch 3 questions

What visual elements are featured in the AI Bongo Drums sketch?

The sketch visually creates two round bongo drums side by side, each with a distinct design that reacts to user interaction.

How can users engage with the AI Bongo Drums instrument?

Users can tap on the left drum to produce a low tone and the right drum for a different sound, simulating a tribal percussion experience.

What creative coding concepts are showcased in this p5.js sketch?

The sketch demonstrates sound synthesis using oscillators and envelopes, as well as hit detection and visual animations to enhance user interaction.

πŸ’¬ AI Chat History 2 messages
πŸ‘€ You
Create a Bongo Drums instrument! Draw two round drums side by side. Click left drum for low tone, right drum for high tone using p5.Oscillator. Show drum skin depression animation when hit. Tribal wooden aesthetic with rope details. Fun percussion sounds!
πŸ€– AI
Here’s a complete bongo drum instrument with two clickable drums, p5.Oscillator-based sounds, hit animation, and a simple tribal wooden aesthetic with rope details.

---

### Updated `index.html`

Loads p5.js and p5.sound correctly before `sketch.js`.

```html
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Bongo Drums - p5.js</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<!-- p5.js will insert the canvas into the body -->
<script src="https://cdn.jsdelivr.net/npm/p5@1.11.3/lib/p5.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/p5@1.11.3/lib/addons/p5.sound.min.js"></script>
<script src="sketch.js"></script>
</body>
</html>
```

---

### Updated `style.css`

Same as before, just ensures full-screen canvas.

```css
/* style.css */
body {
margin: 0;
padding: 0;
overflow: hidden;
background: #1a0f06; /* fallback if canvas not drawn */
font-family: system-ui, sans-serif;
}

canvas {
display: block;
}
```

---

### New `sketch.js`

Two bongos, click/tap to play low/high tones, with skin depression animation and rope/wood visuals.

```js
// sketch.js

// Two Bongo drum objects
let drums = [];
let audioStarted = false;
let reverb;

// Simple Bongo class with sound + drawing + hit animation
class Bongo {
constructor(x, y, r, baseFreq) {
this.x = x; // center of drum head
this.y = y;
this.r = r; // radius of drum head (for hit detection / drawing)
this.baseFreq = baseFreq;
this.hitAmount = 0; // 0..1, used to animate skin depression

// Sound: p5.Oscillator + p5.Envelope
// Docs: https://p5js.org/reference/#/p5.Oscillator
this.osc = new p5.Oscillator('sine');
this.env = new p5.Envelope(); // https://p5js.org/reference/#/p5.Envelope

// Percussive envelope: fast attack, short decay, no sustain, short release
this.env.setADSR(0.001, 0.15, 0.0, 0.18);
this.env.setRange(0.9, 0);

this.osc.freq(this.baseFreq);
this.osc.start();
this.osc.amp(0); // silence until envelope plays
}

setGeometry(x, y, r) {
this.x = x;
this.y = y;
this.r = r;
}

contains(px, py) {
return dist(px, py, this.x, this.y) <= this.r;
}

// Hit the drum at position px,py (for velocity & slight pitch variation)
hit(px, py) {
// Distance from center -> "velocity"
let d = dist(px, py, this.x, this.y);
let velocity = 1 - d / this.r;
velocity = constrain(velocity, 0.25, 1);

// Slight pitch variation: edge hits are a bit lower
const pitchBend = (1 - velocity) * 40; // Hz
this.osc.freq(this.baseFreq + pitchBend);

// Scale envelope loudness with velocity
this.env.setRange(0.9 * velocity, 0);

// Visual depression amount
this.hitAmount = constrain(this.hitAmount + 0.7 * velocity, 0, 1);

// Trigger amplitude envelope
this.env.play(this.osc);
}

update() {
// Exponential decay of visual hit
this.hitAmount *= 0.8;
}

draw() {
push();
translate(this.x, this.y);

// hitAmount controls center depression
const depression = this.hitAmount * (this.r * 0.18);

// Drum body dimensions (2D perspective)
const bodyHeight = this.r * 1.6;
const bodyTopY = this.r * 0.25 + depression * 0.2;
const bodyBottomY = bodyTopY + bodyHeight;
const topWidth = this.r * 1.9;
const bottomWidth = this.r * 1.3;

// Wooden body (trapezoid)
noStroke();
fill(139, 90, 60); // main wood color
beginShape();
vertex(-topWidth / 2, bodyTopY);
vertex(topWidth / 2, bodyTopY);
vertex(bottomWidth / 2, bodyBottomY);
vertex(-bottomWidth / 2, bodyBottomY);
endShape(CLOSE);

// Darker vertical wood grain bands
stroke(110, 70, 45);
strokeWeight(this.r * 0.06);
for (let i = -1; i <= 1; i++) {
const bandX = map(i, -1, 1, -topWidth * 0.25, topWidth * 0.25);
line(bandX, bodyTopY, bandX * 0.9, bodyBottomY);
}

// Rope rings around the body
stroke(230, 214, 180);
strokeWeight(this.r * 0.08);
noFill();
const ropeY1 = bodyTopY + bodyHeight * 0.28;
const ropeY2 = bodyTopY + bodyHeight * 0.63;
arc(0, ropeY1, topWidth * 0.95, this.r * 0.9, PI, 0);
arc(0, ropeY2, bottomWidth * 1.05, this.r * 0.8, PI, 0);

// Rope lacing: from rim to first ring
strokeWeight(this.r * 0.03);
const rimRadiusX = topWidth * 0.47;
const rimY = -this.r * 0.15 + depression * 0.4;
for (let a = -PI * 0.7; a <= PI * 0.7; a += PI / 6) {
const x1 = rimRadiusX * cos(a);
const y1 = rimY + sin(a) * this.r * 0.07;
const x2 = x1 * 0.8;
line(x1, y1, x2, ropeY1);
}

// Wooden rim
noStroke();
fill(94, 57, 34);
ellipse(0, rimY, topWidth, this.r * 0.7);

// Drum skin (with depression)
const skinY = rimY - this.r * 0.02 - depression;
fill(235, 218, 186); // light skin
ellipse(0, skinY, topWidth * 0.88, this.r * 0.6);

// Inner area highlight / tension spot
fill(225, 208, 176);
ellipse(0, skinY + depression * 0.5, topWidth * 0.55, this.r * 0.36);

pop();
}
}

function setup() {
createCanvas(windowWidth, windowHeight);

// Layout: two drums side-by-side
const baseR = min(width, height) * 0.15;
const centerY = height * 0.45;
const spacing = baseR * 2.4;

// Left = low tone, Right = high tone
const leftX = width / 2 - spacing / 2;
const rightX = width / 2 + spacing / 2;

drums.push(new Bongo(leftX, centerY, baseR, 180)); // low bongo
drums.push(new Bongo(rightX, centerY, baseR, 270)); // high bongo

// Add a gentle room reverb to both drums
// p5.Reverb docs: https://p5js.org/reference/#/p5.Reverb
reverb = new p5.Reverb();
for (let d of drums) {
reverb.process(d.osc, 1.8, 2); // seconds, decayRate
}
reverb.amp(0.4);
}

function draw() {
// Dark tribal background
background(26, 15, 6);

// Soft warm spotlight behind the bongos
noStroke();
for (let i = 0; i < 60; i++) {
const alpha = map(i, 0, 59, 90, 0);
fill(120, 80, 40, alpha);
const w = width * 1.4 - i * 12;
const h = height * 1.1 - i * 12;
ellipse(width / 2, height * 0.4, w, h);
}

// Update + draw drums
for (let d of drums) {
d.update();
d.draw();
}

// Instructions text
fill(255, 240);
noStroke();
textAlign(CENTER, CENTER);
textSize(min(width, height) * 0.03);
text('Click or tap the bongos!\nLeft = low, Right = high', width / 2, height * 0.16);
}

function mousePressed() {
// Ensure audio context is started on first user gesture
// userStartAudio: https://p5js.org/reference/#/p5/userStartAudio
if (!audioStarted) {
userStartAudio();
audioStarted = true;
}

triggerDrum(mouseX, mouseY);
}

// On touch devices, p5 usually maps touches to mouse events,
// but this ensures it works reliably on hybrid devices.
function touchStarted() {
if (!audioStarted) {
userStartAudio();
audioStarted = true;
}
if (touches.length > 0) {
triggerDrum(touches[0].x, touches[0].y);
}
return false; // prevent default scrolling on touch
}

function triggerDrum(px, py) {
for (let d of drums) {
if (d.contains(px, py)) {
d.hit(px, py);
break;
}
}
}

function windowResized() {
resizeCanvas(windowWidth, windowHeight);

// Reposition and rescale drums responsively
const baseR = min(width, height) * 0.15;
const centerY = height * 0.45;
const spacing = baseR * 2.4;

if (drums.length === 2) {
drums[0].setGeometry(width / 2 - spacing / 2, centerY, baseR);
drums[1].setGeometry(width / 2 + spacing / 2, centerY, baseR);
}
}
```

You now have:

- Two round tribal-style bongos side by side
- Left drum = low tone, right drum = higher tone (`p5.Oscillator`)
- Percussive envelope + gentle reverb for fun, punchy sounds
- Animated skin depression when hit
- Click/tap support on desktop and touch devices

If you’d like, I can tune the pitches or change the waveform (e.g. add some noise or a different oscillator type) to get closer to a specific bongo sound you have in mind.
🎬 Video Preview