Last active
April 1, 2025 17:43
-
-
Save andremichelle/d6c451ad6a77c768eea5d12f6bd8a312 to your computer and use it in GitHub Desktop.
StereoMatrix
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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