Package limn.sound

Interface AudioStreamSource

All Superinterfaces:
AutoCloseable

public interface AudioStreamSource extends AutoCloseable
A pull source of PCM frames for streamed playback: music and long ambience decoded incrementally instead of AudioClip-style all-at-once (a four minute track fully decoded is ~40 MB of heap; streamed it is a few hundred KB of ring buffers). Obtained from AudioDecoder.openStream(java.nio.file.Path) and consumed by AudioEngine.playStream(limn.sound.AudioStreamSource, limn.sound.PlayOptions).

Threading: after playStream takes ownership, calls come from the thread that starts the stream (initial priming reads) and from the engine's streaming thread (refills, seek(long), the final close()), never concurrently, serialized by the engine. Implementations need no synchronization but must not assume any particular thread.

  • Method Summary

    Modifier and Type
    Method
    Description
    default boolean
     
    int
     
    void
    Releases decoder/file resources.
    int
    readFrames(short[] out, int maxFrames)
    Decodes up to maxFrames frames into out (interleaved, frames × channels shorts from index 0).
    void
    Rewinds to the first frame: how the engine loops a stream seamlessly.
    int
     
    default void
    seek(long micros)
    Moves to micros so that the next readFrames(short[], int) returns audio from there: how a track follows a video that has been seeked, and how a transport control moves a long piece of music without restarting it.
  • Method Details

    • channels

      int channels()
      Returns:
      1 (mono) or 2 (stereo, interleaved)
    • sampleRate

      int sampleRate()
      Returns:
      frames per second (e.g. 44100)
    • readFrames

      int readFrames(short[] out, int maxFrames)
      Decodes up to maxFrames frames into out (interleaved, frames × channels shorts from index 0).
      Returns:
      the number of frames written; 0 means end of stream
    • reset

      void reset()
      Rewinds to the first frame: how the engine loops a stream seamlessly.
    • seek

      default void seek(long micros)
      Moves to micros so that the next readFrames(short[], int) returns audio from there: how a track follows a video that has been seeked, and how a transport control moves a long piece of music without restarting it.

      Repositioning the source is only half of a seek. The engine has already handed whole buffers to the device, and those play out before anything read after this does, so a caller that moves the source and nothing else hears the old position for the depth of the queue and then a jump. Playback.seek(long) is the operation that does both, and it is what a caller wants; this is what the engine calls underneath it.

      Accuracy is the implementation's: a decoder that can only reach a packet boundary lands on one. A target beyond the end leaves the track at its end, where readFrames(short[], int) reports zero; a target at or below zero is the beginning.

      Called on the thread readFrames(short[], int) is called on and never concurrently with it.

      Parameters:
      micros - where to move to, in microseconds from the start of the track; not negative
      Throws:
      UnsupportedOperationException - if canSeek() is false
      IllegalArgumentException - if micros is negative
    • canSeek

      default boolean canSeek()
      Returns:
      whether seek(long) works, which defaults to false so that a source written before seeking existed keeps telling the truth. Independent of reset(), which every source supports: rewinding to the start is not the same capability as reaching the middle.
    • close

      void close()
      Releases decoder/file resources. Idempotent.
      Specified by:
      close in interface AutoCloseable