File size: 7,399 Bytes
f8b493b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
function _class_call_check(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
        throw new TypeError("Cannot call a class as a function");
    }
}
function _defineProperties(target, props) {
    for(var i = 0; i < props.length; i++){
        var descriptor = props[i];
        descriptor.enumerable = descriptor.enumerable || false;
        descriptor.configurable = true;
        if ("value" in descriptor) descriptor.writable = true;
        Object.defineProperty(target, descriptor.key, descriptor);
    }
}
function _create_class(Constructor, protoProps, staticProps) {
    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
    if (staticProps) _defineProperties(Constructor, staticProps);
    return Constructor;
}
function _instanceof(left, right) {
    if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
        return !!right[Symbol.hasInstance](left);
    } else {
        return left instanceof right;
    }
}
import * as THREE from 'three';
// A class to create and manage a waveform visualizer using Tone.Analyser
export var WaveformVisualizer = /*#__PURE__*/ function() {
    "use strict";
    function WaveformVisualizer(scene, analyser, canvasWidth, canvasHeight) {
        _class_call_check(this, WaveformVisualizer);
        this.scene = scene;
        this.analyser = analyser;
        this.mesh = null;
        this.bufferLength = this.analyser.size;
        this.dataArray = new Float32Array(this.bufferLength);
        this.smoothedDataArray = new Float32Array(this.bufferLength); // For smoothing
        // Visual properties
        this.smoothingFactor = 0.4; // How much to smooth the wave (0.0 - 1.0)
        this.width = canvasWidth * 0.8; // Occupy 80% of the screen width
        this.height = 450; // The vertical amplitude of the wave
        this.yPosition = 0; // The vertical center of the wave
        this.thickness = 30.0; // The thickness of the line mesh
        this.currentColor = new THREE.Color('#7B4394');
        this.targetColor = new THREE.Color('#7B4394');
        this.uniforms = {
            solidColor: {
                value: this.currentColor
            }
        };
        this._createVisualizer();
    }
    _create_class(WaveformVisualizer, [
        {
            key: "_createVisualizer",
            value: function _createVisualizer() {
                var material = new THREE.ShaderMaterial({
                    uniforms: this.uniforms,
                    vertexShader: "\n                varying vec2 vUv;\n                void main() {\n                    vUv = uv;\n                    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n                }\n            ",
                    fragmentShader: "\n                uniform vec3 solidColor;\n                void main() {\n                    gl_FragColor = vec4(solidColor, 0.9);\n                }\n            ",
                    transparent: true,
                    side: THREE.DoubleSide
                });
                var geometry = new THREE.BufferGeometry();
                var positions = new Float32Array(this.bufferLength * 2 * 3);
                var uvs = new Float32Array(this.bufferLength * 2 * 2);
                geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
                geometry.setAttribute('uv', new THREE.BufferAttribute(uvs, 2));
                var indices = [];
                for(var i = 0; i < this.bufferLength - 1; i++){
                    var p1 = i * 2; // top-left
                    var p2 = p1 + 1; // bottom-left
                    var p3 = (i + 1) * 2; // top-right
                    var p4 = p3 + 1; // bottom-right
                    indices.push(p1, p2, p3);
                    indices.push(p2, p4, p3);
                }
                geometry.setIndex(indices);
                this.mesh = new THREE.Mesh(geometry, material);
                this.scene.add(this.mesh);
                this.updatePosition(window.innerWidth, window.innerHeight);
            }
        },
        {
            // Call this from the main animation loop
            key: "update",
            value: function update() {
                if (!this.analyser || !this.mesh) return;
                // Smoothly interpolate the current color towards the target color
                this.currentColor.lerp(this.targetColor, 0.05);
                var newArray = this.analyser.getValue();
                if (_instanceof(newArray, Float32Array)) {
                    this.dataArray.set(newArray);
                }
                var positions = this.mesh.geometry.attributes.position.array;
                var uvs = this.mesh.geometry.attributes.uv.array;
                var startX = -this.width / 2;
                var xStep = this.width / (this.bufferLength - 1);
                var halfThickness = this.thickness / 2;
                for(var i = 0; i < this.bufferLength; i++){
                    // Apply exponential smoothing
                    this.smoothedDataArray[i] = this.smoothingFactor * this.dataArray[i] + (1 - this.smoothingFactor) * this.smoothedDataArray[i];
                    var x = startX + i * xStep;
                    var y = this.yPosition + this.smoothedDataArray[i] * this.height;
                    // Set top and bottom vertices for the ribbon
                    var vertexIndex = i * 2 * 3;
                    positions[vertexIndex] = x;
                    positions[vertexIndex + 1] = y + halfThickness;
                    positions[vertexIndex + 2] = 2;
                    positions[vertexIndex + 3] = x;
                    positions[vertexIndex + 4] = y - halfThickness;
                    positions[vertexIndex + 5] = 2;
                    // Set UVs
                    var uvIndex = i * 2 * 2;
                    uvs[uvIndex] = i / (this.bufferLength - 1); // U coordinate
                    uvs[uvIndex + 1] = 1.0; // V for top vertex
                    uvs[uvIndex + 2] = i / (this.bufferLength - 1); // U coordinate
                    uvs[uvIndex + 3] = 0.0; // V for bottom vertex
                }
                this.mesh.geometry.attributes.position.needsUpdate = true;
                this.mesh.geometry.attributes.uv.needsUpdate = true;
                this.mesh.geometry.computeBoundingSphere();
            }
        },
        {
            key: "updateColor",
            value: function updateColor(newColor) {
                if (this.uniforms) {
                    this.targetColor.set(newColor);
                }
            }
        },
        {
            // Call this on window resize
            key: "updatePosition",
            value: function updatePosition(canvasWidth, canvasHeight) {
                this.width = canvasWidth * 0.8;
                this.yPosition = -canvasHeight / 2 + 250; // Position it higher, above the drum beat indicators
            }
        },
        {
            // Clean up Three.js resources
            key: "dispose",
            value: function dispose() {
                if (this.mesh) {
                    this.scene.remove(this.mesh);
                    if (this.mesh.geometry) this.mesh.geometry.dispose();
                    if (this.mesh.material) this.mesh.material.dispose();
                }
            }
        }
    ]);
    return WaveformVisualizer;
}();