来自socket的“Endless”AudioInputStream

时间:2015-11-16 20:38:24

标签: java sockets audio audio-streaming openal

我从Socket创建AudioInputStream时遇到问题。 以下是重要部分:

AudioInputStream audioInputStream = new AudioInputStream(this.getInputStream(), this.soundObject.getAudioFormat(), 100000);

此代码在此行抛出UnsupportedAudioFileException:

{{1}}

但是,当我使用此代码时:

{{1}}

它播放声音但仅在将这100000个样本帧加载到audioinputstream之后。它播放完所有100000帧之后就完成了。

我想如果我可以在第一个AudioInputStream inicialization期间直接将AudioFormat作为参数传递,我会解决这个问题,但似乎不可能。 我正在收到服务器的音频格式规范。

我认为一种可能的解决方案是创建一个数据线,我可以将其作为参数传递给AudioInputStream构造函数。但是我不确定如何将数据从套接字直接传输到dataline。我知道一个使用无限循环的解决方案,它会读取数据并将它们写入数据线。但这似乎很浪费。有更直接的方法吗?

我希望可以使用java-openAL库来解决,因为我需要改变速度,我希望自己不必这样做。

由于

1 个答案:

答案 0 :(得分:2)

我终于解决了这个问题。事实证明java-openAL内置了流媒体支持,但它并没有出现在GitHub的文档中,所以我一开始并没有注意到。 Source类中有一个createOutputStream方法,它返回OutputStream。您可以将字节直接写入OutputStream。

这是我的代码:

在此片段中,我初始化OpenAL:

public void run() {
    try {
        this.socket = new Socket(this.IP, this.port);
        this.openAL = new OpenAL();
    } catch (Exception ex) {
        Log.severe(ex.toString());
    }
    this.mainCycleMethod();
}

这是我的play方法,当InputStream可用时调用:

private void play() {
    try {
        this.source = openAL.createSource();
        this.outputWriter = new OutputWriter(this.socket.getInputStream(), this.source, this.soundObject.getAudioFormat());
        this.source.setGain(1f);
        this.outputWriter.start();
    } catch (Exception ex) {
        Log.severe(ex.toString());
    }
}

您必须使用不带参数的createSource方法,它返回Source的新实例。不要在源上调用play方法,它由SourceOutputStream类处理,该实例由createOutputStream方法返回。手动调用play方法没有任何问题,但是当缓冲区为空时我遇到了不好的经历。基本上,当您开始将数据流式传输到OpenAL时,它不会在以后开始播放。

这是我的OutputWriter代码,它负责将InputStream中的字节传递给OutputStream:

package cz.speechtech.sound;

import org.urish.openal.ALException;
import org.urish.openal.Source;

import javax.sound.sampled.AudioFormat;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * Created by honza on 16.12.15.
 */
public class OutputWriter extends Thread {
    private InputStream inputStream;
    private OutputStream outputStream;

    private int STREAMING_BUFFER_SIZE = 24000;
    private int NUMBER_OF_BUFFERS = 4;

    private boolean run = true;

    public OutputWriter(InputStream inputStream, Source source, AudioFormat audioFormat) {
        this.inputStream = inputStream;
        try {
            this.outputStream = source.createOutputStream(audioFormat, this.NUMBER_OF_BUFFERS, 1024);
        } catch (ALException e) {
            e.printStackTrace();
        }
    }

    public void run() {
        byte[] buffer = new byte[this.STREAMING_BUFFER_SIZE];
        int i;
        try {
            Thread.sleep(1000); // Might cause problems
            while (this.run) {
                i = this.inputStream.read(buffer);
                if (i == -1) break;
                outputStream.write(buffer, 0, i);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void stopRunning() {
        this.run = false;
        try {
            this.outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

度过愉快的一天。