This bug has several causes/issues:
1) Main problem: Clip.getFramePosition() is defined as the number of frames rendered since opening the device. Not very intuitive, but that's the spec.
2) The test program uses default buffer size, i.e. 500 milliseconds. It waits 1 second before it stops the device, so it hits a race condition: either the 3 buffer of 500 millis could just be written, or not. If yes, then the frame position will advance by the buffer size. This is a slight bug -- because that buffer is not actually rendered. Out of coincidence, the test program creates a race condition.
3) An "easy" fix would be a stop() implementation like this: store current position, stop device, set to stored position. However, and that's the problem, getFramePosition may return something completely meaningless with regards to setFramePosition, as outlined in 1).
For a fix I suggest the following:
A) in stop() record the position before stopping the device and use an internal setFramePosition method so that it returns the actual position that it was stopped, and continues counting from that position upon restart.
B) amend the javadoc for Clip.getFramePosition() to always return a value between 0 and getFrameLength() (i.e. add a special case to DataLine.getLongFramePosition).
C) Once B) is done, stop() can just set the frame position that it stored before stopping the device.
Due to code freeze, this cannot be fixed for tiger, but should go into the next possible release.
The cause of the bug is in the DirectSound Clip main playback loop implementation (DirectSoundDevice.DirectClip.run()):
The most part of time loop works inside write(...) method (waiting until DirectSound buffer has space to write data).
When stop() has been called during write(...) call java DS buffer counter (clipBytePosition) isn't increased although some portion of data has been written sucessfully.
From the point DirectSound buffer position and java buffer position (clipBytePosition) became disagreed.
###@###.### 2005-07-08 10:00:40 GMT