\large{\reg{1 kHz}{freq}}at\large{\reg{50 dB}{level}}

sounds like \large{\reg{50 phon}{phon}}

Isolate Curve

Based on

ISO 226:2023-03

Normal

Equal-Loudness-Level

Contours

const f = [5,10,12.5,15,20,25,31.5,40,50,63,80,100,125,160,200,250,315,400,500,630,800,1000,1250,1600,2000,2500,3150,4000,5e3,6.3e3,8e3,10e3,12.5e3,15e3,17.5e3,20e3,30e3] const A = [ [250,150,105,90,79,70,60,50.5,42.5,35.5,29.5,24.5,20,16,13,10,7.5,5,2.8,1,0,0,2.5,1.5,-2,-5,-7,-6,-3,2,9,13,11,12,19,41,150], [250,150,110,95,83.7,76.1,68.7,61.7,55.5,49.5,43.7,38.6,33.9,29.2,25.1,21.5,18.3,15.4,13.2,11.3,10.0,10.0,11.2,10.5,7.3,4.5,3.0,3.9,7.6,14.4,20.9,23.7,22.4,20.5,24,45,150], [250,150,114,100,89.5,82.9,76.3,69.9,64.3,58.8,53.4,48.6,44.1,39.6,35.6,32.1,28.9,25.9,23.6,21.6,20.1,20.0,21.4,21.5,18.2,15.5,14.2,15.3,18.7,25.0,31.4,34.7,33.0,30.5,33,50,150], [250,150,118,105,94.8,88.6,82.5,76.6,71.4,66.2,61.2,56.7,52.6,48.4,44.7,41.4,38.4,35.7,33.5,31.6,30.0,30.0,31.6,32.1,28.7,26.1,24.9,26.1,29.5,35.5,41.6,44.7,42.4,39,40,55,150], [250,150,122,110,99.7,93.9,88.2,82.7,77.8,73.0,68.3,64.2,60.4,56.6,53.3,50.3,47.6,45.1,43.1,41.4,40.0,40.0,41.8,42.6,39.2,36.6,35.5,36.7,40.1,45.8,51.6,54.4,51.3,46,46.5,60,150], [250,150,125,114,104.6,99.1,93.7,88.5,83.9,79.4,75.2,71.4,68.0,64.6,61.6,58.9,56.5,54.3,52.6,51.1,49.9,50.0,52.0,52.9,49.6,47.0,45.9,47.2,50.5,56.1,61.6,63.9,60.0,53,53,65,150], [250,150,128,118,109.4,104.2,99.1,94.2,89.9,85.8,81.9,78.5,75.4,72.4,69.7,67.4,65.4,63.5,62.1,60.8,59.8,60.0,62.1,63.2,60.0,57.4,56.4,57.7,61.0,66.4,71.5,73.2,68.6,60,58,70,150], [250,151,131,122.5,114.1,109.2,104.4,99.8,95.9,92.1,88.5,85.5,82.8,80.1,77.8,75.9,74.2,72.6,71.5,70.4,69.7,70.0,72.3,73.5,70.4,67.8,66.8,68.1,71.4,76.6,81.4,82.6,77.1,68,63,73,150], [250,152.5,134.1,127,118.9,114.2,109.7,105.4,101.8,98.3,95.1,92.5,90.1,87.8,85.9,84.3,82.9,81.8,80.9,80.1,79.6,80.0,82.5,83.8,80.7,78.1,77.2,78.5,81.8,86.9,91.0,91.9,85.6,75,68,76,150], [250,153.8,137,131,123.6,119.2,115.0,111.0,107.7,104.6,101.7,99.4,97.4,95.5,94.0,92.7,91.7,90.9,90.2,89.7,89.5,90.0,92.6,94.1,91.1,88.5,87.5,88.8,92,96.9,101.0,101,94,83,72,79,150], [250,155,140,135,128.3,124.2,120.2,116.6,113.6,110.8,108.3,106.3,104.7,103.2,102.0,101.1,100.4,99.9,99.6,99.4,99.4,100.0,102.6,104.1,101.1,98.5,97.5,98.8,102,106.9,111.0,111,103,90,76,82,150], ] const B = A[0].map((_, j) => A.map(row => row[j])) const p = this.newPlot({ position: [this.left + 100 , this.bottom + 100], size: [this.width - 130, this.height - 130], rangeX: [31.5,16e3], rangeY: [-10,120], labelX: "Frequency [Hz]", labelY: "Sound Pressure Level [dB]", labelGapX: 20, tickArrayX: [31.5, 63, 125, 250, 500, 1000, 2000, 4000, 8000, 16000], tickStepY: 10, typeX: "log", labelGapX: 30, }) groups = [] A.forEach((c,i)=>{ const phon = i const pg = p.group(phon*10+"ph") pg.style.stroke = color.main pg.style.color = color.text groups.push(pg) p.path({ x:f, y:A[i], strokeLinejoin: "round", strokeWidth:6, group:pg, stroke:"inherit", }) p.text({ position:()=>{ const tDex = f.findIndex(v=>v>=630) return [f[tDex],A[i][tDex]] }, opaque:true, text:phon*10, fontSize:35, group:pg, }) const overlay = p.path({ x:f, y:A[i], strokeLinejoin: "round", strokeWidth:35, opacity:0, group:pg, }) overlay.addAction(p=>{ overlay.group.style.stroke = color.highlight }) overlay.addAction(p=>{ overlay.group.style.stroke = color.main },"unhover") }) const h = p.rect({ position: ()=>p.position, size: ()=>p.size, anchor: ()=>[0,0], screen: true, opacity:0, }) h.addAction(w=>{ const level = w.y const freq = w.x const ph = B[f.findIndex(f=>f>=freq)] reg.freq.update(formatPre(freq)+"Hz") reg.level.update(round(level)+" dB") if (level < ph[0]){ groups.forEach(g=>g.style.stroke = color.main) reg.is.textContent = "is" reg.phon.update("inaudible") return } if (level > ph[ph.length-1]){ groups.forEach(g=>g.style.stroke = color.main) reg.is.textContent = "is" reg.phon.update("painful") return } reg.is.textContent = "sounds like" const maxDex = ph.findIndex(v=>level<=v) const min = ph[maxDex-1] const levelPh = round((maxDex + (level-min)/(ph[maxDex] - min) -1)*10) reg.phon.update(levelPh + " phon") groups.forEach((g,i)=>g.style.stroke = i==round(levelPh/10)?color.highlight:color.main) }) reg.isolateTog.onUpdate(v=>{ groups.forEach((g,i)=>{ g.classList.toggle("hidden",v) if (i*10 == reg.isolate.value) g.classList.remove("hidden") }) }) reg.isolate.onUpdate(v=>{ reg.isolateTog.value = true groups.forEach((g,i)=>{ g.classList.toggle("hidden",reg.isolateTog && i*10 !=v) }) })