Skip to content

Instantly share code, notes, and snippets.

@andremichelle
Last active April 1, 2025 17:43
Show Gist options
  • Save andremichelle/d6c451ad6a77c768eea5d12f6bd8a312 to your computer and use it in GitHub Desktop.
Save andremichelle/d6c451ad6a77c768eea5d12f6bd8a312 to your computer and use it in GitHub Desktop.
StereoMatrix
import { int, PI_QUART } from "jet-std"
export type StereoParams = {
gain: number
panning: number // -1 (left) to +1 (right)
invertL: boolean
invertR: boolean
stereo: number // 0 (stereo) to 1 (mono)
}
export type StereoMatrix = {
ll: number // L -> L
rl: number // R -> L
lr: number // L -> R
rr: number // R -> R
}
export type StereoChannels = [Float32Array, Float32Array]
export namespace StereoMatrix {
export const create = (): StereoMatrix => ({ ll: 0.0, lr: 0.0, rl: 0.0, rr: 0.0 })
export const update = (m: StereoMatrix, { gain, panning, invertL, invertR, stereo }: StereoParams): void => {
const panL = Math.cos((panning + 1.0) * PI_QUART)
const panR = Math.sin((panning + 1.0) * PI_QUART)
let lGain = panL * gain
let rGain = panR * gain
if (invertL) lGain *= -1.0
if (invertR) rGain *= -1.0
const mono = Math.max(0.0, -stereo)
const expand = Math.max(0.0, stereo)
const midGain = 1.0 - expand
const sideGain = 1.0 + expand
const monoAmount = mono * 0.5
const stereoWidth = 1.0 - mono
const m00 = (midGain + sideGain) * 0.5
const m01 = (midGain - sideGain) * 0.5
const m10 = (midGain - sideGain) * 0.5
const m11 = (midGain + sideGain) * 0.5
m.ll = (lGain * (monoAmount + stereoWidth)) * m00 + (rGain * monoAmount) * m01
m.rl = (lGain * (monoAmount + stereoWidth)) * m10 + (rGain * monoAmount) * m11
m.lr = (lGain * monoAmount) * m00 + (rGain * (monoAmount + stereoWidth)) * m01
m.rr = (lGain * monoAmount) * m10 + (rGain * (monoAmount + stereoWidth)) * m11
}
export const applyFrame = (m: StereoMatrix, l: number, r: number): [number, number] =>
[m.ll * l + m.rl * r, m.lr * l + m.rr * r]
export const processFrames = (m: StereoMatrix,
source: StereoChannels, target: StereoChannels,
fromIndex: int, toIndex: int): void => {
const [src0, src1] = source
const [trg0, trg1] = target
for (let i = fromIndex; i < toIndex; i++) {
const l = src0[i]
const r = src1[i]
trg0[i] = m.ll * l + m.rl * r
trg1[i] = m.lr * l + m.rr * r
}
}
export const replaceFrames = (m: StereoMatrix, [ch0, ch1]: StereoChannels, fromIndex: int, toIndex: int): void => {
for (let i = fromIndex; i < toIndex; i++) {
const l = ch0[i]
const r = ch1[i]
ch0[i] = m.ll * l + m.rl * r
ch1[i] = m.lr * l + m.rr * r
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment