22
22
.error-message { color : # a94442 ; border : none; box-shadow : none }
23
23
.CodeMirror { font-family : 'Courier' , monospace; border : solid 1px # ddd ; height : 800px }
24
24
# app { margin-top : 15px }
25
+ # canvas { background : # 2c3e50 ; width : 100% ; height : 160px }
25
26
</ style >
26
27
</ head >
27
28
< body >
@@ -34,42 +35,50 @@ <h1>web-audio-engine :: demo</h1>
34
35
</ div >
35
36
< div id ="app " class ="form-horizontal ">
36
37
< div class ="form-group ">
37
- < label class ="col-sm-1 control-label "> </ label >
38
- < div class ="col-sm-4 ">
39
- < button class ="btn " v-bind:class ="isPlaying ? 'btn-success' : 'btn-default' " v-on:click ="run "> Run</ button >
40
- < button class ="btn btn-default " v-on:click ="stop "> Stop</ button >
41
- </ div >
42
- < div class ="col-sm-6 "> < div class ="form-control error-message "> {{ error }}</ div > </ div >
43
- </ div >
38
+ < div class ="col-sm-7 " class ="form-group ">
39
+ < div class ="form-group ">
40
+ < label class ="col-sm-2 control-label "> </ label >
41
+ < div class ="col-sm-10 ">
42
+ < button class ="btn " v-bind:class ="isPlaying ? 'btn-success' : 'btn-default' " v-on:click ="run "> Run</ button >
43
+ < button class ="btn btn-default " v-on:click ="stop "> Stop</ button >
44
+ </ div >
45
+ </ div >
44
46
45
- < div class ="form-group ">
46
- < label class ="col-sm-1 control-label "> api</ label >
47
- < div class ="col-sm-11 ">
48
- < div class ="radio-inline ">
49
- < input type ="radio " id ="engine " value ="web-audio-engine " v-model ="engine ">
50
- < label for ="engine "> web-audio-engine</ label >
47
+ < div class ="form-group ">
48
+ < label class ="col-sm-2 control-label "> api</ label >
49
+ < div class ="col-sm-10 ">
50
+ < div class ="radio ">
51
+ < label for ="engine ">
52
+ < input type ="radio " id ="engine " value ="web-audio-engine " v-model ="engine ">
53
+ web-audio-engine
54
+ </ label >
55
+ </ div >
56
+ < div class ="radio ">
57
+ < label for ="native ">
58
+ < input type ="radio " id ="native " value ="native " v-model ="engine ">
59
+ native Web Audio API
60
+ </ label >
61
+ </ div >
62
+ </ div >
51
63
</ div >
52
- < div class ="radio-inline ">
53
- < input type ="radio " id ="native " value ="native " v-model ="engine ">
54
- < label for ="native "> native Web Audio API</ label >
64
+
65
+ < div class ="form-group ">
66
+ < label class ="col-sm-2 control-label "> demo</ label >
67
+ < div class ="col-sm-10 ">
68
+ < select class ="form-control " v-model ="selected " v-on:change ="loadScript ">
69
+ < option v-for ="name in list " v-bind:value ="name "> {{ name }}</ option >
70
+ </ select >
71
+ </ div >
55
72
</ div >
56
- </ div >
57
- </ div >
58
73
59
- < div class ="form-group ">
60
- < label class ="col-sm-1 control-label "> demo</ label >
61
- < div class ="col-sm-11 ">
62
- < select class ="form-control " v-model ="selected " v-on:change ="loadScript ">
63
- < option v-for ="name in list " v-bind:value ="name "> {{ name }}</ option >
64
- </ select >
74
+ </ div >
75
+ < div class ="col-sm-5 ">
76
+ < canvas id ="canvas "> </ canvas >
65
77
</ div >
66
78
</ div >
67
79
68
80
< div class ="form-group ">
69
- < label class ="col-sm-1 control-label "> code</ label >
70
- < div class ="col-sm-11 ">
71
- < textarea id ="code "> </ textarea >
72
- </ div >
81
+ < textarea id ="code "> </ textarea >
73
82
</ div >
74
83
</ div >
75
84
</ div >
@@ -95,6 +104,13 @@ <h1>web-audio-engine :: demo</h1>
95
104
] ;
96
105
var audioContext = new AudioContext ( ) ;
97
106
var destination = audioContext . destination ;
107
+ var timerId = 0 ;
108
+ var canvas = document . getElementById ( "canvas" ) ;
109
+
110
+ canvas . width = 320 ;
111
+ canvas . height = 160 ;
112
+
113
+ canvas . context = canvas . getContext ( "2d" ) ;
98
114
99
115
Object . defineProperty ( audioContext , "destination" , {
100
116
value : null , enumerate : false , writable : true , configurable : true
@@ -149,8 +165,11 @@ <h1>web-audio-engine :: demo</h1>
149
165
return ;
150
166
}
151
167
152
- audioContext . destination = audioContext . createGain ( ) ;
168
+ var audioAnalyser = audioContext . createAnalyser ( ) ;
169
+
170
+ audioContext . destination = audioAnalyser ;
153
171
audioContext . destination . connect ( destination ) ;
172
+ canvas . audioAnalyser = audioAnalyser ;
154
173
155
174
var context = null ;
156
175
@@ -173,18 +192,77 @@ <h1>web-audio-engine :: demo</h1>
173
192
}
174
193
175
194
promise . then ( function ( ) {
195
+ if ( timerId === 0 ) {
196
+ timerId = timerAPI . setInterval . call ( window , capture , 100 ) ;
197
+ }
176
198
context . resume ( ) ;
177
199
} ) ;
178
200
}
179
201
180
202
function stop ( ) {
203
+ if ( timerId !== 0 ) {
204
+ clearInterval ( timerId ) ;
205
+ timerId = 0 ;
206
+ }
181
207
if ( audioContext . destination ) {
182
208
audioContext . destination . disconnect ( ) ;
183
209
audioContext . destination = null ;
184
210
}
185
211
timerAPI . reset ( ) ;
186
212
}
187
213
214
+ function capture ( ) {
215
+ var analyser = canvas . audioAnalyser ;
216
+ var context = canvas . context ;
217
+ var fft , sig ;
218
+ var width = canvas . width ;
219
+ var height = canvas . height ;
220
+ var i , imax ;
221
+
222
+ // fft
223
+ analyser . fftSize = 64 ;
224
+ fft = new Uint8Array ( analyser . frequencyBinCount ) ;
225
+ analyser . getByteFrequencyData ( fft ) ;
226
+
227
+ context . fillStyle = "#2c3e50" ;
228
+ context . fillRect ( 0 , 0 , width , height ) ;
229
+
230
+ var w = width / fft . length ;
231
+
232
+ for ( i = 0 , imax = fft . length ; i < imax ; i ++ ) {
233
+ var x = w * i ;
234
+ var y = linlin ( fft [ i ] , 0 , 255 , height , 0 ) ;
235
+ var r = linlin ( fft [ i ] , 0 , 255 , 100 , 255 ) | 0 ;
236
+
237
+ context . fillStyle = "rgb(" + r + ", 76, 60)" ;
238
+ context . fillRect ( x , y , w - 1 , height - y ) ;
239
+ }
240
+
241
+ // signal
242
+ analyser . fftSize = 2048 ;
243
+ sig = new Uint8Array ( analyser . fftSize ) ;
244
+ analyser . getByteTimeDomainData ( sig ) ;
245
+
246
+ context . strokeStyle = "#2ecc71" ;
247
+ context . beginPath ( ) ;
248
+
249
+ for ( i = 0 , imax = sig . length ; i < imax ; i ++ ) {
250
+ var x = linlin ( i , 0 , imax , 0 , width ) ;
251
+ var y = linlin ( sig [ i ] , 0 , 255 , height , 0 ) ;
252
+
253
+ if ( i === 0 ) {
254
+ context . moveTo ( x , y ) ;
255
+ } else {
256
+ context . lineTo ( x , y ) ;
257
+ }
258
+ }
259
+ context . stroke ( ) ;
260
+ }
261
+
262
+ function linlin ( value , inMin , inMax , outMin , outMax ) {
263
+ return ( value - inMin ) / ( inMax - inMin ) * ( outMax - outMin ) + outMin ;
264
+ }
265
+
188
266
var vue = new Vue ( {
189
267
el : "#app" ,
190
268
data : {
0 commit comments