Add .gitignore to exclude all node packages and lock files
This commit is contained in:
Generated
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
export declare const complexAdd: (a: [number, number], b: [number, number]) => [number, number];
|
||||
export declare const complexSubtract: (a: [number, number], b: [number, number]) => [number, number];
|
||||
export declare const complexMultiply: (a: [number, number], b: [number, number]) => [number, number];
|
||||
export declare const complexMagnitude: (c: [number, number]) => number;
|
||||
Generated
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
"use strict";
|
||||
// Adapted from node-fft project by Joshua Wong and Ben Bryan
|
||||
// https://github.com/vail-systems/node-fft
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.complexMagnitude = exports.complexMultiply = exports.complexSubtract = exports.complexAdd = void 0;
|
||||
const complexAdd = function (a, b) {
|
||||
return [a[0] + b[0], a[1] + b[1]];
|
||||
};
|
||||
exports.complexAdd = complexAdd;
|
||||
const complexSubtract = function (a, b) {
|
||||
return [a[0] - b[0], a[1] - b[1]];
|
||||
};
|
||||
exports.complexSubtract = complexSubtract;
|
||||
const complexMultiply = function (a, b) {
|
||||
return [a[0] * b[0] - a[1] * b[1], a[0] * b[1] + a[1] * b[0]];
|
||||
};
|
||||
exports.complexMultiply = complexMultiply;
|
||||
const complexMagnitude = function (c) {
|
||||
return Math.sqrt(c[0] * c[0] + c[1] * c[1]);
|
||||
};
|
||||
exports.complexMagnitude = complexMagnitude;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const exponent: (k: number, N: number) => [number, number];
|
||||
Generated
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
// Adapted from node-fft project by Joshua Wong and Ben Bryan
|
||||
// https://github.com/vail-systems/node-fft
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.exponent = void 0;
|
||||
const mapExponent = {};
|
||||
const exponent = function (k, N) {
|
||||
const x = -2 * Math.PI * (k / N);
|
||||
mapExponent[N] = mapExponent[N] || {};
|
||||
mapExponent[N][k] = mapExponent[N][k] || [Math.cos(x), Math.sin(x)]; // [Real, Imaginary]
|
||||
return mapExponent[N][k];
|
||||
};
|
||||
exports.exponent = exponent;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const fftAccurate: (vector: Int16Array) => [number, number][];
|
||||
Generated
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
"use strict";
|
||||
// Adapted from node-fft project by Joshua Wong and Ben Bryan
|
||||
// https://github.com/vail-systems/node-fft
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.fftAccurate = void 0;
|
||||
const complex_1 = require("./complex");
|
||||
const exponent_1 = require("./exponent");
|
||||
const fftAccurate = function (vector) {
|
||||
const X = [];
|
||||
const N = vector.length;
|
||||
// Base case is X = x + 0i since our input is assumed to be real only.
|
||||
if (N === 1) {
|
||||
if (Array.isArray(vector[0])) {
|
||||
// If input vector contains complex numbers
|
||||
return [[vector[0][0], vector[0][1]]];
|
||||
}
|
||||
return [[vector[0], 0]];
|
||||
}
|
||||
// Recurse: all even samples
|
||||
const X_evens = (0, exports.fftAccurate)(vector.filter((_, ix) => ix % 2 === 0));
|
||||
// Recurse: all odd samples
|
||||
const X_odds = (0, exports.fftAccurate)(vector.filter((__, ix) => ix % 2 === 1));
|
||||
// Now, perform N/2 operations!
|
||||
for (let k = 0; k < N / 2; k++) {
|
||||
// t is a complex number!
|
||||
const t = X_evens[k];
|
||||
const e = (0, complex_1.complexMultiply)((0, exponent_1.exponent)(k, N), X_odds[k]);
|
||||
X[k] = (0, complex_1.complexAdd)(t, e);
|
||||
X[k + N / 2] = (0, complex_1.complexSubtract)(t, e);
|
||||
}
|
||||
return X;
|
||||
};
|
||||
exports.fftAccurate = fftAccurate;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const fftFast: (vector: Int16Array) => [number, number][];
|
||||
Generated
Vendored
+76
@@ -0,0 +1,76 @@
|
||||
"use strict";
|
||||
// https://pastebin.com/raw/D42RbPe5
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.fftFast = void 0;
|
||||
// Function to reverse bits in an integer
|
||||
function reverseBits(num, numBits) {
|
||||
let result = 0;
|
||||
for (let i = 0; i < numBits; i++) {
|
||||
result = (result << 1) | ((num >> i) & 1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// Hamming window function
|
||||
function hammingWindow(N) {
|
||||
const win = new Array(N);
|
||||
for (let i = 0; i < N; i++) {
|
||||
win[i] = 0.8 - 0.46 * Math.cos((2 * Math.PI * i) / (N - 1));
|
||||
}
|
||||
return win;
|
||||
}
|
||||
// Function to calculate the bit-reversed permutation indices
|
||||
function bitReversePermutation(N) {
|
||||
const bitReversed = new Array(N);
|
||||
for (let i = 0; i < N; i++) {
|
||||
bitReversed[i] = reverseBits(i, Math.log2(N));
|
||||
}
|
||||
return bitReversed;
|
||||
}
|
||||
const fftFast = function (vector) {
|
||||
const N = vector.length;
|
||||
const X = new Array(N);
|
||||
if (N <= 1) {
|
||||
for (let i = 0; i < vector.length; i++) {
|
||||
const value = vector[i];
|
||||
X[i] = [value * 2, 0];
|
||||
}
|
||||
return X;
|
||||
}
|
||||
// Apply a windowing function to the input data
|
||||
const window = hammingWindow(N); // You can choose a different window function if needed
|
||||
for (let i = 0; i < N; i++) {
|
||||
X[i] = [vector[i] * window[i], 0];
|
||||
}
|
||||
// Bit-Reversal Permutation
|
||||
const bitReversed = bitReversePermutation(N);
|
||||
for (let i = 0; i < N; i++) {
|
||||
X[i] = [vector[bitReversed[i]], 0];
|
||||
}
|
||||
// Cooley-Tukey FFT
|
||||
for (let s = 1; s <= Math.log2(N); s++) {
|
||||
const m = 1 << s; // Number of elements in each subarray
|
||||
const mHalf = m / 2; // Half the number of elements in each subarray
|
||||
const angleIncrement = (2 * Math.PI) / m;
|
||||
for (let k = 0; k < N; k += m) {
|
||||
let omegaReal = 1.0;
|
||||
let omegaImag = 0.0;
|
||||
for (let j = 0; j < mHalf; j++) {
|
||||
const tReal = omegaReal * X[k + j + mHalf][0] - omegaImag * X[k + j + mHalf][1];
|
||||
const tImag = omegaReal * X[k + j + mHalf][1] + omegaImag * X[k + j + mHalf][0];
|
||||
const uReal = X[k + j][0];
|
||||
const uImag = X[k + j][1];
|
||||
X[k + j] = [uReal + tReal, uImag + tImag];
|
||||
X[k + j + mHalf] = [uReal - tReal, uImag - tImag];
|
||||
// Twiddle factor update
|
||||
const tempReal = omegaReal * Math.cos(angleIncrement) -
|
||||
omegaImag * Math.sin(angleIncrement);
|
||||
omegaImag =
|
||||
omegaReal * Math.sin(angleIncrement) +
|
||||
omegaImag * Math.cos(angleIncrement);
|
||||
omegaReal = tempReal;
|
||||
}
|
||||
}
|
||||
}
|
||||
return X;
|
||||
};
|
||||
exports.fftFast = fftFast;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const fftFreq: (fftBins: [number, number][], sampleRate: number) => number[];
|
||||
Generated
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
// Adapted from node-fft project by Joshua Wong and Ben Bryan
|
||||
// https://github.com/vail-systems/node-fft
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.fftFreq = void 0;
|
||||
const fftFreq = function (fftBins, sampleRate) {
|
||||
const stepFreq = sampleRate / fftBins.length;
|
||||
const ret = fftBins.slice(0, fftBins.length / 2);
|
||||
return ret.map((__, ix) => {
|
||||
return ix * stepFreq;
|
||||
});
|
||||
};
|
||||
exports.fftFreq = fftFreq;
|
||||
Generated
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
export type OptimizeFor = 'accuracy' | 'speed';
|
||||
export declare const getVisualization: ({ sampleSize, data, sampleRate, frame, fps, maxInt, optimizeFor, dataOffsetInSeconds, }: {
|
||||
sampleSize: number;
|
||||
data: Float32Array;
|
||||
frame: number;
|
||||
sampleRate: number;
|
||||
fps: number;
|
||||
maxInt: number;
|
||||
optimizeFor: OptimizeFor;
|
||||
dataOffsetInSeconds: number;
|
||||
}) => number[];
|
||||
Generated
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
"use strict";
|
||||
// Adapted from node-fft project by Joshua Wong and Ben Bryan
|
||||
// https://github.com/vail-systems/node-fft
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getVisualization = void 0;
|
||||
const fft_accurate_1 = require("./fft-accurate");
|
||||
const fft_fast_1 = require("./fft-fast");
|
||||
const mag_1 = require("./mag");
|
||||
const smoothing_1 = require("./smoothing");
|
||||
const to_int_16_1 = require("./to-int-16");
|
||||
const getVisualization = ({ sampleSize, data, sampleRate, frame, fps, maxInt, optimizeFor, dataOffsetInSeconds, }) => {
|
||||
const isPowerOfTwo = sampleSize > 0 && (sampleSize & (sampleSize - 1)) === 0;
|
||||
if (!isPowerOfTwo) {
|
||||
throw new TypeError(`The argument "bars" must be a power of two. For example: 64, 128. Got instead: ${sampleSize}`);
|
||||
}
|
||||
if (!fps) {
|
||||
throw new TypeError('The argument "fps" was not provided');
|
||||
}
|
||||
if (data.length < sampleSize) {
|
||||
throw new TypeError('Audio data is not big enough to provide ' + sampleSize + ' bars.');
|
||||
}
|
||||
const start = Math.floor((frame / fps - dataOffsetInSeconds) * sampleRate);
|
||||
const actualStart = Math.max(0, start - sampleSize / 2);
|
||||
const ints = new Int16Array({
|
||||
length: sampleSize,
|
||||
});
|
||||
ints.set(data.subarray(actualStart, actualStart + sampleSize).map((x) => (0, to_int_16_1.toInt16)(x)));
|
||||
const alg = optimizeFor === 'accuracy' ? fft_accurate_1.fftAccurate : fft_fast_1.fftFast;
|
||||
const phasors = alg(ints);
|
||||
const magnitudes = (0, mag_1.fftMag)(phasors).map((p) => p);
|
||||
return (0, smoothing_1.smoothen)(magnitudes).map((m) => m / (sampleSize / 2) / maxInt);
|
||||
};
|
||||
exports.getVisualization = getVisualization;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const fftMag: (fftBins: [number, number][]) => number[];
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
// Adapted from node-fft project by Joshua Wong and Ben Bryan
|
||||
// https://github.com/vail-systems/node-fft
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.fftMag = void 0;
|
||||
const complex_1 = require("./complex");
|
||||
const fftMag = function (fftBins) {
|
||||
const ret = fftBins.map((f) => (0, complex_1.complexMagnitude)(f));
|
||||
return ret.slice(0, ret.length / 2);
|
||||
};
|
||||
exports.fftMag = fftMag;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { MediaUtilsAudioData } from '../types';
|
||||
export declare const getMaxPossibleMagnitude: (metadata: MediaUtilsAudioData) => number;
|
||||
Generated
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
"use strict";
|
||||
// Adapted from node-fft project by Joshua Wong and Ben Bryan
|
||||
// https://github.com/vail-systems/node-fft
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getMaxPossibleMagnitude = void 0;
|
||||
const to_int_16_1 = require("./to-int-16");
|
||||
const getMax = (array) => {
|
||||
let max = 0;
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const val = array[i];
|
||||
if (val > max) {
|
||||
max = val;
|
||||
}
|
||||
}
|
||||
return max;
|
||||
};
|
||||
const cache = {};
|
||||
const getMaxPossibleMagnitude = (metadata) => {
|
||||
if (cache[metadata.resultId]) {
|
||||
return cache[metadata.resultId];
|
||||
}
|
||||
const result = (0, to_int_16_1.toInt16)(getMax(metadata.channelWaveforms[0]));
|
||||
cache[metadata.resultId] = result;
|
||||
return result;
|
||||
};
|
||||
exports.getMaxPossibleMagnitude = getMaxPossibleMagnitude;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const smoothen: (array: number[]) => number[];
|
||||
Generated
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
"use strict";
|
||||
// Adapted from node-fft project by Joshua Wong and Ben Bryan
|
||||
// https://github.com/vail-systems/node-fft
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.smoothen = void 0;
|
||||
const smoothingPasses = 3;
|
||||
const smoothingPoints = 3;
|
||||
const smoothen = function (array) {
|
||||
let lastArray = array;
|
||||
const newArr = [];
|
||||
for (let pass = 0; pass < smoothingPasses; pass++) {
|
||||
const sidePoints = Math.floor(smoothingPoints / 2); // our window is centered so this is both nL and nR
|
||||
const cn = 1 / (2 * sidePoints + 1); // constant
|
||||
for (let i = 0; i < sidePoints; i++) {
|
||||
newArr[i] = lastArray[i];
|
||||
newArr[lastArray.length - i - 1] = lastArray[lastArray.length - i - 1];
|
||||
}
|
||||
for (let i = sidePoints; i < lastArray.length - sidePoints; i++) {
|
||||
let sum = 0;
|
||||
for (let n = -sidePoints; n <= sidePoints; n++) {
|
||||
sum += cn * lastArray[i + n] + n;
|
||||
}
|
||||
newArr[i] = sum;
|
||||
}
|
||||
lastArray = newArr;
|
||||
}
|
||||
return newArr;
|
||||
};
|
||||
exports.smoothen = smoothen;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const toInt16: (x: number) => number;
|
||||
Generated
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.toInt16 = void 0;
|
||||
const toInt16 = (x) => (x > 0 ? x * 0x7fff : x * 0x8000);
|
||||
exports.toInt16 = toInt16;
|
||||
Reference in New Issue
Block a user