nodejs-audio-visualizer 2.1.4 → 3.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.
- package/README.md +6 -5
- package/dist/audio.d.ts +1 -2
- package/dist/audio.js +40 -30
- package/dist/audio.js.map +1 -1
- package/dist/config.d.ts +5 -5
- package/dist/config.js +11 -11
- package/dist/config.js.map +1 -1
- package/dist/dsp.d.ts +15 -1
- package/dist/dsp.js +58 -7
- package/dist/dsp.js.map +1 -1
- package/dist/image.d.ts +3 -1
- package/dist/image.js +64 -18
- package/dist/image.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +38 -47
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
- package/src/audio.ts +35 -33
- package/src/config.ts +15 -12
- package/src/dsp.ts +76 -7
- package/src/image.ts +76 -20
- package/src/index.ts +18 -8
- package/src/tests/audio.test.ts +5 -14
- package/src/tests/config.test.ts +6 -8
- package/src/tests/dsp.test.ts +3 -4
- package/src/tests/image.test.ts +20 -10
- package/src/tests/index.test.ts +1 -1
- package/src/typings.d.ts +7 -0
- package/dist/spectrum.d.ts +0 -1
- package/dist/spectrum.js +0 -72
- package/dist/spectrum.js.map +0 -1
- package/src/spectrum.ts +0 -91
- package/src/tests/snapshots/frameSnapshotSpectrumDown.json +0 -1
- package/src/tests/snapshots/frameSnapshotSpectrumUp.json +0 -1
- package/src/tests/snapshots/frameSnapshotSpectrumUpOpacity50.json +0 -1
package/src/tests/audio.test.ts
CHANGED
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
skipEvery,
|
|
9
9
|
getPeaks,
|
|
10
10
|
correctPeaks,
|
|
11
|
-
smoothValues,
|
|
12
11
|
createSpectrumsProcessor,
|
|
13
12
|
} from '../audio';
|
|
14
13
|
import { createSandbox } from 'sinon';
|
|
@@ -85,21 +84,13 @@ describe('audio', function () {
|
|
|
85
84
|
expect(result).deep.equal(expected);
|
|
86
85
|
});
|
|
87
86
|
|
|
88
|
-
it('smoothValues', () => {
|
|
89
|
-
const spectrums = [1, 2, 3, 4];
|
|
90
|
-
const prevSpectrums = [2, 4, 6, 3];
|
|
91
|
-
const result = smoothValues(spectrums, prevSpectrums);
|
|
92
|
-
const expected = [1.5, 3, 4.5, 3.5];
|
|
93
|
-
expect(result).deep.equal(expected);
|
|
94
|
-
});
|
|
95
87
|
|
|
96
88
|
it('createSpectrumsProcessor', () => {
|
|
97
|
-
const
|
|
98
|
-
const spectrumsProcessor = createSpectrumsProcessor(busesCount);
|
|
89
|
+
const spectrumsProcessor = createSpectrumsProcessor(44100);
|
|
99
90
|
|
|
100
|
-
const frame0 = spectrumsProcessor(
|
|
101
|
-
expect(frame0).to.have.length(
|
|
102
|
-
const frame1 = spectrumsProcessor(
|
|
103
|
-
expect(frame1).to.have.length(
|
|
91
|
+
const frame0 = spectrumsProcessor(() => ([1, 2, 3, 4]));
|
|
92
|
+
expect(frame0).to.have.length(24);
|
|
93
|
+
const frame1 = spectrumsProcessor(() => ([2, 2, 6, 2]));
|
|
94
|
+
expect(frame1).to.have.length(24);
|
|
104
95
|
});
|
|
105
96
|
});
|
package/src/tests/config.test.ts
CHANGED
|
@@ -79,9 +79,9 @@ describe('config', function() {
|
|
|
79
79
|
);
|
|
80
80
|
|
|
81
81
|
const result2 = getSpectrumWidthAbsolute({
|
|
82
|
-
outVideo: { spectrum: { width:
|
|
82
|
+
outVideo: { spectrum: { width: 600 }}
|
|
83
83
|
} as Config, backgroundImageWidth);
|
|
84
|
-
expect(result2).equal(
|
|
84
|
+
expect(result2).equal(600);
|
|
85
85
|
|
|
86
86
|
const result3 = getSpectrumWidthAbsolute({
|
|
87
87
|
outVideo: { spectrum: { width: '69%' }}
|
|
@@ -117,13 +117,11 @@ describe('config', function() {
|
|
|
117
117
|
});
|
|
118
118
|
|
|
119
119
|
it('getSpectrumHeightAbsolute', function() {
|
|
120
|
-
const backgroundImageHeight =
|
|
120
|
+
const backgroundImageHeight = 720;
|
|
121
121
|
const result1 = getSpectrumHeightAbsolute({
|
|
122
122
|
outVideo: {}
|
|
123
123
|
} as Config, backgroundImageHeight);
|
|
124
|
-
expect(result1).equal(
|
|
125
|
-
backgroundImageHeight * (parseInt(defaults.spectrumHeight) / 100)
|
|
126
|
-
);
|
|
124
|
+
expect(result1).equal(160);
|
|
127
125
|
|
|
128
126
|
const result2 = getSpectrumHeightAbsolute({
|
|
129
127
|
outVideo: { spectrum: { height: 420 }}
|
|
@@ -212,7 +210,7 @@ describe('config', function() {
|
|
|
212
210
|
|
|
213
211
|
it('getSpectrumYAbsolute', function() {
|
|
214
212
|
const spectrumHeight = 125;
|
|
215
|
-
const backgroundImageHeight =
|
|
213
|
+
const backgroundImageHeight = 721;
|
|
216
214
|
const result1 = getSpectrumYAbsolute(
|
|
217
215
|
{
|
|
218
216
|
outVideo: {},
|
|
@@ -221,7 +219,7 @@ describe('config', function() {
|
|
|
221
219
|
backgroundImageHeight
|
|
222
220
|
);
|
|
223
221
|
expect(result1).equal(
|
|
224
|
-
|
|
222
|
+
298
|
|
225
223
|
);
|
|
226
224
|
|
|
227
225
|
const result2 = getSpectrumYAbsolute(
|
package/src/tests/dsp.test.ts
CHANGED
|
@@ -16,10 +16,9 @@ describe('fft', function () {
|
|
|
16
16
|
});
|
|
17
17
|
|
|
18
18
|
it('getSpectrum', function () {
|
|
19
|
-
|
|
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).
|
|
21
|
+
const result = getSpectrum(signal, 44100);
|
|
22
|
+
expect(result).to.have.length(24);
|
|
24
23
|
});
|
|
25
24
|
});
|
package/src/tests/image.test.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
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
|
-
|
|
6
|
+
createVisualizerFrameGenerator,
|
|
8
7
|
parseImage,
|
|
9
8
|
convertToBmp,
|
|
10
9
|
mixValues,
|
|
@@ -12,10 +11,6 @@ import {
|
|
|
12
11
|
} from '../image';
|
|
13
12
|
import { createBpmEncoder } from '../bpmEncoder';
|
|
14
13
|
|
|
15
|
-
import frameSnapshotSpectrumDown from './snapshots/frameSnapshotSpectrumDown.json';
|
|
16
|
-
import frameSnapshotSpectrumUp from './snapshots/frameSnapshotSpectrumUp.json';
|
|
17
|
-
import frameSnapshotSpectrumUpOpacity50 from './snapshots/frameSnapshotSpectrumUpOpacity50.json';
|
|
18
|
-
|
|
19
14
|
describe('image', function () {
|
|
20
15
|
it('mixValues', function () {
|
|
21
16
|
expect(mixValues(420, 0.69, 96)).equal(320);
|
|
@@ -82,11 +77,13 @@ describe('image', function () {
|
|
|
82
77
|
});
|
|
83
78
|
|
|
84
79
|
it('createVisualizerFrame', async function () {
|
|
85
|
-
const
|
|
80
|
+
const expectedImageLength = 6220854;
|
|
81
|
+
const backgroundImagePath = path.resolve('example/media/horses.png');
|
|
86
82
|
const backgroundImageBmpBuffer = await convertToBmp(backgroundImagePath);
|
|
87
83
|
const backgroundImage = parseImage(backgroundImageBmpBuffer);
|
|
88
84
|
const bpmEncoder = createBpmEncoder({ width: backgroundImage.width, height: backgroundImage.height });
|
|
89
85
|
const backgroundImageBuffer = bpmEncoder(backgroundImage.data);
|
|
86
|
+
const createVisualizerFrame = createVisualizerFrameGenerator();
|
|
90
87
|
const frameSpectrumDown = createVisualizerFrame({
|
|
91
88
|
backgroundImageBuffer,
|
|
92
89
|
spectrum: [0.5, 0, 1],
|
|
@@ -98,7 +95,7 @@ describe('image', function () {
|
|
|
98
95
|
opacity: 1,
|
|
99
96
|
});
|
|
100
97
|
const resultSpectrumDown = frameSpectrumDown.data.toJSON().data;
|
|
101
|
-
expect(resultSpectrumDown).
|
|
98
|
+
expect(resultSpectrumDown).to.have.length(expectedImageLength);
|
|
102
99
|
|
|
103
100
|
const frameSpectrumUp = createVisualizerFrame({
|
|
104
101
|
backgroundImageBuffer,
|
|
@@ -111,7 +108,20 @@ describe('image', function () {
|
|
|
111
108
|
opacity: 1,
|
|
112
109
|
});
|
|
113
110
|
const resultSpectrumUp = frameSpectrumUp.data.toJSON().data;
|
|
114
|
-
expect(resultSpectrumUp).
|
|
111
|
+
expect(resultSpectrumUp).to.have.length(expectedImageLength);
|
|
112
|
+
|
|
113
|
+
const frameSpectrumMirror = createVisualizerFrame({
|
|
114
|
+
backgroundImageBuffer,
|
|
115
|
+
spectrum: [0.1, 1, 0],
|
|
116
|
+
size: { width: 25, height: 23 },
|
|
117
|
+
position: { x: 10, y: 5 },
|
|
118
|
+
rotation: 'mirror',
|
|
119
|
+
margin: 4,
|
|
120
|
+
color: { red: 0, green: 123, blue: 69 },
|
|
121
|
+
opacity: 1,
|
|
122
|
+
});
|
|
123
|
+
const resultSpectrumMirror = frameSpectrumMirror.data.toJSON().data;
|
|
124
|
+
expect(resultSpectrumMirror).to.have.length(expectedImageLength);
|
|
115
125
|
|
|
116
126
|
const frameSpectrumUpOpacity50 = createVisualizerFrame({
|
|
117
127
|
backgroundImageBuffer,
|
|
@@ -124,6 +134,6 @@ describe('image', function () {
|
|
|
124
134
|
opacity: 0.5,
|
|
125
135
|
});
|
|
126
136
|
const resultSpectrumUpOpacity50 = frameSpectrumUpOpacity50.data.toJSON().data;
|
|
127
|
-
expect(resultSpectrumUpOpacity50).
|
|
137
|
+
expect(resultSpectrumUpOpacity50).to.have.length(expectedImageLength);
|
|
128
138
|
});
|
|
129
139
|
});
|
package/src/tests/index.test.ts
CHANGED
package/src/typings.d.ts
ADDED
package/dist/spectrum.d.ts
DELETED
|
@@ -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
|
package/dist/spectrum.js.map
DELETED
|
@@ -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
|
-
};
|