Search code examples
javaflushjavasoundclipjavax.sound.sampled

Restarting a Clip object - flush() method


The Javadoc for DataLine.flush() states

Flushes queued data from the line. The flushed data is discarded. In some cases, not all queued data can be discarded. For example, a mixer can flush data from the buffer for a specific input line, but any unplayed data already in the output buffer (the result of the mix) will still be played. You can invoke this method after pausing a line (the normal case) if you want to skip the "stale" data when you restart playback or capture. (It is legal to flush a line that is not stopped, but doing so on an active line is likely to cause a discontinuity in the data, resulting in a perceptible click.)

What exactly does this mean?

Also, for restarting a Clip object, many people on this site suggested using this:

clip.stop();
clip.setFramePosition(0);
clip.start();

When using the above code, I noticed that a sample clip (which is about 15 seconds long if that matters) does not restart at the beginning and is inconsistent in its "restarting position." However, when I tried

clip.stop();
clip.flush();
clip.setFramePosition(0);
clip.start();

The clip worked perfectly and restarted right at the beginning of the sound. My question is, what did the flush() method do in order to fix my previous issue? Also, why did I have the issue in the first place?


Solution

  • A data line like Clip has an internal data buffer, probably a byte[]. The buffer will be typically filled in chunks, ahead of the playback position.

    Suppose at some instant we have:

                playback position
                       v
    buffer:         [..|.....]
      file: [..........|.....................]
    

    So if we stop the line, the buffer still has data in it—data which is ahead of the playback position.

    If all we do is set the playback position, the data is still there and will get played back the next time we start it. Flushing the line discards this data.

    We can also call drain to wait for this data to get played back.