Skip to content

Commit 030a394

Browse files
committedApr 27, 2024
SampleEffect
1 parent b04b447 commit 030a394

File tree

2 files changed

+64
-6
lines changed

2 files changed

+64
-6
lines changed
 

‎editor/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import NullVisualizer from './visualizers/NullVisualizer.js';
1212

1313
import DataEffect from './visualizers/effects/DataEffect.js';
1414
import FFTEffect from './visualizers/effects/FFTEffect.js';
15-
//import SampleEffect from './visualizers/effects/SampleEffect.js';
15+
// import SampleEffect from './visualizers/effects/SampleEffect.js';
1616
import VSAEffect from './visualizers/effects/VSAEffect.js';
1717
import WaveEffect from './visualizers/effects/WaveEffect.js';
1818

‎editor/visualizers/effects/SampleEffect.js

+63-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import * as twgl from '../../../js/twgl-full.module.js';
2-
import ByteBeatNode from '../../../src/ByteBeatNode.js';
32
import { drawEffect } from './effect-utils.js';
43

4+
const kChunkSize = 1024;
5+
56
export default class SampleEffect {
67
constructor(gl) {
78
this.programInfo = twgl.createProgramInfo(gl, [
@@ -52,9 +53,6 @@ export default class SampleEffect {
5253
gl.LUMINANCE, gl.UNSIGNED_BYTE, this.sampleBuf);
5354
}
5455
resize(gl) {
55-
this.sampleContext = ByteBeatNode.createContext();
56-
this.sampleStack = ByteBeatNode.createStack();
57-
5856
this.sampleWidth = gl.drawingBufferWidth;
5957
const sampleBuf = new Uint8Array(this.sampleWidth);
6058
this.samplePos = 0;
@@ -65,13 +63,73 @@ export default class SampleEffect {
6563
gl.LUMINANCE, gl.UNSIGNED_BYTE, sampleBuf);
6664
this.sampleBuf = sampleBuf;
6765
this.sampleTime = 0;
66+
this.data = new Map();
67+
this.state = 'init';
68+
}
69+
70+
async #getData(byteBeat) {
71+
this.updating = true;
72+
const start = Math.ceil(this.sampleTime / kChunkSize) * kChunkSize;
73+
const numChannels = byteBeat.getNumChannels();
74+
const dataP = [];
75+
for (let channel = 0; channel < numChannels; ++channel) {
76+
dataP.push(byteBeat.getSamplesForTimeRange(start, start + kChunkSize, kChunkSize, this.sampleContext, this.sampleStack, channel));
77+
}
78+
const data = await Promise.all(dataP);
79+
const chunkId = start / kChunkSize;
80+
this.data.set(chunkId, data);
81+
this.updating = false;
82+
}
83+
84+
#update(byteBeat) {
85+
const noData = this.data.length === 0;
86+
const passingHalfWayPoint = (this.oldSampleTime % kChunkSize) < kChunkSize / 2 && (this.sampleTime % kChunkSize) >= kChunkSize / 2;
87+
const passingChunk = (this.oldSampleTime % kChunkSize) >= kChunkSize - 2 && this.sampleTime % kChunkSize === 0;
88+
const oldChunkId = this.oldSampleTime / kChunkSize | 0;
89+
this.oldSampleTime = this.sampleTime;
90+
if (passingChunk) {
91+
this.data.delete(oldChunkId);
92+
}
93+
if (!this.updating && (noData || passingHalfWayPoint)) {
94+
this.#getData(byteBeat);
95+
}
96+
}
97+
98+
async #init(byteBeat) {
99+
if (this.sampleContext) {
100+
byteBeat.destroyContext(this.sampleContext);
101+
byteBeat.destroyStack(this.sampleStack);
102+
}
103+
this.sampleContext = await byteBeat.createContext();
104+
this.sampleStack = await byteBeat.createStack();
105+
await this.#getData(byteBeat);
106+
this.state = 'running';
68107
}
108+
69109
render(gl, commonUniforms, byteBeat) {
70110
const {uniforms, programInfo, bufferInfo} = this;
71111

112+
if (this.state === 'init') {
113+
this.state = 'initializing';
114+
this.#init(byteBeat);
115+
}
116+
if (this.state !== 'running') {
117+
return;
118+
}
119+
this.#update(byteBeat);
120+
72121
gl.bindTexture(gl.TEXTURE_2D, this.sampleTex);
73122
for (let ii = 0; ii < 2; ++ii) {
74-
this.samplePixel[0] = Math.round(byteBeat.getSampleForTime(this.sampleTime++, this.sampleContext, this.sampleStack) * 127) + 127;
123+
const chunkId = this.sampleTime++ / kChunkSize | 0;
124+
const chunk = this.data.get(chunkId);
125+
const ndx = this.sampleTime % kChunkSize;
126+
try {
127+
const ch = chunk[0];
128+
const sample = ch[ndx];
129+
this.samplePixel[0] = Math.round(sample * 127) + 127;
130+
} catch {
131+
//
132+
}
75133
gl.texSubImage2D(gl.TEXTURE_2D, 0, this.samplePos, 0, 1, 1, gl.LUMINANCE, gl.UNSIGNED_BYTE, this.samplePixel);
76134
this.samplePos = (this.samplePos + 1) % this.sampleWidth;
77135
}

0 commit comments

Comments
 (0)