@Override
    public float getSourcePlaybackTime(AudioSource src) {
        checkDead();
        synchronized (threadLock) {
            if (audioDisabled) {
                return 0;
            }

            if (src.getChannel() < 0) {
                return 0; // Not playing or invalid state
            }

            int sourceId = channels[src.getChannel()];
            AudioData data = src.getAudioData();
            if (data == null) {
                return 0; // No audio data
            }
            int playbackOffsetBytes = 0;

            // For streams, add the bytes from buffers that have already been fully processed and unqueued.
            if (data instanceof AudioStream) {
                AudioStream stream = (AudioStream) data;
                // This value is updated by the decoder thread when buffers are unqueued.
                playbackOffsetBytes = stream.getUnqueuedBufferBytes();
            }

            // Add byte offset from source (for both streams and buffers)
            int byteOffset = al.alGetSourcei(sourceId, AL_BYTE_OFFSET);
            playbackOffsetBytes += byteOffset;

            // Compute time value from bytes
            // E.g. for 44100 source with 2 channels and 16 bits per sample:
            //    (44100 * 2 * 16 / 8) = 176400
            int bytesPerSecond = (data.getSampleRate()
                    * data.getChannels()
                    * data.getBitsPerSample() / 8);

            if (bytesPerSecond <= 0) {
                logger.warning("Invalid bytesPerSecond calculated for source. Cannot get playback time.");
                return 0; // Avoid division by zero
            }

            return (float) playbackOffsetBytes / bytesPerSecond;
        }
    }
Gets the current playback time (in seconds) for a source.
For streams, includes the time represented by already processed buffers.
@param src The audio source.
@return The playback time in seconds, or 0 if not playing or invalid.
jme3-core/src/main/java/com/jme3/audio/openal/ALAudioRenderer.java