{
  "schemaVersion": 1,
  "slug": "bpm-calculator",
  "category": "music",
  "kind": "implementation",
  "independentValidation": false,
  "implementationHash": "65a02f920e44d1d2dc33a69879f0f471568ec22cb7151934508a913fee794a92",
  "provenance": "Generated from the calculation contract used by the published page. Publication is not external validation.",
  "sourceFiles": [
    "data/calculators/bpm-calculator.json",
    "src/engine.js"
  ],
  "runtimeSource": "/sources/engine.txt",
  "runtimeHash": "5c888d8898afbdee36267bb9977829e1e2ac568f6677c8ee87469c139864645c",
  "scope": "The compute function records implemented equations, constants, lookup tables and custom rules. Inputs record defaults and allowed values; outputs record precision and units. Defaults are examples, not recommendations. General background references are not evidence for this specific algorithm.",
  "publishedFormula": {
    "formula": "BPM = 60·B/s; ms = 60000/BPM",
    "vars": [
      [
        "B",
        "Beats counted"
      ],
      [
        "s",
        "Counting time (seconds)"
      ],
      [
        "BPM",
        "Beats per minute"
      ],
      [
        "ms",
        "Milliseconds per beat"
      ]
    ],
    "note": "Tempo words are approximate labels. Bar duration = beat duration × beats per bar; other note values scale by their stated multiples."
  },
  "externalEvidence": null,
  "contract": {
    "compute": "const bpm = seconds > 0 ? beats/seconds*60 : 0; const beat = bpm > 0 ? 60000/bpm : 0; return { bpm: bpm, msPerBeat: beat, msPerBar: beat*beatsPerBar, eighthNote: beat/2, sixteenthNote: beat/4, halfNote: beat*2, wholeNote: beat*4, tempoMarking: bpm < 40 ? 'Largo' : bpm < 60 ? 'Larghetto' : bpm < 76 ? 'Adagio' : bpm < 108 ? 'Andante' : bpm < 120 ? 'Moderato' : bpm < 156 ? 'Allegro' : bpm < 200 ? 'Presto' : 'Prestissimo' };",
    "inputs": [
      {
        "name": "beats",
        "type": "number",
        "default": 32,
        "min": 1,
        "max": 10000,
        "step": 1
      },
      {
        "name": "seconds",
        "type": "number",
        "default": 16,
        "min": 0.001,
        "max": 100000,
        "step": 0.001
      },
      {
        "name": "beatsPerBar",
        "type": "number",
        "default": 4,
        "min": 1,
        "max": 32,
        "step": 1,
        "slider": true
      }
    ],
    "outputs": [
      {
        "name": "bpm",
        "precision": 2,
        "unit": "BPM"
      },
      {
        "name": "msPerBeat",
        "precision": 2,
        "unit": "ms"
      },
      {
        "name": "msPerBar",
        "precision": 2,
        "unit": "ms"
      },
      {
        "name": "eighthNote",
        "precision": 2,
        "unit": "ms"
      },
      {
        "name": "sixteenthNote",
        "precision": 2,
        "unit": "ms"
      },
      {
        "name": "halfNote",
        "precision": 2,
        "unit": "ms"
      },
      {
        "name": "wholeNote",
        "precision": 2,
        "unit": "ms"
      },
      {
        "name": "tempoMarking",
        "precision": 0,
        "unit": "",
        "type": "text"
      }
    ],
    "interpret": null
  }
}
