<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: The Tap Tempo</title>
    <description>The latest articles on DEV Community by The Tap Tempo (@thetaptempo).</description>
    <link>https://dev.to/thetaptempo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4021634%2Fcbc3727a-2d3b-4b5a-8a21-866fafe369b2.png</url>
      <title>DEV Community: The Tap Tempo</title>
      <link>https://dev.to/thetaptempo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thetaptempo"/>
    <language>en</language>
    <item>
      <title>The Math (and Code) Behind Converting BPM to Milliseconds</title>
      <dc:creator>The Tap Tempo</dc:creator>
      <pubDate>Wed, 22 Jul 2026 11:18:27 +0000</pubDate>
      <link>https://dev.to/thetaptempo/the-math-and-code-behind-converting-bpm-to-milliseconds-1gei</link>
      <guid>https://dev.to/thetaptempo/the-math-and-code-behind-converting-bpm-to-milliseconds-1gei</guid>
      <description>&lt;p&gt;Why Every Audio Developer Eventually Needs This Formula&lt;/p&gt;

&lt;p&gt;If you've ever built anything involving rhythm — a metronome, a delay effect, a rhythm game, a DAW plugin, or even a CSS animation that needs to "feel" like it's on-beat — you'll run into the same wall: your code operates in milliseconds, but music operates in BPM (beats per minute). At some point you have to convert between the two, and getting it slightly wrong is the difference between an effect that locks to the groove and one that feels off.&lt;/p&gt;

&lt;p&gt;This post walks through the core formula, the code that implements it, and the edge cases (dotted notes, triplets, LFO sync) that trip people up.&lt;/p&gt;

&lt;p&gt;The Core Formula&lt;/p&gt;

&lt;p&gt;There are 60,000 milliseconds in a minute. If a song has a tempo of BPM beats per minute, then one beat (a quarter note, in standard time) lasts:&lt;/p&gt;

&lt;p&gt;quarterNoteMs = 60000 / BPM&lt;/p&gt;

&lt;p&gt;That's it. Everything else in this post is a variation on that one line.&lt;/p&gt;

&lt;p&gt;js&lt;br&gt;
function bpmToMs(bpm) {&lt;br&gt;
  return 60000 / bpm;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;bpmToMs(120); // 500 — a quarter note at 120 BPM is exactly half a second&lt;br&gt;
Extending to Other Note Values&lt;/p&gt;

&lt;p&gt;Every standard note duration is a simple multiple or fraction of the quarter note:&lt;/p&gt;

&lt;p&gt;js&lt;br&gt;
function noteDurations(bpm) {&lt;br&gt;
  const quarter = 60000 / bpm;&lt;br&gt;
  return {&lt;br&gt;
    whole:            quarter * 4,&lt;br&gt;
    half:             quarter * 2,&lt;br&gt;
    quarter,&lt;br&gt;
    eighth:           quarter / 2,&lt;br&gt;
    sixteenth:        quarter / 4,&lt;br&gt;
    thirtySecond:     quarter / 8,&lt;br&gt;
    dottedQuarter:    quarter * 1.5,&lt;br&gt;
    dottedEighth:     (quarter / 2) * 1.5,&lt;br&gt;
    quarterTriplet:   quarter * (2 / 3),&lt;br&gt;
    eighthTriplet:    (quarter / 2) * (2 / 3),&lt;br&gt;
  };&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;console.log(noteDurations(120));&lt;br&gt;
// { whole: 2000, half: 1000, quarter: 500, eighth: 250, sixteenth: 125,&lt;br&gt;
//   thirtySecond: 62.5, dottedQuarter: 750, dottedEighth: 375,&lt;br&gt;
//   quarterTriplet: 333.33, eighthTriplet: 166.67 }&lt;/p&gt;

&lt;p&gt;Two subtleties that are easy to get backwards:&lt;/p&gt;

&lt;p&gt;Dotted notes are 1.5× their undotted value (a dot adds half the note's original duration).&lt;br&gt;
Triplets divide a beat into three instead of two, so a triplet note is 2/3 the duration of its straight counterpart — not 1/3.&lt;br&gt;
Where This Actually Gets Used&lt;/p&gt;

&lt;p&gt;This isn't just music-theory trivia — it maps directly onto real audio programming tasks:&lt;/p&gt;

&lt;p&gt;Use case    What you're really doing&lt;br&gt;
Delay effect / echo plugin  Setting delayTimeMs so repeats land on a subdivision&lt;br&gt;
Reverb pre-delay    Offsetting the reverb tail so it doesn't smear transients&lt;br&gt;
LFO / tremolo rate  Converting a note duration into a frequency in Hz&lt;br&gt;
Rhythm game timing windows  Defining how wide a "hit window" is, in ms, per difficulty&lt;br&gt;
CSS/Canvas beat-synced animation    setInterval/requestAnimationFrame timed to a groove&lt;br&gt;
Converting a Note Duration to an LFO Frequency&lt;/p&gt;

&lt;p&gt;If you're driving a Web Audio OscillatorNode or any modulation source, you often need Hz, not ms. The conversion is just the reciprocal:&lt;/p&gt;

&lt;p&gt;js&lt;br&gt;
function noteToHz(ms) {&lt;br&gt;
  const seconds = ms / 1000;&lt;br&gt;
  return 1 / seconds;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;noteToHz(bpmToMs(128)); // ≈ 2.13 Hz — one quarter-note cycle per beat at 128 BPM&lt;br&gt;
Going the Other Direction: MS Back to BPM&lt;/p&gt;

&lt;p&gt;Sometimes you have the millisecond value first — say, a delay time that already "feels right" — and you want to know what tempo it implies:&lt;/p&gt;

&lt;p&gt;js&lt;br&gt;
function msToBpm(ms, noteFraction = 1) {&lt;br&gt;
  // noteFraction: 1 = quarter note, 0.5 = eighth, 1.5 = dotted quarter, etc.&lt;br&gt;
  const quarterMs = ms / noteFraction;&lt;br&gt;
  return 60000 / quarterMs;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;msToBpm(300, 0.5); // 100 — a 300ms eighth note implies 100 BPM&lt;/p&gt;

&lt;p&gt;This reverse lookup is genuinely useful when you're reverse-engineering the tempo of a sample or matching a pre-recorded delay loop to a new track.&lt;/p&gt;

&lt;p&gt;The Part Most Tutorials Skip: Precision and Drift&lt;/p&gt;

&lt;p&gt;A few things that will bite you in production code:&lt;/p&gt;

&lt;p&gt;Use performance.now(), not Date.now(), for anything measuring intervals in the browser. Date.now() has coarser resolution and is subject to system clock adjustments; performance.now() gives you a monotonic, sub-millisecond clock.&lt;br&gt;
Sample-rate limits matter for very short intervals. At a 44.1kHz sample rate, 1ms ≈ 44 samples. If you're calculating sub-10ms delay times (like tight slapback echo), round carefully — aggressive rounding compounds into audible drift over many repeats, especially with feedback.&lt;br&gt;
Don't truncate decimals early. 60000 / 128 = 468.75. If you round that to 469 before further math (like converting to Hz), your LFO will drift out of phase over a long session. Keep full float precision until the final assignment.&lt;br&gt;
Putting It Together: A Minimal Tempo Utility&lt;/p&gt;

&lt;p&gt;Here's a small, dependency-free utility that covers the common cases:&lt;/p&gt;

&lt;p&gt;js&lt;br&gt;
const TempoUtils = {&lt;br&gt;
  bpmToMs(bpm, subdivision = 1) {&lt;br&gt;
    return (60000 / bpm) * subdivision;&lt;br&gt;
  },&lt;br&gt;
  msToHz(ms) {&lt;br&gt;
    return 1000 / ms;&lt;br&gt;
  },&lt;br&gt;
  msToBpm(ms, subdivision = 1) {&lt;br&gt;
    return 60000 / (ms / subdivision);&lt;br&gt;
  },&lt;br&gt;
};&lt;/p&gt;

&lt;p&gt;// Dotted eighth delay at 120 BPM (subdivision = 0.5 * 1.5 = 0.75)&lt;br&gt;
TempoUtils.bpmToMs(120, 0.75); // 375&lt;/p&gt;

&lt;p&gt;Subdivision multipliers, for reference: whole = 4, half = 2, quarter = 1, eighth = 0.5, sixteenth = 0.25, dotted-X = X × 1.5, X-triplet = X × (2/3).&lt;/p&gt;

&lt;p&gt;Try It Without Writing Any Code&lt;/p&gt;

&lt;p&gt;If you just need the numbers and don't want to wire this up yourself, I built a free calculator that does exactly this — BPM to ms, dotted notes, triplets, and a genre-based delay/reverb preset chart: &lt;a href="https://www.thetaptempo.com/bpm-to-ms" rel="noopener noreferrer"&gt;BPM to Milliseconds Calculator&lt;/a&gt;. It's part of a small toolkit I've been building — including a &lt;a href="https://www.thetaptempo.com/tap-tempo" rel="noopener noreferrer"&gt;tap tempo BPM finder&lt;/a&gt; that uses the same interval-averaging approach described above, and a &lt;a href="https://www.thetaptempo.com/delay-reverb-time-calculator" rel="noopener noreferrer"&gt;Delay &amp;amp; Reverb Time Calculator&lt;/a&gt; for the full effect-chain workflow.&lt;/p&gt;

&lt;p&gt;Wrap-Up&lt;/p&gt;

&lt;p&gt;The formula is one line: 60000 / BPM. Everything else — dotted notes, triplets, LFO Hz conversion, reverse lookups — is just careful multiplication and remembering which direction you're dividing. If you're building anything rhythm-adjacent, this small utility will save you from the "why does my delay feel almost right but not quite" debugging session everyone eventually has.&lt;/p&gt;

&lt;p&gt;If you've solved beat-detection or tempo-sync problems in an interesting way — especially audio-based BPM detection from a raw waveform rather than manual tapping — I'd love to hear about your approach in the comments.&lt;/p&gt;

</description>
      <category>music</category>
      <category>tap</category>
      <category>thetaptempo</category>
      <category>djs</category>
    </item>
    <item>
      <title>How to Find the BPM of Any Song (7 Proven Methods) | The Tap Tempo</title>
      <dc:creator>The Tap Tempo</dc:creator>
      <pubDate>Wed, 08 Jul 2026 15:37:25 +0000</pubDate>
      <link>https://dev.to/thetaptempo/how-to-find-the-bpm-of-any-song-7-proven-methods-the-tap-tempo-2gj4</link>
      <guid>https://dev.to/thetaptempo/how-to-find-the-bpm-of-any-song-7-proven-methods-the-tap-tempo-2gj4</guid>
      <description>&lt;p&gt;&lt;a href="https://www.thetaptempo.com/blog/how-to-find-bpm-of-any-song" rel="noopener noreferrer"&gt;https://www.thetaptempo.com/blog/how-to-find-bpm-of-any-song&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
