mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-28 20:40:39 +00:00
Type octave buckets
This commit is contained in:
parent
e623761411
commit
cfab50cb94
2 changed files with 47 additions and 41 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useMemo, useCallback } from "react";
|
||||
import React, { useMemo, useCallback, useState } from "react";
|
||||
|
||||
import * as Actions from "../actionCreators";
|
||||
import * as Selectors from "../selectors";
|
||||
|
|
@ -10,11 +10,33 @@ const PIXEL_DENSITY = 2;
|
|||
const BAR_WIDTH = 3 * PIXEL_DENSITY;
|
||||
const GRADIENT_COLOR_COUNT = 16;
|
||||
const PEAK_COLOR_INDEX = 23;
|
||||
const NUM_BARS = 20;
|
||||
|
||||
type Props = {
|
||||
analyser: AnalyserNode;
|
||||
};
|
||||
|
||||
function octaveBucketsForBufferLength(bufferLength: number): number[] {
|
||||
const octaveBuckets = new Array(NUM_BARS).fill(0);
|
||||
const minHz = 200;
|
||||
const maxHz = 22050;
|
||||
const octaveStep = Math.pow(maxHz / minHz, 1 / NUM_BARS);
|
||||
|
||||
octaveBuckets[0] = 0;
|
||||
octaveBuckets[1] = minHz;
|
||||
for (let i = 2; i < NUM_BARS - 1; i++) {
|
||||
octaveBuckets[i] = octaveBuckets[i - 1] * octaveStep;
|
||||
}
|
||||
octaveBuckets[NUM_BARS - 1] = maxHz;
|
||||
|
||||
for (let i = 0; i < NUM_BARS; i++) {
|
||||
const octaveIdx = Math.floor((octaveBuckets[i] / maxHz) * bufferLength);
|
||||
octaveBuckets[i] = octaveIdx;
|
||||
}
|
||||
|
||||
return octaveBuckets;
|
||||
}
|
||||
|
||||
// Return the average value in a slice of dataArray
|
||||
function sliceAverage(
|
||||
dataArray: Uint8Array,
|
||||
|
|
@ -127,6 +149,13 @@ function Visualizer(props: Props) {
|
|||
}
|
||||
}, [props.analyser.fftSize, props.analyser.frequencyBinCount, style]);
|
||||
|
||||
const dataArray = useMemo(() => {
|
||||
return new Uint8Array(bufferLength);
|
||||
}, [bufferLength]);
|
||||
const octaveBuckets = useMemo(() => {
|
||||
return octaveBucketsForBufferLength(bufferLength);
|
||||
}, [bufferLength]);
|
||||
|
||||
const bgCanvas = useMemo(() => {
|
||||
return preRenderBg(
|
||||
width,
|
||||
|
|
@ -170,7 +199,7 @@ function Visualizer(props: Props) {
|
|||
);
|
||||
|
||||
const paintOscilloscopeFrame = useCallback(
|
||||
(canvasCtx: CanvasRenderingContext2D, dataArray: Uint8Array) => {
|
||||
(canvasCtx: CanvasRenderingContext2D) => {
|
||||
props.analyser.getByteTimeDomainData(dataArray);
|
||||
|
||||
canvasCtx.lineWidth = PIXEL_DENSITY;
|
||||
|
|
@ -208,7 +237,15 @@ function Visualizer(props: Props) {
|
|||
}
|
||||
canvasCtx.stroke();
|
||||
},
|
||||
[bufferLength, colors, height, props.analyser, renderWidth, width]
|
||||
[
|
||||
bufferLength,
|
||||
colors,
|
||||
dataArray,
|
||||
height,
|
||||
props.analyser,
|
||||
renderWidth,
|
||||
width,
|
||||
]
|
||||
);
|
||||
|
||||
const innerProps = {
|
||||
|
|
@ -225,6 +262,8 @@ function Visualizer(props: Props) {
|
|||
printBar,
|
||||
paintOscilloscopeFrame,
|
||||
bufferLength,
|
||||
dataArray,
|
||||
octaveBuckets,
|
||||
};
|
||||
return <VisualizerInner {...innerProps} {...props} />;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,28 +6,6 @@ const PIXEL_DENSITY = 2;
|
|||
const NUM_BARS = 20;
|
||||
const BAR_WIDTH = 3 * PIXEL_DENSITY;
|
||||
const BAR_PEAK_DROP_RATE = 0.01;
|
||||
|
||||
function octaveBucketsForBufferLength(bufferLength) {
|
||||
const octaveBuckets = new Array(NUM_BARS).fill(0);
|
||||
const minHz = 200;
|
||||
const maxHz = 22050;
|
||||
const octaveStep = Math.pow(maxHz / minHz, 1 / NUM_BARS);
|
||||
|
||||
octaveBuckets[0] = 0;
|
||||
octaveBuckets[1] = minHz;
|
||||
for (let i = 2; i < NUM_BARS - 1; i++) {
|
||||
octaveBuckets[i] = octaveBuckets[i - 1] * octaveStep;
|
||||
}
|
||||
octaveBuckets[NUM_BARS - 1] = maxHz;
|
||||
|
||||
for (let i = 0; i < NUM_BARS; i++) {
|
||||
const octaveIdx = Math.floor((octaveBuckets[i] / maxHz) * bufferLength);
|
||||
octaveBuckets[i] = octaveIdx;
|
||||
}
|
||||
|
||||
return octaveBuckets;
|
||||
}
|
||||
|
||||
class VisualizerInner extends React.Component {
|
||||
componentDidMount() {
|
||||
this.barPeaks = new Array(NUM_BARS).fill(0);
|
||||
|
|
@ -88,24 +66,13 @@ class VisualizerInner extends React.Component {
|
|||
// TODO: Split this into to methods. One for skin update, one for style
|
||||
// update.
|
||||
this.props.analyser.fftSize = 2048;
|
||||
if (this.props.style === VISUALIZERS.OSCILLOSCOPE) {
|
||||
this.dataArray = new Uint8Array(this.props.bufferLength);
|
||||
} else if (this.props.style === VISUALIZERS.BAR) {
|
||||
this.dataArray = new Uint8Array(this.props.bufferLength);
|
||||
|
||||
if (!this.octaveBuckets) {
|
||||
this.octaveBuckets = octaveBucketsForBufferLength(
|
||||
this.props.bufferLength
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
paintFrame() {
|
||||
switch (this.props.style) {
|
||||
case VISUALIZERS.OSCILLOSCOPE:
|
||||
this.canvasCtx.drawImage(this.props.bgCanvas, 0, 0);
|
||||
this.props.paintOscilloscopeFrame(this.canvasCtx, this.dataArray);
|
||||
this.props.paintOscilloscopeFrame(this.canvasCtx);
|
||||
break;
|
||||
case VISUALIZERS.BAR:
|
||||
this.canvasCtx.drawImage(this.props.bgCanvas, 0, 0);
|
||||
|
|
@ -117,15 +84,15 @@ class VisualizerInner extends React.Component {
|
|||
}
|
||||
|
||||
_paintBarFrame() {
|
||||
this.props.analyser.getByteFrequencyData(this.dataArray);
|
||||
this.props.analyser.getByteFrequencyData(this.props.dataArray);
|
||||
const heightMultiplier = this._renderHeight() / 256;
|
||||
const xOffset = BAR_WIDTH + PIXEL_DENSITY; // Bar width, plus a pixel of spacing to the right.
|
||||
for (let j = 0; j < NUM_BARS - 1; j++) {
|
||||
const start = this.octaveBuckets[j];
|
||||
const end = this.octaveBuckets[j + 1];
|
||||
const start = this.props.octaveBuckets[j];
|
||||
const end = this.props.octaveBuckets[j + 1];
|
||||
let amplitude = 0;
|
||||
for (let k = start; k < end; k++) {
|
||||
amplitude += this.dataArray[k];
|
||||
amplitude += this.props.dataArray[k];
|
||||
}
|
||||
amplitude /= end - start;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue