Skip to content

Commit bf6655b

Browse files
committed
use utils
1 parent e6eb16f commit bf6655b

File tree

1 file changed

+1
-66
lines changed

1 file changed

+1
-66
lines changed

src/Audiovis.tsx

Lines changed: 1 addition & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { FC, useEffect, useMemo, useRef, useState } from "react";
22
import styles from "./Audiovis.module.css";
33
import { useAudioCtx } from "./AudioCtxCtx";
4-
import FFT from "fft.js";
4+
import { spectrum, spectrumToImage } from "./util";
55

66
export const Audiovis: FC<{ srcObject: Blob }> = ({ srcObject }) => {
77
const url = useMemo(() => URL.createObjectURL(srcObject), [srcObject]);
@@ -91,68 +91,3 @@ const Sonogram: FC<{ audio: AudioBuffer }> = ({ audio }) => {
9191

9292
return <canvas ref={canvas} className={styles.waveform} />;
9393
};
94-
95-
// load the spectrum for an entire audio buffer
96-
function spectrum(
97-
audio: AudioBuffer,
98-
fftSize: 2 | 4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096
99-
): Float32Array {
100-
const fft = new FFT(fftSize);
101-
const data = audio.getChannelData(0);
102-
103-
const chunks = Math.floor(audio.length / fftSize);
104-
const target = new Float32Array(fftSize * chunks);
105-
106-
const sample = new Array(fftSize);
107-
const out = fft.createComplexArray();
108-
109-
for (let i = 0; i < chunks; i++) {
110-
const offset = i * fftSize;
111-
for (let i = 0; i < sample.length; i++) sample[i] = data[i + offset];
112-
fft.realTransform(out, sample);
113-
114-
for (let j = 0; j < fftSize; j++) {
115-
target[i * fftSize + j] = Math.abs(out[j]);
116-
}
117-
}
118-
119-
return target;
120-
}
121-
122-
// Render a spectrum as a visible image to be written to canvas
123-
function spectrumToImage(
124-
spectrum: Float32Array,
125-
fftSize: 2 | 4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096
126-
) {
127-
const chunks = spectrum.length / fftSize;
128-
129-
const image = new ImageData(chunks, fftSize);
130-
131-
const max = spectrum.reduce((a, b) => Math.max(a, b), -Infinity);
132-
133-
for (let i = 0; i < chunks; i++) {
134-
for (let j = 0; j < fftSize; j++) {
135-
const idx = j * chunks + i;
136-
const value = spectrum[i * fftSize + j];
137-
138-
const scaledValue = Math.pow(value / max, 0.3); // Apply a power scale
139-
140-
const [r, g, b, a] = valueToColor(scaledValue);
141-
142-
image.data[idx * 4] = r;
143-
image.data[idx * 4 + 1] = g;
144-
image.data[idx * 4 + 2] = b;
145-
image.data[idx * 4 + 3] = a;
146-
}
147-
}
148-
149-
return image;
150-
}
151-
152-
function valueToColor(value: number) {
153-
const r = value < 0.5 ? 0 : 255 * (value - 0.5) * 2;
154-
const g = value < 0.5 ? 255 * value * 2 : 255 * (1 - value) * 2;
155-
const b = value < 0.5 ? 255 * (1 - value * 2) : 0;
156-
const a = value > 0.2 ? 255 : value * 5 * 255;
157-
return [r, g, b, a];
158-
}

0 commit comments

Comments
 (0)