0

我正在尝试使用AudioInputStream skip(long bytes)method 跳过负数的字节。

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

int skipped = audioInputStream.skip(-bytes);

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


这是github 上库的完整代码。

我所做的是每次用户跳过音频时重新创建线路,这非常慢,而我当然可以做得更好......只需向后或向前。现在它只支持转发...

/**                                                                                                                   
 * 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 如何支持负字节数的跳过

4

1 回答 1

2

AudioInputStream.skip不支持否定论点。如果您阅读它的 JavadocInputStream.skip说(强调我的):

跳过并丢弃此输入流中的 n 字节数据。由于各种原因,该skip方法最终可能会跳过一些较小的字节数0。这可能是由多种情况中的任何一种造成的;在跳过 n 个字节之前到达文件末尾只是一种可能性。返回实际跳过的字节数。如果n为负,则skip类的方法InputStream总是返回0,并且不跳过任何字节。子类可能以不同方式处理负值。

它确实提到子类可能会改变这种行为,但文档AudioInputStream并没有给出任何迹象表明它会这样做。

类(AudioInputStream)javadoc:

音频输入流是具有指定音频格式和长度的输入流。长度以样本帧而不是字节表示。提供了几种方法用于从流中读取一定数量的字节,或未指定数量的字节。音频输入流跟踪读取的最后一个字节。您可以跳过任意数量的字节以到达稍后的位置进行读取。音频输入流可能支持标记。设置标记时,会记住当前位置,以便您稍后返回。

该类AudioSystem包括许多操作AudioInputStream对象的方法。例如,这些方法让您:

  • 从外部音频文件、流或URL
  • 从音频输入流写入外部文件
  • 将音频输入流转换为不同的音频格式

AudioInputStream.skip文档:

跳过并丢弃此音频输入流中指定数量的字节。

此方法将始终跳过整数帧。如果n未指定整数帧,n - (n % frameSize)将跳过最大字节数。

此外,如果您查看实现,AudioInputStream.skip您可以看到第二条if语句立即返回0if nis <= 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 源代码。

于 2018-08-19T17:36:45.897 回答