|
|
@@ -35,9 +35,9 @@
|
|
|
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
|
|
|
|
|
|
let camera, scene, renderer;
|
|
|
- let computeNode, computeResetNode;
|
|
|
+ let computeNode;
|
|
|
let waveBuffer, sampleRate;
|
|
|
- let waveArray, originalWaveBuffer;
|
|
|
+ let waveArray;
|
|
|
let currentAudio, currentAnalyser;
|
|
|
const analyserBuffer = new Uint8Array( 1024 );
|
|
|
let analyserTexture;
|
|
|
@@ -49,9 +49,10 @@
|
|
|
|
|
|
if ( currentAudio ) currentAudio.stop();
|
|
|
|
|
|
- await renderer.computeAsync( computeResetNode );
|
|
|
// compute audio
|
|
|
+
|
|
|
await renderer.computeAsync( computeNode );
|
|
|
+
|
|
|
const wave = new Float32Array( await renderer.getArrayBufferAsync( waveArray.value ) );
|
|
|
|
|
|
// play result
|
|
|
@@ -93,18 +94,21 @@
|
|
|
|
|
|
// adding extra silence to delay and pitch
|
|
|
waveBuffer = new Float32Array( [ ...waveBuffer, ...new Float32Array( 200000 ) ] );
|
|
|
- originalWaveBuffer = waveBuffer.slice();
|
|
|
-
|
|
|
+
|
|
|
sampleRate = audioBuffer.sampleRate / audioBuffer.numberOfChannels;
|
|
|
|
|
|
// create webgpu buffers
|
|
|
|
|
|
waveArray = instancedArray( waveBuffer );
|
|
|
- const originalWave = instancedArray( originalWaveBuffer ).toReadOnly();
|
|
|
+
|
|
|
+ // read-only buffer
|
|
|
+
|
|
|
+ const originalWave = instancedArray( waveBuffer ).toReadOnly();
|
|
|
|
|
|
// The Pixel Buffer Object (PBO) is required to get the GPU computed data to the CPU in the WebGL2 fallback.
|
|
|
// As used in `renderer.getArrayBufferAsync( waveArray.value )`.
|
|
|
|
|
|
+ originalWave.setPBO( true );
|
|
|
waveArray.setPBO( true );
|
|
|
|
|
|
// params
|
|
|
@@ -114,9 +118,9 @@
|
|
|
const delayOffset = uniform( .55 );
|
|
|
|
|
|
|
|
|
- // compute
|
|
|
+ // compute (shader-node)
|
|
|
|
|
|
- computeNode = Fn( () => {
|
|
|
+ const computeShaderFn = Fn( () => {
|
|
|
|
|
|
const index = float( instanceIndex );
|
|
|
|
|
|
@@ -124,14 +128,14 @@
|
|
|
|
|
|
const time = index.mul( pitch );
|
|
|
|
|
|
- let wave = waveArray.element( time );
|
|
|
+ let wave = originalWave.element( time );
|
|
|
|
|
|
|
|
|
// delay
|
|
|
|
|
|
for ( let i = 1; i < 7; i ++ ) {
|
|
|
|
|
|
- const waveOffset = waveArray.element( index.sub( delayOffset.mul( sampleRate ).mul( i ) ).mul( pitch ) );
|
|
|
+ const waveOffset = originalWave.element( index.sub( delayOffset.mul( sampleRate ).mul( i ) ).mul( pitch ) );
|
|
|
const waveOffsetVolume = waveOffset.mul( delayVolume.div( i * i ) );
|
|
|
|
|
|
wave = wave.add( waveOffsetVolume );
|
|
|
@@ -145,14 +149,12 @@
|
|
|
|
|
|
waveStorageElementNode.assign( wave );
|
|
|
|
|
|
- } )().compute( waveBuffer.length );
|
|
|
+ } );
|
|
|
|
|
|
- computeResetNode = Fn( () => {
|
|
|
|
|
|
- waveArray.element( instanceIndex ).assign( originalWave.element( instanceIndex ) );
|
|
|
-
|
|
|
- } )().compute( waveBuffer.length );
|
|
|
+ // compute
|
|
|
|
|
|
+ computeNode = computeShaderFn().compute( waveBuffer.length );
|
|
|
|
|
|
|
|
|
// gui
|
|
|
@@ -194,12 +196,10 @@
|
|
|
container.appendChild( renderer.domElement );
|
|
|
|
|
|
window.addEventListener( 'resize', onWindowResize );
|
|
|
+ document.addEventListener( 'click', playAudioBuffer );
|
|
|
|
|
|
playAudioBuffer();
|
|
|
|
|
|
- // on click replay
|
|
|
- renderer.domElement.addEventListener( 'click', playAudioBuffer );
|
|
|
-
|
|
|
}
|
|
|
|
|
|
function onWindowResize() {
|