dsp-collection
Version:
A collection of JavaScript modules for digital signal processing (written in TypeScript)
219 lines • 5.72 kB
JavaScript
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