Sample rate

샘플링 레이트

How many times per second a sound is measured and stored. Set it too low and you get aliasing — a fake, wrong pitch that was never in the original.

Also known as: Sampling rateAliasingNyquist frequency
···
html
<div class="wrap">
  <canvas id="cv"></canvas>
  <div class="cap" id="cap">정상 샘플링</div>
  <button class="play" id="play" type="button" aria-label="play sound"><span class="tri"></span></button>
</div>
css
.wrap{position:relative;width:92%;height:84%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px}
canvas{width:100%;height:68%;display:block}
.cap{font:600 11px/1 monospace;color:var(--muted)}
.play{position:absolute;right:0;bottom:0;width:clamp(28px,15%,40px);aspect-ratio:1;border-radius:50%;border:1px solid var(--line);background:var(--surface);display:grid;place-items:center;cursor:pointer;box-shadow:0 2px 8px rgba(0,0,0,.12)}
.play .tri{width:0;height:0;border-style:solid;border-width:6px 0 6px 9px;border-color:transparent transparent transparent var(--fg);margin-left:2px}
.play:active{transform:scale(.92)}
js
const cv = document.getElementById('cv');
const g2d = cv.getContext('2d');
const cap = document.getElementById('cap');
const cs = getComputedStyle(document.documentElement);
const ACCENT = cs.getPropertyValue('--accent').trim() || '#5b5bf7';
const ACCENT2 = cs.getPropertyValue('--accent-2').trim() || '#f25c8a';
const MUTED = cs.getPropertyValue('--muted').trim() || '#888';
let w, h;
function resize() {
  const dpr = Math.min(devicePixelRatio || 1, 2);
  w = cv.clientWidth; h = cv.clientHeight;
  cv.width = w * dpr; cv.height = h * dpr;
  g2d.setTransform(dpr, 0, 0, dpr, 0, 0);
}
addEventListener('resize', resize);
resize();
function trueWave(x) { return Math.sin(x * Math.PI * 2 * 5.3); }
const CYCLE = 2600;
function draw(t) {
  const p = (t % (CYCLE * 2)) / CYCLE;
  const aliased = p >= 1;
  cap.textContent = aliased ? '언더샘플링 (에일리어싱)' : '정상 샘플링';
  const samples = aliased ? 7 : 34;
  g2d.clearRect(0, 0, w, h);
  const mid = h / 2, amp = h * 0.32;
  g2d.beginPath();
  for (let x = 0; x <= w; x++) {
    const y = mid - trueWave(x / w) * amp;
    if (x === 0) g2d.moveTo(x, y); else g2d.lineTo(x, y);
  }
  g2d.strokeStyle = MUTED;
  g2d.lineWidth = 1;
  g2d.globalAlpha = 0.5;
  g2d.stroke();
  g2d.globalAlpha = 1;
  g2d.beginPath();
  for (let i = 0; i <= samples; i++) {
    const x = (i / samples) * w;
    const y = mid - trueWave(x / w) * amp;
    if (i === 0) g2d.moveTo(x, y); else g2d.lineTo(x, y);
  }
  g2d.strokeStyle = aliased ? ACCENT2 : ACCENT;
  g2d.lineWidth = 2;
  g2d.stroke();
  for (let i = 0; i <= samples; i++) {
    const x = (i / samples) * w;
    const y = mid - trueWave(x / w) * amp;
    g2d.beginPath();
    g2d.arc(x, y, 2.4, 0, Math.PI * 2);
    g2d.fillStyle = aliased ? ACCENT2 : ACCENT;
    g2d.fill();
  }
  requestAnimationFrame(draw);
}
requestAnimationFrame(draw);
function makeHeld(ctx, freq, holdSamples, seconds) {
  const sr = ctx.sampleRate;
  const len = Math.floor(sr * seconds);
  const buf = ctx.createBuffer(1, len, sr);
  const d = buf.getChannelData(0);
  let held = 0;
  for (let i = 0; i < len; i++) {
    if (i % holdSamples === 0) held = Math.sin((2 * Math.PI * freq * i) / sr);
    d[i] = held;
  }
  return buf;
}
document.getElementById('play').addEventListener('click', () => {
  const ctx = new (window.AudioContext || window.webkitAudioContext)();
  const now = ctx.currentTime;
  const clean = makeHeld(ctx, 440, 1, 0.4);
  const aliasedBuf = makeHeld(ctx, 3400, 9, 0.4);
  [clean, aliasedBuf].forEach((buf, i) => {
    const src = ctx.createBufferSource();
    src.buffer = buf;
    const gain = ctx.createGain();
    const t = now + i * 0.45;
    gain.gain.setValueAtTime(0, t);
    gain.gain.linearRampToValueAtTime(0.13, t + 0.01);
    gain.gain.setValueAtTime(0.13, t + 0.36);
    gain.gain.linearRampToValueAtTime(0.0001, t + 0.4);
    src.connect(gain).connect(ctx.destination);
    src.start(t);
  });
  setTimeout(() => ctx.close(), 1200);
});

To store an analog (continuous) sound digitally, you must measure its amplitude many times per second — sampling. CD quality samples 44,100 times per second (44.1kHz), and most web audio uses 44.1-48kHz. The Nyquist theorem says any frequency above half the sample rate (the Nyquist frequency) can't be recorded correctly — instead it "folds back" and gets recorded as a different, lower frequency that was never actually there. That's aliasing.

Aliasing works the same way as a wagon wheel appearing to spin backward on film — a stroboscopic illusion where the sampling interval can't keep up with the real rate of change, so a different pattern gets reconstructed. Audio engineering prevents this with a low-pass filter before sampling (an anti-aliasing filter) that removes anything above the Nyquist frequency. UI/UX designers rarely touch sample rate directly, but the concept explains why a notification sound exported at a low bitrate sounds crunchy or wrong.

Used in audio encoding/compression quality settings, optimizing sound assets for low-end devices, and digital signal processing broadly.

When to use

Relevant when compressing sound assets to a low bitrate. Push it too far and you hear noise (aliasing) that was never in the original.