{
  "schemaVersion": 1,
  "slug": "fret-calculator",
  "category": "music",
  "kind": "implementation",
  "independentValidation": false,
  "implementationHash": "bd16fd83c94a010d215fa49b35914c9979996605d29727680e95d10e562ca67b",
  "provenance": "Generated from the calculation contract used by the published page. Publication is not external validation.",
  "sourceFiles": [
    "data/calculators/fret-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": "d_n = L x (1 - 2^(-n/12)); gap_n = d_n - d_{n-1}; f = 440 x 2^((m-69)/12), m = (O+1) x 12 + i + n",
    "vars": [
      [
        "L",
        "scale length (nut to bridge)"
      ],
      [
        "n",
        "fret number (0 = open)"
      ],
      [
        "d_n",
        "distance from the nut"
      ],
      [
        "O",
        "open-string octave"
      ],
      [
        "i",
        "open-note semitone index (C=0)"
      ],
      [
        "f",
        "fret frequency in Hz"
      ]
    ],
    "note": "Equal temperament: distance from nut = L × (1 − 2^(−n/12)); adjacent fret spacing shrinks by the same twelfth-root-of-two ratio. Note frequency assumes A4 = 440 Hz."
  },
  "externalEvidence": null,
  "contract": {
    "compute": "const L = scaleLength; const n = Math.max(0, Math.round(fretNumber)); const fromNut = L*(1 - Math.pow(2, -n/12)); const fromBridge = L - fromNut; const prev = L*(1 - Math.pow(2, -(n - 1)/12)); const names = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']; const base = names.indexOf(openNote); const midi = (Math.round(openOctave) + 1)*12 + (base < 0 ? 0 : base) + n; const midiNote = midi % 12; return { distanceFromNut: fromNut, distanceFromBridge: fromBridge, distanceFromPrevious: n === 0 ? 0 : fromNut - prev, note: names[midiNote], frequency: 440*Math.pow(2, (midi - 69)/12), cents: n };",
    "inputs": [
      {
        "name": "scaleLength",
        "type": "number",
        "default": 25.5,
        "min": 5,
        "max": 40,
        "step": 0.01,
        "slider": true
      },
      {
        "name": "fretNumber",
        "type": "number",
        "default": 12,
        "min": 0,
        "max": 36,
        "step": 1,
        "slider": true
      },
      {
        "name": "openNote",
        "type": "select",
        "default": "E",
        "options": [
          {
            "value": "E"
          },
          {
            "value": "A"
          },
          {
            "value": "D"
          },
          {
            "value": "G"
          },
          {
            "value": "B"
          }
        ]
      },
      {
        "name": "openOctave",
        "type": "number",
        "default": 2,
        "min": 0,
        "max": 6,
        "step": 1
      }
    ],
    "outputs": [
      {
        "name": "distanceFromNut",
        "precision": 4,
        "unit": "in"
      },
      {
        "name": "distanceFromBridge",
        "precision": 4,
        "unit": "in"
      },
      {
        "name": "distanceFromPrevious",
        "precision": 4,
        "unit": "in"
      },
      {
        "name": "note",
        "precision": 0,
        "unit": "",
        "type": "text"
      },
      {
        "name": "frequency",
        "precision": 2,
        "unit": "Hz"
      },
      {
        "name": "cents",
        "precision": 0,
        "unit": ""
      }
    ],
    "interpret": null
  }
}
