如何确定OGG文件的长度

时间:2013-12-27 03:10:56

标签: java audio file-io ogg

我正在制作一个节奏游戏,我需要一个快速的方法来获取ogg文件的长度。我能想到的唯一方法是在不播放文件的情况下快速传输文件,但如果我有数百首歌曲,这显然是不切实际的。另一种方法是将文件的长度存储在某种属性文件中,但我想避免这种情况。我知道必须有一些方法来做到这一点,因为大多数音乐播放器可以告诉你一首歌的长度。

2 个答案:

答案 0 :(得分:5)

最快捷的方法是找到文件的末尾,然后返回到你找到的最后一个Ogg页面标题并读取它的granulePosition(这是文件中每个通道的样本总数)。这不是万无一失的(你可能正在查看一个链式文件,在这种情况下你只能获得最后一个流的长度),但应该适用于绝大多数的Ogg文件。

如果您在阅读Ogg页面标题时需要帮助,可以阅读Jorbis源代码...简短版本是查找" OggS",读取一个字节(应为0),读取一个字节(只应设置第3位),然后读取64位小端值。

答案 1 :(得分:2)

我实现了ioctlLR描述的解决方案,它似乎有效:

double calculateDuration(final File oggFile) throws IOException {
    int rate = -1;
    int length = -1;

    int size = (int) oggFile.length();
    byte[] t = new byte[size];

    FileInputStream stream = new FileInputStream(oggFile);
    stream.read(t);

    for (int i = size-1-8-2-4; i>=0 && length<0; i--) { //4 bytes for "OggS", 2 unused bytes, 8 bytes for length
        // Looking for length (value after last "OggS")
        if (
                t[i]==(byte)'O'
                && t[i+1]==(byte)'g'
                && t[i+2]==(byte)'g'
                && t[i+3]==(byte)'S'
        ) {
            byte[] byteArray = new byte[]{t[i+6],t[i+7],t[i+8],t[i+9],t[i+10],t[i+11],t[i+12],t[i+13]};
            ByteBuffer bb = ByteBuffer.wrap(byteArray);
            bb.order(ByteOrder.LITTLE_ENDIAN);
            length = bb.getInt(0);
        }
    }
    for (int i = 0; i<size-8-2-4 && rate<0; i++) {
        // Looking for rate (first value after "vorbis")
        if (
                t[i]==(byte)'v'
                && t[i+1]==(byte)'o'
                && t[i+2]==(byte)'r'
                && t[i+3]==(byte)'b'
                && t[i+4]==(byte)'i'
                && t[i+5]==(byte)'s'
        ) {
            byte[] byteArray = new byte[]{t[i+11],t[i+12],t[i+13],t[i+14]};
            ByteBuffer bb = ByteBuffer.wrap(byteArray);
            bb.order(ByteOrder.LITTLE_ENDIAN);
            rate = bb.getInt(0);
        }

    }
    stream.close();

    double duration = (double) (length*1000) / (double) rate;
    return duration;
}

请注意,以这种方式查找费率仅适用于 vorbis OGG!

随意编辑我的答案,它可能不完美。