获取FloatBuffer的AudioInputStream

时间:2018-04-10 12:39:28

标签: java audio audioinputstream

我有一个回调,它将传入的音频数据作为FloatBuffer包含1024个浮点数,每秒调用几次。但我需要一个AudioInputStream,因为我的系统只适用于它们。

将浮点数转换为16位PCM isgned音频数据不是问题,但我无法创建一个InputStream。 AudioInputStream构造函数只接受已知长度的数据,但我有一个常量流。 AudioSystem.getAudioInputStream抛出" java.io.IOException:不支持mark / reset"如果我用包含音频数据的PipedInputStream来提供它。

有什么想法吗?

这是我目前的代码:

Jack jack = Jack.getInstance();
JackClient client = jack.openClient("Test", EnumSet.noneOf(JackOptions.class), EnumSet.noneOf(JackStatus.class));
JackPort in = client.registerPort("in", JackPortType.AUDIO, EnumSet.of(JackPortFlags.JackPortIsInput));

PipedInputStream pin = new PipedInputStream(1024 * 1024 * 1024);
PipedOutputStream pout = new PipedOutputStream(pin);
client.setProcessCallback(new JackProcessCallback() {
public boolean process(JackClient client, int nframes) {
    FloatBuffer inData = in.getFloatBuffer();
    byte[] buffer = new byte[inData.capacity() * 2];
    for (int i = 0; i < inData.capacity(); i++) {
        int sample = Math.round(inData.get(i) * 32767);
        buffer[i * 2] = (byte) sample;
        buffer[i * 2 + 1] = (byte) (sample >> 8);
    }
    try {
        pout.write(buffer, 0, buffer.length);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return true;
}
});
client.activate();
client.transportStart();

Thread.sleep(10000);
client.transportStop();
client.close();

AudioInputStream audio = AudioSystem.getAudioInputStream(new BufferedInputStream(pin, 1024 * 1024 * 1024));
AudioSystem.write(audio, Type.WAVE, new File("test.wav"));

它使用JnaJack库,但数据的来源并不重要。顺便说一下,转换为字节很好:直接将数据写入SourceDataLine将正常工作。但我需要数据 AudioInputStream

1 个答案:

答案 0 :(得分:1)

AudioSystem.getAudioInputStream需要一个符合支持的AudioFileFormat的流,这意味着它必须符合known type。来自the documentation

  

流必须指向有效的音频文件数据。

还有文件:

  

此方法的实现可能需要多个解析器检查流以确定它们是否支持它。这些解析器必须能够标记流,读取足够的数据以确定它们是否支持流,并将流的读指针重置为其原始位置。如果输入流不支持这些操作,则此方法可能会失败并显示IOException

您可以使用三参数构造函数创建自己的AudioInputStream。如果长度未知,则可以指定为AudioSystem.NOT_SPECIFIED。令人沮丧的是,构造函数文档和类文档都没有提到这一点,但other constructor’s documentation确实如此。