使用BufferedInputStream从服务器读取音频

时间:2014-07-07 22:34:12

标签: java inputstream urlconnection javax.sound.sampled

我从AudioInputStream通过URLConnection获得javax.sound.sampled.AudioSystem.getAudioInputStream()。将URL传递给getAudioInputStream()函数时,一切都很完美。但是,为了防止阻止,我使用URLConnection来获取输入流,以便我可以设置timeout。由于AudioInputStream要求对流进行标记支持和重置,因此我将URLConnection输入流包装在BufferedInputStream中。

使用BufferedInputStream时,在流中各个歌曲的末尾(由Icecast提供),AudioInputStream.read()方法会抛出ArrayIndexOutOfBounds异常。每首歌都不会一直发生,而是随机出现。

这是堆栈跟踪:

java.lang.ArrayIndexOutOfBoundsException: 15
    at javazoom.jl.decoder.LayerIDecoder$SubbandLayer1Stereo.read_allocation(Unknown Source)
    at javazoom.jl.decoder.LayerIDecoder.readAllocation(Unknown Source)
    at javazoom.jl.decoder.LayerIDecoder.decodeFrame(Unknown Source)
    at javazoom.jl.decoder.Decoder.decodeFrame(Unknown Source)
    at javazoom.spi.mpeg.sampled.convert.DecodedMpegAudioInputStream.execute(Unknown Source)
    at org.tritonus.share.TCircularBuffer.read(TCircularBuffer.java:138)
    at org.tritonus.share.sampled.convert.TAsynchronousFilteredAudioInputStream.read(TAsynchronousFilteredAudioInputStream.java:189)
    at [line where the AudioInputStream.read() is located]

我想知道,BufferedInputStream的基本属性会导致这种不一致的行为吗?毕竟,BufferedInputStream扩展了InputStream并应该表现出来同样在外面。

我在没有设置URLConnection超时的情况下对此进行了测试,并且错误仍然存​​在,但是当我切换回URL直接传递到getAudioInputStream()函数时,它可以正常工作。

*我正在使用TritonusJLayer

编辑:由于课程规模很大,我无法提供所有代码。这是相关的代码。

URLConnection uc = url.openConnection();
uc.setReadTimeout(30000);
uc.setConnectTimeout(20000);
uc.connect();

AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new BufferedInputStream(uc.getInputStream()));

和read(af是存储音频信息并声明AudioInputStream的自定义类的实例)

//Performs a necessary conversion
AudioInputStream in = AudioSystem.getAudioInputStream(af.getAudioFormat(), af.getAudioStream());

while(play) {
    try {
        int n = 0;
        if ((n = in.read(buffer, 0, buffer.length)) == -1) {
            break;
        }
    } catch (ArrayIndexOutOfBoundsException e) {
        e.printStackTrace();
    }

    // SourceDataLine.write() here...
}

*如果你想知道,我设置了这样的读取循环是有原因的(在while循环中有一个if语句)。

read_allocation()所在的库的源代码:https://github.com/libgdx/jlayer-gdx/blob/master/src/javazoom/jl/decoder/LayerIDecoder.java

1 个答案:

答案 0 :(得分:2)

BufferedInputStream仅允许您标记/重置为缓冲区的大小。尝试增加它超过文件的大小。