Fix FlxSound not completing correctly, & callbacks
This commit is contained in:
@@ -296,8 +296,9 @@ class FlxSound extends FlxBasic {
|
||||
active = false;
|
||||
_lastTime = null;
|
||||
|
||||
if (_channel != null) {
|
||||
_channel.removeEventListener(Event.SOUND_COMPLETE, stopped);
|
||||
if (_source != null) {
|
||||
_source.onComplete.remove(stopped);
|
||||
_source.onLoop.remove(source_looped);
|
||||
}
|
||||
|
||||
if (destroySound) {
|
||||
@@ -496,8 +497,8 @@ class FlxSound extends FlxBasic {
|
||||
_transform.pan = 0;
|
||||
_length = _source.length;
|
||||
|
||||
_source.onComplete.add(_channel.source_onComplete);
|
||||
_source.onLoop.add(_channel.source_onLoop);
|
||||
_source.onComplete.add(stopped);
|
||||
_source.onLoop.add(source_looped);
|
||||
_channel.__soundTransform = _transform;
|
||||
_channel.__isValid = true;
|
||||
}
|
||||
@@ -674,7 +675,7 @@ class FlxSound extends FlxBasic {
|
||||
_paused = false;
|
||||
_time = startTime;
|
||||
_lastTime = FlxG.game.getTicks();
|
||||
if (_channel == null || !_channel.__isValid || _source.__backend == null #if lime_openal || _source.__backend.disposed || _source.__backend.handle == null #end)
|
||||
if (_channel == null || !_channel.__isValid || _source.__backend == null #if lime_cffi || _source.__backend.disposed || _source.__backend.handle == null #end)
|
||||
makeChannel();
|
||||
|
||||
if (_channel != null) {
|
||||
@@ -687,12 +688,11 @@ class FlxSound extends FlxBasic {
|
||||
_channel.__lastPeakTime = -10;
|
||||
_channel.__leftPeak = 0;
|
||||
_channel.__rightPeak = 0;
|
||||
_channel.addEventListener(Event.SOUND_COMPLETE, stopped);
|
||||
|
||||
#if lime_openal _source.__backend.playing = true; #end
|
||||
#if lime_cffi _source.__backend.playing = true; #end
|
||||
_source.offset = 0;
|
||||
_source.currentTime = startTime + _offset;
|
||||
#if !lime_openal _source.play(); #end
|
||||
#if !lime_cffi _source.play(); #end
|
||||
|
||||
looped = looped;
|
||||
loopTime = loopTime;
|
||||
@@ -706,7 +706,7 @@ class FlxSound extends FlxBasic {
|
||||
}
|
||||
}
|
||||
|
||||
function stopped(?_) {
|
||||
function stopped() {
|
||||
onFinish.dispatch();
|
||||
|
||||
if (onComplete != null) onComplete();
|
||||
@@ -718,6 +718,17 @@ class FlxSound extends FlxBasic {
|
||||
else cleanup(autoDestroy);
|
||||
}
|
||||
|
||||
function source_looped() {
|
||||
if (onComplete != null) onComplete();
|
||||
|
||||
if (!looped) {
|
||||
cleanup(autoDestroy);
|
||||
_lastTime = FlxG.game.getTicks();
|
||||
_time = loopTime;
|
||||
}
|
||||
else _channel.loops = 999;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal event handler for ID3 info (i.e. fetching the song name).
|
||||
*/
|
||||
|
||||
@@ -25,7 +25,7 @@ import lime.utils.ArrayBufferView;
|
||||
@:access(lime.media.AudioBuffer)
|
||||
@:access(lime.utils.ArrayBufferView)
|
||||
class NativeAudioSource {
|
||||
private static var STREAM_BUFFER_SIZE:Int = 0x1000;
|
||||
private static var STREAM_BUFFER_SAMPLES:Int = 0x1000;
|
||||
private static var STREAM_MAX_BUFFERS:Int = 32;
|
||||
private static var STREAM_TIMER_FREQUENCY:Int = 100;
|
||||
private static var STREAM_BUFFER_FREQUENCY:Int = 6;
|
||||
@@ -102,13 +102,22 @@ class NativeAudioSource {
|
||||
else if (channels == 2) format = bitsPerSample == 16 ? AL.FORMAT_STEREO16 : AL.FORMAT_STEREO8;
|
||||
else format = bitsPerSample == 16 ? AL.FORMAT_MONO16 : AL.FORMAT_MONO8;
|
||||
|
||||
if (buffer.data != null) {
|
||||
streamed = false;
|
||||
samples = (dataLength = (buffer.data.length >> 0)) / buffer.channels / (buffer.bitsPerSample >> 3);
|
||||
|
||||
if (buffer.__srcBuffer == null && (buffer.__srcBuffer = AL.createBuffer()) != null)
|
||||
AL.bufferData(buffer.__srcBuffer, format, buffer.data, buffer.data.length, buffer.sampleRate);
|
||||
|
||||
AL.sourcei(handle, AL.BUFFER, buffer.__srcBuffer);
|
||||
}
|
||||
#if lime_vorbis
|
||||
if (buffer.__srcVorbisFile != null) {
|
||||
else if (buffer.__srcVorbisFile != null) {
|
||||
streamed = true;
|
||||
dataLength = (samples = getFloat(buffer.__srcVorbisFile.pcmTotal())) * buffer.channels * (buffer.bitsPerSample >> 3);
|
||||
|
||||
var constructor = buffer.bitsPerSample == 32 ? Int32 : buffer.bitsPerSample == 16 ? Int16 : Int8;
|
||||
bufferSize = STREAM_BUFFER_SIZE * buffer.channels * (constructor == Int8 ? buffer.bitsPerSample >> 3 : 1);
|
||||
bufferSize = STREAM_BUFFER_SAMPLES * buffer.channels * (constructor == Int8 ? buffer.bitsPerSample >> 3 : 1);
|
||||
buffers = AL.genBuffers(STREAM_MAX_BUFFERS);
|
||||
bufferDatas = [for (i in 0...STREAM_MAX_BUFFERS) new ArrayBufferView(bufferSize, constructor)];
|
||||
bufferTimes = [for (i in 0...STREAM_MAX_BUFFERS) 0];
|
||||
@@ -116,15 +125,7 @@ class NativeAudioSource {
|
||||
unusedBuffers = [];
|
||||
bufferSize *= constructor == Int8 ? 1 : buffer.bitsPerSample >> 3;
|
||||
}
|
||||
else #end {
|
||||
streamed = false;
|
||||
samples = (dataLength = getFloat(Int64.make(0, buffer.data.length))) / buffer.channels / (buffer.bitsPerSample >> 3);
|
||||
|
||||
if (buffer.__srcBuffer == null && (buffer.__srcBuffer = AL.createBuffer()) != null)
|
||||
AL.bufferData(buffer.__srcBuffer, format, buffer.data, buffer.data.length, buffer.sampleRate);
|
||||
|
||||
AL.sourcei(handle, AL.BUFFER, buffer.__srcBuffer);
|
||||
}
|
||||
#end
|
||||
|
||||
if (dataLength == 0) {
|
||||
trace('NativeAudioSource Bug! dataLength is 0');
|
||||
@@ -188,6 +189,7 @@ class NativeAudioSource {
|
||||
var isBigEndian = lime.system.System.endianness == lime.system.Endian.BIG_ENDIAN, wordSize = parent.buffer.bitsPerSample >> 3;
|
||||
var size = dataLength - (streamTell() * parent.buffer.sampleRate * parent.buffer.channels * wordSize);
|
||||
var n:Int = size < bufferSize ? Math.floor(size) : bufferSize;
|
||||
n -= n % (parent.buffer.channels * wordSize);
|
||||
|
||||
var total = 0, result = 0, wasEOF = false;
|
||||
while (total < bufferSize) {
|
||||
@@ -203,8 +205,8 @@ class NativeAudioSource {
|
||||
|
||||
var samples = getSamples(loopTime != null ? loopTime + parent.offset : parent.offset);
|
||||
streamSeek(samples);
|
||||
if ((size = dataLength - (getFloat(samples) * parent.buffer.channels * wordSize)) < (n = bufferSize - total))
|
||||
n = Math.floor(size);
|
||||
if ((size = dataLength - (getFloat(samples) * parent.buffer.channels * wordSize)) < (n = bufferSize - total)) n = Math.floor(size);
|
||||
n -= n % (parent.buffer.channels * wordSize);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -216,7 +218,7 @@ class NativeAudioSource {
|
||||
|
||||
if (total < bufferSize) data.buffer.fill(total, n, 0);
|
||||
if (result < 0) {
|
||||
trace('NativeAudioSource Streaming Bug! reading result is $result');
|
||||
trace('NativeAudioSource Streaming Bug! reading result is $result, streamEnded: $streamEnded, total: $total, n: $n');
|
||||
return result;
|
||||
}
|
||||
return total;
|
||||
@@ -283,8 +285,10 @@ class NativeAudioSource {
|
||||
}
|
||||
catch(e) trace('NativeAudioSource Bug! in streamRun $e');
|
||||
|
||||
if (AL.getSourcei(handle, AL.SOURCE_STATE) == AL.STOPPED) AL.sourcePlay(handle);
|
||||
if (streamEnded && timer == null) resetTimer((getLength() - getCurrentTime()) / getPitch());
|
||||
if (AL.getSourcei(handle, AL.SOURCE_STATE) == AL.STOPPED) {
|
||||
AL.sourcePlay(handle);
|
||||
resetTimer((getLength() - getCurrentTime()) / getPitch());
|
||||
}
|
||||
}
|
||||
|
||||
// Timers
|
||||
@@ -309,10 +313,8 @@ class NativeAudioSource {
|
||||
}
|
||||
|
||||
private function timer_onRun() {
|
||||
stopTimer();
|
||||
|
||||
var timeRemaining = (getLength() - getCurrentTime()) / getPitch();
|
||||
if (timeRemaining > 30 && AL.getSourcei(handle, AL.SOURCE_STATE) == AL.PLAYING) {
|
||||
if (timeRemaining > 100 && AL.getSourcei(handle, AL.SOURCE_STATE) == AL.PLAYING && (!streamed || !streamEnded)) {
|
||||
resetTimer(timeRemaining);
|
||||
return;
|
||||
}
|
||||
@@ -322,14 +324,16 @@ class NativeAudioSource {
|
||||
return;
|
||||
}
|
||||
|
||||
var start = loopTime != null ? loopTime : 0;
|
||||
if (toLoop <= 0) {
|
||||
var start = loopTime != null ? loopTime : 0;
|
||||
setLoops(--loops);
|
||||
if (start > 0 || AL.getSourcei(handle, AL.SOURCE_STATE) != AL.PLAYING) setCurrentTime(start);
|
||||
else resetTimer((getLength() - start) / getPitch());
|
||||
}
|
||||
else {
|
||||
if ((loops -= toLoop) < 0) loops = 0;
|
||||
toLoop = 0;
|
||||
resetTimer((getLength() - start) / getPitch());
|
||||
}
|
||||
|
||||
parent.onLoop.dispatch();
|
||||
@@ -337,11 +341,18 @@ class NativeAudioSource {
|
||||
|
||||
// Get & Set Methods
|
||||
public function getCurrentTime():Float {
|
||||
if (completed) return getLength();
|
||||
else if (disposed) return 0;
|
||||
if (disposed) return 0;
|
||||
else if (completed) return getLength();
|
||||
|
||||
var time = AL.getSourcef(handle, AL.SAMPLE_OFFSET) / parent.buffer.sampleRate;
|
||||
if (streamed) time += bufferTimes[STREAM_MAX_BUFFERS - queuedBuffers];
|
||||
if (streamed) {
|
||||
if (playing && streamEnded && AL.getSourcei(handle, AL.SOURCE_STATE) == AL.STOPPED) {
|
||||
complete();
|
||||
return getLength();
|
||||
}
|
||||
else
|
||||
time += bufferTimes[STREAM_MAX_BUFFERS - queuedBuffers];
|
||||
}
|
||||
time *= 1000;
|
||||
|
||||
var length = if (length == null) getRealLength(); else length;
|
||||
@@ -361,22 +372,25 @@ class NativeAudioSource {
|
||||
|
||||
if (playing) {
|
||||
var timeRemaining = (getLength() - value) / getPitch();
|
||||
if (completed = timeRemaining <= 0) complete();
|
||||
if (timeRemaining < 8) complete();
|
||||
else {
|
||||
completed = streamEnded = false;
|
||||
if (streamed) {
|
||||
AL.sourceUnqueueBuffers(handle, AL.getSourcei(handle, AL.BUFFERS_QUEUED));
|
||||
|
||||
unusedBuffers.resize(0);
|
||||
streamSeek(getSamples(value + parent.offset));
|
||||
|
||||
for (i in 0...(requestBuffers = queuedBuffers = STREAM_BUFFER_FREQUENCY))
|
||||
if (fillBuffer(buffers[i]) > 0) AL.sourceQueueBuffer(handle, buffers[i]);
|
||||
requestBuffers = queuedBuffers = STREAM_BUFFER_FREQUENCY;
|
||||
for (i in 0...queuedBuffers) {
|
||||
if (!streamEnded && fillBuffer(buffers[i]) > 0) AL.sourceQueueBuffer(handle, buffers[i]);
|
||||
else queuedBuffers = --requestBuffers;
|
||||
}
|
||||
|
||||
resetStreamTimer();
|
||||
if (!streamEnded) resetStreamTimer();
|
||||
}
|
||||
else
|
||||
resetTimer(timeRemaining);
|
||||
|
||||
resetTimer(timeRemaining);
|
||||
AL.sourcePlay(handle);
|
||||
}
|
||||
}
|
||||
@@ -398,9 +412,7 @@ class NativeAudioSource {
|
||||
else dataLength = Math.ffloor(Math.max(0, Math.min(value, getRealLength())) / 1000 * buffer.sampleRate) * buffer.channels * wordSize;
|
||||
|
||||
if (playing) {
|
||||
if (streamed) {
|
||||
if (streamEnded || toLoop > 0) setCurrentTime(getCurrentTime());
|
||||
}
|
||||
if (streamed && (streamEnded || toLoop > 0)) setCurrentTime(getCurrentTime());
|
||||
else {
|
||||
var timeRemaining = ((getLength() - parent.offset) - getCurrentTime()) / getPitch();
|
||||
if (timeRemaining > 0) resetTimer(timeRemaining);
|
||||
@@ -416,7 +428,7 @@ class NativeAudioSource {
|
||||
|
||||
public function setPitch(value:Float):Float {
|
||||
if (disposed || value == AL.getSourcef(handle, AL.PITCH)) return value;
|
||||
if (playing && (streamEnded || !streamed)) {
|
||||
if (playing) {
|
||||
var timeRemaining = (getLength() - getCurrentTime()) / value;
|
||||
if (timeRemaining > 0) resetTimer(timeRemaining);
|
||||
}
|
||||
|
||||
@@ -672,26 +672,10 @@ class Sound extends EventDispatcher
|
||||
#if (js && html5 && howlerjs)
|
||||
return __buffer.src.duration() * 1000;
|
||||
#else
|
||||
if (__buffer.data != null)
|
||||
{
|
||||
// var samples = (__buffer.data.length * 8) / (__buffer.channels * __buffer.bitsPerSample);
|
||||
// return Std.int(samples / __buffer.sampleRate * 1000);
|
||||
var samples = (Int64.make(0, __buffer.data.length) * Int64.ofInt(8)) / Int64.ofInt(__buffer.channels * __buffer.bitsPerSample);
|
||||
var div = Int64.divMod(samples * Int64.ofInt(1000), Int64.ofInt(__buffer.sampleRate));
|
||||
var value = (div.quotient + (div.modulus / __buffer.sampleRate));
|
||||
return Int64.toInt(value);
|
||||
}
|
||||
else if (__buffer.__srcVorbisFile != null)
|
||||
{
|
||||
//var samples = Int64.toInt(__buffer.__srcVorbisFile.pcmTotal());
|
||||
//return Std.int(samples / __buffer.sampleRate * 1000);
|
||||
var samples = __buffer.__srcVorbisFile.pcmTotal();
|
||||
var value = Int64.fromFloat(__buffer.__srcVorbisFile.timeTotal()) * 1000;
|
||||
return Int64.toInt(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
if (__buffer.data != null) return (__buffer.data.length >> 0) / __buffer.channels / (__buffer.bitsPerSample >> 3) / __buffer.sampleRate * 1000;
|
||||
else if (__buffer.__srcVorbisFile != null) {
|
||||
var x = __buffer.__srcVorbisFile.pcmTotal();
|
||||
return (x.high * 4294967296. + (x.low >> 0)) / __buffer.sampleRate * 1000;
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user