@remotion/media-utils 4.0.81 → 4.0.83
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fft/fft-accurate.d.ts +1 -0
- package/dist/fft/fft-accurate.js +33 -0
- package/dist/fft/fft-fast.d.ts +1 -0
- package/dist/fft/fft-fast.js +76 -0
- package/dist/fft/fft.d.ts +1 -1
- package/dist/fft/fft.js +5 -5
- package/dist/fft/get-visualization.d.ts +3 -1
- package/dist/fft/get-visualization.js +5 -3
- package/dist/visualize-audio.d.ts +1 -0
- package/dist/visualize-audio.js +2 -1
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const fftAccurate: (vector: Int16Array) => [number, number][];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Adapted from node-fft project by Joshua Wong and Ben Bryan
|
|
3
|
+
// https://github.com/vail-systems/node-fft
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.fftAccurate = void 0;
|
|
6
|
+
const complex_1 = require("./complex");
|
|
7
|
+
const exponent_1 = require("./exponent");
|
|
8
|
+
const fftAccurate = function (vector) {
|
|
9
|
+
const X = [];
|
|
10
|
+
const N = vector.length;
|
|
11
|
+
// Base case is X = x + 0i since our input is assumed to be real only.
|
|
12
|
+
if (N === 1) {
|
|
13
|
+
if (Array.isArray(vector[0])) {
|
|
14
|
+
// If input vector contains complex numbers
|
|
15
|
+
return [[vector[0][0], vector[0][1]]];
|
|
16
|
+
}
|
|
17
|
+
return [[vector[0], 0]];
|
|
18
|
+
}
|
|
19
|
+
// Recurse: all even samples
|
|
20
|
+
const X_evens = (0, exports.fftAccurate)(vector.filter((_, ix) => ix % 2 === 0));
|
|
21
|
+
// Recurse: all odd samples
|
|
22
|
+
const X_odds = (0, exports.fftAccurate)(vector.filter((__, ix) => ix % 2 === 1));
|
|
23
|
+
// Now, perform N/2 operations!
|
|
24
|
+
for (let k = 0; k < N / 2; k++) {
|
|
25
|
+
// t is a complex number!
|
|
26
|
+
const t = X_evens[k];
|
|
27
|
+
const e = (0, complex_1.complexMultiply)((0, exponent_1.exponent)(k, N), X_odds[k]);
|
|
28
|
+
X[k] = (0, complex_1.complexAdd)(t, e);
|
|
29
|
+
X[k + N / 2] = (0, complex_1.complexSubtract)(t, e);
|
|
30
|
+
}
|
|
31
|
+
return X;
|
|
32
|
+
};
|
|
33
|
+
exports.fftAccurate = fftAccurate;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const fftFast: (vector: Int16Array) => [number, number][];
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// https://pastebin.com/raw/D42RbPe5
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.fftFast = void 0;
|
|
5
|
+
// Function to reverse bits in an integer
|
|
6
|
+
function reverseBits(num, numBits) {
|
|
7
|
+
let result = 0;
|
|
8
|
+
for (let i = 0; i < numBits; i++) {
|
|
9
|
+
result = (result << 1) | ((num >> i) & 1);
|
|
10
|
+
}
|
|
11
|
+
return result;
|
|
12
|
+
}
|
|
13
|
+
// Hamming window function
|
|
14
|
+
function hammingWindow(N) {
|
|
15
|
+
const win = new Array(N);
|
|
16
|
+
for (let i = 0; i < N; i++) {
|
|
17
|
+
win[i] = 0.8 - 0.46 * Math.cos((2 * Math.PI * i) / (N - 1));
|
|
18
|
+
}
|
|
19
|
+
return win;
|
|
20
|
+
}
|
|
21
|
+
// Function to calculate the bit-reversed permutation indices
|
|
22
|
+
function bitReversePermutation(N) {
|
|
23
|
+
const bitReversed = new Array(N);
|
|
24
|
+
for (let i = 0; i < N; i++) {
|
|
25
|
+
bitReversed[i] = reverseBits(i, Math.log2(N));
|
|
26
|
+
}
|
|
27
|
+
return bitReversed;
|
|
28
|
+
}
|
|
29
|
+
const fftFast = function (vector) {
|
|
30
|
+
const N = vector.length;
|
|
31
|
+
const X = new Array(N);
|
|
32
|
+
if (N <= 1) {
|
|
33
|
+
for (let i = 0; i < vector.length; i++) {
|
|
34
|
+
const value = vector[i];
|
|
35
|
+
X[i] = [value * 2, 0];
|
|
36
|
+
}
|
|
37
|
+
return X;
|
|
38
|
+
}
|
|
39
|
+
// Apply a windowing function to the input data
|
|
40
|
+
const window = hammingWindow(N); // You can choose a different window function if needed
|
|
41
|
+
for (let i = 0; i < N; i++) {
|
|
42
|
+
X[i] = [vector[i] * window[i], 0];
|
|
43
|
+
}
|
|
44
|
+
// Bit-Reversal Permutation
|
|
45
|
+
const bitReversed = bitReversePermutation(N);
|
|
46
|
+
for (let i = 0; i < N; i++) {
|
|
47
|
+
X[i] = [vector[bitReversed[i]], 0];
|
|
48
|
+
}
|
|
49
|
+
// Cooley-Tukey FFT
|
|
50
|
+
for (let s = 1; s <= Math.log2(N); s++) {
|
|
51
|
+
const m = 1 << s; // Number of elements in each subarray
|
|
52
|
+
const mHalf = m / 2; // Half the number of elements in each subarray
|
|
53
|
+
const angleIncrement = (2 * Math.PI) / m;
|
|
54
|
+
for (let k = 0; k < N; k += m) {
|
|
55
|
+
let omegaReal = 1.0;
|
|
56
|
+
let omegaImag = 0.0;
|
|
57
|
+
for (let j = 0; j < mHalf; j++) {
|
|
58
|
+
const tReal = omegaReal * X[k + j + mHalf][0] - omegaImag * X[k + j + mHalf][1];
|
|
59
|
+
const tImag = omegaReal * X[k + j + mHalf][1] + omegaImag * X[k + j + mHalf][0];
|
|
60
|
+
const uReal = X[k + j][0];
|
|
61
|
+
const uImag = X[k + j][1];
|
|
62
|
+
X[k + j] = [uReal + tReal, uImag + tImag];
|
|
63
|
+
X[k + j + mHalf] = [uReal - tReal, uImag - tImag];
|
|
64
|
+
// Twiddle factor update
|
|
65
|
+
const tempReal = omegaReal * Math.cos(angleIncrement) -
|
|
66
|
+
omegaImag * Math.sin(angleIncrement);
|
|
67
|
+
omegaImag =
|
|
68
|
+
omegaReal * Math.sin(angleIncrement) +
|
|
69
|
+
omegaImag * Math.cos(angleIncrement);
|
|
70
|
+
omegaReal = tempReal;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return X;
|
|
75
|
+
};
|
|
76
|
+
exports.fftFast = fftFast;
|
package/dist/fft/fft.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const
|
|
1
|
+
export declare const fftAccurate: (vector: Int16Array) => [number, number][];
|
package/dist/fft/fft.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
// Adapted from node-fft project by Joshua Wong and Ben Bryan
|
|
3
3
|
// https://github.com/vail-systems/node-fft
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
exports.
|
|
5
|
+
exports.fftAccurate = void 0;
|
|
6
6
|
const complex_1 = require("./complex");
|
|
7
7
|
const exponent_1 = require("./exponent");
|
|
8
|
-
const
|
|
8
|
+
const fftAccurate = function (vector) {
|
|
9
9
|
const X = [];
|
|
10
10
|
const N = vector.length;
|
|
11
11
|
// Base case is X = x + 0i since our input is assumed to be real only.
|
|
@@ -17,9 +17,9 @@ const fft = function (vector) {
|
|
|
17
17
|
return [[vector[0], 0]];
|
|
18
18
|
}
|
|
19
19
|
// Recurse: all even samples
|
|
20
|
-
const X_evens = (0, exports.
|
|
20
|
+
const X_evens = (0, exports.fftAccurate)(vector.filter((_, ix) => ix % 2 === 0));
|
|
21
21
|
// Recurse: all odd samples
|
|
22
|
-
const X_odds = (0, exports.
|
|
22
|
+
const X_odds = (0, exports.fftAccurate)(vector.filter((__, ix) => ix % 2 === 1));
|
|
23
23
|
// Now, perform N/2 operations!
|
|
24
24
|
for (let k = 0; k < N / 2; k++) {
|
|
25
25
|
// t is a complex number!
|
|
@@ -30,4 +30,4 @@ const fft = function (vector) {
|
|
|
30
30
|
}
|
|
31
31
|
return X;
|
|
32
32
|
};
|
|
33
|
-
exports.
|
|
33
|
+
exports.fftAccurate = fftAccurate;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type OptimizeFor = 'accuracy' | 'speed';
|
|
2
|
+
export declare const getVisualization: ({ sampleSize, data, sampleRate, frame, fps, maxInt, optimizeFor, }: {
|
|
2
3
|
sampleSize: number;
|
|
3
4
|
data: Float32Array;
|
|
4
5
|
frame: number;
|
|
5
6
|
sampleRate: number;
|
|
6
7
|
fps: number;
|
|
7
8
|
maxInt: number;
|
|
9
|
+
optimizeFor: OptimizeFor;
|
|
8
10
|
}) => number[];
|
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
// https://github.com/vail-systems/node-fft
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
5
|
exports.getVisualization = void 0;
|
|
6
|
-
const
|
|
6
|
+
const fft_accurate_1 = require("./fft-accurate");
|
|
7
|
+
const fft_fast_1 = require("./fft-fast");
|
|
7
8
|
const mag_1 = require("./mag");
|
|
8
9
|
const smoothing_1 = require("./smoothing");
|
|
9
10
|
const to_int_16_1 = require("./to-int-16");
|
|
10
|
-
const getVisualization = ({ sampleSize, data, sampleRate, frame, fps, maxInt, }) => {
|
|
11
|
+
const getVisualization = ({ sampleSize, data, sampleRate, frame, fps, maxInt, optimizeFor = 'accuracy', }) => {
|
|
11
12
|
const isPowerOfTwo = sampleSize > 0 && (sampleSize & (sampleSize - 1)) === 0;
|
|
12
13
|
if (!isPowerOfTwo) {
|
|
13
14
|
throw new TypeError(`The argument "bars" must be a power of two. For example: 64, 128. Got instead: ${sampleSize}`);
|
|
@@ -24,7 +25,8 @@ const getVisualization = ({ sampleSize, data, sampleRate, frame, fps, maxInt, })
|
|
|
24
25
|
length: sampleSize,
|
|
25
26
|
});
|
|
26
27
|
ints.set(data.subarray(actualStart, actualStart + sampleSize).map((x) => (0, to_int_16_1.toInt16)(x)));
|
|
27
|
-
const
|
|
28
|
+
const alg = optimizeFor === 'accuracy' ? fft_accurate_1.fftAccurate : fft_fast_1.fftFast;
|
|
29
|
+
const phasors = alg(ints);
|
|
28
30
|
const magnitudes = (0, mag_1.fftMag)(phasors).map((p) => p);
|
|
29
31
|
return (0, smoothing_1.smoothen)(magnitudes).map((m) => m / (sampleSize / 2) / maxInt);
|
|
30
32
|
};
|
package/dist/visualize-audio.js
CHANGED
|
@@ -9,7 +9,7 @@ const cache = {};
|
|
|
9
9
|
* @description part of @remotion/media-utils
|
|
10
10
|
* @see [Documentation](https://www.remotion.dev/docs/visualize-audio)
|
|
11
11
|
*/
|
|
12
|
-
const visualizeAudioFrame = ({ audioData: metadata, frame, fps, numberOfSamples, }) => {
|
|
12
|
+
const visualizeAudioFrame = ({ audioData: metadata, frame, fps, numberOfSamples, optimizeFor, }) => {
|
|
13
13
|
const cacheKey = metadata.resultId + frame + fps + numberOfSamples;
|
|
14
14
|
if (cache[cacheKey]) {
|
|
15
15
|
return cache[cacheKey];
|
|
@@ -22,6 +22,7 @@ const visualizeAudioFrame = ({ audioData: metadata, frame, fps, numberOfSamples,
|
|
|
22
22
|
fps,
|
|
23
23
|
sampleRate: metadata.sampleRate,
|
|
24
24
|
maxInt,
|
|
25
|
+
optimizeFor: optimizeFor !== null && optimizeFor !== void 0 ? optimizeFor : 'accuracy',
|
|
25
26
|
});
|
|
26
27
|
};
|
|
27
28
|
const visualizeAudio = ({ smoothing = true, ...parameters }) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remotion/media-utils",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.83",
|
|
4
4
|
"description": "Utility functions for audio and video",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"url": "https://github.com/remotion-dev/remotion/issues"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"remotion": "4.0.
|
|
16
|
+
"remotion": "4.0.83"
|
|
17
17
|
},
|
|
18
18
|
"peerDependencies": {
|
|
19
19
|
"react": ">=16.8.0",
|