perf: stream propagation working sets
This commit is contained in:
@@ -32,19 +32,36 @@ export function addFrequencyDomainPaths(options) {
|
||||
frequencyResponse,
|
||||
sampleRate,
|
||||
workspace,
|
||||
outputOffsetSamples = 0,
|
||||
pathDelaySampleRate,
|
||||
} = options;
|
||||
if (!Array.isArray(paths) || paths.length === 0) {
|
||||
throw new Error("frequency-domain path가 하나 이상 필요합니다.");
|
||||
}
|
||||
const delaySamplesForPath = (path) => {
|
||||
if (path.delaySamples !== undefined) return path.delaySamples;
|
||||
if (
|
||||
path.delaySeconds !== undefined &&
|
||||
pathDelaySampleRate > 0 &&
|
||||
Number.isFinite(pathDelaySampleRate)
|
||||
) {
|
||||
return path.delaySeconds * pathDelaySampleRate;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
for (const path of paths) {
|
||||
if (!(path.delaySamples >= 0) || !Number.isFinite(path.delaySamples)) {
|
||||
throw new Error("유효하지 않은 delay: " + path.delaySamples);
|
||||
const delaySamples = delaySamplesForPath(path);
|
||||
if (!(delaySamples >= 0) || !Number.isFinite(delaySamples)) {
|
||||
throw new Error("유효하지 않은 delay: " + delaySamples);
|
||||
}
|
||||
if (!Number.isFinite(path.gain)) throw new Error("path gain은 유한한 숫자여야 합니다.");
|
||||
}
|
||||
if (workspace.real.length !== spectrum.fftSize || workspace.imaginary.length !== spectrum.fftSize) {
|
||||
throw new Error("fractional-delay workspace 크기가 spectrum과 다릅니다.");
|
||||
}
|
||||
if (!Number.isSafeInteger(outputOffsetSamples) || outputOffsetSamples < 0) {
|
||||
throw new RangeError("outputOffsetSamples must be a non-negative safe integer.");
|
||||
}
|
||||
const hasFrequencyResponse = Array.isArray(frequencyResponse) && frequencyResponse.length > 0;
|
||||
if (hasFrequencyResponse && (!(sampleRate > 0) || !Number.isFinite(sampleRate))) {
|
||||
throw new Error("frequencyResponse 적용에는 유효한 sampleRate가 필요합니다.");
|
||||
@@ -58,7 +75,7 @@ export function addFrequencyDomainPaths(options) {
|
||||
const halfSize = size / 2;
|
||||
const phaseReanchorInterval = 1024;
|
||||
for (const path of paths) {
|
||||
const phaseStep = (-TAU * path.delaySamples) / size;
|
||||
const phaseStep = (-TAU * delaySamplesForPath(path)) / size;
|
||||
const stepReal = Math.cos(phaseStep);
|
||||
const stepImaginary = Math.sin(phaseStep);
|
||||
let phaseReal = 1;
|
||||
@@ -118,9 +135,12 @@ export function addFrequencyDomainPaths(options) {
|
||||
// bin back to the real axis preserves Hermitian symmetry for fractional delays.
|
||||
workspace.imaginary[size / 2] = 0;
|
||||
fftInPlace(workspace.real, workspace.imaginary, true);
|
||||
const outputLength = Math.min(output.length, workspace.real.length);
|
||||
const outputLength = Math.min(
|
||||
output.length,
|
||||
Math.max(0, workspace.real.length - outputOffsetSamples),
|
||||
);
|
||||
for (let sampleIndex = 0; sampleIndex < outputLength; sampleIndex += 1) {
|
||||
output[sampleIndex] += workspace.real[sampleIndex];
|
||||
output[sampleIndex] += workspace.real[outputOffsetSamples + sampleIndex];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user