diff --git a/guide/audio_test.html b/guide/audio_test.html new file mode 100644 index 00000000..21ba1596 --- /dev/null +++ b/guide/audio_test.html @@ -0,0 +1,53 @@ + + +
+ +If this works in iOS, then we can assume MediaElementAudioSourceNode is now supported.
+ + + + + \ No newline at end of file diff --git a/guide/js/examples/sound_frequency.js b/guide/js/examples/sound_frequency.js index 432ef164..b8750bac 100644 --- a/guide/js/examples/sound_frequency.js +++ b/guide/js/examples/sound_frequency.js @@ -10,22 +10,31 @@ var files = ["/assets/flute.mp3", "/assets/drum.mp3", "/assets/tambourine.mp3"]; var currFile = 0; var sound; - + // Load next sound file - function nextSound() { - sound = Sound.load( files[currFile] ).analyze(32); - currFile = (currFile + 1) % files.length; + function nextSound( play=true ) { + Sound.load( files[currFile] ).then( (result) => { + sound = result; + sound.analyze(32); + currFile = (currFile + 1) % files.length; + if (play) { + sound.start(); + space.replay(); + } else { + space.playOnce(50); + } + }).catch( e => console.error(e) ); } + nextSound(false); + // Draw play button function playButton() { - if (!sound.playing) { + if (!sound || !sound.playing) { form.fillOnly('rgba(0,0,0,.2)').circle( Circle.fromCenter( space.center, 30 ) ); form.fillOnly('#fff').polygon( Triangle.fromCenter( space.center, 15 ).rotate2D( Const.half_pi, space.center ) ); } } - - nextSound(); // animation space.add({ @@ -49,9 +58,10 @@ }, action: (type, x, y) => { - if (type === "up") { - if (!sound.playing) nextSound(); - sound.toggle(); + if (type === "up" && Geom.withinBound( [x,y], space.center.$subtract( 25 ), space.center.$add( 25 ) )) { + if (!sound || !sound.playing) { + nextSound(); + } } } }); @@ -61,9 +71,9 @@ space.playOnce(200).bindMouse().bindTouch(); // For use in demo page only - if (window.registerDemo) window.registerDemo(demoID, space, null, stopFn); - function stopFn() { - if (sound && sound.playing) sound.stop(); + if (window.registerDemo) window.registerDemo(demoID, space, startFn, null, true); + function startFn() { + if (sound && !sound.playing) space.replay(); } diff --git a/guide/js/examples/sound_time.js b/guide/js/examples/sound_time.js index c5f2d313..6231bf05 100644 --- a/guide/js/examples/sound_time.js +++ b/guide/js/examples/sound_time.js @@ -12,31 +12,38 @@ var sound; // Load next sound file - function nextSound() { - sound = Sound.load( files[currFile] ).analyze(512); - currFile = (currFile + 1) % files.length; + function nextSound( play=true ) { + Sound.load( files[currFile] ).then( (result) => { + sound = result; + sound.analyze(256); + currFile = (currFile + 1) % files.length; + if (play) { + sound.start(); + space.replay(); + } else { + space.playOnce(50); + } + }).catch( e => console.error(e) ); } + nextSound(false); + // Draw play button function playButton() { - if (!sound) return; - if (!sound.playing) { + if (!sound || !sound.playing) { form.fillOnly('rgba(0,0,0,.2)').circle( Circle.fromCenter( space.center, 30 ) ); form.fillOnly('#fff').polygon( Triangle.fromCenter( space.center, 15 ).rotate2D( Const.half_pi, space.center ) ); } } - nextSound(); - // animation space.add({ animate: (time, ftime) => { if (sound && sound.playable) { - // map time domain data to lines drawing two half circles let tdata = sound.timeDomainTo( [Const.two_pi, 1] ).map( (t, i) => { - let ln = Line.fromAngle( [ (i>256 ? space.size.x : 0), space.center.y ], t.x-Const.half_pi, space.size.y/0.9 ); + let ln = Line.fromAngle( [ (i>128 ? space.size.x : 0), space.center.y ], t.x-Const.half_pi, space.size.y/0.9 ); return [ ln.p1, ln.interpolate( t.y ) ] }); @@ -45,14 +52,14 @@ form.stroke( `rgba( ${255-c}, 20, ${c}, .7 )`, 1 ).line( tdata[i] ); } } - playButton(); }, action: (type, x, y) => { - if (type === "up") { - if (!sound.playing) nextSound(); - sound.toggle(); + if (type === "up" && Geom.withinBound( [x,y], space.center.$subtract( 25 ), space.center.$add( 25 ) )) { + if (!sound || !sound.playing) { + nextSound(); + } } } }); @@ -62,10 +69,10 @@ space.playOnce(200).bindMouse().bindTouch(); // For use in demo page only - if (window.registerDemo) window.registerDemo(demoID, space, null, stopFn); - function stopFn() { - if (sound && sound.playing) sound.stop(); + if (window.registerDemo) window.registerDemo(demoID, space, startFn, null, true); + function startFn() { + if (sound && !sound.playing) space.replay(); } - + })(); diff --git a/guide/js/examples/sound_visual.js b/guide/js/examples/sound_visual.js index c2941947..70654001 100644 --- a/guide/js/examples/sound_visual.js +++ b/guide/js/examples/sound_visual.js @@ -7,17 +7,23 @@ var space = new CanvasSpace("#"+demoID).setup({ retina: true, bgcolor: "#e2e6ef", resize: true }); var form = space.getForm(); - var sound = Sound.load( "/assets/spacetravel.mp3" ).analyze(bins); + var sound; var bins = 256; var ctrls, radius; var colors = ["#f06", "#62e", "#fff", "#fe3", "#0c9"]; + Sound.load( "/assets/spacetravel.mp3" ).then( s => { + sound = s; + sound.analyze(bins); + }).catch( e => console.error(e) ); + // Draw play button function playButton() { - form.fillOnly( sound.playing ? "rgba(0,0,0,.2)" : "#f06").rect( [[0,0], [50,50]] ); - if (!sound.playing) { + if (!sound || !sound.playing) { + form.fillOnly("#f06").rect( [[0,0], [50,50]] ); form.fillOnly('#fff').polygon( Triangle.fromCenter( [25,25], 10 ).rotate2D( Const.half_pi, [25,25] ) ); } else { + form.fillOnly("rgba(0,0,0,.2)").rect( [[0,0], [50,50]] ); form.fillOnly("#fff").rect( [[18, 18], [32,32]] ); } } @@ -142,13 +148,7 @@ space.playOnce(200).bindMouse().bindTouch(); // For use in demo page only - if (window.registerDemo) window.registerDemo(demoID, space, null, stopFn); - function stopFn() { - if (sound && sound.playing) { - // shouldStop = true; - // sound.stop(); - } - } + if (window.registerDemo) window.registerDemo(demoID, space); })(); diff --git a/src/Play.ts b/src/Play.ts index e464b97d..d2ef804f 100644 --- a/src/Play.ts +++ b/src/Play.ts @@ -200,10 +200,11 @@ export class Sound { /** * Create a `Sound` by loading from a sound file or an audio element. * @param source either an url string to load a sound file, or an audio element. + * @param crossOrigin whether to support loading cross-origin. Default is "anonymous". * @returns a `Sound` instance * @example `Sound.load( '/path/to/file.mp3' )` */ - static load( source:HTMLMediaElement|string ):Promise