问题
I am trying to skip a negative number of bytes with
AudioInputStream
skip(long bytes)
method .
The problem is trying to (let's say a small number of bytes...) :
int skipped = audioInputStream.skip(-bytes);
always returns 0 .... i don't know what to do .
Here is the full code of the library on github .
What i do is recreating the line every time the user skips audio which is extremely slow when i can of course do much better ... by just going backward or forward . Now it supports only forward ...
/**
* Skip bytes in the File input stream. It will skip N frames matching to bytes, so it will never skip given bytes len
*
* @param bytes
* the bytes
* @return value bigger than 0 for File and value = 0 for URL and InputStream
* @throws StreamPlayerException
* the stream player exception
*/
public long seek(long bytes) throws StreamPlayerException {
long totalSkipped = 0;
//If it is File
if (dataSource instanceof File) {
//Check if the requested bytes are more than totalBytes of Audio
long bytesLength = getTotalBytes();
System.out.println("Bytes: " + bytes + " BytesLength: " + bytesLength);
if ( ( bytesLength <= 0 ) || ( bytes >= bytesLength )) {
generateEvent(Status.EOM, getEncodedStreamPosition(), null);
return totalSkipped;
}
logger.info(() -> "Bytes to skip : " + bytes);
Status previousStatus = status;
status = Status.SEEKING;
try {
synchronized (audioLock) {
generateEvent(Status.SEEKING, AudioSystem.NOT_SPECIFIED, null);
initAudioInputStream();
if (audioInputStream != null) {
long skipped;
// Loop until bytes are really skipped.
while (totalSkipped < ( bytes )) { //totalSkipped < (bytes-SKIP_INACCURACY_SIZE)))
//System.out.println("Running");
skipped = audioInputStream.skip(bytes - totalSkipped);
if (skipped == 0)
break;
totalSkipped += skipped;
logger.info("Skipped : " + totalSkipped + "/" + bytes);
if (totalSkipped == -1)
throw new StreamPlayerException(StreamPlayerException.PlayerException.SKIP_NOT_SUPPORTED);
logger.info("Skeeping:" + totalSkipped);
}
}
}
generateEvent(Status.SEEKED, getEncodedStreamPosition(), null);
status = Status.OPENED;
if (previousStatus == Status.PLAYING)
play();
else if (previousStatus == Status.PAUSED) {
play();
pause();
}
} catch (IOException ex) {
logger.log(Level.WARNING, ex.getMessage(), ex);
}
}
return totalSkipped;
}
Continuation of this question is here ... Java AudioInputStream how to support skip with negative number of bytes
回答1:
AudioInputStream.skip
does not support negative arguments. If you read the Javadoc of InputStream.skip
it says (emphasis mine):
Skips over and discards n bytes of data from this input stream. The
skip
method may, for a variety of reasons, end up skipping over some smaller number of bytes, possibly0
. This may result from any of a number of conditions; reaching end of file before n bytes have been skipped is only one possibility. The actual number of bytes skipped is returned. Ifn
is negative, theskip
method for classInputStream
always returns0
, and no bytes are skipped. Subclasses may handle the negative value differently.
It does mention that subclasses may change this behavior but the documentation of AudioInputStream
does not give any indication it does this.
Class (AudioInputStream
) javadoc:
An audio input stream is an input stream with a specified audio format and length. The length is expressed in sample frames, not bytes. Several methods are provided for reading a certain number of bytes from the stream, or an unspecified number of bytes. The audio input stream keeps track of the last byte that was read. You can skip over an arbitrary number of bytes to get to a later position for reading. An audio input stream may support marks. When you set a mark, the current position is remembered so that you can return to it later.
The
AudioSystem
class includes many methods that manipulateAudioInputStream
objects. For example, the methods let you:
- obtain an audio input stream from an external audio file, stream, or
URL
- write an external file from an audio input stream
- convert an audio input stream to a different audio format
AudioInputStream.skip
javadoc:
Skips over and discards a specified number of bytes from this audio input stream.
This method will always skip an integral number of frames. If
n
does not specify an integral number of frames, a maximum ofn - (n % frameSize)
bytes will be skipped.
Also, if you look at the implementation of AudioInputStream.skip
you can see that the second if
statement immediately returns 0
if n
is <= 0
.
@Override
public long skip(long n) throws IOException {
// make sure not to skip fractional frames
final long reminder = n % frameSize;
if (reminder != 0) {
n -= reminder;
}
if (n <= 0) {
return 0;
}
if (frameLength != AudioSystem.NOT_SPECIFIED) {
// don't skip more than our set length in frames.
if ((n / frameSize) > (frameLength - framePos)) {
n = (frameLength - framePos) * frameSize;
}
}
long remaining = n;
while (remaining > 0) {
// Some input streams like FileInputStream can return more bytes,
// when EOF is reached.
long ret = Math.min(stream.skip(remaining), remaining);
if (ret == 0) {
// EOF or not? we need to check.
if (stream.read() == -1) {
break;
}
ret = 1;
} else if (ret < 0) {
// the skip should not return negative value, but check it also
break;
}
remaining -= ret;
}
final long temp = n - remaining;
// if no error, update our position.
if (temp % frameSize != 0) {
// Throw an IOException if we've skipped a fractional number of frames
throw new IOException("Could not skip an integer number of frames.");
}
framePos += temp/frameSize;
return temp;
}
Java 10 source code.
来源:https://stackoverflow.com/questions/51919403/java-audioinputstream-skip-with-negative-number-of-bytes-always-returns-0