需要在使用Java的ogg游戏中应用seeking

需要在使用Java的ogg游戏中应用seeking,java,ogg,seek,multiplatform,audio-player,Java,Ogg,Seek,Multiplatform,Audio Player,我一直在为一个多平台桌面应用程序工作,该应用程序需要实现mp3和ogg播放器,包括搜索,现在我的mp3部分还可以,但ogg播放中的搜索不起作用 我正在使用javazoom.jlgui的basiclayer,下面是我的seek函数 /** * Skip bytes in the File inputstream. It will skip N frames matching to * bytes, so it will never skip given bytes length exactly

我一直在为一个多平台桌面应用程序工作,该应用程序需要实现mp3和ogg播放器,包括搜索,现在我的mp3部分还可以,但ogg播放中的搜索不起作用

我正在使用javazoom.jlgui的
basiclayer
,下面是我的seek函数

/**
 * Skip bytes in the File inputstream. It will skip N frames matching to
 * bytes, so it will never skip given bytes length exactly.
 *
 * @param bytes
 * @return value>0 for File and value=0 for URL and InputStream
 * @throws BasicPlayerException
 * @throws IOException
 */
protected long skipBytes(long bytes) throws BasicPlayerException, NullPointerException, IOException {

    long totalSkipped = 0;

    if (m_dataSource instanceof File) {
        log.info("Bytes to skip : " + bytes);
        int previousStatus = m_status;
        m_status = SEEKING;
        long skipped = 0;

        synchronized (m_audioInputStream) {
            notifyEvent(BasicPlayerEvent.SEEKING, getEncodedStreamPosition(), -1, null);
            initAudioInputStream();

            if (m_audioInputStream != null) {
                // Loop until bytes are really skipped.
                while (totalSkipped < (bytes - SKIP_INACCURACY_SIZE)) {
                    skipped = m_audioInputStream.skip(bytes - totalSkipped);
                    if (skipped == 0) {
                        break;
                    }

                    totalSkipped = totalSkipped + skipped;
                    log.info("Skipped : " + totalSkipped + "/" + bytes);

                    if (totalSkipped == -1) {
                        throw new BasicPlayerException(BasicPlayerException.SKIPNOTSUPPORTED);
                    }
                }
            }
        }

        notifyEvent(BasicPlayerEvent.SEEKED, getEncodedStreamPosition(), -1, null);
        m_status = OPENED;

        if (previousStatus == PLAYING) {
            startPlayback();
        } else if (previousStatus == PAUSED) {
            startPlayback();
            pausePlayback();
        }
    }

    return totalSkipped;
}
/**
*跳过文件inputstream中的字节。它将跳过N个匹配到的帧
*字节,因此它永远不会精确跳过给定的字节长度。
*
*@param字节
*@return value>0表示文件,value=0表示URL和InputStream
*@crows-basicLayerException
*@抛出异常
*/
受保护的长skipBytes(长字节)抛出BasicLayerException、NullPointerException、IOException{
长时间总计=0;
if(m_数据源实例文件){
log.info(“要跳过的字节:+字节”);
int-previousStatus=m_状态;
m_状态=寻找;
长跳过=0;
已同步(m_audioInputStream){
notifyEvent(BasicLayerEvent.SEEKING,getEncodedStreamPosition(),-1,null);
initAudioInputStream();
如果(m_audioInputStream!=null){
//循环,直到真正跳过字节。
while(totalSkipped<(字节-skipped\u不准确度\u大小)){
跳过=m_audioInputStream.skip(字节-总计跳过);
如果(跳过==0){
打破
}
totalSkipped=totalSkipped+skipped;
log.info(“跳过:“+totalSkipped+”/“+bytes”);
如果(总跳过==-1){
抛出新的BasicLayerException(BasicLayerException.SKIPNOTSUPPORTED);
}
}
}
}
notifyEvent(BasicLayerEvent.Seek,getEncodedStreamPosition(),-1,null);
m_状态=打开;
如果(先前状态==正在播放){
startPlayback();
}else if(先前状态==暂停){
startPlayback();
pausePlayback();
}
}
返回全部跳过;
}
有没有办法添加另一个seek函数来实现seek for ogg?先谢谢你

我不知道它是如何工作的,但它对mp3很好,包括搜索, 音频播放、暂停、停止 在ogg播放中,暂停、停止都可以,但查找是问题所在,搜索音频播放从一开始就开始

我没有更改代码的任何部分 BasicLayer Api的源代码是

当我深入查看详细信息时,使用此代码实现的jlgui3.0播放器也没有为Ogg play实现,他们已经提到了这一点。因此,当前代码需要为Ogg播放添加一个单独的seek函数,并在播放音频为Ogg时使用它而不是当前的
seek()


我不知道如何做到这一点,帮助我与良好的源代码参考和简单的方法来实现相同的

我认为这个图书馆可能不足以满足您的需要。查看jlGui的源代码,(粘贴在下面)seeking仅支持.mp3文件和.wav文件

此外,它背后的逻辑有些幼稚,因为它只向前跳一个固定的字节数。对于PCM格式的.wav文件,跳过的字节数始终与跳过的时间量成正比,但对于可变比特率的.mp3文件,跳过的时间量将随文件中不同点的瞬时比特率而变化。Ogg Vorbis是一种支持多路复用的容器格式,这使得查找比在文件中向前跳并重新同步解码器更加复杂

作为替代方案,我建议使用JavaSound或JavaFXAPI,这两种API都可以播放音频文件并查找您提供的时间,而不是字节偏移量

从jlGui:

protected void processSeek(double rate)
{
    try
    {
        if ((audioInfo != null) && (audioInfo.containsKey("audio.type")))
        {
            String type = (String) audioInfo.get("audio.type");
            // Seek support for MP3.
            if ((type.equalsIgnoreCase("mp3")) && (audioInfo.containsKey("audio.length.bytes")))
            {
                long skipBytes = (long) Math.round(((Integer) audioInfo.get("audio.length.bytes")).intValue() * rate);
                log.debug("Seek value (MP3) : " + skipBytes);
                theSoundPlayer.seek(skipBytes);
            }
            // Seek support for WAV.
            else if ((type.equalsIgnoreCase("wave")) && (audioInfo.containsKey("audio.length.bytes")))
            {
                long skipBytes = (long) Math.round(((Integer) audioInfo.get("audio.length.bytes")).intValue() * rate);
                log.debug("Seek value (WAVE) : " + skipBytes);
                theSoundPlayer.seek(skipBytes);
            }
            else posValueJump = false;
        }
        else posValueJump = false;
    }
    catch (BasicPlayerException ioe)
    {
        log.error("Cannot skip", ioe);
        posValueJump = false;
    }
}

“在ogg游戏中寻找不起作用”它在做什么?还是不做?如果(previousStatus==PAUSED){startPlayback();pausePlayback();},是否也使用
else?(我可能不知道您的程序是如何工作的,但立即开始
暂停
似乎有点可疑。)@Radiodef:Question edited…我认为这不是一项简单、直接的任务。OGG格式非常不同,对Seek的底层支持似乎不正确。OGG。。最好先尝试将整个曲目解码到PCM,然后再播放/搜索。所有音频解码器必须先从压缩格式转换为PCM格式,然后才能听到声音。因此,为什么不在发送到扬声器之前查找PCM?无论如何,对于OGG搜索,您必须遍历文件的字节以找到OGG页面的开头
(x4F\x67\x67\x53)
,然后前进6个字节,从7到14个字节读取Granular Pos(8个字节)。现在的复杂问题是:什么是音频编解码器?Flac,Opus,Vorbis?GranulePos可能表示到目前为止解码的PCM样本数(样本数=时间)是的,这是可能的,但对于大尺寸(30mb将使用大约318mb的内存容量?)。有些应用程序将临时文件写入硬盘。但我听到了你的担忧,并将尽快提供解决方案。我不使用Java,所以正确地提出建议是个问题。你能处理字节吗?意思是从位置查找和读取?您还可以将值写入一些新的字节数组吗?这是因为在某些系统中,寻道意味着从寻道pos中提取剩余的字节部分并馈送给OGG解码器。每次搜索都会从原始文件字节变成一个新的“抓取”