nodejs-audio-visualizer 2.1.3 → 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/src/index.ts CHANGED
@@ -3,7 +3,6 @@ import {
3
3
  getBackgroundImagePath,
4
4
  getOutVideoPath,
5
5
  getFPS,
6
- getSpectrumBusesCount,
7
6
  getSpectrumBusMargin,
8
7
  getSpectrumWidthAbsolute,
9
8
  getSpectrumHeightAbsolute,
@@ -15,10 +14,12 @@ import {
15
14
  getFfmpeg_preset,
16
15
  getFrame_processing_delay,
17
16
  rotationAliasValues,
18
- getSpectrumRotation
17
+ getSpectrumRotation,
18
+ getSpectrumEffect,
19
+ SpectrumEffect,
19
20
  } from './config';
20
21
  import { createAudioBuffer, bufferToUInt8, createSpectrumsProcessor } from './audio';
21
- import { parseImage, createVisualizerFrame, getImageColor, invertColor, Color, convertToBmp } from './image';
22
+ import { parseImage, getImageColor, invertColor, Color, convertToBmp, createVisualizerFrameGenerator } from './image';
22
23
  import { spawnFfmpegVideoWriter, getProgress, calculateProgress, waitDrain } from './video';
23
24
  import { createBpmEncoder } from './bpmEncoder';
24
25
 
@@ -28,6 +29,7 @@ export const PCM_FORMAT = {
28
29
  parseFunction: bufferToUInt8
29
30
  };
30
31
  const FFMPEG_FORMAT = `${PCM_FORMAT.sign}${PCM_FORMAT.bit}`;
32
+ const PROCESSING_BUFFER_SIZE = Math.pow(2, 12);
31
33
 
32
34
  export interface Config {
33
35
  audio: {
@@ -45,6 +47,7 @@ export interface Config {
45
47
  x?: number | PositionAliasName;
46
48
  y?: number | PositionAliasName;
47
49
  rotation?: RotationAliasName;
50
+ effect?: SpectrumEffect;
48
51
  color?: Color | string;
49
52
  opacity?: string;
50
53
  }
@@ -86,7 +89,6 @@ export const renderAudioVisualizer = (config: Config, onProgress?: (progress: nu
86
89
  throw new Error('ffmpeg didn\'t show audio sample rate');
87
90
  }
88
91
 
89
- const spectrumBusesCount = getSpectrumBusesCount();
90
92
  const spectrumBusMargin = getSpectrumBusMargin();
91
93
  const FPS = getFPS(config);
92
94
  const spectrumWidth =
@@ -102,6 +104,7 @@ export const renderAudioVisualizer = (config: Config, onProgress?: (progress: nu
102
104
  const spectrumColor =
103
105
  getSpectrumColor(config) ||
104
106
  invertColor(getImageColor(backgroundImage));
107
+ const spectrumEffect = getSpectrumEffect(config);
105
108
  const spectrumOpacity = getSpectrumOpacityParsed(config);
106
109
  const ffmpeg_cfr = getFfmpeg_cfr(config);
107
110
  const ffmpeg_preset = getFfmpeg_preset(config);
@@ -110,6 +113,7 @@ export const renderAudioVisualizer = (config: Config, onProgress?: (progress: nu
110
113
  const audioDuration = audioBuffer.length / sampleRate;
111
114
  const framesCount = Math.trunc(audioDuration * FPS);
112
115
  const audioDataStep = Math.trunc(audioBuffer.length / framesCount);
116
+ const processingBuffer = new Float32Array(PROCESSING_BUFFER_SIZE).fill(0);
113
117
 
114
118
  const ffmpegVideoWriter = spawnFfmpegVideoWriter({
115
119
  audioFilename: audioFilePath,
@@ -123,11 +127,16 @@ export const renderAudioVisualizer = (config: Config, onProgress?: (progress: nu
123
127
 
124
128
  const bpmEncoder = createBpmEncoder({ width: backgroundImage.width, height: backgroundImage.height });
125
129
  const backgroundImageBuffer = bpmEncoder(backgroundImage.data);
126
- const processSpectrum = createSpectrumsProcessor(spectrumBusesCount);
130
+ const skipFramesCount = FPS < 45 ? 1 : 2;
131
+ const processSpectrum = createSpectrumsProcessor(sampleRate, skipFramesCount);
132
+ const createVisualizerFrame = createVisualizerFrameGenerator();
127
133
  for (let i = 0; i < framesCount; i++) {
128
- const audioDataParser = () =>
129
- PCM_FORMAT.parseFunction(audioBuffer, i * audioDataStep, i * audioDataStep + audioDataStep);
130
- const spectrum = processSpectrum(i, audioDataParser);
134
+ const currentFrameData = PCM_FORMAT.parseFunction(audioBuffer, i * audioDataStep, i * audioDataStep + audioDataStep);
135
+ processingBuffer.copyWithin(0, currentFrameData.length);
136
+ processingBuffer.set(currentFrameData, PROCESSING_BUFFER_SIZE - currentFrameData.length);
137
+
138
+ const audioDataParser = () => Array.from(processingBuffer);
139
+ const spectrum = processSpectrum(audioDataParser);
131
140
  const frameImage = createVisualizerFrame({
132
141
  backgroundImageBuffer,
133
142
  spectrum,
@@ -137,6 +146,7 @@ export const renderAudioVisualizer = (config: Config, onProgress?: (progress: nu
137
146
  margin: spectrumBusMargin,
138
147
  color: spectrumColor,
139
148
  opacity: spectrumOpacity,
149
+ spectrumEffect,
140
150
  });
141
151
  const isFrameProcessed = ffmpegVideoWriter.stdin.write(frameImage.data);
142
152
  if (!isFrameProcessed) {
@@ -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 busesCount = 2;
98
- const spectrumsProcessor = createSpectrumsProcessor(busesCount);
89
+ const spectrumsProcessor = createSpectrumsProcessor(44100);
99
90
 
100
- const frame0 = spectrumsProcessor(0, () => ([1, 2, 3, 4]));
101
- expect(frame0).to.have.length(2);
102
- const frame1 = spectrumsProcessor(1, () => ([2, 2, 6, 2]));
103
- expect(frame1).to.have.length(2);
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
  });
@@ -79,9 +79,9 @@ describe('config', function() {
79
79
  );
80
80
 
81
81
  const result2 = getSpectrumWidthAbsolute({
82
- outVideo: { spectrum: { width: 420 }}
82
+ outVideo: { spectrum: { width: 600 }}
83
83
  } as Config, backgroundImageWidth);
84
- expect(result2).equal(420);
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 = 768;
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 = 768;
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
- 0
222
+ 298
225
223
  );
226
224
 
227
225
  const result2 = getSpectrumYAbsolute(
@@ -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,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
- createVisualizerFrame,
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 backgroundImagePath = path.resolve('example/media/background.png');
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).deep.equal(frameSnapshotSpectrumDown);
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).deep.equal(frameSnapshotSpectrumUp);
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).deep.equal(frameSnapshotSpectrumUpOpacity50);
137
+ expect(resultSpectrumUpOpacity50).to.have.length(expectedImageLength);
128
138
  });
129
139
  });
@@ -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
+ }
package/src/video.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Writable } from 'stream';
2
2
  import { spawn } from 'child_process';
3
- import { path as ffmpegPath } from 'ffmpeg-static';
3
+ import ffmpegPath from 'ffmpeg-static';
4
4
 
5
5
  interface FfmpegVideoWriterConfig {
6
6
  audioFilename: string;
@@ -12,6 +12,9 @@ interface FfmpegVideoWriterConfig {
12
12
  }
13
13
 
14
14
  export const spawnFfmpegVideoWriter = (config: FfmpegVideoWriterConfig) => {
15
+ if (!ffmpegPath) {
16
+ throw new Error('ffmpeg path not found');
17
+ }
15
18
  const crf = config.crf || '23';
16
19
  const preset = config.preset || 'medium';
17
20
  const args = [
@@ -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":";;AAAa,QAAA,sBAAsB,GAAG,UAAC,UAAkB;IACvD,IAAM,IAAI,GAAG,IAAI,YAAY,CAAC,UAAU,CAAC,CAAC;IAC1C,IAAM,IAAI,GAAG,IAAI,YAAY,CAAC,UAAU,CAAC,CAAC;IAC1C,IAAM,YAAY,GAAG,IAAI,WAAW,CAAC,UAAU,CAAC,CAAC;IAEjD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,GAAG,GAAG,UAAU,IAAI,CAAC,CAAC;IAE1B,OAAO,KAAK,GAAG,UAAU,EAAE;QACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE;YAC9B,YAAY,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;SACjD;QAED,KAAK,GAAG,KAAK,IAAI,CAAC,CAAC;QACnB,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC;KAChB;IAED,IAAM,QAAQ,GAAG,IAAI,YAAY,CAAC,UAAU,CAAC,CAAC;IAC9C,IAAM,QAAQ,GAAG,IAAI,YAAY,CAAC,UAAU,CAAC,CAAC;IAE9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE;QACnC,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QACrC,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;KACtC;IAED,IAAM,iBAAiB,GAAG;QACxB,IAAM,QAAQ,GAAa,IAAI,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;QACrD,IAAM,GAAG,GAAG,CAAC,GAAG,UAAU,CAAC;QAE3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;YAC9C,IAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACrB,IAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACrB,IAAM,GAAG,GAAG,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;YAEvD,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;SACnB;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAA;IAED,OAAO,UAAC,MAAgB;QACtB,IAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QAEtD,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,UAAU,EAAE;YACjC,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;SAC9D;QACD,IAAI,UAAU,KAAK,MAAM,CAAC,MAAM,EAAE;YAChC,MAAM,IAAI,KAAK,CAAC,oEAAkE,UAAU,sBAAiB,MAAM,CAAC,MAAQ,CAAC,CAAC;SAC/H;QAED,IAAI,QAAQ,GAAG,CAAC,CAAC;QAEjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE;YACnC,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;YAClC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;SACb;QAED,OAAO,QAAQ,GAAG,UAAU,EAAE;YAC5B,IAAM,kBAAkB,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC9C,IAAM,kBAAkB,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAE9C,IAAI,qBAAqB,GAAG,CAAC,CAAC;YAC9B,IAAI,qBAAqB,GAAG,CAAC,CAAC;YAE9B,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,QAAQ,EAAE,OAAO,EAAE,EAAE;gBACnD,IAAI,CAAC,GAAG,OAAO,CAAC;gBAEhB,OAAO,CAAC,GAAG,UAAU,EAAE;oBACrB,IAAM,GAAG,GAAG,CAAC,GAAG,QAAQ,CAAC;oBACzB,IAAM,EAAE,GAAG,CAAC,qBAAqB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,qBAAqB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;oBACrF,IAAM,EAAE,GAAG,CAAC,qBAAqB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,qBAAqB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;oBAErF,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;oBACzB,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;oBACzB,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;oBACd,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;oBAEd,CAAC,IAAI,QAAQ,IAAI,CAAC,CAAC;iBACpB;gBAED,IAAM,OAAO,GAAG,qBAAqB,CAAC;gBACtC,qBAAqB,GAAG,CAAC,OAAO,GAAG,kBAAkB,CAAC,GAAG,CAAC,qBAAqB,GAAG,kBAAkB,CAAC,CAAC;gBACtG,qBAAqB,GAAG,CAAC,OAAO,GAAG,kBAAkB,CAAC,GAAG,CAAC,qBAAqB,GAAG,kBAAkB,CAAC,CAAC;aACvG;YAED,QAAQ,GAAG,QAAQ,IAAI,CAAC,CAAC;SAC1B;QAED,OAAO,iBAAiB,EAAE,CAAC;IAC7B,CAAC,CAAC;AACJ,CAAC,CAAC"}
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
- };