diff --git a/lime/audio/AudioSource.hx b/lime/audio/AudioSource.hx index ebe8cea3d..509e96337 100644 --- a/lime/audio/AudioSource.hx +++ b/lime/audio/AudioSource.hx @@ -11,7 +11,6 @@ import flash.media.SoundChannel; import lime.audio.fmod.Channel; #end - #if lime_console // TODO(james4k): this is terribly hacky. looking for more sane solutions. the // caller uses an extern declaration of this function so that it does not need @@ -24,6 +23,7 @@ void haxe_staticfunc_onFmodChannelEnd (ConsoleFmodChannel c) { ") #end + class AudioSource { @@ -151,53 +151,47 @@ class AudioSource { #if html5 #elseif flash - - if (channel != null) channel.stop (); - var channel = buffer.src.play (pauseTime / 1000); - + + if (channel != null) channel.stop (); + var channel = buffer.src.play (pauseTime / 1000); + #elseif lime_console - - if (channel.valid) { - - channel.resume (); - - } else { - - channel = buffer.src.play (); - channel.setLoopCount (this.__loops); - - var old = setFmodActive (channel, this); - if (old != this) { - old.channel = Channel.INVALID; - } - + + if (channel.valid) { + + channel.resume (); + + } else { + + channel = buffer.src.play (); + channel.setLoopCount (this.__loops); + + var old = setFmodActive (channel, this); + + if (old != this) { + + old.channel = Channel.INVALID; + } - + + } + #else + + if (playing || id == 0) { - if (playing || id == 0) { - - return; - - } - - playing = true; - - var time = currentTime; - - AL.sourcePlay (id); - - currentTime = time; - - if (timer != null) { - - timer.stop (); - - } - - timer = new Timer (length - currentTime); - timer.run = timer_onRun; + return; + } + + playing = true; + + var time = currentTime; + + AL.sourcePlay (id); + + currentTime = time; + #end } @@ -207,33 +201,33 @@ class AudioSource { #if html5 #elseif flash + + if (channel != null) { - if (channel != null) { - - pauseTime = Std.int (channel.position * 1000); - channel.stop (); - - } + pauseTime = Std.int (channel.position * 1000); + channel.stop (); + } + #elseif lime_console - - if (channel.valid) { - - channel.pause (); - - } - + + if (channel.valid) { + + channel.pause (); + + } + #else + + playing = false; + AL.sourcePause (id); + + if (timer != null) { - playing = false; - AL.sourcePause (id); - - if (timer != null) { - - timer.stop (); - - } + timer.stop (); + } + #end } @@ -243,34 +237,121 @@ class AudioSource { #if html5 #elseif flash + + pauseTime = 0; + + if (channel != null) { - pauseTime = 0; - if (channel != null) channel.stop (); + channel.stop (); + } + #elseif lime_console - - if (channel.valid) { - - channel.stop (); - - } - + + if (channel.valid) { + + channel.stop (); + + } + #else + + playing = false; + AL.sourceStop (id); + + if (timer != null) { - playing = false; - AL.sourceStop (id); - - if (timer != null) { - - timer.stop (); - - } + timer.stop (); + } + #end } + #if lime_console + + // TODO(james4k): these arrays become Array so a lot of hidden + // boxing and allocations going on. + + // can't use Maps because we need by-value key comparisons, so use two arrays. + private static var fmodActiveChannels = new Array (); + private static var fmodActiveSources = new Array (); + + + // onFmodChannelEnd is called from C++ when an fmod channel end callback is + // called. + private static function onFmodChannelEnd (channel:Channel) { + + var source = removeFmodActive (channel); + + if (source != null) { + + source.channel = Channel.INVALID; + source.onComplete.dispatch (); + + } + + } + + + // removeFmodActive disassociates a Channel with its AudioSource, returning + // the AudioSource it was associated with. + private static function removeFmodActive(key:Channel):AudioSource { + + for (i in 0...fmodActiveChannels.length) { + + if (fmodActiveChannels[i] == key) { + + var source = fmodActiveSources[i]; + + // swap in the last element and pop() to remove from array + var last = fmodActiveChannels.length - 1; + fmodActiveChannels[i] = fmodActiveChannels[last]; + fmodActiveSources[i] = fmodActiveSources[last]; + + fmodActiveChannels.pop (); + fmodActiveSources.pop (); + + return source; + + } + + } + + return null; + + } + + + // setFmodActive associates a Channel with an AudioSource to allow for fmod + // channel callbacks to propagate to the user's AudioSource onComplete + // callbacks. Returns the previous AudioSource associated with the channel + // if there was one, or the passed in AudioSource if not. + private static function setFmodActive (key:Channel, value:AudioSource):AudioSource { + + for (i in 0...fmodActiveChannels.length) { + + if (fmodActiveChannels[i] == key) { + + var old = fmodActiveSources[i]; + fmodActiveSources[i] = value; + return old; + + } + + } + + fmodActiveChannels.push (key); + fmodActiveSources.push (value); + return value; + + } + + #end + + // Event Handlers @@ -303,84 +384,6 @@ class AudioSource { #end } - - - #if lime_console - - - // TODO(james4k): these arrays become Array so a lot of hidden - // boxing and allocations going on. - - // can't use Maps because we need by-value key comparisons, so use two arrays. - private static var fmodActiveChannels = new Array (); - private static var fmodActiveSources = new Array (); - - - // setFmodActive associates a Channel with an AudioSource to allow for fmod - // channel callbacks to propagate to the user's AudioSource onComplete - // callbacks. Returns the previous AudioSource associated with the channel - // if there was one, or the passed in AudioSource if not. - private static function setFmodActive (key:Channel, value:AudioSource):AudioSource { - - for (i in 0...fmodActiveChannels.length) { - if (fmodActiveChannels[i] == key) { - var old = fmodActiveSources[i]; - fmodActiveSources[i] = value; - return old; - } - } - - fmodActiveChannels.push (key); - fmodActiveSources.push (value); - return value; - - } - - - // removeFmodActive disassociates a Channel with its AudioSource, returning - // the AudioSource it was associated with. - private static function removeFmodActive(key:Channel):AudioSource { - - for (i in 0...fmodActiveChannels.length) { - - if (fmodActiveChannels[i] == key) { - - var source = fmodActiveSources[i]; - - // swap in the last element and pop() to remove from array - var last = fmodActiveChannels.length - 1; - fmodActiveChannels[i] = fmodActiveChannels[last]; - fmodActiveSources[i] = fmodActiveSources[last]; - - fmodActiveChannels.pop (); - fmodActiveSources.pop (); - - return source; - - } - - } - - return null; - - } - - - // onFmodChannelEnd is called from C++ when an fmod channel end callback is - // called. - private static function onFmodChannelEnd (channel:Channel) { - - var source = removeFmodActive (channel); - - if (source != null) { - source.channel = Channel.INVALID; - source.onComplete.dispatch (); - } - - } - - - #end @@ -393,19 +396,19 @@ class AudioSource { private function get_currentTime ():Int { #if html5 - - return 0; - + + return 0; + #elseif flash - - return Std.int (channel.position); - + + return Std.int (channel.position); + #else - - var time = Std.int (AL.getSourcef (id, AL.SEC_OFFSET) * 1000) - offset; - if (time < 0) return 0; - return time; - + + var time = Std.int (AL.getSourcef (id, AL.SEC_OFFSET) * 1000) - offset; + if (time < 0) return 0; + return time; + #end } @@ -414,27 +417,46 @@ class AudioSource { private function set_currentTime (value:Int):Int { #if html5 - - return pauseTime = value; - + + return pauseTime = value; + #elseif flash - - // TODO: create new sound channel - //channel.position = value; - return pauseTime = value; - + + // TODO: create new sound channel + //channel.position = value; + return pauseTime = value; + #else + + if (buffer != null) { - if (buffer != null) { + AL.sourceRewind (id); + if (playing) AL.sourcePlay (id); + AL.sourcef (id, AL.SEC_OFFSET, (value + offset) / 1000); + + } + + if (playing) { + + if (timer != null) { - AL.sourceRewind (id); - if (playing) AL.sourcePlay (id); - AL.sourcef (id, AL.SEC_OFFSET, (value + offset) / 1000); + timer.stop (); } - return value; + var timeRemaining = length - (value + offset); + if (timeRemaining > 0) { + + timer = new Timer (timeRemaining); + timer.run = timer_onRun; + + } + + } + + return value; + #end } @@ -443,17 +465,17 @@ class AudioSource { private function get_gain ():Float { #if html5 - - return 1; - + + return 1; + #elseif flash - - return channel.soundTransform.volume; - + + return channel.soundTransform.volume; + #else - - return AL.getSourcef (id, AL.GAIN); - + + return AL.getSourcef (id, AL.GAIN); + #end } @@ -462,51 +484,25 @@ class AudioSource { private function set_gain (value:Float):Float { #if html5 - - return 1; - + + return 1; + #elseif flash - - var soundTransform = channel.soundTransform; - soundTransform.volume = value; - channel.soundTransform = soundTransform; - return value; - + + var soundTransform = channel.soundTransform; + soundTransform.volume = value; + channel.soundTransform = soundTransform; + return value; + #else - - AL.sourcef (id, AL.GAIN, value); - return value; - + + AL.sourcef (id, AL.GAIN, value); + return value; + #end } - - - private inline function get_loops ():Int { - - #if lime_console - if (channel.valid) { - __loops = channel.getLoopCount (); - } - #end - - return __loops; - - } - - - private inline function set_loops (loops:Int):Int { - - #if lime_console - if (channel.valid) { - channel.setLoopCount (loops); - } - #end - - return __loops = loops; - - } - + private function get_length ():Int { @@ -517,18 +513,18 @@ class AudioSource { } #if html5 - - return 0; - + + return 0; + #elseif flash - - return Std.int (buffer.src.length); - + + return Std.int (buffer.src.length); + #else - - var samples = (buffer.data.length * 8) / (buffer.channels * buffer.bitsPerSample); - return Std.int (samples / buffer.sampleRate * 1000) - offset; - + + var samples = (buffer.data.length * 8) / (buffer.channels * buffer.bitsPerSample); + return Std.int (samples / buffer.sampleRate * 1000) - offset; + #end } @@ -536,9 +532,62 @@ class AudioSource { private function set_length (value:Int):Int { + if (playing && __length != value) { + + if (timer != null) { + + timer.stop (); + + } + + var timeRemaining = value - currentTime; + + if (timeRemaining > 0) { + + timer = new Timer (value - currentTime); + timer.run = timer_onRun; + + } + + } + return __length = value; } + private function get_loops ():Int { + + #if lime_console + + if (channel.valid) { + + __loops = channel.getLoopCount (); + + } + + #end + + return __loops; + + } + + + private function set_loops (loops:Int):Int { + + #if lime_console + + if (channel.valid) { + + channel.setLoopCount (loops); + + } + + #end + + return __loops = loops; + + } + + }