如何在Java中同步几个ogg文件的播放?

如何在Java中同步几个ogg文件的播放?,java,ogg,vorbis,Java,Ogg,Vorbis,我有一首歌,在不同的ogg文件中有不同的曲目。我可以使用Vorbis SPI一起播放这些ogg文件,以获得完整的歌曲。然而,我是通过在一个单独的线程中播放每个ogg来做到这一点的,我没有任何保护措施来防止每个ogg文件的播放失去同步 你将如何确保它们保持同步。理想情况下,如果读取任何磁道有延迟,则所有磁道都会暂停 一旦我有了这个工作,我也会希望与屏幕上显示的图形同步 我觉得我需要的是一些时间/地点记录,这样我就知道ogg的每一次回放都有多远了。然后,我可以延迟其他线程,直到一切恢复同步 我在早期

我有一首歌,在不同的ogg文件中有不同的曲目。我可以使用Vorbis SPI一起播放这些ogg文件,以获得完整的歌曲。然而,我是通过在一个单独的线程中播放每个ogg来做到这一点的,我没有任何保护措施来防止每个ogg文件的播放失去同步

你将如何确保它们保持同步。理想情况下,如果读取任何磁道有延迟,则所有磁道都会暂停

一旦我有了这个工作,我也会希望与屏幕上显示的图形同步

我觉得我需要的是一些时间/地点记录,这样我就知道ogg的每一次回放都有多远了。然后,我可以延迟其他线程,直到一切恢复同步

<>我在早期,所以我很乐意考虑其他的回放库。

编辑:

按照JimmyB的建议,我现在能够读入4字节缓冲区。然后,我使用以下代码将缓冲区添加到一起:

for (int i = 0; i < byteLength; i++) {
    data[0][i] = data[0][i];
    for (int j = 1; j < numInputs; j++) {
        data[0][i] += data[j][i];
    }
}

看起来字节读取和时间之间的关系可能不是线性的?也许这是我的想法。

在将保证同步的音频传送到声卡之前,您可以解码所有曲目中的一块,然后自己对解码后的音频进行混合。然后重复。使用双缓冲避免播放间隙。感谢Jimmy的建议,但我在Java处理音频方面绝对是个新手。你能告诉我任何地方可以帮助我解决如何做你所建议的事情吗?看看第一个例子。
rawplay
方法从(Ogg)AudioInputStream读取(最多)4kb的音频数据,然后将该数据传递到源数据线进行播放。在这两个步骤之间是可以拦截的点。你得到所有频道的一块解码音频,根据需要将它们混合到一块音频数据中,然后将单个块传递到SourceDataLine。越来越近。关于剪辑问题有什么想法吗?请注意,流提供了单个字节;根据音频格式,单个样本可能包含多个字节。在混合这些值之前,您可能需要将两个字节转换为一个16位采样值。您可以解码所有曲目中的一个块,然后在将保证同步的音频传递到声卡之前,自己进行解码音频的混合。然后重复。使用双缓冲避免播放间隙。感谢Jimmy的建议,但我在Java处理音频方面绝对是个新手。你能告诉我任何地方可以帮助我解决如何做你所建议的事情吗?看看第一个例子。
rawplay
方法从(Ogg)AudioInputStream读取(最多)4kb的音频数据,然后将该数据传递到源数据线进行播放。在这两个步骤之间是可以拦截的点。你得到所有频道的一块解码音频,根据需要将它们混合到一块音频数据中,然后将单个块传递到SourceDataLine。越来越近。关于剪辑问题有什么想法吗?请注意,流提供了单个字节;根据音频格式,单个样本可能包含多个字节。在混合这些值之前,可能需要将两个字节转换为一个16位采样值。
// return true if there is more to come
private boolean fillBuffer(AudioInputStream audioInputStream, byte[] soundBytes) throws IOException {
    byte empty = 0;
    int offset = 0;
    while (offset != soundBytes.length) {
        int bytesRead;
        try {
            bytesRead = audioInputStream.read(soundBytes, offset, soundBytes.length - offset);

            offset += bytesRead;
            if (bytesRead == -1) {
                Arrays.fill(soundBytes, offset, soundBytes.length, empty);
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.info("Boom");
        }
    }
    return true;
}