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,
...