@classytic/stage 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/_rolldown/runtime.mjs +18 -0
- package/dist/atomic/aufbau.d.mts +144 -0
- package/dist/atomic/aufbau.mjs +384 -0
- package/dist/atomic/elements.d.mts +67 -0
- package/dist/atomic/elements.mjs +785 -0
- package/dist/atomic/emission.d.mts +112 -0
- package/dist/atomic/emission.mjs +179 -0
- package/dist/atomic/index.d.mts +8 -0
- package/dist/atomic/index.mjs +9 -0
- package/dist/atomic/periodic.d.mts +82 -0
- package/dist/atomic/periodic.mjs +231 -0
- package/dist/atomic/properties.d.mts +100 -0
- package/dist/atomic/properties.mjs +574 -0
- package/dist/atomic/shells.d.mts +137 -0
- package/dist/atomic/shells.mjs +170 -0
- package/dist/atomic/trends.d.mts +148 -0
- package/dist/atomic/trends.mjs +225 -0
- package/dist/chem/chromatography.d.mts +66 -0
- package/dist/chem/chromatography.mjs +63 -0
- package/dist/chem/complex.d.mts +114 -0
- package/dist/chem/complex.mjs +234 -0
- package/dist/chem/cycle.d.mts +75 -0
- package/dist/chem/cycle.mjs +145 -0
- package/dist/chem/equation.d.mts +86 -0
- package/dist/chem/equation.mjs +168 -0
- package/dist/chem/formula.d.mts +90 -0
- package/dist/chem/formula.mjs +201 -0
- package/dist/chem/functional-groups.d.mts +31 -0
- package/dist/chem/functional-groups.mjs +187 -0
- package/dist/chem/hazard.d.mts +94 -0
- package/dist/chem/hazard.mjs +329 -0
- package/dist/chem/index.d.mts +34 -33
- package/dist/chem/index.mjs +34 -28
- package/dist/chem/ionic.d.mts +98 -0
- package/dist/chem/ionic.mjs +156 -0
- package/dist/chem/layout.d.mts +46 -0
- package/dist/chem/layout.mjs +342 -0
- package/dist/chem/lewis.d.mts +79 -0
- package/dist/chem/lewis.mjs +163 -0
- package/dist/chem/molecular-orbital.d.mts +114 -0
- package/dist/chem/molecular-orbital.mjs +201 -0
- package/dist/chem/molecule.d.mts +154 -0
- package/dist/chem/molecule.mjs +282 -0
- package/dist/chem/nmr.d.mts +153 -0
- package/dist/chem/nmr.mjs +165 -0
- package/dist/chem/polymer.d.mts +65 -0
- package/dist/chem/polymer.mjs +179 -0
- package/dist/chem/redox.d.mts +138 -0
- package/dist/chem/redox.mjs +328 -0
- package/dist/chem/relations.d.mts +183 -0
- package/dist/chem/relations.mjs +299 -0
- package/dist/chem/skeleton.d.mts +51 -0
- package/dist/chem/skeleton.mjs +186 -0
- package/dist/chem/solution.d.mts +116 -0
- package/dist/chem/solution.mjs +186 -0
- package/dist/chem/species.d.mts +47 -0
- package/dist/chem/species.mjs +128 -0
- package/dist/chem/stereo.d.mts +108 -0
- package/dist/chem/stereo.mjs +286 -0
- package/dist/chem/stoichiometry.d.mts +95 -0
- package/dist/chem/stoichiometry.mjs +145 -0
- package/dist/chem/synthesis.d.mts +113 -0
- package/dist/chem/synthesis.mjs +281 -0
- package/dist/chem/vsepr.d.mts +80 -0
- package/dist/chem/vsepr.mjs +247 -0
- package/dist/circuit/ac.d.mts +163 -0
- package/dist/circuit/ac.mjs +452 -0
- package/dist/circuit/dc.d.mts +92 -0
- package/dist/circuit/dc.mjs +333 -0
- package/dist/circuit/index.d.mts +5 -92
- package/dist/circuit/index.mjs +5 -332
- package/dist/circuit/network.d.mts +99 -0
- package/dist/circuit/network.mjs +440 -0
- package/dist/circuit/topology.d.mts +102 -0
- package/dist/circuit/topology.mjs +143 -0
- package/dist/colour/absorption.d.mts +79 -0
- package/dist/colour/absorption.mjs +137 -0
- package/dist/colour/index.d.mts +6 -0
- package/dist/colour/index.mjs +7 -0
- package/dist/colour/name.d.mts +14 -0
- package/dist/colour/name.mjs +76 -0
- package/dist/colour/observer.d.mts +31 -0
- package/dist/colour/observer.mjs +46 -0
- package/dist/colour/spectrum.d.mts +61 -0
- package/dist/colour/spectrum.mjs +108 -0
- package/dist/colour/srgb.d.mts +49 -0
- package/dist/colour/srgb.mjs +108 -0
- package/dist/core/constants.d.mts +138 -0
- package/dist/core/constants.mjs +139 -0
- package/dist/core/index.d.mts +3 -1
- package/dist/core/index.mjs +3 -1
- package/dist/core/vec3.d.mts +94 -0
- package/dist/core/vec3.mjs +123 -0
- package/dist/core/worked.d.mts +35 -0
- package/dist/core/worked.mjs +44 -0
- package/dist/electro/cell.d.mts +102 -0
- package/dist/electro/cell.mjs +170 -0
- package/dist/electro/conductivity.d.mts +157 -0
- package/dist/electro/conductivity.mjs +156 -0
- package/dist/electro/couples.d.mts +114 -0
- package/dist/electro/couples.mjs +334 -0
- package/dist/electro/electrolysis.d.mts +96 -0
- package/dist/electro/electrolysis.mjs +274 -0
- package/dist/electro/faraday.d.mts +150 -0
- package/dist/electro/faraday.mjs +118 -0
- package/dist/electro/index.d.mts +6 -0
- package/dist/electro/index.mjs +7 -0
- package/dist/finance/accounting/adjustments.d.mts +17 -0
- package/dist/finance/accounting/adjustments.mjs +202 -0
- package/dist/finance/accounting/analysis.d.mts +8 -0
- package/dist/finance/accounting/analysis.mjs +205 -0
- package/dist/finance/accounting/clubs.d.mts +21 -0
- package/dist/finance/accounting/clubs.mjs +217 -0
- package/dist/finance/accounting/company-statements.d.mts +7 -0
- package/dist/finance/accounting/company-statements.mjs +150 -0
- package/dist/finance/accounting/harness.d.mts +7 -0
- package/dist/finance/accounting/harness.mjs +45 -0
- package/dist/finance/accounting/index.d.mts +18 -0
- package/dist/finance/accounting/index.mjs +18 -0
- package/dist/finance/accounting/journalize.d.mts +16 -0
- package/dist/finance/accounting/journalize.mjs +128 -0
- package/dist/finance/accounting/manufacturing.d.mts +8 -0
- package/dist/finance/accounting/manufacturing.mjs +236 -0
- package/dist/finance/accounting/partnership.d.mts +7 -0
- package/dist/finance/accounting/partnership.mjs +152 -0
- package/dist/finance/accounting/period-case.d.mts +6 -0
- package/dist/finance/accounting/period-case.mjs +71 -0
- package/dist/finance/accounting/post.d.mts +9 -0
- package/dist/finance/accounting/post.mjs +84 -0
- package/dist/finance/accounting/precision.d.mts +9 -0
- package/dist/finance/accounting/precision.mjs +15 -0
- package/dist/finance/accounting/rules.d.mts +21 -0
- package/dist/finance/accounting/rules.mjs +37 -0
- package/dist/finance/accounting/solve.d.mts +28 -0
- package/dist/finance/accounting/solve.mjs +92 -0
- package/dist/finance/accounting/statements.d.mts +7 -0
- package/dist/finance/accounting/statements.mjs +142 -0
- package/dist/finance/accounting/types.d.mts +649 -0
- package/dist/finance/accounting/validate.d.mts +7 -0
- package/dist/finance/accounting/validate.mjs +67 -0
- package/dist/finance/accounting/verification.d.mts +24 -0
- package/dist/finance/accounting/verification.mjs +386 -0
- package/dist/finance/bizsim.d.mts +21 -39
- package/dist/finance/bizsim.mjs +276 -97
- package/dist/finance/index.d.mts +20 -43
- package/dist/finance/index.mjs +19 -77
- package/dist/finance/investment-math.d.mts +7 -0
- package/dist/finance/investment-math.mjs +18 -0
- package/dist/finance/management-accounting/budgeting.d.mts +7 -0
- package/dist/finance/management-accounting/budgeting.mjs +189 -0
- package/dist/finance/management-accounting/cash-budget.d.mts +7 -0
- package/dist/finance/management-accounting/cash-budget.mjs +154 -0
- package/dist/finance/management-accounting/costing.d.mts +8 -0
- package/dist/finance/management-accounting/costing.mjs +175 -0
- package/dist/finance/management-accounting/decisions.d.mts +8 -0
- package/dist/finance/management-accounting/decisions.mjs +164 -0
- package/dist/finance/management-accounting/index.d.mts +13 -0
- package/dist/finance/management-accounting/index.mjs +13 -0
- package/dist/finance/management-accounting/integrated-budget.d.mts +8 -0
- package/dist/finance/management-accounting/integrated-budget.mjs +67 -0
- package/dist/finance/management-accounting/inventory-costing.d.mts +7 -0
- package/dist/finance/management-accounting/inventory-costing.mjs +173 -0
- package/dist/finance/management-accounting/investment-appraisal.d.mts +7 -0
- package/dist/finance/management-accounting/investment-appraisal.mjs +148 -0
- package/dist/finance/management-accounting/management-case.d.mts +8 -0
- package/dist/finance/management-accounting/management-case.mjs +91 -0
- package/dist/finance/management-accounting/master-budget.d.mts +7 -0
- package/dist/finance/management-accounting/master-budget.mjs +137 -0
- package/dist/finance/management-accounting/production-costing.d.mts +8 -0
- package/dist/finance/management-accounting/production-costing.mjs +214 -0
- package/dist/finance/management-accounting/types.d.mts +644 -0
- package/dist/finance/management-accounting/variances.d.mts +7 -0
- package/dist/finance/management-accounting/variances.mjs +150 -0
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +1 -1
- package/dist/math/analysis.d.mts +61 -0
- package/dist/math/analysis.mjs +187 -0
- package/dist/math/answer-check.d.mts +50 -0
- package/dist/math/answer-check.mjs +106 -0
- package/dist/math/calculus.d.mts +4 -9
- package/dist/math/calculus.mjs +216 -7
- package/dist/math/complex.d.mts +93 -0
- package/dist/math/complex.mjs +239 -0
- package/dist/math/expr.d.mts +23 -0
- package/dist/math/expr.mjs +36 -0
- package/dist/math/index.d.mts +8 -22
- package/dist/math/index.mjs +8 -37
- package/dist/math/latex.mjs +2 -1
- package/dist/math/parse.mjs +1 -1
- package/dist/math/poly.d.mts +55 -0
- package/dist/math/poly.mjs +273 -0
- package/dist/math/rearrange.d.mts +14 -0
- package/dist/math/rearrange.mjs +125 -0
- package/dist/math/solve.d.mts +21 -0
- package/dist/math/solve.mjs +75 -0
- package/dist/networking/addressing.d.mts +26 -0
- package/dist/networking/addressing.mjs +33 -0
- package/dist/networking/cloud/access.d.mts +36 -0
- package/dist/networking/cloud/access.mjs +95 -0
- package/dist/networking/cloud/containers.d.mts +43 -0
- package/dist/networking/cloud/containers.mjs +54 -0
- package/dist/networking/cloud/edge.d.mts +17 -0
- package/dist/networking/cloud/edge.mjs +31 -0
- package/dist/networking/cloud/failure-domains.d.mts +19 -0
- package/dist/networking/cloud/failure-domains.mjs +22 -0
- package/dist/networking/cloud/geo-routing.d.mts +22 -0
- package/dist/networking/cloud/geo-routing.mjs +64 -0
- package/dist/networking/cloud/index.d.mts +18 -0
- package/dist/networking/cloud/index.mjs +19 -0
- package/dist/networking/cloud/inference-reliability.d.mts +30 -0
- package/dist/networking/cloud/inference-reliability.mjs +76 -0
- package/dist/networking/cloud/inference.d.mts +118 -0
- package/dist/networking/cloud/inference.mjs +179 -0
- package/dist/networking/cloud/infrastructure.d.mts +45 -0
- package/dist/networking/cloud/infrastructure.mjs +96 -0
- package/dist/networking/cloud/observability.d.mts +24 -0
- package/dist/networking/cloud/observability.mjs +34 -0
- package/dist/networking/cloud/orchestration.d.mts +32 -0
- package/dist/networking/cloud/orchestration.mjs +38 -0
- package/dist/networking/cloud/recovery.d.mts +21 -0
- package/dist/networking/cloud/recovery.mjs +27 -0
- package/dist/networking/cloud/releases.d.mts +42 -0
- package/dist/networking/cloud/releases.mjs +135 -0
- package/dist/networking/cloud/scaling.d.mts +25 -0
- package/dist/networking/cloud/scaling.mjs +65 -0
- package/dist/networking/cloud/secrets.d.mts +39 -0
- package/dist/networking/cloud/secrets.mjs +68 -0
- package/dist/networking/cloud/server-deployment.d.mts +29 -0
- package/dist/networking/cloud/server-deployment.mjs +72 -0
- package/dist/networking/cloud/storage.d.mts +16 -0
- package/dist/networking/cloud/storage.mjs +58 -0
- package/dist/networking/cloud/vpc.d.mts +18 -0
- package/dist/networking/cloud/vpc.mjs +100 -0
- package/dist/networking/delivery.d.mts +34 -0
- package/dist/networking/delivery.mjs +52 -0
- package/dist/networking/index.d.mts +47 -0
- package/dist/networking/index.mjs +47 -0
- package/dist/networking/ipv6.d.mts +28 -0
- package/dist/networking/ipv6.mjs +17 -0
- package/dist/networking/journeys.d.mts +83 -0
- package/dist/networking/journeys.mjs +161 -0
- package/dist/networking/models/airtime.d.mts +87 -0
- package/dist/networking/models/airtime.mjs +130 -0
- package/dist/networking/models/cellular.d.mts +157 -0
- package/dist/networking/models/cellular.mjs +252 -0
- package/dist/networking/models/encapsulation.d.mts +98 -0
- package/dist/networking/models/encapsulation.mjs +132 -0
- package/dist/networking/models/handover.d.mts +116 -0
- package/dist/networking/models/handover.mjs +209 -0
- package/dist/networking/models/handshake.d.mts +90 -0
- package/dist/networking/models/handshake.mjs +122 -0
- package/dist/networking/models/index.d.mts +14 -0
- package/dist/networking/models/index.mjs +15 -0
- package/dist/networking/models/media.d.mts +82 -0
- package/dist/networking/models/media.mjs +188 -0
- package/dist/networking/models/satellite.d.mts +86 -0
- package/dist/networking/models/satellite.mjs +121 -0
- package/dist/networking/models/spectrum.d.mts +83 -0
- package/dist/networking/models/spectrum.mjs +235 -0
- package/dist/networking/models/switch.d.mts +80 -0
- package/dist/networking/models/switch.mjs +155 -0
- package/dist/networking/models/vlan.d.mts +62 -0
- package/dist/networking/models/vlan.mjs +100 -0
- package/dist/networking/models/vpn.d.mts +66 -0
- package/dist/networking/models/vpn.mjs +125 -0
- package/dist/networking/models/wifi-privacy.d.mts +82 -0
- package/dist/networking/models/wifi-privacy.mjs +130 -0
- package/dist/networking/models/wifi.d.mts +240 -0
- package/dist/networking/models/wifi.mjs +562 -0
- package/dist/networking/nat-traversal.d.mts +24 -0
- package/dist/networking/nat-traversal.mjs +38 -0
- package/dist/networking/protocols.d.mts +17 -0
- package/dist/networking/protocols.mjs +57 -0
- package/dist/networking/queue.d.mts +12 -0
- package/dist/networking/queue.mjs +18 -0
- package/dist/networking/route-learning.d.mts +23 -0
- package/dist/networking/route-learning.mjs +43 -0
- package/dist/networking/routing.d.mts +11 -0
- package/dist/networking/routing.mjs +25 -0
- package/dist/networking/signals.d.mts +26 -0
- package/dist/networking/signals.mjs +35 -0
- package/dist/networking/subnet.d.mts +49 -0
- package/dist/networking/subnet.mjs +89 -0
- package/dist/networking/tcp-reliability.d.mts +24 -0
- package/dist/networking/tcp-reliability.mjs +38 -0
- package/dist/networking/topology/contract.d.mts +123 -0
- package/dist/networking/topology/index.d.mts +4 -0
- package/dist/networking/topology/index.mjs +4 -0
- package/dist/networking/topology/presets.d.mts +7 -0
- package/dist/networking/topology/presets.mjs +302 -0
- package/dist/networking/topology/simulation.d.mts +8 -0
- package/dist/networking/topology/simulation.mjs +179 -0
- package/dist/networking/wireless.d.mts +11 -0
- package/dist/networking/wireless.mjs +17 -0
- package/dist/optics/imaging.d.mts +218 -0
- package/dist/optics/imaging.mjs +276 -0
- package/dist/optics/index.d.mts +7 -0
- package/dist/optics/index.mjs +8 -0
- package/dist/optics/laws.d.mts +70 -0
- package/dist/optics/laws.mjs +195 -0
- package/dist/optics/prism.d.mts +148 -0
- package/dist/optics/prism.mjs +197 -0
- package/dist/optics/refraction.d.mts +201 -0
- package/dist/optics/refraction.mjs +270 -0
- package/dist/optics/wave-optics.d.mts +171 -0
- package/dist/optics/wave-optics.mjs +259 -0
- package/dist/physics/ac/index.d.mts +183 -0
- package/dist/physics/ac/index.mjs +203 -0
- package/dist/physics/dynamics/forces.d.mts +98 -0
- package/dist/physics/dynamics/forces.mjs +153 -0
- package/dist/physics/dynamics/friction.d.mts +76 -0
- package/dist/physics/dynamics/friction.mjs +119 -0
- package/dist/physics/dynamics/system.d.mts +68 -0
- package/dist/physics/dynamics/system.mjs +125 -0
- package/dist/physics/electrostatics/index.d.mts +169 -0
- package/dist/physics/electrostatics/index.mjs +249 -0
- package/dist/physics/energy/centre-of-mass.d.mts +115 -0
- package/dist/physics/energy/centre-of-mass.mjs +180 -0
- package/dist/physics/energy/conservation.d.mts +81 -0
- package/dist/physics/energy/conservation.mjs +129 -0
- package/dist/physics/energy/power.d.mts +90 -0
- package/dist/physics/energy/power.mjs +167 -0
- package/dist/physics/energy/spring.d.mts +73 -0
- package/dist/physics/energy/spring.mjs +129 -0
- package/dist/physics/energy/store.d.mts +63 -0
- package/dist/physics/energy/store.mjs +108 -0
- package/dist/physics/energy/theorem.d.mts +65 -0
- package/dist/physics/energy/theorem.mjs +113 -0
- package/dist/physics/energy/work.d.mts +114 -0
- package/dist/physics/energy/work.mjs +219 -0
- package/dist/physics/gravitation/body.d.mts +85 -0
- package/dist/physics/gravitation/body.mjs +168 -0
- package/dist/physics/gravitation/kepler.d.mts +127 -0
- package/dist/physics/gravitation/kepler.mjs +216 -0
- package/dist/physics/gravitation/law.d.mts +117 -0
- package/dist/physics/gravitation/law.mjs +175 -0
- package/dist/physics/gravitation/orbit.d.mts +119 -0
- package/dist/physics/gravitation/orbit.mjs +202 -0
- package/dist/physics/gravitation/potential.d.mts +114 -0
- package/dist/physics/gravitation/potential.mjs +202 -0
- package/dist/physics/gravitation/variation.d.mts +97 -0
- package/dist/physics/gravitation/variation.mjs +175 -0
- package/dist/physics/index.d.mts +35 -0
- package/dist/physics/index.mjs +36 -0
- package/dist/physics/integral-sweep.d.mts +63 -0
- package/dist/physics/integral-sweep.mjs +126 -0
- package/dist/physics/kinematics/equations.d.mts +47 -0
- package/dist/physics/kinematics/equations.mjs +126 -0
- package/dist/physics/kinematics/free-fall.d.mts +53 -0
- package/dist/physics/kinematics/free-fall.mjs +71 -0
- package/dist/physics/kinematics/given.d.mts +16 -0
- package/dist/physics/kinematics/given.mjs +55 -0
- package/dist/physics/kinematics/roots.d.mts +41 -0
- package/dist/physics/kinematics/roots.mjs +72 -0
- package/dist/physics/kinematics/solve.d.mts +52 -0
- package/dist/physics/kinematics/solve.mjs +172 -0
- package/dist/physics/magnetism/biot-savart.d.mts +161 -0
- package/dist/physics/magnetism/biot-savart.mjs +353 -0
- package/dist/physics/magnetism/flux.d.mts +94 -0
- package/dist/physics/magnetism/flux.mjs +313 -0
- package/dist/physics/magnetism/geomagnetism.d.mts +151 -0
- package/dist/physics/magnetism/geomagnetism.mjs +184 -0
- package/dist/physics/magnetism/index.d.mts +12 -0
- package/dist/physics/magnetism/index.mjs +74 -0
- package/dist/physics/magnetism/lorentz.d.mts +28 -0
- package/dist/physics/magnetism/lorentz.mjs +88 -0
- package/dist/physics/magnetism/magnetic-force.d.mts +102 -0
- package/dist/physics/magnetism/magnetic-force.mjs +169 -0
- package/dist/physics/momentum/collide.d.mts +77 -0
- package/dist/physics/momentum/collide.mjs +115 -0
- package/dist/physics/momentum/impulse.d.mts +89 -0
- package/dist/physics/momentum/impulse.mjs +159 -0
- package/dist/physics/momentum/planar.d.mts +60 -0
- package/dist/physics/momentum/planar.mjs +110 -0
- package/dist/physics/projectile.d.mts +107 -0
- package/dist/physics/projectile.mjs +185 -0
- package/dist/physics/rotation/angular.d.mts +85 -0
- package/dist/physics/rotation/angular.mjs +130 -0
- package/dist/physics/rotation/circular.d.mts +79 -0
- package/dist/physics/rotation/circular.mjs +131 -0
- package/dist/physics/rotation/inertia.d.mts +164 -0
- package/dist/physics/rotation/inertia.mjs +332 -0
- package/dist/physics/rotation/torque.d.mts +65 -0
- package/dist/physics/rotation/torque.mjs +134 -0
- package/dist/physics/vectors.d.mts +64 -0
- package/dist/physics/vectors.mjs +114 -0
- package/dist/quantity/index.d.mts +119 -0
- package/dist/quantity/index.mjs +417 -0
- package/dist/relation/derive.d.mts +74 -0
- package/dist/relation/derive.mjs +73 -0
- package/dist/relation/index.d.mts +56 -0
- package/dist/relation/index.mjs +234 -0
- package/dist/scene/evaluators.mjs +1 -1
- package/dist/sim/thermal.mjs +45 -20
- package/dist/thermo/calorimetry.d.mts +207 -0
- package/dist/thermo/calorimetry.mjs +345 -0
- package/dist/thermo/cycles.d.mts +142 -0
- package/dist/thermo/cycles.mjs +256 -0
- package/dist/thermo/entropy.d.mts +87 -0
- package/dist/thermo/entropy.mjs +140 -0
- package/dist/thermo/expansion.d.mts +130 -0
- package/dist/thermo/expansion.mjs +178 -0
- package/dist/thermo/gas.d.mts +197 -0
- package/dist/thermo/gas.mjs +279 -0
- package/dist/thermo/heat-transfer.d.mts +164 -0
- package/dist/thermo/heat-transfer.mjs +217 -0
- package/dist/thermo/index.d.mts +9 -82
- package/dist/thermo/index.mjs +9 -132
- package/dist/thermo/processes.d.mts +95 -0
- package/dist/thermo/processes.mjs +154 -0
- package/dist/thermo/temperature.d.mts +174 -0
- package/dist/thermo/temperature.mjs +236 -0
- package/dist/waves/damping.d.mts +224 -0
- package/dist/waves/damping.mjs +317 -0
- package/dist/waves/doppler.d.mts +72 -0
- package/dist/waves/doppler.mjs +125 -0
- package/dist/waves/index.d.mts +10 -0
- package/dist/waves/index.mjs +10 -0
- package/dist/waves/pendulum.d.mts +130 -0
- package/dist/waves/pendulum.mjs +211 -0
- package/dist/waves/pitch.d.mts +125 -0
- package/dist/waves/pitch.mjs +158 -0
- package/dist/waves/shm.d.mts +170 -0
- package/dist/waves/shm.mjs +279 -0
- package/dist/waves/springs.d.mts +103 -0
- package/dist/waves/springs.mjs +176 -0
- package/dist/waves/superposition.d.mts +124 -0
- package/dist/waves/superposition.mjs +196 -0
- package/dist/waves/wave.d.mts +154 -0
- package/dist/waves/wave.mjs +178 -0
- package/package.json +74 -2
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
//#region src/waves/doppler.ts
|
|
2
|
+
const finitePositive = (value, what) => {
|
|
3
|
+
if (!Number.isFinite(value) || value <= 0) throw new RangeError(`${what} must be positive and finite`);
|
|
4
|
+
return value;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Component of a velocity along the line from source to observer, positive when closing.
|
|
8
|
+
*
|
|
9
|
+
* This is what turns the one-dimensional textbook formula into something a scene can use: only the
|
|
10
|
+
* radial part shifts the pitch, so a source passing to one side is at its unshifted frequency at
|
|
11
|
+
* the moment of closest approach, when all of its motion is transverse. That instant is the thing a
|
|
12
|
+
* learner should see and almost never does.
|
|
13
|
+
*/
|
|
14
|
+
function radialSpeed(source, observer, velocity) {
|
|
15
|
+
const dx = observer.x - source.x;
|
|
16
|
+
const dy = observer.y - source.y;
|
|
17
|
+
const distance = Math.hypot(dx, dy);
|
|
18
|
+
if (distance === 0) return 0;
|
|
19
|
+
return (velocity.x * dx + velocity.y * dy) / distance;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Observed frequency for a source moving through a still medium: `f_s v / (v - v_r)`.
|
|
23
|
+
*
|
|
24
|
+
* `radialSourceSpeed` is positive when the source is closing on the observer. Returns `Infinity` at
|
|
25
|
+
* exactly Mach 1 (see the header) and a NEGATIVE frequency above it, which is the honest reading of
|
|
26
|
+
* the formula in a regime where it no longer describes anything: past the sound barrier the wave
|
|
27
|
+
* arrives before the source does, and this expression stops being the right model. Callers should
|
|
28
|
+
* branch on `machNumber >= 1` rather than trusting the number.
|
|
29
|
+
*/
|
|
30
|
+
function observedFrequencyMovingSource(sourceFrequency, waveSpeed, radialSourceSpeed) {
|
|
31
|
+
finitePositive(sourceFrequency, "source frequency");
|
|
32
|
+
finitePositive(waveSpeed, "wave speed");
|
|
33
|
+
if (!Number.isFinite(radialSourceSpeed)) throw new RangeError("radial speed must be finite");
|
|
34
|
+
const denominator = waveSpeed - radialSourceSpeed;
|
|
35
|
+
if (denominator === 0) return Number.POSITIVE_INFINITY;
|
|
36
|
+
return sourceFrequency * waveSpeed / denominator;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Observed frequency for an observer moving through a still medium: `f_s (v + v_r) / v`.
|
|
40
|
+
*
|
|
41
|
+
* Note the different shape: this one cannot diverge, because the observer cannot outrun the wave
|
|
42
|
+
* into a zero denominator. Racing away at exactly the wave speed gives zero, which is right, as the
|
|
43
|
+
* crests never catch up.
|
|
44
|
+
*/
|
|
45
|
+
function observedFrequencyMovingObserver(sourceFrequency, waveSpeed, radialObserverSpeed) {
|
|
46
|
+
finitePositive(sourceFrequency, "source frequency");
|
|
47
|
+
finitePositive(waveSpeed, "wave speed");
|
|
48
|
+
if (!Number.isFinite(radialObserverSpeed)) throw new RangeError("radial speed must be finite");
|
|
49
|
+
return sourceFrequency * (waveSpeed + radialObserverSpeed) / waveSpeed;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Both moving, the general case: `f_s (v + v_o) / (v - v_s)`.
|
|
53
|
+
*
|
|
54
|
+
* Provided because a scene with a moving listener needs it, not because the syllabus asks. Radial
|
|
55
|
+
* speeds are positive when closing, for both.
|
|
56
|
+
*/
|
|
57
|
+
function observedFrequency(sourceFrequency, waveSpeed, radialSourceSpeed, radialObserverSpeed = 0) {
|
|
58
|
+
finitePositive(sourceFrequency, "source frequency");
|
|
59
|
+
const v = finitePositive(waveSpeed, "wave speed");
|
|
60
|
+
const denominator = v - radialSourceSpeed;
|
|
61
|
+
if (denominator === 0) return Number.POSITIVE_INFINITY;
|
|
62
|
+
return sourceFrequency * (v + radialObserverSpeed) / denominator;
|
|
63
|
+
}
|
|
64
|
+
/** Wavelength in the medium ahead of a moving source: `(v - v_s) / f_s`. Goes to zero at Mach 1. */
|
|
65
|
+
function wavelengthAhead(sourceFrequency, waveSpeed, sourceSpeed) {
|
|
66
|
+
finitePositive(sourceFrequency, "source frequency");
|
|
67
|
+
finitePositive(waveSpeed, "wave speed");
|
|
68
|
+
return (waveSpeed - sourceSpeed) / sourceFrequency;
|
|
69
|
+
}
|
|
70
|
+
/** Wavelength behind a moving source: `(v + v_s) / f_s`. */
|
|
71
|
+
function wavelengthBehind(sourceFrequency, waveSpeed, sourceSpeed) {
|
|
72
|
+
finitePositive(sourceFrequency, "source frequency");
|
|
73
|
+
finitePositive(waveSpeed, "wave speed");
|
|
74
|
+
return (waveSpeed + sourceSpeed) / sourceFrequency;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The rise coming and the fall going, as multiples of the source frequency.
|
|
78
|
+
*
|
|
79
|
+
* Returns `{ approaching, receding, riseOverFall }`. The third number is the one worth showing: it
|
|
80
|
+
* is never 1, and it grows with speed, so "the pitch drops as it passes" is only half the story.
|
|
81
|
+
*/
|
|
82
|
+
function frequencyShiftAsymmetry(waveSpeed, sourceSpeed) {
|
|
83
|
+
const v = finitePositive(waveSpeed, "wave speed");
|
|
84
|
+
if (!Number.isFinite(sourceSpeed) || sourceSpeed < 0) throw new RangeError("source speed must be >= 0");
|
|
85
|
+
const approaching = sourceSpeed === v ? Number.POSITIVE_INFINITY : v / (v - sourceSpeed);
|
|
86
|
+
const receding = v / (v + sourceSpeed);
|
|
87
|
+
return {
|
|
88
|
+
approaching,
|
|
89
|
+
receding,
|
|
90
|
+
riseOverFall: sourceSpeed === 0 ? 1 : (approaching - 1) / (1 - receding)
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/** Mach number: source speed as a multiple of the wave speed. */
|
|
94
|
+
function machNumber(sourceSpeed, waveSpeed) {
|
|
95
|
+
return sourceSpeed / finitePositive(waveSpeed, "wave speed");
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Half-angle of the Mach cone, radians: `asin(1 / M)`.
|
|
99
|
+
*
|
|
100
|
+
* `null` below Mach 1, because there is no cone: the wavefronts still nest inside one another and
|
|
101
|
+
* nothing piles up. Returning null rather than NaN lets a scene ask "is there a cone" by asking.
|
|
102
|
+
*/
|
|
103
|
+
function machConeHalfAngle(mach) {
|
|
104
|
+
if (!Number.isFinite(mach) || mach < 1) return null;
|
|
105
|
+
return Math.asin(1 / mach);
|
|
106
|
+
}
|
|
107
|
+
/** Radius a wavefront has reached, given when it left and the time now. */
|
|
108
|
+
function wavefrontRadius(waveSpeed, emittedAt, now) {
|
|
109
|
+
finitePositive(waveSpeed, "wave speed");
|
|
110
|
+
return Math.max(0, waveSpeed * (now - emittedAt));
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Speed of a source from a measured frequency shift, which is the direction the astronomy and radar
|
|
114
|
+
* uses run in: you have `f_o` and want `v`.
|
|
115
|
+
*
|
|
116
|
+
* `v_s = v (1 - f_s / f_o)`, positive when closing.
|
|
117
|
+
*/
|
|
118
|
+
function sourceSpeedFromShift(sourceFrequency, observedFrequency, waveSpeed) {
|
|
119
|
+
finitePositive(sourceFrequency, "source frequency");
|
|
120
|
+
finitePositive(observedFrequency, "observed frequency");
|
|
121
|
+
return finitePositive(waveSpeed, "wave speed") * (1 - sourceFrequency / observedFrequency);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
//#endregion
|
|
125
|
+
export { frequencyShiftAsymmetry, machConeHalfAngle, machNumber, observedFrequency, observedFrequencyMovingObserver, observedFrequencyMovingSource, radialSpeed, sourceSpeedFromShift, wavefrontRadius, wavelengthAhead, wavelengthBehind };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Vec2 } from "../core/vec.mjs";
|
|
2
|
+
import { Direction, Wave, angularFrequency, displacement, frequencyFromAngular, frequencyFromPeriod, frequencyFromSpeed, intensityRatio, interferenceAt, maxParticleSpeed, particleAcceleration, particleVelocity, pathFromPhase, period, phaseAt, phaseFromPath, sampleWave, speedOf, waveNumber, waveSpeed, wavelengthFromSpeed, wavelengthFromWaveNumber } from "./wave.mjs";
|
|
3
|
+
import { OscillatorEnergy, OscillatorState, amplitudeFromState, angularFrequencyFromPeriod, displacementAtSpeed, energyAt, energyAtSteps, energyPeriod, equalEnergyDisplacement, maxAcceleration, maxSpeed, oscillatorStateAt, periodFromAngularFrequency, phaseFromState, shmAcceleration, shmDisplacement, shmVelocity, speedAtDisplacement, springAngularFrequency, springPeriod, totalEnergy } from "./shm.mjs";
|
|
4
|
+
import { cutSpringStiffness, splitSpringStiffness, springExtension, springForce, springPeriodFromExtension, staticExtension, stiffnessFromAngularFrequency, stiffnessFromExtension, stiffnessFromExtensionSteps, stiffnessInParallel, stiffnessInSeries } from "./springs.mjs";
|
|
5
|
+
import { SECONDS_PER_DAY, clockDriftPerDay, clockDriftSteps, effectiveGravityInLift, graphSlopeForGravity, gravityFromGraphSlope, gravityFromPendulumSteps, gravityFromPeriod, gravityFromPeriodRatio, liftAccelerationFromPeriod, pendulumAmplitudeCorrection, pendulumAngularFrequency, pendulumLength, pendulumPeriod, periodAtGravity, periodForDailyDrift, secondsPendulumLength } from "./pendulum.mjs";
|
|
6
|
+
import { DampingRegime, amplificationFactor, amplitudeRatioPerCycle, criticalDamping, dampedAmplitude, dampedAngularFrequency, dampedDisplacement, dampedEnergy, dampedVelocity, dampingRatio, dampingRatioFromDecrement, dampingRegime, decayTimeConstant, drivenAmplitude, drivenPhaseLag, logarithmicDecrement, mechanicalQ, qFromDampingRatio, resonantAngularFrequency, settlingTime } from "./damping.mjs";
|
|
7
|
+
import { A4_HZ, CENTS_PER_OCTAVE, SEMITONE_NAMES, SEMITONE_RATIO, centsBetween, frequencyAfterCents, frequencyAfterSemitones, fretPosition, fretSpacing, frettedLength, isInTune, justIntervalCents, nearestNote, semitonesBetween, temperedIntervalCents } from "./pitch.mjs";
|
|
8
|
+
import { BoundaryKind, TwoSourcePoint, antinodePositions, beatDisplacement, beatEnvelope, beatFrequency, harmonicFrequency, harmonicSeries, harmonicWavelength, nodePositions, nodeSpacing, standingWave, stringWaveSpeed, superpose, twoSourceDisplacement, twoSourceEnvelope, twoSourceField } from "./superposition.mjs";
|
|
9
|
+
import { frequencyShiftAsymmetry, machConeHalfAngle, machNumber, observedFrequency, observedFrequencyMovingObserver, observedFrequencyMovingSource, radialSpeed, sourceSpeedFromShift, wavefrontRadius, wavelengthAhead, wavelengthBehind } from "./doppler.mjs";
|
|
10
|
+
export { A4_HZ, BoundaryKind, CENTS_PER_OCTAVE, DampingRegime, Direction, OscillatorEnergy, OscillatorState, SECONDS_PER_DAY, SEMITONE_NAMES, SEMITONE_RATIO, TwoSourcePoint, type Vec2, Wave, amplificationFactor, amplitudeFromState, amplitudeRatioPerCycle, angularFrequency, angularFrequencyFromPeriod, antinodePositions, beatDisplacement, beatEnvelope, beatFrequency, centsBetween, clockDriftPerDay, clockDriftSteps, criticalDamping, cutSpringStiffness, dampedAmplitude, dampedAngularFrequency, dampedDisplacement, dampedEnergy, dampedVelocity, dampingRatio, dampingRatioFromDecrement, dampingRegime, decayTimeConstant, displacement, displacementAtSpeed, drivenAmplitude, drivenPhaseLag, effectiveGravityInLift, energyAt, energyAtSteps, energyPeriod, equalEnergyDisplacement, frequencyAfterCents, frequencyAfterSemitones, frequencyFromAngular, frequencyFromPeriod, frequencyFromSpeed, frequencyShiftAsymmetry, fretPosition, fretSpacing, frettedLength, graphSlopeForGravity, gravityFromGraphSlope, gravityFromPendulumSteps, gravityFromPeriod, gravityFromPeriodRatio, harmonicFrequency, harmonicSeries, harmonicWavelength, intensityRatio, interferenceAt, isInTune, justIntervalCents, liftAccelerationFromPeriod, logarithmicDecrement, machConeHalfAngle, machNumber, maxAcceleration, maxParticleSpeed, maxSpeed, mechanicalQ, nearestNote, nodePositions, nodeSpacing, observedFrequency, observedFrequencyMovingObserver, observedFrequencyMovingSource, oscillatorStateAt, particleAcceleration, particleVelocity, pathFromPhase, pendulumAmplitudeCorrection, pendulumAngularFrequency, pendulumLength, pendulumPeriod, period, periodAtGravity, periodForDailyDrift, periodFromAngularFrequency, phaseAt, phaseFromPath, phaseFromState, qFromDampingRatio, radialSpeed, resonantAngularFrequency, sampleWave, secondsPendulumLength, semitonesBetween, settlingTime, shmAcceleration, shmDisplacement, shmVelocity, sourceSpeedFromShift, speedAtDisplacement, speedOf, splitSpringStiffness, springAngularFrequency, springExtension, springForce, springPeriod, springPeriodFromExtension, standingWave, staticExtension, stiffnessFromAngularFrequency, stiffnessFromExtension, stiffnessFromExtensionSteps, stiffnessInParallel, stiffnessInSeries, stringWaveSpeed, superpose, temperedIntervalCents, totalEnergy, twoSourceDisplacement, twoSourceEnvelope, twoSourceField, waveNumber, waveSpeed, wavefrontRadius, wavelengthAhead, wavelengthBehind, wavelengthFromSpeed, wavelengthFromWaveNumber };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { amplitudeFromState, angularFrequencyFromPeriod, displacementAtSpeed, energyAt, energyAtSteps, energyPeriod, equalEnergyDisplacement, maxAcceleration, maxSpeed, oscillatorStateAt, periodFromAngularFrequency, phaseFromState, shmAcceleration, shmDisplacement, shmVelocity, speedAtDisplacement, springAngularFrequency, springPeriod, totalEnergy } from "./shm.mjs";
|
|
2
|
+
import { angularFrequency, displacement, frequencyFromAngular, frequencyFromPeriod, frequencyFromSpeed, intensityRatio, interferenceAt, maxParticleSpeed, particleAcceleration, particleVelocity, pathFromPhase, period, phaseAt, phaseFromPath, sampleWave, speedOf, waveNumber, waveSpeed, wavelengthFromSpeed, wavelengthFromWaveNumber } from "./wave.mjs";
|
|
3
|
+
import { cutSpringStiffness, splitSpringStiffness, springExtension, springForce, springPeriodFromExtension, staticExtension, stiffnessFromAngularFrequency, stiffnessFromExtension, stiffnessFromExtensionSteps, stiffnessInParallel, stiffnessInSeries } from "./springs.mjs";
|
|
4
|
+
import { SECONDS_PER_DAY, clockDriftPerDay, clockDriftSteps, effectiveGravityInLift, graphSlopeForGravity, gravityFromGraphSlope, gravityFromPendulumSteps, gravityFromPeriod, gravityFromPeriodRatio, liftAccelerationFromPeriod, pendulumAmplitudeCorrection, pendulumAngularFrequency, pendulumLength, pendulumPeriod, periodAtGravity, periodForDailyDrift, secondsPendulumLength } from "./pendulum.mjs";
|
|
5
|
+
import { amplificationFactor, amplitudeRatioPerCycle, criticalDamping, dampedAmplitude, dampedAngularFrequency, dampedDisplacement, dampedEnergy, dampedVelocity, dampingRatio, dampingRatioFromDecrement, dampingRegime, decayTimeConstant, drivenAmplitude, drivenPhaseLag, logarithmicDecrement, mechanicalQ, qFromDampingRatio, resonantAngularFrequency, settlingTime } from "./damping.mjs";
|
|
6
|
+
import { A4_HZ, CENTS_PER_OCTAVE, SEMITONE_NAMES, SEMITONE_RATIO, centsBetween, frequencyAfterCents, frequencyAfterSemitones, fretPosition, fretSpacing, frettedLength, isInTune, justIntervalCents, nearestNote, semitonesBetween, temperedIntervalCents } from "./pitch.mjs";
|
|
7
|
+
import { antinodePositions, beatDisplacement, beatEnvelope, beatFrequency, harmonicFrequency, harmonicSeries, harmonicWavelength, nodePositions, nodeSpacing, standingWave, stringWaveSpeed, superpose, twoSourceDisplacement, twoSourceEnvelope, twoSourceField } from "./superposition.mjs";
|
|
8
|
+
import { frequencyShiftAsymmetry, machConeHalfAngle, machNumber, observedFrequency, observedFrequencyMovingObserver, observedFrequencyMovingSource, radialSpeed, sourceSpeedFromShift, wavefrontRadius, wavelengthAhead, wavelengthBehind } from "./doppler.mjs";
|
|
9
|
+
|
|
10
|
+
export { A4_HZ, CENTS_PER_OCTAVE, SECONDS_PER_DAY, SEMITONE_NAMES, SEMITONE_RATIO, amplificationFactor, amplitudeFromState, amplitudeRatioPerCycle, angularFrequency, angularFrequencyFromPeriod, antinodePositions, beatDisplacement, beatEnvelope, beatFrequency, centsBetween, clockDriftPerDay, clockDriftSteps, criticalDamping, cutSpringStiffness, dampedAmplitude, dampedAngularFrequency, dampedDisplacement, dampedEnergy, dampedVelocity, dampingRatio, dampingRatioFromDecrement, dampingRegime, decayTimeConstant, displacement, displacementAtSpeed, drivenAmplitude, drivenPhaseLag, effectiveGravityInLift, energyAt, energyAtSteps, energyPeriod, equalEnergyDisplacement, frequencyAfterCents, frequencyAfterSemitones, frequencyFromAngular, frequencyFromPeriod, frequencyFromSpeed, frequencyShiftAsymmetry, fretPosition, fretSpacing, frettedLength, graphSlopeForGravity, gravityFromGraphSlope, gravityFromPendulumSteps, gravityFromPeriod, gravityFromPeriodRatio, harmonicFrequency, harmonicSeries, harmonicWavelength, intensityRatio, interferenceAt, isInTune, justIntervalCents, liftAccelerationFromPeriod, logarithmicDecrement, machConeHalfAngle, machNumber, maxAcceleration, maxParticleSpeed, maxSpeed, mechanicalQ, nearestNote, nodePositions, nodeSpacing, observedFrequency, observedFrequencyMovingObserver, observedFrequencyMovingSource, oscillatorStateAt, particleAcceleration, particleVelocity, pathFromPhase, pendulumAmplitudeCorrection, pendulumAngularFrequency, pendulumLength, pendulumPeriod, period, periodAtGravity, periodForDailyDrift, periodFromAngularFrequency, phaseAt, phaseFromPath, phaseFromState, qFromDampingRatio, radialSpeed, resonantAngularFrequency, sampleWave, secondsPendulumLength, semitonesBetween, settlingTime, shmAcceleration, shmDisplacement, shmVelocity, sourceSpeedFromShift, speedAtDisplacement, speedOf, splitSpringStiffness, springAngularFrequency, springExtension, springForce, springPeriod, springPeriodFromExtension, standingWave, staticExtension, stiffnessFromAngularFrequency, stiffnessFromExtension, stiffnessFromExtensionSteps, stiffnessInParallel, stiffnessInSeries, stringWaveSpeed, superpose, temperedIntervalCents, totalEnergy, twoSourceDisplacement, twoSourceEnvelope, twoSourceField, waveNumber, waveSpeed, wavefrontRadius, wavelengthAhead, wavelengthBehind, wavelengthFromSpeed, wavelengthFromWaveNumber };
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { Worked } from "../core/worked.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/waves/pendulum.d.ts
|
|
4
|
+
/** Seconds in a day, the unit clock-drift questions are posed in. */
|
|
5
|
+
declare const SECONDS_PER_DAY = 86400;
|
|
6
|
+
/**
|
|
7
|
+
* Period of a simple pendulum: T = 2π√(L/g), seconds.
|
|
8
|
+
*
|
|
9
|
+
* An APPROXIMATION, valid while sin θ ≈ θ. The true period is larger, by about
|
|
10
|
+
* 0.2 % at 10 degrees and 1.7 % at 30, so a pendulum swung wide runs slow. The
|
|
11
|
+
* mass does not appear, which is why a pendulum clock is not affected by the
|
|
12
|
+
* weight of its bob and is affected by the temperature of its rod.
|
|
13
|
+
*/
|
|
14
|
+
declare const pendulumPeriod: (length: number, gravity?: number) => number;
|
|
15
|
+
/** Angular frequency of a simple pendulum: ω = √(g/L), rad/s. */
|
|
16
|
+
declare const pendulumAngularFrequency: (length: number, gravity?: number) => number;
|
|
17
|
+
/** The length that gives a wanted period, metres: L = gT²/4π². */
|
|
18
|
+
declare const pendulumLength: (period: number, gravity?: number) => number;
|
|
19
|
+
/**
|
|
20
|
+
* The length of a SECONDS pendulum, metres: the one that beats once a second.
|
|
21
|
+
*
|
|
22
|
+
* Its period is TWO seconds, not one, because a beat is half a swing: the bob
|
|
23
|
+
* passes the centre once each way. That factor of two is the whole trap in the
|
|
24
|
+
* name, and it is why the answer is about 0.99 m rather than 0.25 m.
|
|
25
|
+
*/
|
|
26
|
+
declare const secondsPendulumLength: (gravity?: number) => number;
|
|
27
|
+
/**
|
|
28
|
+
* The first correction to the pendulum period, as a multiplier.
|
|
29
|
+
*
|
|
30
|
+
* T = T₀·(1 + θ₀²/16 + …) for an amplitude θ₀ in radians. Exposed so a lab can
|
|
31
|
+
* SHOW the small-angle approximation breaking rather than only warning that it
|
|
32
|
+
* does.
|
|
33
|
+
*/
|
|
34
|
+
declare function pendulumAmplitudeCorrection(amplitudeRad: number): number;
|
|
35
|
+
/**
|
|
36
|
+
* The gravity a pendulum in an accelerating lift behaves as if it were in.
|
|
37
|
+
*
|
|
38
|
+
* `acceleration` is the lift's, positive UPWARD. Going up: the floor pushes
|
|
39
|
+
* harder, the bob hangs heavier, g_eff = g + a and the pendulum runs FAST.
|
|
40
|
+
* Going down: g_eff = g − a and it runs slow. In free fall a = g, g_eff = 0,
|
|
41
|
+
* and the pendulum stops swinging altogether: it has nothing to fall back
|
|
42
|
+
* towards. That limiting case is the one worth showing, because it is where
|
|
43
|
+
* the equivalence principle stops being a slogan.
|
|
44
|
+
*
|
|
45
|
+
* Note the sign convention is on the LIFT'S acceleration, not on its velocity.
|
|
46
|
+
* A lift moving upward while slowing down has a downward acceleration and its
|
|
47
|
+
* pendulum runs slow, which catches almost everybody.
|
|
48
|
+
*/
|
|
49
|
+
declare function effectiveGravityInLift(gravity: number, acceleration: number): number;
|
|
50
|
+
/**
|
|
51
|
+
* Gravity from one length and one timing: g = 4π²L/T².
|
|
52
|
+
*
|
|
53
|
+
* Correct, and a poor experiment. A single pair of readings carries every one
|
|
54
|
+
* of its errors straight into the answer, which is why the practical plots a
|
|
55
|
+
* graph instead. Use `gravityFromGraphSlope` where there is more than one
|
|
56
|
+
* reading.
|
|
57
|
+
*/
|
|
58
|
+
declare const gravityFromPeriod: (length: number, period: number) => number;
|
|
59
|
+
/**
|
|
60
|
+
* Gravity from the gradient of a T²-against-L graph: g = 4π²/slope.
|
|
61
|
+
*
|
|
62
|
+
* T² = (4π²/g)·L is a straight line through the origin, so the gradient is
|
|
63
|
+
* 4π²/g and every reading contributes to it. This is the version the practical
|
|
64
|
+
* is actually marked on, and the reason the graph is drawn at all: a systematic
|
|
65
|
+
* error in measuring the length shifts the intercept and leaves the gradient,
|
|
66
|
+
* and therefore g, untouched.
|
|
67
|
+
*
|
|
68
|
+
* `slope` is in s²/m.
|
|
69
|
+
*/
|
|
70
|
+
declare const gravityFromGraphSlope: (slope: number) => number;
|
|
71
|
+
/**
|
|
72
|
+
* The lift acceleration a measured period implies, m/s². Positive means upward.
|
|
73
|
+
*
|
|
74
|
+
* The pendulum used backwards, as an accelerometer. A period SHORTER than the
|
|
75
|
+
* one the same pendulum has at rest means the lift is accelerating upward.
|
|
76
|
+
*/
|
|
77
|
+
declare const liftAccelerationFromPeriod: (length: number, period: number, gravity?: number) => number;
|
|
78
|
+
/** The gradient a T²-against-L graph should have for a given g, s²/m. The inverse of the above. */
|
|
79
|
+
declare const graphSlopeForGravity: (gravity?: number) => number;
|
|
80
|
+
/**
|
|
81
|
+
* The gravity implied by a pendulum's period changing: g₂ = g₁(T₁/T₂)².
|
|
82
|
+
*
|
|
83
|
+
* The seam to `gravitation`. Take the same pendulum somewhere else, time it,
|
|
84
|
+
* and this says what g is there without the length ever being needed, because
|
|
85
|
+
* the length is the thing that did not change.
|
|
86
|
+
*
|
|
87
|
+
* To answer "how high is the mountain", compose: this gives g at the top, and
|
|
88
|
+
* `gravitation`'s `heightForGravity` turns that into a height. The
|
|
89
|
+
* inverse-square law is deliberately not repeated here.
|
|
90
|
+
*/
|
|
91
|
+
declare const gravityFromPeriodRatio: (gravity: number, period: number, newPeriod: number) => number;
|
|
92
|
+
/** The period the same pendulum would have where gravity is `newGravity`: T₂ = T₁√(g₁/g₂). */
|
|
93
|
+
declare const periodAtGravity: (period: number, gravity: number, newGravity: number) => number;
|
|
94
|
+
/**
|
|
95
|
+
* Seconds a pendulum clock gains (+) or loses (−) per day, from its wrong period.
|
|
96
|
+
*
|
|
97
|
+
* The clock counts each swing as `truePeriod` seconds whatever the pendulum
|
|
98
|
+
* actually does, so in a real day of 86,400 s it makes 86400/T' swings and
|
|
99
|
+
* displays 86400·T/T' seconds.
|
|
100
|
+
*
|
|
101
|
+
* drift = 86400·(T − T')/T'
|
|
102
|
+
*
|
|
103
|
+
* A pendulum running SLOW (T' > T) gives a negative drift: the clock loses. The
|
|
104
|
+
* sensitivity is the part worth seeing: a period wrong by one part in ten
|
|
105
|
+
* thousand costs 8.6 seconds a day, so a clock that is right to a second a day
|
|
106
|
+
* has a pendulum right to one part in a hundred thousand.
|
|
107
|
+
*/
|
|
108
|
+
declare function clockDriftPerDay(truePeriod: number, actualPeriod: number): number;
|
|
109
|
+
/**
|
|
110
|
+
* The period a clock must be running at to drift by a given amount per day.
|
|
111
|
+
*
|
|
112
|
+
* `drift` is signed the same way as `clockDriftPerDay`: positive gains, negative
|
|
113
|
+
* loses. The exact inverse, so a question posed either way round is one call.
|
|
114
|
+
*/
|
|
115
|
+
declare function periodForDailyDrift(truePeriod: number, drift: number): number;
|
|
116
|
+
/**
|
|
117
|
+
* The pendulum-as-gravimeter question, worked.
|
|
118
|
+
*
|
|
119
|
+
* Reports the single-reading value and the gradient value side by side so the
|
|
120
|
+
* gap between "correct" and "good experiment" is visible rather than asserted.
|
|
121
|
+
*/
|
|
122
|
+
declare function gravityFromPendulumSteps(length: number, period: number, sf?: number): Worked;
|
|
123
|
+
/**
|
|
124
|
+
* The clock-drift question, worked, in the direction it is usually asked:
|
|
125
|
+
* the pendulum has changed length or moved, and how far out is the clock by
|
|
126
|
+
* bedtime.
|
|
127
|
+
*/
|
|
128
|
+
declare function clockDriftSteps(truePeriod: number, actualPeriod: number, sf?: number): Worked;
|
|
129
|
+
//#endregion
|
|
130
|
+
export { SECONDS_PER_DAY, clockDriftPerDay, clockDriftSteps, effectiveGravityInLift, graphSlopeForGravity, gravityFromGraphSlope, gravityFromPendulumSteps, gravityFromPeriod, gravityFromPeriodRatio, liftAccelerationFromPeriod, pendulumAmplitudeCorrection, pendulumAngularFrequency, pendulumLength, pendulumPeriod, periodAtGravity, periodForDailyDrift, secondsPendulumLength };
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { calc, texSigFigs } from "../core/worked.mjs";
|
|
2
|
+
import { G_EARTH } from "../physics/kinematics/free-fall.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/waves/pendulum.ts
|
|
5
|
+
/**
|
|
6
|
+
* The simple pendulum, and the three things it is actually used for.
|
|
7
|
+
*
|
|
8
|
+
* ## It is a clock
|
|
9
|
+
*
|
|
10
|
+
* T = 2π√(L/g)
|
|
11
|
+
*
|
|
12
|
+
* No mass. A pendulum clock is not affected by the weight of its bob, and IS
|
|
13
|
+
* affected by the temperature of its rod, because only the length appears.
|
|
14
|
+
* `clockDriftPerDay` turns a wrong period into the seconds a clock gains or
|
|
15
|
+
* loses in a day, which is the form every exam question asks for and is a
|
|
16
|
+
* surprisingly large number: one part in 10,000 is nine seconds a day.
|
|
17
|
+
*
|
|
18
|
+
* ## It is a gravimeter
|
|
19
|
+
*
|
|
20
|
+
* Rearranged, g = 4π²L/T², and that is a real measurement rather than a
|
|
21
|
+
* contrivance: timing a pendulum is how g was mapped before anyone had an
|
|
22
|
+
* accelerometer. `gravityFromGraphSlope` is the honest version of it, because
|
|
23
|
+
* the school practical plots T² against L and takes the gradient rather than
|
|
24
|
+
* trusting a single pair of readings.
|
|
25
|
+
*
|
|
26
|
+
* ## It is an accelerometer
|
|
27
|
+
*
|
|
28
|
+
* Hang it in a lift and it does not know the difference between gravity and
|
|
29
|
+
* acceleration, so its period measures g + a. `effectiveGravityInLift` is that,
|
|
30
|
+
* and it is the equivalence principle doing something useful.
|
|
31
|
+
*
|
|
32
|
+
* ## Where this module stops
|
|
33
|
+
*
|
|
34
|
+
* It does NOT compute how g varies with height, depth or latitude. That is
|
|
35
|
+
* `@classytic/stage/physics`'s `gravitation` module, and a pendulum question
|
|
36
|
+
* about a mountain top is those two composed: gravitation says what g is up
|
|
37
|
+
* there, this module says what the pendulum then does. `gravityFromPeriodRatio`
|
|
38
|
+
* is the seam, and keeping it a seam is what stops a second copy of the
|
|
39
|
+
* inverse-square law growing here.
|
|
40
|
+
*
|
|
41
|
+
* ## Scope
|
|
42
|
+
*
|
|
43
|
+
* SMALL AMPLITUDE. The pendulum is only approximately harmonic, and
|
|
44
|
+
* `pendulumAmplitudeCorrection` says by how much it is not. Units are SI.
|
|
45
|
+
*/
|
|
46
|
+
const finite = (value, what) => {
|
|
47
|
+
if (!Number.isFinite(value)) throw new RangeError(`${what} must be a finite number.`);
|
|
48
|
+
return value;
|
|
49
|
+
};
|
|
50
|
+
const positive = (value, what) => {
|
|
51
|
+
if (!Number.isFinite(value) || value <= 0) throw new RangeError(`${what} must be positive.`);
|
|
52
|
+
return value;
|
|
53
|
+
};
|
|
54
|
+
/** Seconds in a day, the unit clock-drift questions are posed in. */
|
|
55
|
+
const SECONDS_PER_DAY = 86400;
|
|
56
|
+
/**
|
|
57
|
+
* Period of a simple pendulum: T = 2π√(L/g), seconds.
|
|
58
|
+
*
|
|
59
|
+
* An APPROXIMATION, valid while sin θ ≈ θ. The true period is larger, by about
|
|
60
|
+
* 0.2 % at 10 degrees and 1.7 % at 30, so a pendulum swung wide runs slow. The
|
|
61
|
+
* mass does not appear, which is why a pendulum clock is not affected by the
|
|
62
|
+
* weight of its bob and is affected by the temperature of its rod.
|
|
63
|
+
*/
|
|
64
|
+
const pendulumPeriod = (length, gravity = G_EARTH) => 2 * Math.PI * Math.sqrt(positive(length, "A pendulum length") / positive(gravity, "A gravitational field strength"));
|
|
65
|
+
/** Angular frequency of a simple pendulum: ω = √(g/L), rad/s. */
|
|
66
|
+
const pendulumAngularFrequency = (length, gravity = G_EARTH) => Math.sqrt(positive(gravity, "A gravitational field strength") / positive(length, "A pendulum length"));
|
|
67
|
+
/** The length that gives a wanted period, metres: L = gT²/4π². */
|
|
68
|
+
const pendulumLength = (period, gravity = G_EARTH) => positive(gravity, "A gravitational field strength") * positive(period, "A period") ** 2 / (4 * Math.PI ** 2);
|
|
69
|
+
/**
|
|
70
|
+
* The length of a SECONDS pendulum, metres: the one that beats once a second.
|
|
71
|
+
*
|
|
72
|
+
* Its period is TWO seconds, not one, because a beat is half a swing: the bob
|
|
73
|
+
* passes the centre once each way. That factor of two is the whole trap in the
|
|
74
|
+
* name, and it is why the answer is about 0.99 m rather than 0.25 m.
|
|
75
|
+
*/
|
|
76
|
+
const secondsPendulumLength = (gravity = G_EARTH) => pendulumLength(2, gravity);
|
|
77
|
+
/**
|
|
78
|
+
* The first correction to the pendulum period, as a multiplier.
|
|
79
|
+
*
|
|
80
|
+
* T = T₀·(1 + θ₀²/16 + …) for an amplitude θ₀ in radians. Exposed so a lab can
|
|
81
|
+
* SHOW the small-angle approximation breaking rather than only warning that it
|
|
82
|
+
* does.
|
|
83
|
+
*/
|
|
84
|
+
function pendulumAmplitudeCorrection(amplitudeRad) {
|
|
85
|
+
const theta = Math.abs(finite(amplitudeRad, "An angular amplitude"));
|
|
86
|
+
if (theta >= Math.PI) throw new RangeError("A pendulum swinging past vertical is not oscillating.");
|
|
87
|
+
return 1 + theta * theta / 16;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The gravity a pendulum in an accelerating lift behaves as if it were in.
|
|
91
|
+
*
|
|
92
|
+
* `acceleration` is the lift's, positive UPWARD. Going up: the floor pushes
|
|
93
|
+
* harder, the bob hangs heavier, g_eff = g + a and the pendulum runs FAST.
|
|
94
|
+
* Going down: g_eff = g − a and it runs slow. In free fall a = g, g_eff = 0,
|
|
95
|
+
* and the pendulum stops swinging altogether: it has nothing to fall back
|
|
96
|
+
* towards. That limiting case is the one worth showing, because it is where
|
|
97
|
+
* the equivalence principle stops being a slogan.
|
|
98
|
+
*
|
|
99
|
+
* Note the sign convention is on the LIFT'S acceleration, not on its velocity.
|
|
100
|
+
* A lift moving upward while slowing down has a downward acceleration and its
|
|
101
|
+
* pendulum runs slow, which catches almost everybody.
|
|
102
|
+
*/
|
|
103
|
+
function effectiveGravityInLift(gravity, acceleration) {
|
|
104
|
+
const g = positive(gravity, "A gravitational field strength");
|
|
105
|
+
const a = finite(acceleration, "An acceleration");
|
|
106
|
+
const effective = g + a;
|
|
107
|
+
if (effective <= 0) throw new RangeError(`A lift falling at ${-a} m/s² leaves an effective gravity of ${effective}: the pendulum is weightless and does not oscillate.`);
|
|
108
|
+
return effective;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Gravity from one length and one timing: g = 4π²L/T².
|
|
112
|
+
*
|
|
113
|
+
* Correct, and a poor experiment. A single pair of readings carries every one
|
|
114
|
+
* of its errors straight into the answer, which is why the practical plots a
|
|
115
|
+
* graph instead. Use `gravityFromGraphSlope` where there is more than one
|
|
116
|
+
* reading.
|
|
117
|
+
*/
|
|
118
|
+
const gravityFromPeriod = (length, period) => 4 * Math.PI ** 2 * positive(length, "A pendulum length") / positive(period, "A period") ** 2;
|
|
119
|
+
/**
|
|
120
|
+
* Gravity from the gradient of a T²-against-L graph: g = 4π²/slope.
|
|
121
|
+
*
|
|
122
|
+
* T² = (4π²/g)·L is a straight line through the origin, so the gradient is
|
|
123
|
+
* 4π²/g and every reading contributes to it. This is the version the practical
|
|
124
|
+
* is actually marked on, and the reason the graph is drawn at all: a systematic
|
|
125
|
+
* error in measuring the length shifts the intercept and leaves the gradient,
|
|
126
|
+
* and therefore g, untouched.
|
|
127
|
+
*
|
|
128
|
+
* `slope` is in s²/m.
|
|
129
|
+
*/
|
|
130
|
+
const gravityFromGraphSlope = (slope) => 4 * Math.PI ** 2 / positive(slope, "A graph gradient");
|
|
131
|
+
/**
|
|
132
|
+
* The lift acceleration a measured period implies, m/s². Positive means upward.
|
|
133
|
+
*
|
|
134
|
+
* The pendulum used backwards, as an accelerometer. A period SHORTER than the
|
|
135
|
+
* one the same pendulum has at rest means the lift is accelerating upward.
|
|
136
|
+
*/
|
|
137
|
+
const liftAccelerationFromPeriod = (length, period, gravity = G_EARTH) => gravityFromPeriod(length, period) - positive(gravity, "A gravitational field strength");
|
|
138
|
+
/** The gradient a T²-against-L graph should have for a given g, s²/m. The inverse of the above. */
|
|
139
|
+
const graphSlopeForGravity = (gravity = G_EARTH) => 4 * Math.PI ** 2 / positive(gravity, "A gravitational field strength");
|
|
140
|
+
/**
|
|
141
|
+
* The gravity implied by a pendulum's period changing: g₂ = g₁(T₁/T₂)².
|
|
142
|
+
*
|
|
143
|
+
* The seam to `gravitation`. Take the same pendulum somewhere else, time it,
|
|
144
|
+
* and this says what g is there without the length ever being needed, because
|
|
145
|
+
* the length is the thing that did not change.
|
|
146
|
+
*
|
|
147
|
+
* To answer "how high is the mountain", compose: this gives g at the top, and
|
|
148
|
+
* `gravitation`'s `heightForGravity` turns that into a height. The
|
|
149
|
+
* inverse-square law is deliberately not repeated here.
|
|
150
|
+
*/
|
|
151
|
+
const gravityFromPeriodRatio = (gravity, period, newPeriod) => positive(gravity, "A gravitational field strength") * (positive(period, "A period") / positive(newPeriod, "A period")) ** 2;
|
|
152
|
+
/** The period the same pendulum would have where gravity is `newGravity`: T₂ = T₁√(g₁/g₂). */
|
|
153
|
+
const periodAtGravity = (period, gravity, newGravity) => positive(period, "A period") * Math.sqrt(positive(gravity, "A gravitational field strength") / positive(newGravity, "A gravitational field strength"));
|
|
154
|
+
/**
|
|
155
|
+
* Seconds a pendulum clock gains (+) or loses (−) per day, from its wrong period.
|
|
156
|
+
*
|
|
157
|
+
* The clock counts each swing as `truePeriod` seconds whatever the pendulum
|
|
158
|
+
* actually does, so in a real day of 86,400 s it makes 86400/T' swings and
|
|
159
|
+
* displays 86400·T/T' seconds.
|
|
160
|
+
*
|
|
161
|
+
* drift = 86400·(T − T')/T'
|
|
162
|
+
*
|
|
163
|
+
* A pendulum running SLOW (T' > T) gives a negative drift: the clock loses. The
|
|
164
|
+
* sensitivity is the part worth seeing: a period wrong by one part in ten
|
|
165
|
+
* thousand costs 8.6 seconds a day, so a clock that is right to a second a day
|
|
166
|
+
* has a pendulum right to one part in a hundred thousand.
|
|
167
|
+
*/
|
|
168
|
+
function clockDriftPerDay(truePeriod, actualPeriod) {
|
|
169
|
+
const target = positive(truePeriod, "A period");
|
|
170
|
+
const actual = positive(actualPeriod, "A period");
|
|
171
|
+
return SECONDS_PER_DAY * (target - actual) / actual;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* The period a clock must be running at to drift by a given amount per day.
|
|
175
|
+
*
|
|
176
|
+
* `drift` is signed the same way as `clockDriftPerDay`: positive gains, negative
|
|
177
|
+
* loses. The exact inverse, so a question posed either way round is one call.
|
|
178
|
+
*/
|
|
179
|
+
function periodForDailyDrift(truePeriod, drift) {
|
|
180
|
+
const target = positive(truePeriod, "A period");
|
|
181
|
+
const d = finite(drift, "A daily drift");
|
|
182
|
+
if (d <= -86400) throw new RangeError(`A clock cannot lose ${-d} seconds in a day: that is more than the day holds.`);
|
|
183
|
+
return SECONDS_PER_DAY * target / (SECONDS_PER_DAY + d);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* The pendulum-as-gravimeter question, worked.
|
|
187
|
+
*
|
|
188
|
+
* Reports the single-reading value and the gradient value side by side so the
|
|
189
|
+
* gap between "correct" and "good experiment" is visible rather than asserted.
|
|
190
|
+
*/
|
|
191
|
+
function gravityFromPendulumSteps(length, period, sf = 3) {
|
|
192
|
+
const L = positive(length, "A pendulum length");
|
|
193
|
+
const T = positive(period, "A period");
|
|
194
|
+
const g = gravityFromPeriod(L, T);
|
|
195
|
+
return calc().step("T = 2\\pi\\sqrt{\\frac{L}{g}}", "no mass appears, so the bob can be anything").step("T^2 = \\frac{4\\pi^2}{g}L", "square it, and T² against L is a straight line through the origin").step(`g = \\frac{4\\pi^2 L}{T^2} = \\frac{4\\pi^2 \\times ${texSigFigs(L, sf)}}{${texSigFigs(T, sf)}^2} = ${texSigFigs(g, sf)}\\ \\mathrm{m\\,s^{-2}}`).step(`\\text{gradient} = \\frac{4\\pi^2}{g} = ${texSigFigs(graphSlopeForGravity(g), sf)}\\ \\mathrm{s^2\\,m^{-1}}`, "from several readings, take the gradient instead: a constant error in L then misses g entirely").done(g);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* The clock-drift question, worked, in the direction it is usually asked:
|
|
199
|
+
* the pendulum has changed length or moved, and how far out is the clock by
|
|
200
|
+
* bedtime.
|
|
201
|
+
*/
|
|
202
|
+
function clockDriftSteps(truePeriod, actualPeriod, sf = 3) {
|
|
203
|
+
const target = positive(truePeriod, "A period");
|
|
204
|
+
const actual = positive(actualPeriod, "A period");
|
|
205
|
+
const drift = clockDriftPerDay(target, actual);
|
|
206
|
+
const verb = drift >= 0 ? "gains" : "loses";
|
|
207
|
+
return calc().step(`n = \\frac{86400}{T'} = \\frac{86400}{${texSigFigs(actual, sf)}}`, "swings the pendulum really makes in one real day").step(`\\text{displayed} = nT = 86400 \\times \\frac{${texSigFigs(target, sf)}}{${texSigFigs(actual, sf)}}\\ \\mathrm{s}`, "the clock counts every swing as T seconds, whatever the pendulum is doing").step(`\\Delta t = 86400\\,\\frac{T - T'}{T'} = ${texSigFigs(drift, sf)}\\ \\mathrm{s}`, `so the clock ${verb} about ${Math.abs(drift).toFixed(0)} s a day`).done(drift);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
//#endregion
|
|
211
|
+
export { SECONDS_PER_DAY, clockDriftPerDay, clockDriftSteps, effectiveGravityInLift, graphSlopeForGravity, gravityFromGraphSlope, gravityFromPendulumSteps, gravityFromPeriod, gravityFromPeriodRatio, liftAccelerationFromPeriod, pendulumAmplitudeCorrection, pendulumAngularFrequency, pendulumLength, pendulumPeriod, periodAtGravity, periodForDailyDrift, secondsPendulumLength };
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
//#region src/waves/pitch.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Pitch: turning a frequency into a note, and a note into a place on a string.
|
|
4
|
+
*
|
|
5
|
+
* ## Why pitch is logarithmic, and why that is not a convention
|
|
6
|
+
*
|
|
7
|
+
* Doubling a frequency sounds like the same step wherever you start. 220 to
|
|
8
|
+
* 440 Hz and 440 to 880 Hz are both "an octave", although the second gap is
|
|
9
|
+
* twice as many hertz. So the ear measures RATIOS, and anything that behaves
|
|
10
|
+
* like a distance in pitch has to be a logarithm of one.
|
|
11
|
+
*
|
|
12
|
+
* one octave = ratio 2 = 1200 cents
|
|
13
|
+
* one semitone = ratio 2^(1/12) = 100 cents
|
|
14
|
+
*
|
|
15
|
+
* A cent is a hundredth of a semitone and is the unit tuners actually use,
|
|
16
|
+
* because "three hertz flat" means something different on a bass string and a
|
|
17
|
+
* piccolo while "eight cents flat" means the same thing everywhere.
|
|
18
|
+
*
|
|
19
|
+
* ## The twelfth root of two, and what it costs
|
|
20
|
+
*
|
|
21
|
+
* Equal temperament divides the octave into twelve identical ratio steps. The
|
|
22
|
+
* price is that no interval except the octave is exactly a whole-number ratio:
|
|
23
|
+
*
|
|
24
|
+
* pure fifth (3:2) 701.955 cents
|
|
25
|
+
* equal-tempered fifth 700 cents
|
|
26
|
+
*
|
|
27
|
+
* Two cents flat, everywhere, forever. That deliberate two-cent error is what
|
|
28
|
+
* buys you the ability to change key, and it is the reason a guitar is fretted
|
|
29
|
+
* the way it is. `centsBetween` makes the compromise something you can measure
|
|
30
|
+
* rather than a claim.
|
|
31
|
+
*
|
|
32
|
+
* ## Frets are geometric, not evenly spaced
|
|
33
|
+
*
|
|
34
|
+
* A fret shortens the vibrating length by a RATIO, so the gaps shrink as you go
|
|
35
|
+
* up the neck. The twelfth fret is exactly halfway along the string, because
|
|
36
|
+
* halving the length doubles the frequency: 2^(−12/12) = 1/2. That is a fact
|
|
37
|
+
* you can check with a ruler on a real guitar, which is the best kind.
|
|
38
|
+
*
|
|
39
|
+
* Units: frequencies in hertz, lengths in metres (or any one consistent unit,
|
|
40
|
+
* since `fretPosition` is a proportion of what it is given).
|
|
41
|
+
*/
|
|
42
|
+
/** Concert A, hertz. The peg the whole system hangs from, fixed by agreement rather than physics. */
|
|
43
|
+
declare const A4_HZ = 440;
|
|
44
|
+
/** The frequency ratio of one equal-tempered semitone: the twelfth root of two. */
|
|
45
|
+
declare const SEMITONE_RATIO: number;
|
|
46
|
+
/** Cents in one octave. A cent is a hundredth of a semitone. */
|
|
47
|
+
declare const CENTS_PER_OCTAVE = 1200;
|
|
48
|
+
/**
|
|
49
|
+
* The frequency a given number of semitones away: f·2^(n/12).
|
|
50
|
+
*
|
|
51
|
+
* `n` may be negative for downward, and need not be a whole number: a
|
|
52
|
+
* half-semitone is a perfectly good quarter tone, and bending a guitar string
|
|
53
|
+
* lands you between the frets.
|
|
54
|
+
*/
|
|
55
|
+
declare const frequencyAfterSemitones: (frequency: number, semitones: number) => number;
|
|
56
|
+
/** How many semitones apart two frequencies are: 12·log₂(f₂/f₁). Signed. */
|
|
57
|
+
declare const semitonesBetween: (from: number, to: number) => number;
|
|
58
|
+
/**
|
|
59
|
+
* The interval between two frequencies in CENTS: 1200·log₂(f₂/f₁).
|
|
60
|
+
*
|
|
61
|
+
* Signed, so a negative result means `to` is flat of `from`. The numbers worth
|
|
62
|
+
* carrying: about 5 cents is the smallest error most people hear on a sustained
|
|
63
|
+
* note, 10 to 15 cents sounds wrong, and a semitone is 100.
|
|
64
|
+
*
|
|
65
|
+
* This is the function that makes "how out of tune is it" answerable. A gap of
|
|
66
|
+
* 3 Hz is badly out on a low E at 82 Hz and inaudible on a harmonic at 1300 Hz;
|
|
67
|
+
* in cents both questions have the same answer scale.
|
|
68
|
+
*/
|
|
69
|
+
declare const centsBetween: (from: number, to: number) => number;
|
|
70
|
+
/** The frequency a number of cents away from a reference. The inverse of `centsBetween`. */
|
|
71
|
+
declare const frequencyAfterCents: (frequency: number, cents: number) => number;
|
|
72
|
+
/**
|
|
73
|
+
* Whether a frequency counts as in tune against a target.
|
|
74
|
+
*
|
|
75
|
+
* `toleranceCents` defaults to 5, which is roughly the threshold at which a
|
|
76
|
+
* sustained note starts to sound wrong to an ordinary listener. Expressed in
|
|
77
|
+
* cents rather than hertz on purpose: a fixed hertz tolerance would be far too
|
|
78
|
+
* strict at the top of the range and useless at the bottom.
|
|
79
|
+
*/
|
|
80
|
+
declare const isInTune: (frequency: number, target: number, toleranceCents?: number) => boolean;
|
|
81
|
+
/**
|
|
82
|
+
* The length of string still free to vibrate when a fret is held down.
|
|
83
|
+
*
|
|
84
|
+
* `L·2^(−n/12)`: each fret divides the length by the same ratio, which is why
|
|
85
|
+
* they crowd together going up the neck.
|
|
86
|
+
*/
|
|
87
|
+
declare const frettedLength: (scaleLength: number, fret: number) => number;
|
|
88
|
+
/**
|
|
89
|
+
* How far along the string a fret sits, measured from the nut.
|
|
90
|
+
*
|
|
91
|
+
* `L(1 − 2^(−n/12))`. Fret 12 comes out at exactly L/2, which is the check that
|
|
92
|
+
* the formula is the right way round and the thing to verify against a real
|
|
93
|
+
* instrument.
|
|
94
|
+
*/
|
|
95
|
+
declare const fretPosition: (scaleLength: number, fret: number) => number;
|
|
96
|
+
/** The gap between two consecutive frets. Always smaller than the one below it. */
|
|
97
|
+
declare const fretSpacing: (scaleLength: number, fret: number) => number;
|
|
98
|
+
/** The names of the twelve semitones, starting at C. Sharps only; no enharmonic choice is made. */
|
|
99
|
+
declare const SEMITONE_NAMES: readonly ["C", "C♯", "D", "D♯", "E", "F", "F♯", "G", "G♯", "A", "A♯", "B"];
|
|
100
|
+
/**
|
|
101
|
+
* The nearest named note to a frequency, and how far off it is.
|
|
102
|
+
*
|
|
103
|
+
* Returns the note with its octave number in scientific pitch notation (A4 is
|
|
104
|
+
* concert A), plus the signed error in cents. The error is the useful half: a
|
|
105
|
+
* tuner is a device for driving that number to zero.
|
|
106
|
+
*/
|
|
107
|
+
declare function nearestNote(frequency: number): {
|
|
108
|
+
name: string;
|
|
109
|
+
octave: number;
|
|
110
|
+
cents: number;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* The size of a just interval in cents, for comparison with the tempered one.
|
|
114
|
+
*
|
|
115
|
+
* `justIntervalCents(3, 2)` is the pure fifth at 701.955, against the
|
|
116
|
+
* equal-tempered 700. Feeding the small whole-number ratios through this is how
|
|
117
|
+
* the compromise in equal temperament stops being a story: the major third is
|
|
118
|
+
* the bad one, 386.3 just against 400 tempered, nearly 14 cents sharp, and it
|
|
119
|
+
* is audible.
|
|
120
|
+
*/
|
|
121
|
+
declare const justIntervalCents: (numerator: number, denominator: number) => number;
|
|
122
|
+
/** The equal-tempered size of an interval of `semitones`, in cents. Always a multiple of 100. */
|
|
123
|
+
declare const temperedIntervalCents: (semitones: number) => number;
|
|
124
|
+
//#endregion
|
|
125
|
+
export { A4_HZ, CENTS_PER_OCTAVE, SEMITONE_NAMES, SEMITONE_RATIO, centsBetween, frequencyAfterCents, frequencyAfterSemitones, fretPosition, fretSpacing, frettedLength, isInTune, justIntervalCents, nearestNote, semitonesBetween, temperedIntervalCents };
|