Необходимо применить поиск в ogg при воспроизведении с использованием Java

Я работаю над многоплатформенным настольным приложением, в котором необходимо реализовать как проигрыватель mp3, так и ogg, включая поиск. Теперь моя часть mp3 в порядке, но поиск в ogg play не работает...

Я использую BasicPlayer из javazoom.jlgui, и ниже приведена моя функция поиска.

/**
 * 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;
}

Есть ли способ добавить еще одну функцию поиска для реализации поиска ogg? заранее спасибо...

Не знаю много о том, как это работает, но он отлично работает для mp3, включая поиск, воспроизведение аудио, паузу, остановку. .

Я не менял никакую часть исходного кода BasicPlayer Api: http://www.javazoom.net/jlgui/sources/basicplayer3.0.zip

когда я подробно проверил детали, проигрыватель jlgui3.0, реализованный с использованием этого кода, также не реализует поиск воспроизведения Ogg, они упомянули об этом. Таким образом, текущий код необходимо добавить с отдельной функцией поиска для воспроизведения Ogg и использовать ее вместо текущего seek() всякий раз, когда воспроизводится звук Ogg...

Я не знаю, как это сделать, помогите мне с хорошим источником для ссылки и простым способом реализовать то же самое...


person Fahad    schedule 23.10.2014    source источник
comment
Поиск в ogg play не работает Что он делает? Или не делать? Также else if (previousStatus == PAUSED) { startPlayback(); pausePlayback(); }? (Возможно, я не знаю, как работает ваша программа, но start -> сразу pause кажется подозрительным.)   -  person Radiodef    schedule 27.10.2014
comment
@Radiodef: вопрос отредактирован...   -  person Fahad    schedule 27.10.2014
comment
Я не думаю, что это будет простая задача для реализации поиска. Формат OGG очень отличается, и базовая поддержка поиска не кажется правильной.   -  person helmy    schedule 02.11.2014
comment
@helmy: Как я могу легко написать код для поиска ogg, соответствующий этому классу Basicplayer??? Можете ли вы помочь мне с любой хорошей ссылкой или шаблонами кода .. ???   -  person Fahad    schedule 06.11.2014
comment
Что случилось с наградой?? Было странно, что вы предложили 200+, когда у вас есть максимум 18+. Это решено или у вас все еще есть идеи (я не использую Java, но мог бы оказать помощь, не относящуюся к языку)   -  person VC.One    schedule 15.11.2014
comment
@VC.One: До того, как я начал баунти, у меня была репутация 210+... :)   -  person Fahad    schedule 16.11.2014
comment
@ VC.One: проблема еще не решена, может быть, я мог бы использовать ваш алгоритм, рад услышать ваши предложения ...   -  person Fahad    schedule 17.11.2014
comment
Ааа теперь вижу. Я мельком увидел его во время визита, когда вы уже потеряли несколько очков, поэтому я был немного сбит с толку тем, как работает вся эта щедрость (я подумал: «А? Ты можешь это сделать??»).   -  person VC.One    schedule 21.11.2014
comment
OGG .. Лучше сначала попробовать декодировать весь трек в PCM, а затем вместо этого воспроизвести / поискать его. Все аудиодекодеры должны конвертировать из сжатых форматов в PCM, прежде чем вы сможете его услышать, так почему бы не искать PCM перед отправкой на динамики? В любом случае для поиска OGG вам придется пройтись по байтам вашего файла, чтобы найти начало страницы OGG (x4F\x67\x67\x53), затем вы идете на 6 байт вперед и с 7 по 14 байт читаете Granule Pos (8 байт). Теперь осложнение: ЧТО ТАКОЕ АУДИОКОДЕК? Flac, Opus, Vorbis? GranulePos может означать, сколько сэмплов PCM уже декодировано (сэмплы = время).   -  person VC.One    schedule 21.11.2014
comment
спасибо за подсказку, я не очень хорошо разбираюсь в алгоритмах декодирования, сейчас пытаюсь наверстать упущенное, в любом случае попробую этот метод...   -  person Fahad    schedule 26.11.2014
comment
@VC. Один аудиокодек - vorbis, и некоторые файлы, которые нужно воспроизвести в этом инструменте, могут иметь размер около 30 МБ, возможно ли это ???   -  person Fahad    schedule 27.11.2014
comment
Да, это возможно, но не идеально для больших размеров (30 МБ будут использовать около 318 МБ из скольких гигабайт оперативной памяти?). некоторые приложения вместо этого записывают на жесткий диск временный файл. Но я слышу ваше беспокойство и постараюсь найти решение в ближайшее время. Я не использую Java, поэтому мне сложно дать правильный совет по этому поводу. Вы можете обрабатывать байты, хотя? Что означает найти и прочитать с позиции? а также можете ли вы записать значение(я) в какой-нибудь новый массив байтов? Это связано с тем, что в некоторых системах поиск означает извлечение оставшейся части байтов из искомой позиции и передачу их в декодер OGG. Каждый поиск становится новым захватом исходных байтов файла.   -  person VC.One    schedule 01.12.2014
comment
@ VC.One: да, использование массива байтов возможно в java, не беспокойтесь о части кода java, достаточно хорошего алгоритма ...   -  person Fahad    schedule 16.12.2014


Ответы (1)


Я думаю, что этой библиотеки может быть недостаточно для ваших нужд. Глядя на исходный код jlGui (вставленный ниже), поиск поддерживается только для файлов .mp3 и .wav.

Более того, его логика несколько наивна, потому что он перемещается вперед только на фиксированное количество байтов. Для файлов формата PCM .wav количество пропущенных байтов всегда будет пропорционально количеству пропущенного времени, но для файлов .mp3 с переменным битрейтом количество пропущенного времени будет зависеть от мгновенного битрейта в разных точках файла. . Ogg Vorbis — это контейнерный формат, поддерживающий мультиплексирование, что делает поиск более сложным, чем просто переход вперед в файле и повторная синхронизация декодера.

В качестве альтернативы я бы рекомендовал использовать API-интерфейсы JavaSound или JavaFX, которые могут воспроизводить аудиофайлы и искать указанное вами время, а не смещение в байтах.

Из 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;
    }
}
person dncook    schedule 08.11.2014