UNPKG

dsp-collection

Version:

A collection of JavaScript modules for digital signal processing (written in TypeScript)

219 lines 5.72 kB
import * as ArrayUtils from "../utils/ArrayUtils.js"; function handleTrivialCases(ia, oa, preserveScale = false, neNe = false) { const iLen = ia.length; const oLen = oa.length; if (iLen == oLen) { ArrayUtils.copy(ia, oa); return true; } if (oLen == 0) { return true; } if (iLen == 0) { ArrayUtils.fill(oa, NaN); return true; } if (iLen == 1) { ArrayUtils.fill(oa, ia[0]); return true; } if (oLen == 1) { if (preserveScale) { oa[0] = ia[0]; } else if (neNe) { oa[0] = ia[Math.trunc(iLen / 2)]; } else { oa[0] = ArrayUtils.sum(ia) / iLen; } return true; } return false; } export function resampleNearestNeighbor(ia, oa, preserveScale = false, extraValues = 0) { if (handleTrivialCases(ia, oa, preserveScale, true)) { return; } const iLen = ia.length; const oLen = oa.length; const id = iLen * 2; const od = oLen * 2; const oLen1 = preserveScale ? Math.trunc((iLen - 0.5) / iLen * oLen + 1 - 1E-9) : oLen; let ip = 0; let op = 0; let d = preserveScale ? od / 2 : id / 2; while (op < oLen1) { if (d >= od) { if (od >= id) { ip++; d -= od; } else { const i = Math.trunc(d / od); ip += i; d -= i * od; } } oa[op++] = ia[ip]; d += id; } while (op < oLen) { oa[op++] = extraValues; } } export function resampleNearestNeighborRef(ia, oa, preserveScale = false, extraValues = 0) { if (handleTrivialCases(ia, oa, preserveScale, true)) { return; } for (let op = 0; op < oa.length; op++) { let ip; if (preserveScale) { ip = op / oa.length * ia.length; } else { ip = (op + 0.5) / oa.length * ia.length - 0.5; } if (ip <= ia.length - 0.5 - 1E-9) { oa[op] = interpolateNearestNeighbor(ia, ip); } else { oa[op] = extraValues; } } } function interpolateNearestNeighbor(a, pos) { if (a.length == 0) { return NaN; } const p0 = Math.round(pos + 1E-9); const p = Math.max(0, Math.min(a.length - 1, p0)); return a[p]; } export function resampleLinear(ia, oa, preserveScale = false, extraValues = 0) { if (handleTrivialCases(ia, oa, preserveScale)) { return; } const iLen = ia.length; const oLen = oa.length; const id = preserveScale ? iLen : iLen - 1; const od = preserveScale ? oLen : oLen - 1; const oLen1 = preserveScale ? Math.trunc((iLen - 1) * oLen / iLen + 1 + 1E-9) : oLen; let ip = 0; let op = 0; let d = 0; while (op < oLen1) { if (d >= od) { if (od >= id) { ip++; d -= od; } else { const i = Math.trunc(d / od); ip += i; d -= i * od; } } let x; if (d == 0) { x = ia[ip]; } else { x = ia[ip] * ((od - d) / od) + ia[ip + 1] * (d / od); } oa[op++] = x; d += id; } while (op < oLen) { oa[op++] = extraValues; } } export function resampleLinearRef(ia, oa, preserveScale = false, extraValues = 0) { if (handleTrivialCases(ia, oa, preserveScale)) { return; } for (let op = 0; op < oa.length; op++) { let ip; if (preserveScale) { ip = op / oa.length * ia.length; } else { ip = op / (oa.length - 1) * (ia.length - 1); } if (Math.abs(ip - Math.round(ip)) < 1E-10) { ip = Math.round(ip); } if (ip <= ia.length - 1) { oa[op] = interpolateLinear(ia, ip); } else { oa[op] = extraValues; } } } function interpolateLinear(a, pos) { const p1 = Math.floor(pos); const p2 = Math.ceil(pos); if (p1 < 0 || p2 >= a.length) { return NaN; } if (p1 == p2) { return a[p1]; } const v1 = a[p1]; const v2 = a[p2]; return v1 + (pos - p1) * (v2 - v1); } export function resampleAverage(ia, oa) { if (handleTrivialCases(ia, oa)) { return; } const iLen = ia.length; const oLen = oa.length; let ip = 0; let op = 0; let d = 0; while (op < oLen) { d += iLen; let acc = 0; while (d >= oLen) { const w = Math.min(oLen, iLen + oLen - d); acc += ia[ip++] * w; d -= oLen; } if (d > 0) { acc += ia[ip] * Math.min(d, iLen); } oa[op++] = acc / iLen; } } export function resampleAverageRef(ia, oa) { if (handleTrivialCases(ia, oa)) { return; } const w = 1 / oa.length * ia.length; for (let i = 0; i < oa.length; i++) { const p = i / oa.length * ia.length - 0.5; oa[i] = computeAverageOfRange(ia, p, p + w); } } function computeAverageOfRange(a, pos1, pos2) { const p1 = Math.max(-0.5, pos1); const p2 = Math.min(a.length - 0.5, pos2); if (p1 >= p2) { return NaN; } const p1i = Math.round(p1); const p2i = Math.min(Math.round(p2), a.length - 1); if (p1i >= p2i) { return a[p1i]; } let sum = 0; sum += a[p1i] * (p1i + 0.5 - p1); for (let i = p1i + 1; i < p2i; i++) { sum += a[i]; } sum += a[p2i] * (p2 - (p2i - 0.5)); return sum / (p2 - p1); } //# sourceMappingURL=Resampling.js.map