# Music box drum

A pinned barrel plucking a comb tuned by length. The notes are data you pass it: one row per tine, any non-blank character a pin.

> For the complete index, see [llms.txt](https://robocn.dev/llms.txt). A Markdown version of any page is available by appending `.md` to its URL or by sending an `Accept: text/markdown` header.

## Install

```bash
bunx --bun shadcn@latest add https://robocn.dev/r/music-box-drum.json
```

Registry item: `music-box-drum` · [`https://robocn.dev/r/music-box-drum.json`](https://robocn.dev/r/music-box-drum.json)

## Notes

- The pluck is a discontinuity, not a wobble. A pin bends its tine further and further as it comes round, is at full bend exactly at the step, and is gone the instant after — which is what a released tine does and what `combLift` returns.
- The comb is tuned by length: a cantilever's frequency goes as one over the length squared, so a semitone is a factor of 2^(−1/24) and an octave up is exactly one over root two the length. That is why the fan is a curve.
- The tips all stand in a line along the barrel and the roots step away from it, because a pin can only reach a tip that is on the barrel's surface. The stepped base is the consequence, not decoration.
- It shares its mechanism with `busker-droid`: a step sequencer is this barrel unrolled flat, and the same `combLift` raises a beater there.
- No acoustics and no dynamics. Nothing here computes a frequency, a decay or a damper, the mainspring is a great wheel with no spring behind it, and the fly is geared rather than braked.

## Usage

```tsx
import { MusicBoxDrum } from "@/components/ui/music-box-drum"

<MusicBoxDrum tines={12} />

// Your own cylinder, or a barrel you can crank by hand.
<MusicBoxDrum pattern={["x...x...", "..x...x."]} tines={2} />
<MusicBoxDrum interactive onStepChange={setStep} />
```

## Props

| name | type | default | description |
| --- | --- | --- | --- |
| `view` | `"plan" | "front" | "profile" | "iso"` | `"plan"` | Where the camera stands. One movement, four projections: straight down, straight on, side elevation, or three-quarter from above. |
| `turn` | `number` | — | Controlled barrel rotation in degrees. Omit it and the barrel runs behavior. |
| `behavior` | `"play" | "cadence" | "static"` | `"play"` | Turn steadily, or hunt the way a governor does — swelling and easing within each revolution without ever running backwards. |
| `tines` | `number` | `12` | Tines on the comb, rounded and clamped to 4–20. Rows beyond the count are ignored; tines beyond the pattern simply never sound. |
| `pattern` | `readonly string[]` | — | One row per tine; any non-blank character is a pin at that step. An empty array is a barrel with no pins, not a fallback. |
| `speed` | `number` | `0.12` | Revolutions of the barrel per second. |
| `animate` | `boolean` | `true` | Off parks the machine at phase and stops rendering. A reduced-motion preference does the same. |
| `paused` | `boolean` | `false` | Freeze where it stands. |
| `phase` | `number` | `0` | Seconds of offset, so a row of machines breaks step. |
| `interactive` | `boolean` | `false` | Drag across to turn the barrel by hand — the frame's width is one revolution — or arrow-key it a step at a time. |
| `onTurnChange` | `(turn: number) => void` | — | Barrel rotation in degrees throughout a drag or a key press. |
| `onStepChange` | `(step: number) => void` | — | The step now standing under the comb, 0-based. |
| `showFly` | `boolean` | `true` | Draw the air-brake fly that regulates the turn. |
| `label` | `string` | — | Caption below the state readout. |
| `variant` | `"solid" | "outline" | "blueprint" | "wire"` | `"solid"` | How the machine is painted. Geometry never changes between variants. |
| `size` | `"xs" | "sm" | "md" | "lg" | "xl" | number` | `"md"` | Rendered width in pixels, or a step on the scale. |
| `color` | `string` | `var(--robot-shell)` | Body panels — the colour the machine reads as. |
| `accent` | `string` | `var(--robot-accent)` | Status colour: tip light, live tool, readouts. |
| `metal` | `string` | `var(--robot-metal)` | Bare machined parts: collars, bolts, tool bodies. |
| `dark` | `string` | `var(--robot-dark)` | Cast joints, base, shadow side. |
| `palette` | `Partial<RobotPalette>` | — | Override any subset of roles at once, including glow and grid. |

## Source

- `src/components/ui/music-box-drum.tsx`
