oneshotlm
Compare all models on this prompt →

Drum machine · gpt-4.1-mini

Build a 16-step drum machine with a clickable grid for kick, snare, hi-hat, and clap, all sounds synthesized with the Web Audio API, plus play/stop and an adjustable BPM.

⚠ no runnable output

This one-shot run produced no runnable artifact.

agent produced no index.html

The transcript below shows what the model did — read it to see why the one shot fell short.

transcript · 2 messages
user

Build a 16-step drum machine with a clickable grid for kick, snare, hi-hat, and clap, all sounds synthesized with the Web Audio API, plus play/stop and an adjustable BPM.

assistant

Creating a 16-step drum machine with four drum sounds (kick, snare, hi-hat, clap), a clickable grid, play/stop button, and adjustable BPM, all synthesized with Web Audio API, inline and self-contained: ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>16-step Drum Machine</title> <style> body { font-family: Arial, sans-serif; background: #121212; color: #eee; display: flex; flex-direction: column; align-items: center; padding: 1rem; user-select: none; } h1 { margin-bottom: 0.5rem; } #controls { margin-bottom: 1rem; display: flex; align-items: center; gap: 1rem; } #bpmLabel { font-weight: bold; } #bpmInput { width: 60px; } button { background: #222; border: 1px solid #444; border-radius: 5px; color: #eee; padding: 0.5rem 1rem; font-size: 1rem; cursor: pointer; transition: background 0.3s; } button:hover { background: #555; } #grid { display: grid; grid-template-columns: repeat(16, 30px); grid-auto-rows: 40px; gap: 4px; } .label-column { writing-mode: vertical-rl; text-orientation: mixed; font-weight: bold; font-size: 0.875rem; line-height: 40px; color: #888; } .step-button { width: 30px; height: 40px; background: #222; border-radius: 4px; border: 1px solid #444; cursor: pointer; transition: background 0.2s; } .step-button.active { background: #0f7ea0; box-shadow: 0 0 8px #0f7ea0; } .step-button.playing { border-color: #ffcb05; } #grid-container { display: flex; flex-direction: column; gap: 6px; } .row-label { width: 70px; text-align: right; font-weight: bold; line-height: 40px; margin-right: 8px; color: #aaa; } .row { display: flex; align-items: center; } </style> </head> <body> <h1>16-Step Drum Machine</h1> <div id="controls"> <button id="playStopBtn">Play</button> <label for="bpmInput" id="bpmLabel">BPM:</label> <input type="number" id="bpmInput" min="40" max="240" step="1" value="120" /> </div> <div id="grid-container"></div> <script> (() => { const audioCtx = new (window.AudioContext || window.webkitAudioContext)(); // Drum sound synthesizers function playKick(time) { // Kick: sine with descending frequency + short noise burst const osc = audioCtx.createOscillator(); const gain = audioCtx.createGain(); osc.type = 'sine'; osc.frequency.setValueAtTime(150, time); osc.frequency.exponentialRampToValueAtTime(0.001, time + 0.3); gain.gain.setValueAtTime(1, time); gain.gain.exponentialRampToValueAtTime(0.001, time + 0.3); osc.connect(gain); gain.connect(audioCtx.destination); osc.start(time); osc.stop(time + 0.3); } function playSnare(time) { // Snare: noise + bandpass filtered white noise + pitch envelope on noise const noiseBuffer = audioCtx.createBuffer(1, audioCtx.sampleRate * 0.2, audioCtx.sampleRate); const output = noiseBuffer.getChannelData(0); for (let i = 0; i < output.length; i++) { output[i] = Math.random() * 2 - 1; } const noise = audioCtx.createBufferSource(); noise.buffer = noiseBuffer; const noiseFilter = audioCtx.createBiquadFilter(); noiseFilter.type = 'bandpass'; noiseFilter.frequency.setValueAtTime(1000, time); const noiseGain = audioCtx.createGain(); noiseGain.gain.setValueAtTime(1, time); noiseGain.gain.exponentialRampToValueAtTime(0.01, time + 0.15); noise.connect(noiseFilter); noiseFilter.connect(noiseGain); noiseGain.connect(audioCtx.destination); noise.start(time); noise.stop(time + 0.15); } function playHiHat(time) { // Hi-hat: bandpass filtered white noise with high frequency const noiseBuffer = audioCtx.createBuffer(1, audioCtx.sampleRate * 0.05, audioCtx.sampleRate); const output = noiseBuffer.getChannelData(0); for (let i = 0; i < output.length; i++) { output[i] = Math.random() * 2 - 1; } const noise = audioCtx.createBufferSource(); noise.buffer = noiseBuffer; const bandpass = audioCtx.createBiquadFilter(); bandpass.type = 'bandpass'; bandpass.frequency.setValueAtTime(8000, time); const gain = audioCtx.createGain(); gain.gain.setValueAtTime(0.6, time); gain.gain.exponentialRampToValueAtTime(0.01, time + 0.05); noise.connect(bandpass); bandpass.connect(gain); gain.connect(audioCtx.destination); noise.start(time); noise.stop(time + 0.05); } function playClap(time) { // Clap: multiple noise bursts with envelope const noiseBuffer = audioCtx.createBuffer(1, audioCtx.sampleRate * 0.03, audioCtx.sampleRate); const output = noiseBuffer.getChannelData(0); for (let i = 0; i < output.length; i++) { output[i] = Math.random() * 2 - 1; } const gain = audioCtx.createGain(); gain.gain.setValueAtTime(0, time); const bandpass = audioCtx.createBiquadFilter(); bandpass.type = 'bandpass'; bandpass.frequency.setValueAtTime(1800, time); bandpass.connect(gain); gain.connect(audioCtx.destination); function burst(t, gainValue) { const noise = audioCtx.createBufferSource(); noise.buffer = noiseBuffer; noise.connect(bandpass); noise.start(t); noise.stop(t + 0.03); gain.gain.setValueAtTime(gainValue, t); gain.gain.exponentialRampToValueAtTime(0.01, t + 0.03); } burst(time, 0.4); burst(time + 0.02, 0.3); burst(time + 0.04, 0.2); } const instruments = [ { name: 'Kick', play: playKick }, { name: 'Snare', play: playSnare }, { name: 'Hi-Hat', play: playHiHat }, { name: 'Clap', play: playClap } ]; const steps = 16; let currentStep = 0; let isPlaying = false; let timerId = null; let bpm = 120; // Sequencer state: 4 rows (instruments) x 16 steps const sequence = []; for (let i = 0; i < instruments.length; i++) { sequence[i] = new Array(steps).fill(false); } const gridContainer = document.getElementById('grid-container'); // Create grid UI rows with labels + 16 step buttons function createGrid() { gridContainer.innerHTML = ''; for (let i = 0; i < instruments.length; i++) { const rowDiv = document.createElement('div'); rowDiv.className = 'row'; const labelDiv = document.createElement('div'); labelDiv.className = 'row-label'; labelDiv.textContent = instruments[i].name; rowDiv.appendChild(labelDiv); for (let step = 0; step < steps; step++) { const btn = document.createElement('button'); btn.className = 'step-button'; btn.dataset.instrument = i; btn.dataset.step = step; btn.title = instruments[i].name + ' - Step ' + (step + 1); btn.addEventListener('click', () => { sequence[i][step] = !sequence[i][step]; btn.classList.toggle('active', sequence[i][step]); }); rowDiv.appendChild(btn); } gridContainer.appendChild(rowDiv); } } createGrid(); // Play current step and schedule next step function playStep() { const now = audioCtx.currentTime; for (let i = 0; i < instruments.length; i++) { if (sequence[i][currentStep]) { instruments[i].play(now); } } updatePlayingStepHighlight(currentStep); currentStep = (currentStep + 1) % steps; const interval = (60 / bpm) / 4; // 16th notes timerId = setTimeout(playStep, interval * 1000); } // Highlight currently playing step column function updatePlayingStepHighlight(step) { // Remove playing highlight from all buttons document.querySelectorAll('.step-button.playing').forEach(btn => { btn.classList.remove('playing'); }); // Add playing highlight to current step buttons document.querySelectorAll(`.step-button[data-step='${step}']`).forEach(btn => { btn.classList.add('playing'); }); } // Controls const playStopBtn = document.getElementById('playStopBtn'); const bpmInput = document.getElementById('bpmInput'); playStopBtn.addEventListener('click', () => { if (!isPlaying) { if (audioCtx.state === 'suspended') { audioCtx.resume(); } isPlaying = true; playStopBtn.textContent = 'Stop'; currentStep = 0; playStep(); } else { isPlaying = false; playStopBtn.textContent = 'Play'; clearTimeout(timerId); updatePlayingStepHighlight(-1); } }); bpmInput.addEventListener('input', () => { const val = Number(bpmInput.value); if (val >= 40 && val <= 240) { bpm = val; // If playing, restart timer with new BPM if (isPlaying) { clearTimeout(timerId); playStep(); } } }); })(); </script> </body> </html> ``` This HTML file includes: - A heading and controls for play/stop and BPM input. - A grid of 4 rows (kick, snare, hi-hat, clap) × 16 steps with toggle buttons. - Web Audio API synthesized drum sounds: kick, snare, hi-hat, clap. - The sequencer plays the pattern at the chosen BPM with visual highlighting for the active step. - The grid buttons toggle enabling/disabling instruments on steps. Open this file in a modern browser to try the drum machine.

TAKE IT TO CODE

This run produced no artifact — reuse the prompt with a different model or your own pi-agent run.

RUN

modelgpt-4.1-mini
vendorOpenAI
harnesspi-agent
generated2026-08-01

METRICS

runtime33.0s
tokens in1.2k
tokens out2.6k
cached0
cost / run$0.0046