diff --git a/src/org/newdawn/slick/openal/OpenALStreamPlayer.java b/src/org/newdawn/slick/openal/OpenALStreamPlayer.java index 8b33d905..8fbe3694 100644 --- a/src/org/newdawn/slick/openal/OpenALStreamPlayer.java +++ b/src/org/newdawn/slick/openal/OpenALStreamPlayer.java @@ -36,6 +36,7 @@ import java.nio.IntBuffer; import org.lwjgl.BufferUtils; import org.lwjgl.Sys; import org.lwjgl.openal.AL10; +import org.lwjgl.openal.AL11; import org.lwjgl.openal.OpenALException; import org.newdawn.slick.util.Log; import org.newdawn.slick.util.ResourceLoader; @@ -96,11 +97,17 @@ public class OpenALStreamPlayer { /** The music length. */ long musicLength = -1; - /** The time of the last update, in ms. */ - long lastUpdateTime = getTime(); + /** The assumed time of when the music position would be 0. */ + long syncStartTime; - /** The offset time. */ - long offsetTime = 0; + /** The last value that was returned for the music position. */ + float lastUpdatePosition = 0; + + /** The average difference between the sync time and the music position. */ + float avgDiff; + + /** The time when the music was paused. */ + long pauseTime; /** * Create a new player to work on an audio stream @@ -207,6 +214,7 @@ public class OpenALStreamPlayer { AL10.alSourceStop(source); startPlayback(); + syncStartTime = getTime(); } /** @@ -239,8 +247,6 @@ public class OpenALStreamPlayer { return; } - long playedPos_ = playedPos; - long lastUpdateTime_ = lastUpdateTime; int processed = AL10.alGetSourcei(source, AL10.AL_BUFFERS_PROCESSED); while (processed > 0) { unqueued.clear(); @@ -250,11 +256,10 @@ public class OpenALStreamPlayer { int bufferLength = AL10.alGetBufferi(bufferIndex, AL10.AL_SIZE); - playedPos_ += bufferLength; - lastUpdateTime_ = getTime(); + playedPos += bufferLength; - if (musicLength > 0 && playedPos_ > musicLength) - playedPos_ -= musicLength; + if (musicLength > 0 && playedPos > musicLength) + playedPos -= musicLength; if (stream(bufferIndex)) { AL10.alSourceQueueBuffers(source, unqueued); @@ -266,8 +271,6 @@ public class OpenALStreamPlayer { } processed--; } - playedPos = playedPos_; - lastUpdateTime = lastUpdateTime_; int state = AL10.alGetSourcei(source, AL10.AL_SOURCE_STATE); @@ -351,6 +354,7 @@ public class OpenALStreamPlayer { } playedPos = streamPos; + syncStartTime = getTime() - playedPos * 1000 / sampleSize / sampleRate; startPlayback(); @@ -377,7 +381,17 @@ public class OpenALStreamPlayer { AL10.alSourceQueueBuffers(source, bufferNames); AL10.alSourcePlay(source); - lastUpdateTime = getTime(); + } + + /** + * Return the current playing position in the sound + * + * @return The current position in seconds. + */ + public float getALPosition() { + float playedTime = ((float) playedPos / (float) sampleSize) / sampleRate; + float timePosition = playedTime + AL10.alGetSourcef(source, AL11.AL_SEC_OFFSET); + return timePosition; } /** @@ -386,24 +400,40 @@ public class OpenALStreamPlayer { * @return The current position in seconds. */ public float getPosition() { - float playedTime = ((float) playedPos / sampleSize) / sampleRate; - float timePosition = playedTime + (getTime() - lastUpdateTime) / 1000f; -// + AL10.alGetSourcef(source, AL11.AL_SEC_OFFSET); - return timePosition; + float thisPosition = getALPosition(); + long thisTime = getTime(); + float dxPosition = thisPosition - lastUpdatePosition; + long dxTime = thisTime - syncStartTime; + + // hard reset + if (Math.abs(thisPosition - dxTime / 1000f) > 1 / 2f) { + syncStartTime = thisTime - ((long) (thisPosition * 1000)); + dxTime = thisTime - syncStartTime; + avgDiff = 0; + } + if ((int) (dxPosition * 1000) != 0) { // lastPosition != thisPosition + float diff = thisPosition * 1000 - (dxTime); + avgDiff = (diff + avgDiff * 9) / 10; + syncStartTime -= (int) (avgDiff/2); + dxTime = thisTime - syncStartTime; + lastUpdatePosition = thisPosition; + } + + return dxTime / 1000f; } /** * Processes a track pause. */ public void pausing() { - offsetTime = getTime() - lastUpdateTime; + pauseTime = getTime(); } /** * Processes a track resume. */ public void resuming() { - lastUpdateTime = getTime() - offsetTime; + syncStartTime += getTime() - pauseTime; } /**