Skip to content

Commit

Permalink
WaveEffect
Browse files Browse the repository at this point in the history
  • Loading branch information
greggman committed Apr 27, 2024
1 parent e4716c9 commit e2d48bd
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 34 deletions.
4 changes: 2 additions & 2 deletions editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ 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';
//import WaveEffect from './visualizers/effects/WaveEffect.js';
import WaveEffect from './visualizers/effects/WaveEffect.js';

import songList from './songList.js';

Expand Down Expand Up @@ -254,7 +254,7 @@ async function main() {
const effects = [
new DataEffect(gl),
// ...(showSample ? [new SampleEffect(gl)] : []),
//new WaveEffect(gl),
new WaveEffect(gl),
new FFTEffect(gl),
];
g_visualizers = [
Expand Down
2 changes: 1 addition & 1 deletion editor/visualizers/effects/DataEffect.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export default class DataEffect {
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));
dataP.push(byteBeat.getSamplesForTimeRange(start, start + kChunkSize, kChunkSize, this.dataContext, this.dataStack, channel));
}
const data = await Promise.all(dataP);
const chunkId = start / kChunkSize;
Expand Down
65 changes: 42 additions & 23 deletions editor/visualizers/effects/WaveEffect.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as twgl from '../../../js/twgl-full.module.js';
import ByteBeatNode from '../../../src/ByteBeatNode.js';
import { drawEffect } from './effect-utils.js';

const colorRed = new Float32Array([1, 0, 0, 1]);
Expand Down Expand Up @@ -44,13 +43,11 @@ export default class WaveEffect {
this.position = 0;
}
resize(gl) {
this.beatContext = ByteBeatNode.createContext();
this.beatStack = ByteBeatNode.createStack();

const width = gl.drawingBufferWidth;
const lineHeight = new Float32Array(width);
const column = new Float32Array(width);

this.state = 'init';
this.width = width;
this.position = 0;
this.then = performance.now();
Expand Down Expand Up @@ -80,8 +77,46 @@ export default class WaveEffect {
this.bufferInfoR.numElements = width;
}
}
async #update(gl, byteBeat, elapsedTimeMS) {
if (this.state === 'init') {
this.state = 'initializing';
if (this.beatContext) {
byteBeat.destroyContext(this.beatContext);
byteBeat.destroyStack(this.beatStack);
}
this.beatContext = await byteBeat.createContext();
this.beatStack = await byteBeat.createStack();
this.state = 'running';
}
if (this.state === 'running') {
this.state = 'waiting';
const {bufferInfoL, bufferInfoR, beatContext: context, beatStack: stack} = this;
const numChannels = byteBeat.getNumChannels();
const startTime = this.position;
const endTime = startTime + elapsedTimeMS * 0.001 * byteBeat.getDesiredSampleRate() | 0;
this.position = endTime;
const dataP = [];
for (let channel = 0; channel < numChannels; ++channel) {
dataP.push(byteBeat.getSamplesForTimeRange(
startTime,
endTime,
this.lineHeightL.length,
context,
stack,
channel,
));
}
const data = await Promise.all(dataP);
for (let channel = 0; channel < numChannels; ++channel) {
const bufferInfo = channel ? bufferInfoR : bufferInfoL;
gl.bindBuffer(gl.ARRAY_BUFFER, bufferInfo.attribs.height.buffer);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, data[channel].subarray(0, this.lineHeightL.length));
}
this.state = 'running';
}
}
render(gl, commonUniforms, byteBeat) {
const {uniforms, programInfo, bufferInfoL, bufferInfoR, beatContext: context, beatStack: stack} = this;
const {uniforms, programInfo, bufferInfoL, bufferInfoR} = this;
const numChannels = byteBeat.getNumChannels();

const targetTimeMS = 1000 / (48000 / 4096);
Expand All @@ -90,24 +125,8 @@ export default class WaveEffect {
const run = elapsedTimeMS >= targetTimeMS;
if (run) {
this.then = now;
if (byteBeat.isRunning() ) {
const startTime = this.position;
const endTime = startTime + elapsedTimeMS * 0.001 * byteBeat.getDesiredSampleRate() | 0;
const duration = (endTime - startTime);

this.position = endTime;
for (let channel = 0; channel < numChannels; ++channel) {
const bufferInfo = channel ? bufferInfoR : bufferInfoL;

const dst = channel ? this.lineHeightR : this.lineHeightL;
for (let i = 0; i < dst.length; ++i) {
const position = startTime + i * duration / dst.length | 0;
dst[i] = byteBeat.getSampleForTime(position, context, stack, channel);
}

gl.bindBuffer(gl.ARRAY_BUFFER, bufferInfo.attribs.height.buffer);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, dst);
}
if (byteBeat.isRunning()) {
this.#update(gl, byteBeat, elapsedTimeMS);
}
}

Expand Down
21 changes: 13 additions & 8 deletions src/ByteBeatNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,13 @@ class BeatWorkletProcessor extends AudioWorkletProcessor {
const transferables = [];
try {
result = this[fn].call(this, ...args);
if (result instanceof Float32Array) {
//transferables.push(result);
if (result && result.length) {
for (let i = 0; i < result.length; ++i) {
const o = result[i];
if (o instanceof Float32Array) {
transferables.push(o);
}
}
}
} catch (e) {
error = e;
Expand Down Expand Up @@ -166,14 +171,14 @@ class BeatWorkletProcessor extends AudioWorkletProcessor {
this.#deregisterObj(id);
}
getSamplesForTimeRange(start, end, step, contextId, stackId, channel = 0) {
getSamplesForTimeRange(start, end, numSamples, contextId, stackId, channel = 0) {
const context = this.idToObj.get(contextId);
const stack = this.idToObj.get(stackId);
const len = Math.ceil((end - start) / step);
const data = new Float32Array(len);
let cursor = 0;
for (let time = start; time < end; time += step) {
data[cursor++] = this.byteBeat.getSampleForTime(time, context, stack, channel);
const data = new Float32Array(numSamples);
const duration = end - start;
for (let i = 0; i < numSamples; ++i) {
const time = start + duration * i / numSamples | 0;
data[i] = this.byteBeat.getSampleForTime(time, context, stack, channel);
}
return data;
}
Expand Down

0 comments on commit e2d48bd

Please sign in to comment.