Skip to content

Commit

Permalink
DataEffect
Browse files Browse the repository at this point in the history
  • Loading branch information
greggman committed Apr 27, 2024
1 parent b28f455 commit e4716c9
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 51 deletions.
11 changes: 7 additions & 4 deletions editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import WebGLVisualizer from './visualizers/WebGLVisualizer.js';
import CanvasVisualizer from './visualizers/CanvasVisualizer.js';
import NullVisualizer from './visualizers/NullVisualizer.js';

//import DataEffect from './visualizers/effects/DataEffect.js';
import DataEffect from './visualizers/effects/DataEffect.js';
import FFTEffect from './visualizers/effects/FFTEffect.js';
//import SampleEffect from './visualizers/effects/SampleEffect.js';
import VSAEffect from './visualizers/effects/VSAEffect.js';
Expand Down Expand Up @@ -252,7 +252,7 @@ async function main() {
g_vsaVisualizer = new WebGLVisualizer(gl, [g_vsaEffect]);

const effects = [
//new DataEffect(gl),
new DataEffect(gl),
// ...(showSample ? [new SampleEffect(gl)] : []),
//new WaveEffect(gl),
new FFTEffect(gl),
Expand Down Expand Up @@ -599,7 +599,7 @@ async function setExpressions(expressions, resetToZero) {
setURL();
}

function compile(text, resetToZero) {
async function compile(text, resetToZero) {
const sections = splitBySections(text);
if (sections.default || sections.channel1) {
const expressions = [sections.default?.body || sections.channel1?.body];
Expand All @@ -609,7 +609,10 @@ function compile(text, resetToZero) {
if (resetToZero) {
g_visualizer.reset();
}
setExpressions(expressions, resetToZero);
await setExpressions(expressions, resetToZero);
if (resetToZero) {
g_visualizer.reset();
}
}
if (sections.vsa) {
g_vsaEffect.setURL(sections.vsa.argString);
Expand Down
80 changes: 67 additions & 13 deletions editor/visualizers/effects/DataEffect.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import * as twgl from '../../../js/twgl-full.module.js';
import ByteBeatNode from '../../../src/ByteBeatNode.js';
import { drawEffect } from './effect-utils.js';

const colorBlue = new Float32Array([0, 0, 1, 1]);
const colorGray = new Float32Array([0.25, 0.25, 0.25, 1]);

const kChunkSize = 1024;

export default class DataEffect {
constructor(gl) {
this.programInfo = twgl.createProgramInfo(gl, [
Expand Down Expand Up @@ -52,24 +53,17 @@ export default class DataEffect {
wrap: gl.CLAMP_TO_EDGE,
}),
];
this.dataCursor = 0;
this.data = [];
}
reset(gl) {
this.dataTime = 0;
this.dataPos = 0;
for (let i = 0; i < this.dataWidth; ++i) {
this.dataBuf[i] = 0;
}
for (const tex of this.dataTex) {
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(
gl.TEXTURE_2D, 0, gl.LUMINANCE, this.dataWidth, 1, 0,
gl.LUMINANCE, gl.UNSIGNED_BYTE, this.dataBuf);
}
this.resize(gl);
}
resize(gl) {
this.dataContext = ByteBeatNode.createContext();
this.dataStack = ByteBeatNode.createStack();

async resize(gl) {
this.dataWidth = gl.drawingBufferWidth;
const dataBuf = new Uint8Array(this.dataWidth);
this.dataPos = 0;
Expand All @@ -82,15 +76,74 @@ export default class DataEffect {
}
this.dataBuf = dataBuf;
this.dataTime = 0;
this.oldDataTime = 0;
this.data = new Map();
this.state = 'init';
}

async #getData(byteBeat) {
this.updating = true;
const start = Math.ceil(this.dataTime / kChunkSize) * kChunkSize;
const numChannels = byteBeat.getNumChannels();
const dataP = [];
for (let channel = 0; channel < numChannels; ++channel) {
dataP.push(byteBeat.getSamplesForTimeRange(start, start + kChunkSize, 1, this.dataContext, this.dataStack, channel));
}
const data = await Promise.all(dataP);
const chunkId = start / kChunkSize;
this.data.set(chunkId, data);
this.updating = false;
}

#update(byteBeat) {
const noData = this.data.length === 0;
const passingHalfWayPoint = (this.oldDataTime % kChunkSize) < kChunkSize / 2 && (this.dataTime % kChunkSize) >= kChunkSize / 2;
const passingChunk = (this.oldDataTime % kChunkSize) === kChunkSize - 1 && this.dataTime % kChunkSize === 0;
const oldChunkId = this.oldDataTime / kChunkSize | 0;
this.oldDataTime = this.dataTime;
if (passingChunk) {
this.data.delete(oldChunkId);
}
if (!this.updating && (noData || passingHalfWayPoint)) {
this.#getData(byteBeat);
}
}

async #init(byteBeat) {
if (this.dataContext) {
byteBeat.destroyContext(this.dataContext);
byteBeat.destroyStack(this.dataStack);
}
this.dataContext = await byteBeat.createContext();
this.dataStack = await byteBeat.createStack();
await this.#getData(byteBeat);
this.state = 'running';
}

render(gl, commonUniforms, byteBeat) {
if (this.state === 'init') {
this.state = 'initializing';
this.#init(byteBeat);
}
if (this.state !== 'running') {
return;
}
this.#update(byteBeat);
const numChannels = byteBeat.getNumChannels();

const {uniforms, programInfo, bufferInfo} = this;

const chunkId = this.dataTime / kChunkSize | 0;
const chunk = this.data.get(chunkId);
const ndx = this.dataTime % kChunkSize;
for (let channel = 0; channel < numChannels; ++channel) {
this.dataPixel[0] = Math.round(byteBeat.getSampleForTime(this.dataTime++, this.dataContext, this.dataStack, channel) * 127) + 127;
try {
const ch = chunk[channel];
const sample = ch[ndx];
this.dataPixel[0] = Math.round(sample * 127) + 127;
} catch {
//
}
gl.bindTexture(gl.TEXTURE_2D, this.dataTex[channel]);
gl.texSubImage2D(gl.TEXTURE_2D, 0, this.dataPos, 0, 1, 1, gl.LUMINANCE, gl.UNSIGNED_BYTE, this.dataPixel);
this.dataPos = (this.dataPos + 1) % this.dataWidth;
Expand All @@ -107,5 +160,6 @@ export default class DataEffect {
gl.disable(gl.BLEND);
}
}
++this.dataTime;
}
}
Loading

0 comments on commit e4716c9

Please sign in to comment.