@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.
@@ -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 fft: (vector: Int16Array) => [number, number][];
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.fft = void 0;
5
+ exports.fftAccurate = void 0;
6
6
  const complex_1 = require("./complex");
7
7
  const exponent_1 = require("./exponent");
8
- const fft = function (vector) {
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.fft)(vector.filter((_, ix) => ix % 2 === 0));
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.fft)(vector.filter((__, ix) => ix % 2 === 1));
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.fft = fft;
33
+ exports.fftAccurate = fftAccurate;
@@ -1,8 +1,10 @@
1
- export declare const getVisualization: ({ sampleSize, data, sampleRate, frame, fps, maxInt, }: {
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 fft_1 = require("./fft");
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 phasors = (0, fft_1.fft)(ints);
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
  };
@@ -4,6 +4,7 @@ type FnParameters = {
4
4
  frame: number;
5
5
  fps: number;
6
6
  numberOfSamples: number;
7
+ optimizeFor?: 'accuracy' | 'speed';
7
8
  };
8
9
  export declare const visualizeAudio: ({ smoothing, ...parameters }: FnParameters & {
9
10
  smoothing?: boolean | undefined;
@@ -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.81",
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.81"
16
+ "remotion": "4.0.83"
17
17
  },
18
18
  "peerDependencies": {
19
19
  "react": ">=16.8.0",