import Head from "next/head"; import { ChangeEventHandler, useState } from "react"; const calculateFrequency = (root: number, noteDescriptor: string) => { const match = noteDescriptor.match( /([a-gA-G])\s*(#?)(b?)\s*(-?\d+)([+-]\d+)?/ ); if (match == null) return undefined; const [value, note, sharp, flat, octave, cents] = match; const dists: { [key: string]: number | undefined } = { C: -9, D: -7, E: -5, F: -4, G: -2, A: 0, B: 2, }; let distanceFromA = dists[note.toUpperCase()]; if (distanceFromA == null) return; if (sharp) distanceFromA += 1; if (flat) distanceFromA -= 1; if (cents) distanceFromA += parseInt(cents) / 100; let octaveDistance = parseInt(octave) - 4; return root * Math.pow(2, octaveDistance + distanceFromA / 12); }; const calculateNote = (root: number, frequency: number) => { const distanceFromA = 12 * Math.log2(frequency / root); const semis = Math.round(distanceFromA); const cents = Math.round((distanceFromA - semis) * 100); let octave = 4 + Math.floor(semis / 12); const octaveBoundSemis = ((semis % 12) + 12) % 12; if (octaveBoundSemis >= 3) octave += 1; const notes = [ "A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", ]; const note = notes[octaveBoundSemis]; let centsStr = ""; if (cents <= -1) { centsStr = cents.toString().padStart(2, "0"); } else if (cents >= 1) { centsStr = "+" + cents.toString().padStart(2, "0"); } return `${note}${octave}${centsStr}`; }; export default function Main() { const [root, setRoot] = useState(440); const [note, setNote] = useState("C5"); const [frequency, setFrequency] = useState("523.251"); const setRootValue: ChangeEventHandler = (e) => { const newRoot = parseFloat(e.target.value); if (!isNaN(newRoot)) setRoot(newRoot); const frequency = calculateFrequency(newRoot, note); if (frequency != null) setFrequency(frequency.toFixed(3)); }; const setNoteValue: ChangeEventHandler = (e) => { setNote(e.target.value); const frequency = calculateFrequency(root, e.target.value); if (frequency != null) setFrequency(frequency.toFixed(3)); }; const setFrequencyValue: ChangeEventHandler = (e) => { setFrequency(e.target.value); const newFrequency = parseFloat(e.target.value); if (!isNaN(newFrequency)) { const noteDescriptor = calculateNote(root, newFrequency); setNote(noteDescriptor); } }; return ( <> 12 tone equal temperament :)
(by charlotte som)
{"if A4 is "} {" Hz"}, then
{" is "} {" Hz "}
); }