Reputation: 193
I have been working for a multi-platform desktop application that need to implement both mp3 and ogg player including seeking, Now my mp3 part is Ok, but seeking in ogg play is not working...
I am using BasicPlayer
of javazoom.jlgui and following is my seek function
/**
* 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;
}
is there any way to add another seek function to implement seek for ogg? thanks in advance...
Don't know much about how this works,but it works fine for mp3 including for seeking, audio play,pause,stop In ogg playing,pause,stop are fine, but seeking is the problem, when seeked audio playing starts from the beginning.
I didn't change any part of the code source of BasicPlayer Api is http://www.javazoom.net/jlgui/sources/basicplayer3.0.zip
when I checked details in depth, jlgui3.0 player implemented using this code is also not implemented seeking for Ogg play, they have mentioned it. So the current code needs to be added with a separate seek function for Ogg playing and use it instead of current seek()
, whenever the playing audio is Ogg...
I don't know how to do so, help me with good source to refer and easy way to implement the same...
Upvotes: 3
Views: 1144
Reputation: 341
I think this library may not be sufficient for your needs. Looking at the source code of jlGui, (pasted below) seeking is only supported for .mp3 files and .wav files.
Moreover, the logic behind it is somewhat naive, because it only hops forward by a fixed number of bytes. For PCM format .wav files, the number of bytes skipped will always be proportional to the amount of time skipped, but for variable bit rate .mp3 files, the amount of time you skip will vary with the instantaneous bitrate at different points in the file. Ogg Vorbis is a container format that supports multiplexing, which makes seeking more complicated than just jumping ahead in the file and resynchronizing the decoder.
As an alternative, I would recommend using the JavaSound or JavaFX APIs, which both can play audio files and seek to a time you provide, rather than a byte offset.
From 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;
}
}
Upvotes: 1