nodejs-audio-visualizer 2.1.4 → 4.0.0

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.
@@ -16,10 +16,9 @@ describe('fft', function () {
16
16
  });
17
17
 
18
18
  it('getSpectrum', function () {
19
- var signal = [1, 0, 0, 0, 1, 0, 0, 0];
20
- const fft = [8.317766166719343, 0, 11.090354888959125, 0];
19
+ const signal = Array(Math.pow(2, 12)).fill(1);
21
20
 
22
- const result = getSpectrum(signal);
23
- expect(result).deep.equal(fft);
21
+ const result = getSpectrum(signal, 44100);
22
+ expect(result).to.have.length(24);
24
23
  });
25
24
  });
@@ -1,10 +1,10 @@
1
1
  import { expect } from 'chai';
2
2
  import path from 'path';
3
- import fs from 'fs';
4
3
  import {
5
4
  drawRect,
6
5
  Color,
7
- createVisualizerFrame,
6
+ createSpectrumVisualizerFrameGenerator,
7
+ createPolarVisualizerFrameGenerator,
8
8
  parseImage,
9
9
  convertToBmp,
10
10
  mixValues,
@@ -12,10 +12,6 @@ import {
12
12
  } from '../image';
13
13
  import { createBpmEncoder } from '../bpmEncoder';
14
14
 
15
- import frameSnapshotSpectrumDown from './snapshots/frameSnapshotSpectrumDown.json';
16
- import frameSnapshotSpectrumUp from './snapshots/frameSnapshotSpectrumUp.json';
17
- import frameSnapshotSpectrumUpOpacity50 from './snapshots/frameSnapshotSpectrumUpOpacity50.json';
18
-
19
15
  describe('image', function () {
20
16
  it('mixValues', function () {
21
17
  expect(mixValues(420, 0.69, 96)).equal(320);
@@ -81,12 +77,14 @@ describe('image', function () {
81
77
  expect(imageDstBuffer.data).deep.equal(expectedImageData);
82
78
  });
83
79
 
84
- it('createVisualizerFrame', async function () {
85
- const backgroundImagePath = path.resolve('example/media/background.png');
80
+ it('createSpectrumVisualizerFrameGenerator', async function () {
81
+ const expectedImageLength = 6220854;
82
+ const backgroundImagePath = path.resolve('example/media/horses.png');
86
83
  const backgroundImageBmpBuffer = await convertToBmp(backgroundImagePath);
87
84
  const backgroundImage = parseImage(backgroundImageBmpBuffer);
88
85
  const bpmEncoder = createBpmEncoder({ width: backgroundImage.width, height: backgroundImage.height });
89
86
  const backgroundImageBuffer = bpmEncoder(backgroundImage.data);
87
+ const createVisualizerFrame = createSpectrumVisualizerFrameGenerator();
90
88
  const frameSpectrumDown = createVisualizerFrame({
91
89
  backgroundImageBuffer,
92
90
  spectrum: [0.5, 0, 1],
@@ -98,7 +96,7 @@ describe('image', function () {
98
96
  opacity: 1,
99
97
  });
100
98
  const resultSpectrumDown = frameSpectrumDown.data.toJSON().data;
101
- expect(resultSpectrumDown).deep.equal(frameSnapshotSpectrumDown);
99
+ expect(resultSpectrumDown).to.have.length(expectedImageLength);
102
100
 
103
101
  const frameSpectrumUp = createVisualizerFrame({
104
102
  backgroundImageBuffer,
@@ -111,7 +109,20 @@ describe('image', function () {
111
109
  opacity: 1,
112
110
  });
113
111
  const resultSpectrumUp = frameSpectrumUp.data.toJSON().data;
114
- expect(resultSpectrumUp).deep.equal(frameSnapshotSpectrumUp);
112
+ expect(resultSpectrumUp).to.have.length(expectedImageLength);
113
+
114
+ const frameSpectrumMirror = createVisualizerFrame({
115
+ backgroundImageBuffer,
116
+ spectrum: [0.1, 1, 0],
117
+ size: { width: 25, height: 23 },
118
+ position: { x: 10, y: 5 },
119
+ rotation: 'mirror',
120
+ margin: 4,
121
+ color: { red: 0, green: 123, blue: 69 },
122
+ opacity: 1,
123
+ });
124
+ const resultSpectrumMirror = frameSpectrumMirror.data.toJSON().data;
125
+ expect(resultSpectrumMirror).to.have.length(expectedImageLength);
115
126
 
116
127
  const frameSpectrumUpOpacity50 = createVisualizerFrame({
117
128
  backgroundImageBuffer,
@@ -124,6 +135,88 @@ describe('image', function () {
124
135
  opacity: 0.5,
125
136
  });
126
137
  const resultSpectrumUpOpacity50 = frameSpectrumUpOpacity50.data.toJSON().data;
127
- expect(resultSpectrumUpOpacity50).deep.equal(frameSnapshotSpectrumUpOpacity50);
138
+ expect(resultSpectrumUpOpacity50).to.have.length(expectedImageLength);
139
+ });
140
+
141
+ it('createPolarVisualizerFrameGenerator', async function () {
142
+ const expectedImageLength = 6220854;
143
+ const backgroundImagePath = path.resolve('example/media/horses.png');
144
+ const backgroundImageBmpBuffer = await convertToBmp(backgroundImagePath);
145
+ const backgroundImage = parseImage(backgroundImageBmpBuffer);
146
+ const bpmEncoder = createBpmEncoder({ width: backgroundImage.width, height: backgroundImage.height });
147
+ const backgroundImageBuffer = bpmEncoder(backgroundImage.data);
148
+ const createPolarVisualizerFrame = createPolarVisualizerFrameGenerator();
149
+
150
+ const framePolarBasic = createPolarVisualizerFrame({
151
+ backgroundImageBuffer,
152
+ spectrum: [0.5, 0.8, 0.3, 0.9, 0.6, 0.4, 0.7, 0.2],
153
+ centerX: 500,
154
+ centerY: 400,
155
+ innerRadius: 100,
156
+ maxBarLength: 150,
157
+ barWidth: 5,
158
+ color: { red: 255, green: 100, blue: 50 },
159
+ opacity: 1,
160
+ });
161
+ const resultPolarBasic = framePolarBasic.data.toJSON().data;
162
+ expect(resultPolarBasic).to.have.length(expectedImageLength);
163
+
164
+ const framePolarVolume = createPolarVisualizerFrame({
165
+ backgroundImageBuffer,
166
+ spectrum: [0.2, 0.5, 0.8, 0.3, 0.6, 0.9, 0.4, 0.7],
167
+ centerX: 500,
168
+ centerY: 400,
169
+ innerRadius: 80,
170
+ maxBarLength: 120,
171
+ barWidth: 4,
172
+ color: { red: 100, green: 200, blue: 255 },
173
+ opacity: 1,
174
+ spectrumEffect: 'volume',
175
+ });
176
+ const resultPolarVolume = framePolarVolume.data.toJSON().data;
177
+ expect(resultPolarVolume).to.have.length(expectedImageLength);
178
+
179
+ const framePolarSmooth = createPolarVisualizerFrame({
180
+ backgroundImageBuffer,
181
+ spectrum: [0.7, 0.4, 0.9, 0.2, 0.5, 0.8, 0.3, 0.6],
182
+ centerX: 500,
183
+ centerY: 400,
184
+ innerRadius: 90,
185
+ maxBarLength: 130,
186
+ barWidth: 6,
187
+ color: { red: 255, green: 255, blue: 0 },
188
+ opacity: 1,
189
+ spectrumEffect: 'smooth',
190
+ });
191
+ const resultPolarSmooth = framePolarSmooth.data.toJSON().data;
192
+ expect(resultPolarSmooth).to.have.length(expectedImageLength);
193
+
194
+ const framePolarOpacity50 = createPolarVisualizerFrame({
195
+ backgroundImageBuffer,
196
+ spectrum: [0.6, 0.3, 0.8, 0.5, 0.4, 0.7, 0.2, 0.9],
197
+ centerX: 500,
198
+ centerY: 400,
199
+ innerRadius: 100,
200
+ maxBarLength: 140,
201
+ barWidth: 5,
202
+ color: { red: 0, green: 255, blue: 128 },
203
+ opacity: 0.5,
204
+ });
205
+ const resultPolarOpacity50 = framePolarOpacity50.data.toJSON().data;
206
+ expect(resultPolarOpacity50).to.have.length(expectedImageLength);
207
+
208
+ const framePolarHexColor = createPolarVisualizerFrame({
209
+ backgroundImageBuffer,
210
+ spectrum: [0.5, 0.6, 0.7, 0.8, 0.9, 0.4, 0.3, 0.2],
211
+ centerX: 500,
212
+ centerY: 400,
213
+ innerRadius: 110,
214
+ maxBarLength: 160,
215
+ barWidth: 7,
216
+ color: '#FF5733',
217
+ opacity: 1,
218
+ });
219
+ const resultPolarHexColor = framePolarHexColor.data.toJSON().data;
220
+ expect(resultPolarHexColor).to.have.length(expectedImageLength);
128
221
  });
129
222
  });
@@ -42,7 +42,7 @@ describe('index', function () {
42
42
  path: 'audioPath'
43
43
  },
44
44
  image: {
45
- path: 'example/media/background.png'
45
+ path: 'example/media/horses.png'
46
46
  },
47
47
  outVideo: {
48
48
  path: 'outVideoPath',
@@ -0,0 +1,7 @@
1
+ declare module 'fft-js' {
2
+ export function fft(signal: number[]): [number, number][];
3
+ export const util: {
4
+ fftFreq(phasors: [number, number][], sampleRate: number): number[];
5
+ fftMag(phasors: [number, number][]): number[];
6
+ };
7
+ }
@@ -1 +0,0 @@
1
- export declare const createSpectrumAnalyzer: (bufferSize: number) => (buffer: number[]) => number[];
package/dist/spectrum.js DELETED
@@ -1,72 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createSpectrumAnalyzer = function (bufferSize) {
4
- var real = new Float64Array(bufferSize);
5
- var imag = new Float64Array(bufferSize);
6
- var reverseTable = new Uint32Array(bufferSize);
7
- var limit = 1;
8
- var bit = bufferSize >> 1;
9
- while (limit < bufferSize) {
10
- for (var i = 0; i < limit; i++) {
11
- reverseTable[i + limit] = reverseTable[i] + bit;
12
- }
13
- limit = limit << 1;
14
- bit = bit >> 1;
15
- }
16
- var sinTable = new Float64Array(bufferSize);
17
- var cosTable = new Float64Array(bufferSize);
18
- for (var i = 0; i < bufferSize; i++) {
19
- sinTable[i] = Math.sin(-Math.PI / i);
20
- cosTable[i] = Math.cos(-Math.PI / i);
21
- }
22
- var calculateSpectrum = function () {
23
- var spectrum = new Array(bufferSize / 2);
24
- var bSi = 2 / bufferSize;
25
- for (var i = 0, N = bufferSize / 2; i < N; i++) {
26
- var rval = real[i];
27
- var ival = imag[i];
28
- var mag = bSi * Math.sqrt(rval * rval + ival * ival);
29
- spectrum[i] = mag;
30
- }
31
- return spectrum;
32
- };
33
- return function (buffer) {
34
- var k = Math.floor(Math.log(bufferSize) / Math.LN2);
35
- if (Math.pow(2, k) !== bufferSize) {
36
- throw new Error('Invalid buffer size, must be a power of 2');
37
- }
38
- if (bufferSize !== buffer.length) {
39
- throw new Error("Supplied buffer is not the same size as defined FFT. FFT Size: " + bufferSize + " Buffer Size: " + buffer.length);
40
- }
41
- var halfSize = 1;
42
- for (var i = 0; i < bufferSize; i++) {
43
- real[i] = buffer[reverseTable[i]];
44
- imag[i] = 0;
45
- }
46
- while (halfSize < bufferSize) {
47
- var phaseShiftStepReal = cosTable[halfSize];
48
- var phaseShiftStepImag = sinTable[halfSize];
49
- var currentPhaseShiftReal = 1;
50
- var currentPhaseShiftImag = 0;
51
- for (var fftStep = 0; fftStep < halfSize; fftStep++) {
52
- var i = fftStep;
53
- while (i < bufferSize) {
54
- var off = i + halfSize;
55
- var tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]);
56
- var ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]);
57
- real[off] = real[i] - tr;
58
- imag[off] = imag[i] - ti;
59
- real[i] += tr;
60
- imag[i] += ti;
61
- i += halfSize << 1;
62
- }
63
- var tmpReal = currentPhaseShiftReal;
64
- currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag);
65
- currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal);
66
- }
67
- halfSize = halfSize << 1;
68
- }
69
- return calculateSpectrum();
70
- };
71
- };
72
- //# sourceMappingURL=spectrum.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"spectrum.js","sourceRoot":"","sources":["../src/spectrum.ts"],"names":[],"mappings":"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"}
package/src/spectrum.ts DELETED
@@ -1,91 +0,0 @@
1
- export const createSpectrumAnalyzer = (bufferSize: number) => {
2
- const real = new Float64Array(bufferSize);
3
- const imag = new Float64Array(bufferSize);
4
- const reverseTable = new Uint32Array(bufferSize);
5
-
6
- let limit = 1;
7
- let bit = bufferSize >> 1;
8
-
9
- while (limit < bufferSize) {
10
- for (let i = 0; i < limit; i++) {
11
- reverseTable[i + limit] = reverseTable[i] + bit;
12
- }
13
-
14
- limit = limit << 1;
15
- bit = bit >> 1;
16
- }
17
-
18
- const sinTable = new Float64Array(bufferSize);
19
- const cosTable = new Float64Array(bufferSize);
20
-
21
- for (let i = 0; i < bufferSize; i++) {
22
- sinTable[i] = Math.sin(-Math.PI / i);
23
- cosTable[i] = Math.cos(-Math.PI / i);
24
- }
25
-
26
- const calculateSpectrum = () => {
27
- const spectrum: number[] = new Array(bufferSize / 2);
28
- const bSi = 2 / bufferSize;
29
-
30
- for (var i = 0, N = bufferSize / 2; i < N; i++) {
31
- const rval = real[i];
32
- const ival = imag[i];
33
- const mag = bSi * Math.sqrt(rval * rval + ival * ival);
34
-
35
- spectrum[i] = mag;
36
- }
37
-
38
- return spectrum;
39
- }
40
-
41
- return (buffer: number[]) => {
42
- const k = Math.floor(Math.log(bufferSize) / Math.LN2);
43
-
44
- if (Math.pow(2, k) !== bufferSize) {
45
- throw new Error('Invalid buffer size, must be a power of 2');
46
- }
47
- if (bufferSize !== buffer.length) {
48
- throw new Error(`Supplied buffer is not the same size as defined FFT. FFT Size: ${bufferSize} Buffer Size: ${buffer.length}`);
49
- }
50
-
51
- let halfSize = 1;
52
-
53
- for (let i = 0; i < bufferSize; i++) {
54
- real[i] = buffer[reverseTable[i]];
55
- imag[i] = 0;
56
- }
57
-
58
- while (halfSize < bufferSize) {
59
- const phaseShiftStepReal = cosTable[halfSize];
60
- const phaseShiftStepImag = sinTable[halfSize];
61
-
62
- let currentPhaseShiftReal = 1;
63
- let currentPhaseShiftImag = 0;
64
-
65
- for (var fftStep = 0; fftStep < halfSize; fftStep++) {
66
- let i = fftStep;
67
-
68
- while (i < bufferSize) {
69
- const off = i + halfSize;
70
- const tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]);
71
- const ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]);
72
-
73
- real[off] = real[i] - tr;
74
- imag[off] = imag[i] - ti;
75
- real[i] += tr;
76
- imag[i] += ti;
77
-
78
- i += halfSize << 1;
79
- }
80
-
81
- const tmpReal = currentPhaseShiftReal;
82
- currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag);
83
- currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal);
84
- }
85
-
86
- halfSize = halfSize << 1;
87
- }
88
-
89
- return calculateSpectrum();
90
- };
91
- };