Pitch finder

(c) vHW

by PhilQ

HTML

<input type="range" id="volume" min="0" max="1.0" step="0.1" value="1" />
<input type="file" id="midi" />
<audio id="player" controls></audio>

<div id="notes">
	<svg
		id="sheet"
		version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
		x="0px" y="0px" viewBox="0 -97.5 200 195"
		xml:space="preserve"
	>
		<defs>
			<g id="clefs" viewBox="0 0 200 195">
				<g id="f-clef">
					<path d="M52.8,23.1c0.9,0,1.6-0.3,2.3-0.9c0.6-0.6,1-1.4,1-2.2c0-0.8-0.3-1.6-1-2.2c-0.7-0.7-1.4-1-2.2-1c-0.9,0-1.7,0.3-2.3,0.9c-0.6,0.6-1,1.3-1,2.2c0,0.9,0.3,1.7,0.9,2.3C51.1,22.8,51.9,23.1,52.8,23.1z"/>
					<path d="M39.8,14.4c-2.3-1.3-4.8-2-7.4-2c-2.4,0-4.8,0.5-7,1.4c-2.3,0.9-4.2,2.2-5.7,4c-1.5,1.8-2.2,3.9-2.2,6.3c0,1.9,0.7,3.4,2,4.7c1.3,1.2,3,1.8,5,1.8c1.1,0,2.1-0.2,3-0.7c0.9-0.5,1.6-1.1,2.1-1.9c0.5-0.8,0.8-1.7,0.8-2.6c0-1.3-0.5-2.4-1.5-3.3c-1.1-0.9-2.2-1.4-3.5-1.4c-0.5,0-1.1,0.1-1.6,0.2c-0.6,0.1-1,0.2-1.2,0.2c-0.3,0-0.6-0.1-0.9-0.3c-0.3-0.2-0.5-0.5-0.6-0.9c0.1-0.3,0.2-0.5,0.2-0.7c0.7-1.8,1.9-3.1,3.7-3.9c1.8-0.8,3.7-1.2,5.7-1.2c2.1,0,3.8,0.6,5.1,1.8c1.3,1.2,2.2,2.7,2.7,4.6c0.5,1.8,0.8,3.8,0.8,5.8c-0.1,2.3-0.5,4.6-1.2,6.9c-0.7,2.4-1.7,4.5-2.7,6.4c-1.4,2.5-3,4.7-5,6.7c-2,2-3.9,3.6-5.8,5c-2,1.5-5.3,3.7-8.5,5.9l0,0l0.4,1.3l0,0c6.8-3.4,11.8-6.1,14.8-8.1c4.5-2.9,8.4-6.4,11.5-10.4c3.1-4,4.7-8.3,4.7-12.9c0-2.6-0.7-5-2.1-7.3C44,17.5,42.1,15.7,39.8,14.4z"/>
					<path d="M52.9,29.4c-1,0-1.7,0.3-2.3,0.9c-0.6,0.6-0.9,1.4-0.9,2.2c0,1,0.3,1.7,0.9,2.3c0.6,0.6,1.4,0.9,2.3,0.9c0.8,0,1.6-0.3,2.2-0.9c0.6-0.6,0.9-1.4,0.9-2.3c0-0.8-0.3-1.5-1-2.1C54.4,29.7,53.7,29.4,52.9,29.4z"/>
				</g>
				<path id="g-clef"...

SCSS

#notes {
	position: relative;
}

#sheet {
	position: absolute;
	top: 0;
	left: 0;
	z-index: 0;
}

.staff-line {
	fill: none;
	stroke-width: 2px;
	stroke: #AAAAAA;
	stroke-linecap: square;
}

.clefs {
	fill: #131516;
}

.current-note,
.note-btn {
	position: absolute;
	z-index: 1;
	left: 0px;
	top: 0px;
	transform: translate(-50%, -50%);
	font-family: sans-serif;
	font-size: 0.75rem;
	font-weight: bold;
	text-transform: uppercase;
	line-height: 1;
	padding: 0;
	margin: 0;
	border: 0;
	background: transparent;
	
	&::after {
		content: attr(title);
		white-space: nowrap;
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		color: #fff;
	}	
}

.note-btn {
	--color: 29, 78, 216;
	--opacity: 0.8;
	color: rgba(var(--color), var(--opacity));

	&:hover, &:focus {
		--opacity: 1;
		outline: none;
		// color: #fff;
		
		&::after {
			// color: rgba(var(--color), var(--opacity));
		}
	
		path, use {
			color: currentColor;
		}
	}
	
	&.playing {
		path, use {
			color: black !important;
		}
	}
}

.current-note {
	--hue: 160;
	--saturation: 0%;
	color: hsl(var(--hue), var(--saturation), 40%);
}

.octave-7 { --color: 77, 124, 15; }
.octave-6 { --color: 4, 120, 87; }
.octave-5 { --color: 14, 116, 144; }
.octave-4 { --color: 29, 78, 216; }
.octave-3 { --color: 109, 40, 217; }
.octave-2 { --color: 162, 28, 175; }
.octave-1 { --color: 190, 18, 60; }

#oscilloscope {}

JavaScript

// Source: https://github.com/GoogleChromeLabs/web-audio-samples/tree/main/src/demos/wavetable-synth/wave-tables
const wavetable = {
    'real': [
        0.000000,
        0.246738,
        0.083890,
        0.095378,
        0.087885,
        0.165621,
        0.287369,
        -0.328845,
        -0.099613,
        -0.198535,
        0.260484,
        0.012771,
        0.013351,
        0.006221,
        0.003106,
        0.000629,
        -0.003591,
        -0.002876,
        -0.003527,
        -0.002975,
        -0.002648,
        -0.006996,
        -0.004165,
        -0.004266,
        -0.000731,
        0.003727,
        0.018167,
        0.012018,
        -0.017044,
        -0.004816,
        -0.001255,
        -0.002032,
        0.000272,
        -0.001849,
        0.004334,
        0.000773,
        -0.000690,
        -0.000207,
        0.000136,
        -0.000108,
        0.000508,
        -0.000701,
        -0.000958,
        -0.004677,
        0.002005,
        -0.001925,
        -0.001450,
        -0.002212,
        -0.001163,
        -0.000227,
        0.000182,
        -0.000448,
        0.000152,
        -0.000316,
        -0.000054,
        -0.000193,
        -0.000170,
        -0.000138,
        -0.000179,
        0.000059,
        0.000017,
        0.000008,
        0.000252,
        0.000382,
        -0.000319,
        0.000020,
        -0.000087,
        0.000020,
        -0.000024,
        -0.000002,
        0.000044,
        -0.000131,
        0.000145,
        -0.000581,
        -0.000182,
        -0.001087,
        -0.000746,
        -0.002759,
        -0.001195,
        -0.002868,
        -0.000729,
        -0.002915,
        0.000325,
        -0.001489,
        0.000419,
        -0.000322,
        0.000054,
        -0.000200,
        0.000032,
        0.000071,
        0.000196,
        -0.000127,
        0.000355,
        -0.000328,
        0.000518,
        -0.000280,
        0.000620,
        -0.000360,
        0.000553,
       ...