Skip to content

Commit

Permalink
use utils
Browse files Browse the repository at this point in the history
  • Loading branch information
benfoxall committed Nov 30, 2024
1 parent e6eb16f commit bf6655b
Showing 1 changed file with 1 addition and 66 deletions.
67 changes: 1 addition & 66 deletions src/Audiovis.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FC, useEffect, useMemo, useRef, useState } from "react";
import styles from "./Audiovis.module.css";
import { useAudioCtx } from "./AudioCtxCtx";
import FFT from "fft.js";
import { spectrum, spectrumToImage } from "./util";

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

return <canvas ref={canvas} className={styles.waveform} />;
};

// load the spectrum for an entire audio buffer
function spectrum(
audio: AudioBuffer,
fftSize: 2 | 4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096
): Float32Array {
const fft = new FFT(fftSize);
const data = audio.getChannelData(0);

const chunks = Math.floor(audio.length / fftSize);
const target = new Float32Array(fftSize * chunks);

const sample = new Array(fftSize);
const out = fft.createComplexArray();

for (let i = 0; i < chunks; i++) {
const offset = i * fftSize;
for (let i = 0; i < sample.length; i++) sample[i] = data[i + offset];
fft.realTransform(out, sample);

for (let j = 0; j < fftSize; j++) {
target[i * fftSize + j] = Math.abs(out[j]);
}
}

return target;
}

// Render a spectrum as a visible image to be written to canvas
function spectrumToImage(
spectrum: Float32Array,
fftSize: 2 | 4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096
) {
const chunks = spectrum.length / fftSize;

const image = new ImageData(chunks, fftSize);

const max = spectrum.reduce((a, b) => Math.max(a, b), -Infinity);

for (let i = 0; i < chunks; i++) {
for (let j = 0; j < fftSize; j++) {
const idx = j * chunks + i;
const value = spectrum[i * fftSize + j];

const scaledValue = Math.pow(value / max, 0.3); // Apply a power scale

const [r, g, b, a] = valueToColor(scaledValue);

image.data[idx * 4] = r;
image.data[idx * 4 + 1] = g;
image.data[idx * 4 + 2] = b;
image.data[idx * 4 + 3] = a;
}
}

return image;
}

function valueToColor(value: number) {
const r = value < 0.5 ? 0 : 255 * (value - 0.5) * 2;
const g = value < 0.5 ? 255 * value * 2 : 255 * (1 - value) * 2;
const b = value < 0.5 ? 255 * (1 - value * 2) : 0;
const a = value > 0.2 ? 255 : value * 5 * 255;
return [r, g, b, a];
}

0 comments on commit bf6655b

Please sign in to comment.