Java AudioInputStream 总是以负字节数跳过 returns 0

Java AudioInputStream skip with negative number of bytes always returns 0

I am trying to skip a negative number of bytes with AudioInputStream skip(long bytes) method .

问题是试图(假设字节数很少...):

int skipped = audioInputStream.skip(-bytes);

总是returns 0 ....我不知道该怎么办。


Here is the full code 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;                                                                                              
}                                                                                                                     

这个问题的继续... Java AudioInputStream how to support skip with negative number of bytes

AudioInputStream.skip 不支持否定参数。如果您阅读 InputStream.skip 的 Java 文档,它会说(强调 我的):

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, possibly 0. 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. If n is negative, the skip method for class InputStream always returns 0, and no bytes are skipped. Subclasses may handle the negative value differently.

它确实提到子类可能会改变这种行为,但 AudioInputStream 的文档没有给出任何指示它会这样做。

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 manipulate AudioInputStream 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 of n - (n % frameSize) bytes will be skipped.

此外,如果您查看 AudioInputStream.skip 的实现,您会发现第二个 if 语句立即 returns 0 如果 n<= 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个源代码。