Simulating Vocal Cord Mucosal Waves in Matter.js
This article explains how to simulate the biomechanical mucosal wave of vocal fold vibration using Matter.js, a 2D physics engine. By combining a multi-mass spring-damper model with dynamic aerodynamic forces derived from the myoelastic-aerodynamic theory of phonation, developers can recreate the phase-delayed, self-oscillating vertical wave motion characteristic of human vocal folds.
The Biomechanics of the Mucosal Wave
The mucosal wave is a surface wave that travels vertically from the inferior (bottom) margin to the superior (top) margin of the vocal folds during phonation. It is driven by two interdependent forces:
- Tissue Elasticity: The viscoelastic tissue layers (cover, transition, body) that resist displacement and return the vocal folds to equilibrium.
- Aerodynamics (The Bernoulli Effect): Subglottic pressure forces the folds apart from bottom to top. As air rushes through the narrow glottal constriction, pressure drops, pulling the lower margins back together while the upper margins are still opening.
Because Matter.js is a rigid-body physics engine rather than a fluid-structure interaction simulator, this mechanism is approximated using a discretized two-mass or multi-mass model driven by custom force calculations applied per frame.
1. Setting Up the Multi-Mass Model
To capture the out-of-phase vertical motion, each vocal fold (left and right) must be split into at least two vertically stacked horizontal masses: a lower mass (\(m_1\)) and an upper mass (\(m_2\)).
const { Engine, World, Bodies, Constraint, Body, Vector } = Matter;
const engine = Engine.create();
engine.gravity.scale = 0; // Disable default gravity to isolate aerodynamic forces
// Geometry parameters
const massWidth = 40;
const massHeight = 15;
const foldSeparation = 10; // Neutral glottal gap
// Left vocal fold masses
const leftLower = Bodies.rectangle(180, 215, massWidth, massHeight, { frictionAir: 0.05 });
const leftUpper = Bodies.rectangle(180, 195, massWidth, massHeight, { frictionAir: 0.05 });
// Right vocal fold masses
const rightLower = Bodies.rectangle(220 + foldSeparation, 215, massWidth, massHeight, { frictionAir: 0.05 });
const rightUpper = Bodies.rectangle(220 + foldSeparation, 195, massWidth, massHeight, { frictionAir: 0.05 });
World.add(engine.world, [leftLower, leftUpper, rightLower, rightUpper]);2. Defining Viscoelastic Tissue Constraints
Link each mass to an anatomical anchor point (representing cartilage) with lateral spring-dampers. Crucially, connect the lower mass to the upper mass using a vertical shear spring. This shear constraint propagates energy and creates the vertical phase lag responsible for the mucosal wave.
// Anchor coordinates
const leftAnchorX = 120;
const rightAnchorX = 300;
// Lateral tissue elasticity
const leftLowerSpring = Constraint.create({
pointA: { x: leftAnchorX, y: 215 },
bodyB: leftLower,
stiffness: 0.08,
damping: 0.01
});
const leftUpperSpring = Constraint.create({
pointA: { x: leftAnchorX, y: 195 },
bodyB: leftUpper,
stiffness: 0.06, // Upper cover is typically more pliable
damping: 0.01
});
// Vertical shear coupling (mediates the mucosal wave)
const leftShearSpring = Constraint.create({
bodyA: leftLower,
bodyB: leftUpper,
stiffness: 0.04,
damping: 0.02
});
// Duplicate mirrored constraints for the right vocal fold
const rightLowerSpring = Constraint.create({ pointA: { x: rightAnchorX, y: 215 }, bodyB: rightLower, stiffness: 0.08, damping: 0.01 });
const rightUpperSpring = Constraint.create({ pointA: { x: rightAnchorX, y: 195 }, bodyB: rightUpper, stiffness: 0.06, damping: 0.01 });
const rightShearSpring = Constraint.create({ bodyA: rightLower, bodyB: rightUpper, stiffness: 0.04, damping: 0.02 });
World.add(engine.world, [
leftLowerSpring, leftUpperSpring, leftShearSpring,
rightLowerSpring, rightUpperSpring, rightShearSpring
]);3. Implementing Aerodynamic Pressure Loops
The mucosal wave cannot sustain itself without energy input from lung pressure (\(P_{sub}\)). On every engine update, measure the instantaneous glottal width at the lower and upper apertures and compute the resulting aerodynamic forces:
- Convergent Shape (Lower gap > Upper gap): High intraglottal pressure pushes the walls outward.
- Divergent Shape (Lower gap < Upper gap): Air separates from the walls, producing negative Bernoulli pressure that pulls the folds inward.
- Collision / Closure: When the gap is zero, collision response halts inward momentum, and subglottal pressure builds up underneath.
const P_SUBGLOTTAL = 1.2; // Driving lung pressure
Matter.Events.on(engine, 'beforeUpdate', () => {
// Calculate instantaneous apertures
const lowerGap = Math.max(0.1, rightLower.position.x - leftLower.position.x - massWidth);
const upperGap = Math.max(0.1, rightUpper.position.x - leftUpper.position.x - massWidth);
// Bernoulli-driven intraglottal pressures
let lowerPressure, upperPressure;
if (lowerGap <= 1.0) {
// Glottal closure: full subglottic pressure forces lower masses apart
lowerPressure = P_SUBGLOTTAL;
upperPressure = 0;
} else {
// Open glottis: pressure distribution depends on profile convergence/divergence
const areaRatio = lowerGap / upperGap;
if (areaRatio >= 1.0) {
// Convergent profile: positive driving pressure
lowerPressure = P_SUBGLOTTAL * 0.7;
upperPressure = P_SUBGLOTTAL * 0.3;
} else {
// Divergent profile: negative Bernoulli suction pulls upper/lower masses together
lowerPressure = P_SUBGLOTTAL * 0.1;
upperPressure = -P_SUBGLOTTAL * 0.4;
}
}
// Apply forces laterally to simulate pressure
Body.applyForce(leftLower, leftLower.position, { x: -lowerPressure * 0.05, y: 0 });
Body.applyForce(rightLower, rightLower.position, { x: lowerPressure * 0.05, y: 0 });
Body.applyForce(leftUpper, leftUpper.position, { x: -upperPressure * 0.05, y: 0 });
Body.applyForce(rightUpper, rightUpper.position, { x: upperPressure * 0.05, y: 0 });
});4. Tuning and Observing the Wave
To maintain stable self-oscillation and visually confirm the mucosal wave:
- Stiffness Gradient: Keep the upper masses slightly less stiff than the lower masses. This ensures the lower tissue opens first and forces the upper tissue to trail behind.
- Shear Coupling: If the shear stiffness is set too high, both masses will move in unison as a single rigid block, destroying the wave. If set too low, the masses decouple and destabilize.
- Collision Handling: Ensure
restitutionon the fold bodies is set between0.0and0.1to prevent unrealistic elastic bouncing upon closure; real vocal fold impact is largely inelastic.
When tuned correctly, plotting the horizontal positions of
leftLower and leftUpper over time will reveal
matching sinusoidal waveforms where leftUpper consistently
lags behind leftLower by approximately \(60^\circ\) to \(90^\circ\), reproducing the mucosal
wave.