-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwebgl-a440.html
154 lines (126 loc) · 4.46 KB
/
webgl-a440.html
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
<html>
<script>
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var sample_rate = audioCtx.sampleRate; // 44100 hz
var samples_per_frame = 1024;
var inputChannelCount = 1; var outputChannelCount = 1;
var width = samples_per_frame;
var height = 512;
function begin() {
var canvas = document.getElementById("glcanvas");
var gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
var vertex_shader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertex_shader, document.getElementById('vertex-shader').text);
gl.compileShader(vertex_shader);
var success = gl.getShaderParameter(vertex_shader, gl.COMPILE_STATUS);
if (!success) {
console.log(gl.getShaderInfoLog(vertex_shader));
}
var fragment_shader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragment_shader, document.getElementById('fragment-shader').text);
gl.compileShader(fragment_shader);
var success = gl.getShaderParameter(fragment_shader, gl.COMPILE_STATUS);
if (!success) {
console.log(gl.getShaderInfoLog(fragment_shader));
}
var program = gl.createProgram();
gl.attachShader(program, vertex_shader);
gl.attachShader(program, fragment_shader);
gl.linkProgram(program);
var success = gl.getProgramParameter(program, gl.LINK_STATUS);
if (!success) {
console.log(gl.getProgramInfoLog(program));
}
gl.useProgram(program);
var positions = [
0, 0, 1, 1, 0, 1,
0, 0, 1, 1, 1, 0,
];
var positionAttribute = gl.getAttribLocation(program, "position");
var positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
gl.enableVertexAttribArray(positionAttribute);
gl.vertexAttribPointer(positionAttribute, 2, gl.FLOAT, false, 0, 0);
gl.uniform2f(
gl.getUniformLocation(program, "resolution"),
width, height
);
gl.uniform1i(
gl.getUniformLocation(program, "samples_per_frame"),
samples_per_frame
);
gl.uniform1i(
gl.getUniformLocation(program, "sample_rate"),
sample_rate
);
gl.viewport(0, 0, width, height);
var frame_count = -1;
var scriptNode = audioCtx.createScriptProcessor(
samples_per_frame, inputChannelCount, outputChannelCount
);
scriptNode.connect(audioCtx.destination);
scriptNode.onaudioprocess = function (event) {
frame_count += 1;
var channelData = event.outputBuffer.getChannelData(0);
gl.uniform1i(
gl.getUniformLocation(program, "frame_count"),
frame_count
);
gl.drawArrays(gl.TRIANGLES, 0, 6);
var pixels = new Uint8Array(width * height * 4);
gl.readPixels(
0, 0, width, height,
gl.RGBA, gl.UNSIGNED_BYTE,
pixels
);
for(i = 0; i < width; i+=1) {
var column_sum = 0;
for(var c = 0; c < 3; c++) { // RGB
var column_sum_of_color = 0;
for(var y = 0; y < height; y++) {
column_sum_of_color += pixels[((y * width) + i) * 4 + c];
}
column_sum += column_sum_of_color;
}
var column_average = column_sum / (height * 3); // 0..255
var column_intensity = column_average / 255; // 0..1
var audio_sample = (column_intensity * 2) - 1;
channelData[i] = audio_sample;
}
}
}
</script>
<script id="vertex-shader" type="x-shader/x-vertex">
precision highp float;
attribute vec4 position;
uniform vec2 resolution;
varying vec2 coordinates;
void main() {
coordinates = position.xy * resolution;
gl_Position = 2.0 * position - 1.0;
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
precision highp float;
varying vec2 coordinates;
uniform vec2 resolution;
uniform int samples_per_frame;
uniform int sample_rate;
uniform int frame_count;
void main() {
float pi = acos(-1.);
float t = (float(frame_count * samples_per_frame) + coordinates.x)
/ float(sample_rate);
float value = sin(t * 2. * pi * 440.); // -1..1
float color = 0.; // black
if(coordinates.y < value * 150. + resolution.y/2.) {
color = 1.; // white
}
gl_FragColor.rgba = vec4(color, color, color, 1.);
}
</script>
<body onload="begin()" style="margin: 0px; padding: 0px">
<canvas id="glcanvas" width="1024" height="512" style="border:0px; margin: 0px; padding: 0px"></canvas>
</body>
</html>